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