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