genevent for userspace generic
[lttv.git] / genevent-new / parser.c
CommitLineData
3583026d 1/*
2
3parser.c: Generate helper declarations and functions to trace events
4 from an event description file.
5
a3e6ce64 6 Copyright (C) 2005, Mathieu Desnoyers
7 Copyright (C) 2002, Xianxiu Yang
8 Copyright (C) 2002, Michel Dagenais
9 This program is free software; you can redistribute it and/or modify
3583026d 10 it under the terms of the GNU General Public License as published by
a3e6ce64 11 the Free Software Foundation; version 2 of the License.
3583026d 12
a3e6ce64 13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
3583026d 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21*/
22
23/* This program reads the ".xml" event definitions input files
24 and constructs structure for each event.
25
26 The program uses a very simple tokenizer, called from a hand written
27 recursive descent parser to fill a data structure describing the events.
28 The result is a sequence of events definitions which refer to type
29 definitions.
30
31 A table of named types is maintained to allow refering to types by name
32 when the same type is used at several places. Finally a sequence of
33 all types is maintained to facilitate the freeing of all type
34 information when the processing of an ".xml" file is finished. */
35
36#include <stdlib.h>
37#include <string.h>
38#include <stdio.h>
39#include <stdarg.h>
40#include <linux/errno.h>
41#include <assert.h>
42#include <ctype.h>
43
44#include "parser.h"
45
46
2d2d14a7 47char *intOutputTypes[] = {
48 "int8_t", "int16_t", "int32_t", "int64_t" };
3583026d 49
2d2d14a7 50char *uintOutputTypes[] = {
51 "uint8_t", "uint16_t", "uint32_t", "uint64_t" };
3583026d 52
2d2d14a7 53char *floatOutputTypes[] = {
54 "undef", "undef", "float", "double" };
3583026d 55
56
57
58
59/* helper function */
60void strupper(char *string)
61{
62 char *ptr = string;
63
64 while(*ptr != '\0') {
65 *ptr = toupper(*ptr);
66 ptr++;
67 }
68}
69
70
2d2d14a7 71int getSizeindex(unsigned int value)
3583026d 72{
73 switch(value) {
74 case 1:
75 return 0;
76 case 2:
77 return 1;
78 case 4:
79 return 2;
80 case 8:
81 return 3;
82 default:
83 printf("Error : unknown value size %d\n", value);
84 exit(-1);
85 }
86}
87
88/*****************************************************************************
89 *Function name
90 * getSize : translate from string to integer
91 *Input params
92 * in : input file handle
93 *Return values
94 * size
95 *****************************************************************************/
96
2d2d14a7 97unsigned long long int getSize(parse_file_t *in)
3583026d 98{
99 char *token;
bb9014e6 100 int has_quotes = 0;
101 unsigned long long int ret;
3583026d 102
103 token = getToken(in);
bb9014e6 104 if(token[0] == '"') {
105 has_quotes = 1;
106 token = getToken(in);
107 }
3583026d 108 if(in->type == NUMBER) {
bb9014e6 109 ret = strtoull(token, NULL, 0);
110 } else {
111 goto error;
112 }
113 if(has_quotes) {
114 token = getToken(in);
115 if(token[0] != '"') goto error;
116 }
117
118 return ret;
119error:
3583026d 120 in->error(in,"incorrect size specification");
121 return -1;
122}
123
124/*****************************************************************************
125 *Function name
126 * error_callback : print out error info
127 *Input params
128 * in : input file handle
129 * msg : message to be printed
130 ****************************************************************************/
131
132void error_callback(parse_file_t *in, char *msg)
133{
134 if(in)
135 printf("Error in file %s, line %d: %s\n", in->name, in->lineno, msg);
136 else
137 printf("%s\n",msg);
138 assert(0);
139 exit(1);
140}
141
142/*****************************************************************************
143 *Function name
144 * memAlloc : allocate memory
145 *Input params
146 * size : required memory size
147 *return value
148 * void * : pointer to allocate memory or NULL
149 ****************************************************************************/
150
151void * memAlloc(int size)
152{
153 void * addr;
154 if(size == 0) return NULL;
155 addr = malloc(size);
156 if(!addr){
157 printf("Failed to allocate memory");
158 exit(1);
159 }
160 return addr;
161}
162
163/*****************************************************************************
164 *Function name
165 * allocAndCopy : allocate memory and initialize it
166 *Input params
167 * str : string to be put in memory
168 *return value
169 * char * : pointer to allocate memory or NULL
170 ****************************************************************************/
171
172char *allocAndCopy(char *str)
173{
174 char * addr;
175 if(str == NULL) return NULL;
176 addr = (char *)memAlloc(strlen(str)+1);
177 strcpy(addr,str);
178 return addr;
179}
180
181/**************************************************************************
182 * Function :
183 * getTypeAttributes
184 * Description :
185 * Read the attribute from the input file.
186 *
187 * Parameters :
188 * in , input file handle.
189 * t , the type descriptor to fill.
190 *
191 **************************************************************************/
192
be97b953 193void getTypeAttributes(parse_file_t *in, type_descriptor_t *t,
194 sequence_t * unnamed_types, table_t * named_types)
3583026d 195{
196 char * token;
197
198 t->fmt = NULL;
2d2d14a7 199 t->size = 0;
64a6ab10 200 t->custom_write = 0;
7479dd85 201 t->network = 0;
3583026d 202
203 while(1) {
204 token = getToken(in);
205 if(strcmp("/",token) == 0 || strcmp(">",token) == 0){
206 ungetToken(in);
207 break;
208 }
209
210 if(!strcmp("format",token)) {
211 getEqual(in);
212 t->fmt = allocAndCopy(getQuotedString(in));
213 //} else if(!strcmp("name",token)) {
214 // getEqual(in);
215 // car = seekNextChar(in);
216 // if(car == EOF) in->error(in,"name was expected");
217 // else if(car == '\"') t->type_name = allocAndCopy(getQuotedString(in));
218 // else t->type_name = allocAndCopy(getName(in));
be97b953 219 } else if(!strcmp("size",token)) {
3583026d 220 getEqual(in);
221 t->size = getSize(in);
64a6ab10 222 } else if(!strcmp("custom_write", token)) {
223 t->custom_write = 1;
7479dd85 224 } else if(!strcmp("network", token)) {
225 t->network = 1;
226 }
3583026d 227 }
228}
229
230/**************************************************************************
231 * Function :
232 * getEventAttributes
233 * Description :
234 * Read the attribute from the input file.
235 *
236 * Parameters :
237 * in , input file handle.
238 * ev , the event to fill.
239 *
240 **************************************************************************/
241
242void getEventAttributes(parse_file_t *in, event_t *ev)
243{
244 char * token;
245 char car;
246
247 ev->name = NULL;
248 ev->per_trace = 0;
249 ev->per_tracefile = 0;
250
251 while(1) {
252 token = getToken(in);
253 if(strcmp("/",token) == 0 || strcmp(">",token) == 0){
254 ungetToken(in);
255 break;
256 }
257
258 if(!strcmp("name",token)) {
259 getEqual(in);
260 car = seekNextChar(in);
261 if(car == EOF) in->error(in,"name was expected");
262 else if(car == '\"') ev->name = allocAndCopy(getQuotedString(in));
263 else ev->name = allocAndCopy(getName(in));
264 } else if(!strcmp("per_trace", token)) {
265 ev->per_trace = 1;
266 } else if(!strcmp("per_tracefile", token)) {
267 ev->per_tracefile = 1;
268 }
269
270 }
271}
272
273/**************************************************************************
274 * Function :
275 * getFacilityAttributes
276 * Description :
277 * Read the attribute from the input file.
278 *
279 * Parameters :
280 * in , input file handle.
281 * fac , the facility to fill.
282 *
283 **************************************************************************/
284
285void getFacilityAttributes(parse_file_t *in, facility_t *fac)
286{
287 char * token;
288 char car;
289
290 fac->name = NULL;
ffaf5031 291 fac->arch = NULL;
bd7b8ca6 292 fac->user = 0;
3583026d 293
294 while(1) {
295 token = getToken(in);
296 if(strcmp("/",token) == 0 || strcmp(">",token) == 0){
297 ungetToken(in);
298 break;
299 }
300
301 if(!strcmp("name",token)) {
302 getEqual(in);
303 car = seekNextChar(in);
304 if(car == EOF) in->error(in,"name was expected");
305 else if(car == '\"') fac->name = allocAndCopy(getQuotedString(in));
306 else fac->name = allocAndCopy(getName(in));
bd7b8ca6 307 if(!strncmp(fac->name, "user_", sizeof("user_")) == 0)
308 fac->user = 1;
ffaf5031 309 } else if(!strcmp("arch", token)) {
310 getEqual(in);
311 car = seekNextChar(in);
312 if(car == '\"') fac->name = allocAndCopy(getQuotedString(in));
313 else fac->arch = allocAndCopy(getName(in));
314 }
3583026d 315 }
316}
317
318/**************************************************************************
319 * Function :
320 * getFieldAttributes
321 * Description :
322 * Read the attribute from the input file.
323 *
324 * Parameters :
325 * in , input file handle.
326 * f , the field to fill.
327 *
328 **************************************************************************/
329
330void getFieldAttributes(parse_file_t *in, field_t *f)
331{
332 char * token;
333 char car;
334
335 f->name = NULL;
336
337 while(1) {
338 token = getToken(in);
339 if(strcmp("/",token) == 0 || strcmp(">",token) == 0){
340 ungetToken(in);
341 break;
342 }
343
344 if(!strcmp("name",token)) {
345 getEqual(in);
346 car = seekNextChar(in);
347 if(car == EOF) in->error(in,"name was expected");
348 else if(car == '\"') f->name = allocAndCopy(getQuotedString(in));
349 else f->name = allocAndCopy(getName(in));
350 }
7479dd85 351 }
3583026d 352}
353
354char *getNameAttribute(parse_file_t *in)
355{
356 char * token;
357 char *name = NULL;
358 char car;
359
360 while(1) {
361 token = getToken(in);
3583026d 362 if(!strcmp("name",token)) {
363 getEqual(in);
364 car = seekNextChar(in);
365 if(car == EOF) in->error(in,"name was expected");
366 else if(car == '\"') name = allocAndCopy(getQuotedString(in));
367 else name = allocAndCopy(getName(in));
64a6ab10 368 } else {
369 ungetToken(in);
370 break;
3583026d 371 }
64a6ab10 372
3583026d 373 }
374 if(name == NULL) in->error(in, "Name was expected");
375 return name;
3583026d 376}
377
378
379
380//for <label name=label_name value=n format="..."/>, value is an option
bb9014e6 381//Return value : 0 : no value, 1 : has a value
382int getValueAttribute(parse_file_t *in, long long *value)
3583026d 383{
384 char * token;
bb9014e6 385 int has_quotes = 0;
3583026d 386
387 token = getToken(in);
388 if(strcmp("/",token) == 0){
389 ungetToken(in);
bb9014e6 390 return 0;
3583026d 391 }
392
393 if(strcmp("value",token))in->error(in,"value was expected");
394 getEqual(in);
395 token = getToken(in);
bb9014e6 396
397 if(token[0] == '"') {
398 has_quotes = 1;
399 token = getToken(in);
400 }
401 if(in->type == NUMBER) {
402 *value = strtoll(token, NULL, 0);
403 } else {
404 goto error;
405 }
406 if(has_quotes) {
407 token = getToken(in);
408 if(token[0] != '"') goto error;
409 }
410 return 1;
411
412error:
413 in->error(in,"incorrect size specification");
414 return 0;
3583026d 415}
416
417char * getDescription(parse_file_t *in)
418{
419 long int pos;
420 char * token, car, *str;
421
422 pos = ftell(in->fp);
423
424 getLAnglebracket(in);
425 token = getName(in);
426 if(strcmp("description",token)){
427 fseek(in->fp, pos, SEEK_SET);
428 return NULL;
429 }
430
431 getRAnglebracket(in);
432
433 pos = 0;
434 while((car = getc(in->fp)) != EOF) {
435 if(car == '<') break;
436 if(car == '\0') continue;
437 in->buffer[pos] = car;
438 pos++;
439 }
440 if(car == EOF)in->error(in,"not a valid description");
441 in->buffer[pos] = '\0';
442
443 str = allocAndCopy(in->buffer);
444
445 getForwardslash(in);
446 token = getName(in);
447 if(strcmp("description", token))in->error(in,"not a valid description");
448 getRAnglebracket(in);
449
450 return str;
451}
452
453/*****************************************************************************
454 *Function name
455 * parseFacility : generate event list
456 *Input params
457 * in : input file handle
458 * fac : empty facility
459 *Output params
460 * fac : facility filled with event list
461 ****************************************************************************/
462
463void parseFacility(parse_file_t *in, facility_t * fac)
464{
465 char * token;
466 event_t *ev;
467
468 getFacilityAttributes(in, fac);
469 if(fac->name == NULL) in->error(in, "Attribute not named");
ffaf5031 470
3583026d 471 fac->capname = allocAndCopy(fac->name);
472 strupper(fac->capname);
473 getRAnglebracket(in);
474
475 fac->description = getDescription(in);
476
477 while(1){
478 getLAnglebracket(in);
479
480 token = getToken(in);
481 if(in->type == ENDFILE)
482 in->error(in,"the definition of the facility is not finished");
483
484 if(strcmp("event",token) == 0){
485 ev = (event_t*) memAlloc(sizeof(event_t));
486 sequence_push(&(fac->events),ev);
487 parseEvent(in,ev, &(fac->unnamed_types), &(fac->named_types));
488 }else if(strcmp("type",token) == 0){
489 parseTypeDefinition(in, &(fac->unnamed_types), &(fac->named_types));
490 }else if(in->type == FORWARDSLASH){
491 break;
492 }else in->error(in,"event or type token expected\n");
493 }
494
495 token = getName(in);
496 if(strcmp("facility",token)) in->error(in,"not the end of the facility");
497 getRAnglebracket(in); //</facility>
498}
499
500/*****************************************************************************
501 *Function name
502 * parseEvent : generate event from event definition
503 *Input params
504 * in : input file handle
505 * ev : new event
506 * unnamed_types : array of unamed types
507 * named_types : array of named types
508 *Output params
509 * ev : new event (parameters are passed to it)
510 ****************************************************************************/
511
512void parseEvent(parse_file_t *in, event_t * ev, sequence_t * unnamed_types,
513 table_t * named_types)
514{
515 char *token;
47299663 516 field_t *f;
3583026d 517
47299663 518 sequence_init(&(ev->fields));
3583026d 519 //<event name=eventtype_name>
520 getEventAttributes(in, ev);
521 if(ev->name == NULL) in->error(in, "Event not named");
522 getRAnglebracket(in);
523
47299663 524 //<description>...</description>
3583026d 525 ev->description = getDescription(in);
526
47299663 527 int got_end = 0;
528 /* Events can have multiple fields. each field form at least a function
529 * parameter of the logging function. */
530 while(!got_end) {
531 getLAnglebracket(in);
532 token = getToken(in);
533
534 switch(in->type) {
535 case FORWARDSLASH: /* </event> */
536 token = getName(in);
537 if(strcmp("event",token))in->error(in,"not an event definition");
538 getRAnglebracket(in); //</event>
539 got_end = 1;
540 break;
541 case NAME: /* a field */
542 if(strcmp("field",token))in->error(in,"expecting a field");
543 f = (field_t *)memAlloc(sizeof(field_t));
544 sequence_push(&(ev->fields),f);
a67cd958 545 parseFields(in, f, unnamed_types, named_types, 1);
47299663 546 break;
547 default:
548 in->error(in, "expecting </event> or <field >");
549 break;
550 }
551 }
552#if 0
553 if(in->type == FORWARDSLASH){ //</event> NOTHING
554 ev->type = NULL;
555 }else if(in->type == NAME){
556 if(strcmp("struct",token)==0 || strcmp("typeref",token)==0){
557 ungetToken(in);
558 ev->type = parseType(in,NULL, unnamed_types, named_types);
559 if(ev->type->type != STRUCT && ev->type->type != NONE)
560 in->error(in,"type must be a struct");
561 }else in->error(in, "not a valid type");
562
563 getLAnglebracket(in);
564 getForwardslash(in);
565 }else in->error(in,"not a struct type");
566 getLAnglebracket(in);
567 getForwardslash(in);
568 token = getName(in);
569 if(strcmp("event",token))in->error(in,"not an event definition");
570 getRAnglebracket(in); //</event>
571#endif //0
3583026d 572}
573
574/*****************************************************************************
575 *Function name
576 * parseField : get field infomation from buffer
577 *Input params
578 * in : input file handle
47299663 579 * f : field
3583026d 580 * unnamed_types : array of unamed types
581 * named_types : array of named types
a67cd958 582 * tag : is field surrounded by a <field> </field> tag ?
3583026d 583 ****************************************************************************/
584
47299663 585void parseFields(parse_file_t *in, field_t *f,
3583026d 586 sequence_t * unnamed_types,
a67cd958 587 table_t * named_types,
588 int tag)
3583026d 589{
590 char * token;
a67cd958 591 if(tag) {
592 //<field name=field_name> <description> <type> </field>
593 getFieldAttributes(in, f);
594 if(f->name == NULL) in->error(in, "Field not named");
595 getRAnglebracket(in);
3583026d 596
a67cd958 597 f->description = getDescription(in);
7479dd85 598 } else {
599 f->description = NULL;
a67cd958 600 }
3583026d 601
602 //<int size=...>
603 getLAnglebracket(in);
604 f->type = parseType(in,NULL, unnamed_types, named_types);
605
a67cd958 606 if(tag) {
607 getLAnglebracket(in);
608 getForwardslash(in);
609 token = getName(in);
610 if(strcmp("field",token))in->error(in,"not a valid field definition");
611 getRAnglebracket(in); //</field>
612 }
3583026d 613}
614
615
616/*****************************************************************************
617 *Function name
618 * parseType : get type information, type can be :
619 * Primitive:
620 * int(size,fmt); uint(size,fmt); float(size,fmt);
621 * string(fmt); enum(size,fmt,(label1,label2...))
622 * Compound:
623 * array(arraySize, type); sequence(lengthSize,type)
624 * struct(field(name,type,description)...)
625 * type name:
626 * type(name,type)
627 *Input params
628 * in : input file handle
629 * inType : a type descriptor
630 * unnamed_types : array of unamed types
631 * named_types : array of named types
632 *Return values
633 * type_descriptor* : a type descriptor
634 ****************************************************************************/
635
636type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType,
637 sequence_t * unnamed_types, table_t * named_types)
638{
639 char *token;
640 type_descriptor_t *t;
47299663 641 field_t *f;
3583026d 642
643 if(inType == NULL) {
644 t = (type_descriptor_t *) memAlloc(sizeof(type_descriptor_t));
645 t->type_name = NULL;
646 t->type = NONE;
647 t->fmt = NULL;
648 sequence_push(unnamed_types,t);
649 }
650 else t = inType;
651
652 token = getName(in);
653
654 if(strcmp(token,"struct") == 0) {
655 t->type = STRUCT;
be97b953 656 getTypeAttributes(in, t, unnamed_types, named_types);
3583026d 657 getRAnglebracket(in); //<struct>
658 getLAnglebracket(in); //<field name=..>
659 token = getToken(in);
660 sequence_init(&(t->fields));
661 while(strcmp("field",token) == 0){
47299663 662 f = (field_t *)memAlloc(sizeof(field_t));
663 sequence_push(&(t->fields),f);
664
a67cd958 665 parseFields(in, f, unnamed_types, named_types, 1);
3583026d 666
667 //next field
668 getLAnglebracket(in);
669 token = getToken(in);
670 }
671 if(strcmp("/",token))in->error(in,"not a valid structure definition");
672 token = getName(in);
673 if(strcmp("struct",token)!=0)
674 in->error(in,"not a valid structure definition");
675 getRAnglebracket(in); //</struct>
676 }
677 else if(strcmp(token,"union") == 0) {
678 t->type = UNION;
be97b953 679 getTypeAttributes(in, t, unnamed_types, named_types);
2d2d14a7 680 getRAnglebracket(in); //<union>
3583026d 681
682 getLAnglebracket(in); //<field name=..>
683 token = getToken(in);
684 sequence_init(&(t->fields));
685 while(strcmp("field",token) == 0){
47299663 686 f = (field_t *)memAlloc(sizeof(field_t));
687 sequence_push(&(t->fields),f);
a67cd958 688 parseFields(in, f, unnamed_types, named_types, 1);
3583026d 689
690 //next field
691 getLAnglebracket(in);
692 token = getToken(in);
693 }
694 if(strcmp("/",token))in->error(in,"not a valid union definition");
695 token = getName(in);
696 if(strcmp("union",token)!=0)
697 in->error(in,"not a valid union definition");
698 getRAnglebracket(in); //</union>
699 }
700 else if(strcmp(token,"array") == 0) {
701 t->type = ARRAY;
a67cd958 702 sequence_init(&(t->fields));
be97b953 703 getTypeAttributes(in, t, unnamed_types, named_types);
2d2d14a7 704 if(t->size == 0) in->error(in, "Array has empty size");
705 getForwardslash(in);
3583026d 706 getRAnglebracket(in); //<array size=n>
707
2e415130 708 //getLAnglebracket(in); //<subtype>
a67cd958 709 /* subfield */
710 f = (field_t *)memAlloc(sizeof(field_t));
711 sequence_push(&(t->fields),f);
712 parseFields(in, f, unnamed_types, named_types, 0);
713
714 //getLAnglebracket(in); //<type struct>
715 //t->nested_type = parseType(in, NULL, unnamed_types, named_types);
3583026d 716
717 getLAnglebracket(in); //</array>
718 getForwardslash(in);
719 token = getName(in);
720 if(strcmp("array",token))in->error(in,"not a valid array definition");
721 getRAnglebracket(in); //</array>
722 }
723 else if(strcmp(token,"sequence") == 0) {
724 t->type = SEQUENCE;
a67cd958 725 sequence_init(&(t->fields));
64a6ab10 726 getTypeAttributes(in, t, unnamed_types, named_types);
727 getForwardslash(in);
be97b953 728 getRAnglebracket(in); //<sequence>
3583026d 729
2e415130 730 //getLAnglebracket(in); //<sequence size type>
a67cd958 731 /* subfield */
732 f = (field_t *)memAlloc(sizeof(field_t));
733 sequence_push(&(t->fields),f);
734 parseFields(in, f, unnamed_types, named_types, 0);
735
2e415130 736 //getLAnglebracket(in); //<subtype>
a67cd958 737 /* subfield */
738 f = (field_t *)memAlloc(sizeof(field_t));
739 sequence_push(&(t->fields),f);
740 parseFields(in, f, unnamed_types, named_types, 0);
3583026d 741
a67cd958 742 //getLAnglebracket(in); //<type sequence>
743 //t->length_type = parseType(in, NULL, unnamed_types, named_types);
be97b953 744
a67cd958 745 //getLAnglebracket(in); //<type sequence>
be97b953 746
a67cd958 747 //t->nested_type = parseType(in, NULL, unnamed_types, named_types);
748
749 if(t->fields.position < 1) in->error(in, "Sequence has no length type");
750 if(t->fields.position < 2) in->error(in, "Sequence has no subtype");
751 switch(((field_t*)t->fields.array[0])->type->type) {
be97b953 752 case UINT_FIXED :
753 case UCHAR :
754 case USHORT :
755 case UINT :
756 case ULONG :
757 case SIZE_T :
758 case OFF_T :
759 break;
760 default:
761 in->error(in, "Wrong length type for sequence");
762 }
763
3583026d 764 getLAnglebracket(in); //</sequence>
765 getForwardslash(in);
766 token = getName(in);
767 if(strcmp("sequence",token))in->error(in,"not a valid sequence definition");
768 getRAnglebracket(in); //</sequence>
769 }
770 else if(strcmp(token,"enum") == 0) {
70f46ac3 771 char * str;
bb9014e6 772 long long value = -1;
70f46ac3 773
3583026d 774 t->type = ENUM;
775 sequence_init(&(t->labels));
70f46ac3 776 sequence_init(&(t->labels_values));
3583026d 777 sequence_init(&(t->labels_description));
778 t->already_printed = 0;
be97b953 779 getTypeAttributes(in, t, unnamed_types, named_types);
2d2d14a7 780 //if(t->size == 0) in->error(in, "Sequence has empty size");
bf6349fa 781 //Mathieu : we fix enum size to target int size. GCC is always like this.
2d2d14a7 782 //fox copy optimisation.
bf6349fa 783 if(t->size != 0) in->error(in, "Enum has fixed size of target int.");
784 t->size = 0;
3583026d 785 getRAnglebracket(in);
786
787 //<label name=label1 value=n/>
788 getLAnglebracket(in);
789 token = getToken(in); //"label" or "/"
790 while(strcmp("label",token) == 0){
70f46ac3 791 int *label_value = malloc(sizeof(int));
bb9014e6 792 int has_value = 0;
793 long long loc_value;
70f46ac3 794
9dae5ec2 795 str = allocAndCopy(getNameAttribute(in));
bb9014e6 796 has_value = getValueAttribute(in, &loc_value);
70f46ac3 797
798 sequence_push(&(t->labels),str);
799
bb9014e6 800 if(has_value) value = loc_value;
70f46ac3 801 else value++;
802
803 *label_value = value;
804 sequence_push(&(t->labels_values), label_value);
3583026d 805
806 getForwardslash(in);
807 getRAnglebracket(in);
808
809 //read description if any. May be NULL.
810 str = allocAndCopy(getDescription(in));
811 sequence_push(&(t->labels_description),str);
812
813 //next label definition
814 getLAnglebracket(in);
815 token = getToken(in); //"label" or "/"
816 }
817 if(strcmp("/",token))in->error(in, "not a valid enum definition");
818 token = getName(in);
819 if(strcmp("enum",token))in->error(in, "not a valid enum definition");
820 getRAnglebracket(in); //</label>
821 }
2d2d14a7 822 else if(strcmp(token,"int_fixed") == 0) {
823 t->type = INT_FIXED;
be97b953 824 getTypeAttributes(in, t, unnamed_types, named_types);
2d2d14a7 825 if(t->size == 0) in->error(in, "int has empty size");
826 getForwardslash(in);
827 getRAnglebracket(in);
828 }
829 else if(strcmp(token,"uint_fixed") == 0) {
830 t->type = UINT_FIXED;
be97b953 831 getTypeAttributes(in, t, unnamed_types, named_types);
2d2d14a7 832 if(t->size == 0) in->error(in, "uint has empty size");
833 getForwardslash(in);
834 getRAnglebracket(in);
835 }
836 else if(strcmp(token,"char") == 0) {
837 t->type = CHAR;
be97b953 838 getTypeAttributes(in, t, unnamed_types, named_types);
294f0059 839 t->size = 1;
2d2d14a7 840 getForwardslash(in);
841 getRAnglebracket(in);
842 }
843 else if(strcmp(token,"uchar") == 0) {
844 t->type = UCHAR;
be97b953 845 getTypeAttributes(in, t, unnamed_types, named_types);
294f0059 846 t->size = 1;
2d2d14a7 847 getForwardslash(in);
848 getRAnglebracket(in);
849 }
850 else if(strcmp(token,"short") == 0) {
851 t->type = SHORT;
be97b953 852 getTypeAttributes(in, t, unnamed_types, named_types);
294f0059 853 t->size = 2;
2d2d14a7 854 getForwardslash(in);
855 getRAnglebracket(in);
856 }
857 else if(strcmp(token,"ushort") == 0) {
858 t->type = USHORT;
be97b953 859 getTypeAttributes(in, t, unnamed_types, named_types);
294f0059 860 t->size = 2;
2d2d14a7 861 getForwardslash(in);
862 getRAnglebracket(in);
863 }
3583026d 864 else if(strcmp(token,"int") == 0) {
865 t->type = INT;
be97b953 866 getTypeAttributes(in, t, unnamed_types, named_types);
3583026d 867 getForwardslash(in);
868 getRAnglebracket(in);
869 }
870 else if(strcmp(token,"uint") == 0) {
871 t->type = UINT;
be97b953 872 getTypeAttributes(in, t, unnamed_types, named_types);
3583026d 873 getForwardslash(in);
874 getRAnglebracket(in);
875 }
2d2d14a7 876
3583026d 877 else if(strcmp(token,"pointer") == 0) {
878 t->type = POINTER;
be97b953 879 getTypeAttributes(in, t, unnamed_types, named_types);
3583026d 880 getForwardslash(in);
881 getRAnglebracket(in);
882 }
883 else if(strcmp(token,"long") == 0) {
884 t->type = LONG;
be97b953 885 getTypeAttributes(in, t, unnamed_types, named_types);
3583026d 886 getForwardslash(in);
887 getRAnglebracket(in);
888 }
889 else if(strcmp(token,"ulong") == 0) {
890 t->type = ULONG;
be97b953 891 getTypeAttributes(in, t, unnamed_types, named_types);
3583026d 892 getForwardslash(in);
893 getRAnglebracket(in);
894 }
895 else if(strcmp(token,"size_t") == 0) {
896 t->type = SIZE_T;
be97b953 897 getTypeAttributes(in, t, unnamed_types, named_types);
3583026d 898 getForwardslash(in);
899 getRAnglebracket(in);
900 }
901 else if(strcmp(token,"ssize_t") == 0) {
902 t->type = SSIZE_T;
be97b953 903 getTypeAttributes(in, t, unnamed_types, named_types);
3583026d 904 getForwardslash(in);
905 getRAnglebracket(in);
906 }
907 else if(strcmp(token,"off_t") == 0) {
908 t->type = OFF_T;
be97b953 909 getTypeAttributes(in, t, unnamed_types, named_types);
3583026d 910 getForwardslash(in);
911 getRAnglebracket(in);
912 }
913 else if(strcmp(token,"float") == 0) {
914 t->type = FLOAT;
be97b953 915 getTypeAttributes(in, t, unnamed_types, named_types);
3583026d 916 getForwardslash(in);
917 getRAnglebracket(in);
918 }
919 else if(strcmp(token,"string") == 0) {
920 t->type = STRING;
be97b953 921 getTypeAttributes(in, t, unnamed_types, named_types);
3583026d 922 getForwardslash(in);
923 getRAnglebracket(in);
924 }
925 else if(strcmp(token,"typeref") == 0){
926 // Must be a named type
a67cd958 927 free(t);
928 sequence_pop(unnamed_types);
929 token = getNameAttribute(in);
930 t = find_named_type(token, named_types);
931 if(t == NULL) in->error(in,"Named referred to must be pre-declared.");
932 getForwardslash(in); //<typeref name=type_name/>
933 getRAnglebracket(in);
934 return t;
3583026d 935 }else in->error(in,"not a valid type");
936
937 return t;
938}
939
940/*****************************************************************************
941 *Function name
942 * find_named_type : find a named type from hash table
943 *Input params
944 * name : type name
945 * named_types : array of named types
946 *Return values
947 * type_descriptor * : a type descriptor
948 *****************************************************************************/
949
950type_descriptor_t * find_named_type(char *name, table_t * named_types)
951{
952 type_descriptor_t *t;
953
954 t = table_find(named_types,name);
34c1d1b5 955
3583026d 956 return t;
34c1d1b5 957}
958
959type_descriptor_t * create_named_type(char *name, table_t * named_types)
960{
961 type_descriptor_t *t;
962
963 t = (type_descriptor_t *)memAlloc(sizeof(type_descriptor_t));
964 t->type_name = allocAndCopy(name);
965 t->type = NONE;
966 t->fmt = NULL;
967 table_insert(named_types,t->type_name,t);
968 // table_insert(named_types,allocAndCopy(name),t);
969 return t;
970}
3583026d 971
972/*****************************************************************************
973 *Function name
974 * parseTypeDefinition : get type information from type definition
975 *Input params
976 * in : input file handle
977 * unnamed_types : array of unamed types
978 * named_types : array of named types
979 *****************************************************************************/
980
981void parseTypeDefinition(parse_file_t * in, sequence_t * unnamed_types,
982 table_t * named_types)
983{
984 char *token;
985 type_descriptor_t *t;
986
987 token = getNameAttribute(in);
988 if(token == NULL) in->error(in, "Type has empty name");
34c1d1b5 989 t = create_named_type(token, named_types);
3583026d 990
991 if(t->type != NONE) in->error(in,"redefinition of named type");
992 getRAnglebracket(in); //<type name=type_name>
993 getLAnglebracket(in); //<
994 token = getName(in);
995 //MD ??if(strcmp("struct",token))in->error(in,"not a valid type definition");
996 ungetToken(in);
997 parseType(in,t, unnamed_types, named_types);
998
999 //</type>
1000 getLAnglebracket(in);
1001 getForwardslash(in);
1002 token = getName(in);
1003 if(strcmp("type",token))in->error(in,"not a valid type definition");
1004 getRAnglebracket(in); //</type>
1005}
1006
1007/**************************************************************************
1008 * Function :
1009 * getComa, getName, getNumber, getEqual
1010 * Description :
1011 * Read a token from the input file, check its type, return it scontent.
1012 *
1013 * Parameters :
1014 * in , input file handle.
1015 *
1016 * Return values :
1017 * address of token content.
1018 *
1019 **************************************************************************/
1020
1021char *getName(parse_file_t * in)
1022{
1023 char *token;
1024
1025 token = getToken(in);
9dae5ec2 1026 // Optional descriptions
1027 // if(in->type != NAME) in->error(in,"Name token was expected");
3583026d 1028 return token;
1029}
1030
1031int getNumber(parse_file_t * in)
1032{
1033 char *token;
1034
1035 token = getToken(in);
1036 if(in->type != NUMBER) in->error(in, "Number token was expected");
1037 return atoi(token);
1038}
1039
1040char *getForwardslash(parse_file_t * in)
1041{
1042 char *token;
1043
1044 token = getToken(in);
2d2d14a7 1045 //if(in->type != FORWARDSLASH) in->error(in, "forward slash token was expected");
1046 /* Mathieu : final / is optional now. */
1047 if(in->type != FORWARDSLASH) ungetToken(in);
1048
3583026d 1049 return token;
1050}
1051
1052char *getLAnglebracket(parse_file_t * in)
1053{
1054 char *token;
1055
1056 token = getToken(in);
1057 if(in->type != LANGLEBRACKET) in->error(in, "Left angle bracket was expected");
1058 return token;
1059}
1060
1061char *getRAnglebracket(parse_file_t * in)
1062{
1063 char *token;
1064
1065 token = getToken(in);
1066 if(in->type != RANGLEBRACKET) in->error(in, "Right angle bracket was expected");
1067 return token;
1068}
1069
1070char *getQuotedString(parse_file_t * in)
1071{
1072 char *token;
1073
1074 token = getToken(in);
1075 if(in->type != QUOTEDSTRING) in->error(in, "quoted string was expected");
1076 return token;
1077}
1078
1079char * getEqual(parse_file_t *in)
1080{
1081 char *token;
1082
1083 token = getToken(in);
1084 if(in->type != EQUAL) in->error(in, "equal was expected");
1085 return token;
1086}
1087
1088char seekNextChar(parse_file_t *in)
1089{
1090 char car;
1091 while((car = getc(in->fp)) != EOF) {
1092 if(!isspace(car)){
1093 ungetc(car,in->fp);
1094 return car;
1095 }
1096 }
1097 return EOF;
1098}
1099
1100/******************************************************************
1101 * Function :
1102 * getToken, ungetToken
1103 * Description :
1104 * Read a token from the input file and return its type and content.
1105 * Line numbers are accounted for and whitespace/comments are skipped.
1106 *
1107 * Parameters :
1108 * in, input file handle.
1109 *
1110 * Return values :
1111 * address of token content.
1112 *
1113 ******************************************************************/
1114
1115void ungetToken(parse_file_t * in)
1116{
1117 in->unget = 1;
1118}
1119
1120char *getToken(parse_file_t * in)
1121{
1122 FILE *fp = in->fp;
1123 char car, car1;
1124 int pos = 0, escaped;
1125
1126 if(in->unget == 1) {
1127 in->unget = 0;
1128 return in->buffer;
1129 }
1130
1131 /* skip whitespace and comments */
1132
1133 while((car = getc(fp)) != EOF) {
1134 if(car == '/') {
1135 car1 = getc(fp);
1136 if(car1 == '*') skipComment(in);
1137 else if(car1 == '/') skipEOL(in);
1138 else {
1139 car1 = ungetc(car1,fp);
1140 break;
1141 }
1142 }
1143 else if(car == '\n') in->lineno++;
1144 else if(!isspace(car)) break;
1145 }
1146
1147 switch(car) {
1148 case EOF:
1149 in->type = ENDFILE;
1150 break;
1151 case '/':
1152 in->type = FORWARDSLASH;
1153 in->buffer[pos] = car;
1154 pos++;
1155 break;
1156 case '<':
1157 in->type = LANGLEBRACKET;
1158 in->buffer[pos] = car;
1159 pos++;
1160 break;
1161 case '>':
1162 in->type = RANGLEBRACKET;
1163 in->buffer[pos] = car;
1164 pos++;
1165 break;
1166 case '=':
1167 in->type = EQUAL;
1168 in->buffer[pos] = car;
1169 pos++;
1170 break;
1171 case '"':
1172 escaped = 0;
1173 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
1174 if(car == '\\' && escaped == 0) {
1175 in->buffer[pos] = car;
1176 pos++;
1177 escaped = 1;
1178 continue;
1179 }
1180 if(car == '"' && escaped == 0) break;
1181 if(car == '\n' && escaped == 0) {
1182 in->error(in, "non escaped newline inside quoted string");
1183 }
1184 if(car == '\n') in->lineno++;
1185 in->buffer[pos] = car;
1186 pos++;
1187 escaped = 0;
1188 }
1189 if(car == EOF) in->error(in,"no ending quotemark");
1190 if(pos == BUFFER_SIZE) in->error(in, "quoted string token too large");
1191 in->type = QUOTEDSTRING;
1192 break;
1193 default:
1194 if(isdigit(car)) {
1195 in->buffer[pos] = car;
1196 pos++;
1197 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
1198 if(!isdigit(car)) {
1199 ungetc(car,fp);
1200 break;
1201 }
1202 in->buffer[pos] = car;
1203 pos++;
1204 }
1205 if(car == EOF) ungetc(car,fp);
1206 if(pos == BUFFER_SIZE) in->error(in, "number token too large");
1207 in->type = NUMBER;
1208 }
9dae5ec2 1209 else if(isalnum(car) || car == '_' || car == '-') {
3583026d 1210 in->buffer[0] = car;
1211 pos = 1;
1212 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
9dae5ec2 1213 if(!(isalnum(car) || car == '_' || car == '-')) {
3583026d 1214 ungetc(car,fp);
1215 break;
1216 }
1217 in->buffer[pos] = car;
1218 pos++;
1219 }
1220 if(car == EOF) ungetc(car,fp);
1221 if(pos == BUFFER_SIZE) in->error(in, "name token too large");
1222 in->type = NAME;
1223 }
1224 else in->error(in, "invalid character, unrecognized token");
1225 }
1226 in->buffer[pos] = 0;
1227 return in->buffer;
1228}
1229
1230void skipComment(parse_file_t * in)
1231{
1232 char car;
1233 while((car = getc(in->fp)) != EOF) {
1234 if(car == '\n') in->lineno++;
1235 else if(car == '*') {
1236 car = getc(in->fp);
1237 if(car ==EOF) break;
1238 if(car == '/') return;
1239 ungetc(car,in->fp);
1240 }
1241 }
1242 if(car == EOF) in->error(in,"comment begining with '/*' has no ending '*/'");
1243}
1244
1245void skipEOL(parse_file_t * in)
1246{
1247 char car;
1248 while((car = getc(in->fp)) != EOF) {
1249 if(car == '\n') {
1250 ungetc(car,in->fp);
1251 break;
1252 }
1253 }
1254 if(car == EOF)ungetc(car, in->fp);
1255}
1256
1257/*****************************************************************************
1258 *Function name
1259 * checkNamedTypesImplemented : check if all named types have definition
1260 ****************************************************************************/
1261
1262void checkNamedTypesImplemented(table_t * named_types)
1263{
1264 type_descriptor_t *t;
1265 int pos;
1266 char str[256];
1267
1268 for(pos = 0 ; pos < named_types->values.position; pos++) {
1269 t = (type_descriptor_t *) named_types->values.array[pos];
1270 if(t->type == NONE){
1271 sprintf(str,"named type '%s' has no definition",
1272 (char*)named_types->keys.array[pos]);
1273 error_callback(NULL,str);
1274 }
1275 }
1276}
1277
1278
1279/*****************************************************************************
1280 *Function name
1281 * generateChecksum : generate checksum for the facility
1282 *Input Params
1283 * facName : name of facility
1284 *Output Params
1285 * checksum : checksum for the facility
1286 ****************************************************************************/
1287
1288void generateChecksum(char* facName,
30d72138 1289 unsigned int * checksum, sequence_t * events)
3583026d 1290{
1291 unsigned long crc ;
1292 int pos;
1293 event_t * ev;
bf6349fa 1294 unsigned int i;
3583026d 1295
1296 crc = crc32(facName);
1297 for(pos = 0; pos < events->position; pos++){
1298 ev = (event_t *)(events->array[pos]);
47299663 1299 crc = partial_crc32(ev->name, crc);
bf6349fa 1300 for(i = 0; i < ev->fields.position; i++) {
47299663 1301 field_t *f = (field_t*)ev->fields.array[i];
1302 crc = partial_crc32(f->name, crc);
1303 crc = getTypeChecksum(crc, f->type);
1304 }
3583026d 1305 }
1306 *checksum = crc;
1307}
1308
1309/*****************************************************************************
1310 *Function name
1311 * getTypeChecksum : generate checksum by type info
1312 *Input Params
1313 * crc : checksum generated so far
1314 * type : type descriptor containing type info
1315 *Return value
1316 * unsigned long : checksum
1317 *****************************************************************************/
1318
1319unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor_t * type)
1320{
1321 unsigned long crc = aCrc;
1322 char * str = NULL, buf[16];
1323 int flag = 0, pos;
1324 field_t * fld;
1325
1326 switch(type->type){
2d2d14a7 1327 case INT_FIXED:
1328 str = intOutputTypes[getSizeindex(type->size)];
3583026d 1329 break;
2d2d14a7 1330 case UINT_FIXED:
1331 str = uintOutputTypes[getSizeindex(type->size)];
3583026d 1332 break;
1333 case POINTER:
1334 str = allocAndCopy("void *");
1335 flag = 1;
1336 break;
2d2d14a7 1337 case CHAR:
1338 str = allocAndCopy("signed char");
1339 flag = 1;
1340 break;
1341 case UCHAR:
1342 str = allocAndCopy("unsigned char");
1343 flag = 1;
1344 break;
1345 case SHORT:
1346 str = allocAndCopy("short");
1347 flag = 1;
1348 break;
1349 case USHORT:
1350 str = allocAndCopy("unsigned short");
1351 flag = 1;
1352 break;
1353 case INT:
1354 str = allocAndCopy("int");
1355 flag = 1;
1356 break;
1357 case UINT:
1358 str = allocAndCopy("uint");
1359 flag = 1;
1360 break;
3583026d 1361 case LONG:
1362 str = allocAndCopy("long");
1363 flag = 1;
1364 break;
1365 case ULONG:
1366 str = allocAndCopy("unsigned long");
1367 flag = 1;
1368 break;
1369 case SIZE_T:
1370 str = allocAndCopy("size_t");
1371 flag = 1;
1372 break;
1373 case SSIZE_T:
1374 str = allocAndCopy("ssize_t");
1375 flag = 1;
1376 break;
1377 case OFF_T:
1378 str = allocAndCopy("off_t");
1379 flag = 1;
1380 break;
1381 case FLOAT:
2d2d14a7 1382 str = floatOutputTypes[getSizeindex(type->size)];
3583026d 1383 break;
1384 case STRING:
1385 str = allocAndCopy("string");
1386 flag = 1;
1387 break;
1388 case ENUM:
2d2d14a7 1389 //str = appendString("enum ", uintOutputTypes[getSizeindex(type->size)]);
1390 str = allocAndCopy("enum");
3583026d 1391 flag = 1;
1392 break;
1393 case ARRAY:
2e415130 1394 sprintf(buf,"%zu", type->size);
3583026d 1395 str = appendString("array ",buf);
1396 flag = 1;
1397 break;
1398 case SEQUENCE:
294f0059 1399 str = allocAndCopy("sequence ");
3583026d 1400 flag = 1;
1401 break;
1402 case STRUCT:
1403 str = allocAndCopy("struct");
1404 flag = 1;
1405 break;
1406 case UNION:
1407 str = allocAndCopy("union");
1408 flag = 1;
1409 break;
1410 default:
1411 error_callback(NULL, "named type has no definition");
1412 break;
1413 }
1414
1415 crc = partial_crc32(str,crc);
1416 if(flag) free(str);
1417
1418 if(type->fmt) crc = partial_crc32(type->fmt,crc);
1419
2e415130 1420 if(type->type == ARRAY){
1421 crc = getTypeChecksum(crc,((field_t*)type->fields.array[0])->type);
1422 } else if(type->type ==SEQUENCE) {
1423 crc = getTypeChecksum(crc,((field_t*)type->fields.array[0])->type);
1424 crc = getTypeChecksum(crc,((field_t*)type->fields.array[1])->type);
1425 } else if(type->type == STRUCT || type->type == UNION){
3583026d 1426 for(pos =0; pos < type->fields.position; pos++){
1427 fld = (field_t *) type->fields.array[pos];
1428 crc = partial_crc32(fld->name,crc);
1429 crc = getTypeChecksum(crc, fld->type);
1430 }
1431 }else if(type->type == ENUM){
1432 for(pos = 0; pos < type->labels.position; pos++)
1433 crc = partial_crc32((char*)type->labels.array[pos],crc);
1434 }
1435
1436 return crc;
1437}
1438
1439
1440/* Event type descriptors */
1441void freeType(type_descriptor_t * tp)
1442{
1443 int pos2;
1444 field_t *f;
1445
1446 if(tp->fmt != NULL) free(tp->fmt);
1447 if(tp->type == ENUM) {
1448 for(pos2 = 0; pos2 < tp->labels.position; pos2++) {
1449 free(tp->labels.array[pos2]);
1450 }
1451 sequence_dispose(&(tp->labels));
70f46ac3 1452 for(pos2 = 0; pos2 < tp->labels_values.position; pos2++) {
1453 free(tp->labels_values.array[pos2]);
1454 }
1455 sequence_dispose(&(tp->labels_values));
3583026d 1456 }
1457 if(tp->type == STRUCT) {
1458 for(pos2 = 0; pos2 < tp->fields.position; pos2++) {
1459 f = (field_t *) tp->fields.array[pos2];
1460 free(f->name);
1461 free(f->description);
1462 free(f);
1463 }
1464 sequence_dispose(&(tp->fields));
1465 }
1466}
1467
1468void freeNamedType(table_t * t)
1469{
1470 int pos;
1471 type_descriptor_t * td;
1472
1473 for(pos = 0 ; pos < t->keys.position; pos++) {
1474 free((char *)t->keys.array[pos]);
1475 td = (type_descriptor_t*)t->values.array[pos];
1476 freeType(td);
1477 free(td);
1478 }
1479}
1480
1481void freeTypes(sequence_t *t)
1482{
1483 int pos;
1484 type_descriptor_t *tp;
1485
1486 for(pos = 0 ; pos < t->position; pos++) {
1487 tp = (type_descriptor_t *)t->array[pos];
1488 freeType(tp);
1489 free(tp);
1490 }
1491}
1492
1493void freeEvents(sequence_t *t)
1494{
1495 int pos;
1496 event_t *ev;
1497
1498 for(pos = 0 ; pos < t->position; pos++) {
1499 ev = (event_t *) t->array[pos];
1500 free(ev->name);
1501 free(ev->description);
47299663 1502 sequence_dispose(&ev->fields);
3583026d 1503 free(ev);
1504 }
1505
1506}
1507
1508
1509/* Extensible array */
1510
1511void sequence_init(sequence_t *t)
1512{
1513 t->size = 10;
1514 t->position = 0;
1515 t->array = (void **)memAlloc(t->size * sizeof(void *));
1516}
1517
1518void sequence_dispose(sequence_t *t)
1519{
1520 t->size = 0;
1521 free(t->array);
1522 t->array = NULL;
1523}
1524
1525void sequence_push(sequence_t *t, void *elem)
1526{
1527 void **tmp;
1528
1529 if(t->position >= t->size) {
1530 tmp = t->array;
1531 t->array = (void **)memAlloc(t->size * 2 * sizeof(void *));
1532 memcpy(t->array, tmp, t->size * sizeof(void *));
1533 t->size = t->size * 2;
1534 free(tmp);
1535 }
1536 t->array[t->position] = elem;
1537 t->position++;
1538}
1539
1540void *sequence_pop(sequence_t *t)
1541{
b0f04dc3 1542 if(t->position == 0) printf("Error : trying to pop an empty sequence");
1543 return t->array[--t->position];
3583026d 1544}
1545
1546
1547/* Hash table API, implementation is just linear search for now */
1548
1549void table_init(table_t *t)
1550{
1551 sequence_init(&(t->keys));
1552 sequence_init(&(t->values));
1553}
1554
1555void table_dispose(table_t *t)
1556{
1557 sequence_dispose(&(t->keys));
1558 sequence_dispose(&(t->values));
1559}
1560
1561void table_insert(table_t *t, char *key, void *value)
1562{
1563 sequence_push(&(t->keys),key);
1564 sequence_push(&(t->values),value);
1565}
1566
1567void *table_find(table_t *t, char *key)
1568{
1569 int pos;
1570 for(pos = 0 ; pos < t->keys.position; pos++) {
1571 if(strcmp((char *)key,(char *)t->keys.array[pos]) == 0)
1572 return(t->values.array[pos]);
1573 }
1574 return NULL;
1575}
1576
1577void table_insert_int(table_t *t, int *key, void *value)
1578{
1579 sequence_push(&(t->keys),key);
1580 sequence_push(&(t->values),value);
1581}
1582
1583void *table_find_int(table_t *t, int *key)
1584{
1585 int pos;
1586 for(pos = 0 ; pos < t->keys.position; pos++) {
1587 if(*key == *(int *)t->keys.array[pos])
1588 return(t->values.array[pos]);
1589 }
1590 return NULL;
1591}
1592
1593
1594/* Concatenate strings */
1595
1596char *appendString(char *s, char *suffix)
1597{
1598 char *tmp;
1599 if(suffix == NULL) return s;
1600
1601 tmp = (char *)memAlloc(strlen(s) + strlen(suffix) + 1);
1602 strcpy(tmp,s);
1603 strcat(tmp,suffix);
1604 return tmp;
1605}
This page took 0.085583 seconds and 4 git commands to generate.