fix print style
[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
755 f->name = NULL;
756 sequence_push(&(t->fields),f);
757 parseFields(in, f, unnamed_types, named_types, 0);
758
759 //getLAnglebracket(in); //<type struct>
760 //t->nested_type = parseType(in, NULL, unnamed_types, named_types);
761
762 getLAnglebracket(in); //</array>
763 getForwardslash(in);
764 token = getName(in);
765 if(strcmp("array",token))in->error(in,"not a valid array definition");
766 getRAnglebracket(in); //</array>
767 }
768 else if(strcmp(token,"sequence") == 0) {
769 t->type = SEQUENCE;
770 sequence_init(&(t->fields));
771 getTypeAttributes(in, t, unnamed_types, named_types);
772 getForwardslash(in);
773 getRAnglebracket(in); //<sequence>
774
775 //getLAnglebracket(in); //<sequence size type>
776 /* subfield */
777 f = (field_t *)memAlloc(sizeof(field_t));
778 f->name = NULL;
779 sequence_push(&(t->fields),f);
780 parseFields(in, f, unnamed_types, named_types, 0);
781
782 //getLAnglebracket(in); //<subtype>
783 /* subfield */
784 f = (field_t *)memAlloc(sizeof(field_t));
785 f->name = NULL;
786 sequence_push(&(t->fields),f);
787 parseFields(in, f, unnamed_types, named_types, 0);
788
789 //getLAnglebracket(in); //<type sequence>
790 //t->length_type = parseType(in, NULL, unnamed_types, named_types);
791
792 //getLAnglebracket(in); //<type sequence>
793
794 //t->nested_type = parseType(in, NULL, unnamed_types, named_types);
795
796 if(t->fields.position < 1) in->error(in, "Sequence has no length type");
797 if(t->fields.position < 2) in->error(in, "Sequence has no subtype");
798 switch(((field_t*)t->fields.array[0])->type->type) {
799 case UINT_FIXED :
800 case UCHAR :
801 case USHORT :
802 case UINT :
803 case ULONG :
804 case SIZE_T :
805 case OFF_T :
806 break;
807 default:
808 in->error(in, "Wrong length type for sequence");
809 }
810
811 getLAnglebracket(in); //</sequence>
812 getForwardslash(in);
813 token = getName(in);
814 if(strcmp("sequence",token))in->error(in,"not a valid sequence definition");
815 getRAnglebracket(in); //</sequence>
816 }
817 else if(strcmp(token,"enum") == 0) {
818 char * str;
819 long long value = -1;
820
821 t->type = ENUM;
822 sequence_init(&(t->labels));
823 sequence_init(&(t->labels_values));
824 sequence_init(&(t->labels_description));
825 t->already_printed = 0;
826 getTypeAttributes(in, t, unnamed_types, named_types);
827 //if(t->size == 0) in->error(in, "Sequence has empty size");
828 //Mathieu : we fix enum size to target int size. GCC is always like this.
829 //fox copy optimisation.
830 if(t->size != 0) in->error(in, "Enum has fixed size of target int.");
831 t->size = 0;
832 getRAnglebracket(in);
833
834 //<label name=label1 value=n/>
835 getLAnglebracket(in);
836 token = getToken(in); //"label" or "/"
837 while(strcmp("label",token) == 0){
838 int *label_value = malloc(sizeof(int));
839 int has_value = 0;
840 long long loc_value;
841
842 str = allocAndCopy(getNameAttribute(in));
843 has_value = getValueAttribute(in, &loc_value);
844
845 sequence_push(&(t->labels),str);
846
847 if(has_value) value = loc_value;
848 else value++;
849
850 *label_value = value;
851 sequence_push(&(t->labels_values), label_value);
852
853 getForwardslash(in);
854 getRAnglebracket(in);
855
856 //read description if any. May be NULL.
857 str = allocAndCopy(getDescription(in));
858 sequence_push(&(t->labels_description),str);
859
860 //next label definition
861 getLAnglebracket(in);
862 token = getToken(in); //"label" or "/"
863 }
864 if(strcmp("/",token))in->error(in, "not a valid enum definition");
865 token = getName(in);
866 if(strcmp("enum",token))in->error(in, "not a valid enum definition");
867 getRAnglebracket(in); //</label>
868 }
869 else if(strcmp(token,"int_fixed") == 0) {
870 t->type = INT_FIXED;
871 getTypeAttributes(in, t, unnamed_types, named_types);
872 if(t->size == 0) in->error(in, "int has empty size");
873 getForwardslash(in);
874 getRAnglebracket(in);
875 }
876 else if(strcmp(token,"uint_fixed") == 0) {
877 t->type = UINT_FIXED;
878 getTypeAttributes(in, t, unnamed_types, named_types);
879 if(t->size == 0) in->error(in, "uint has empty size");
880 getForwardslash(in);
881 getRAnglebracket(in);
882 }
883 else if(strcmp(token,"char") == 0) {
884 t->type = CHAR;
885 getTypeAttributes(in, t, unnamed_types, named_types);
886 t->size = 1;
887 getForwardslash(in);
888 getRAnglebracket(in);
889 }
890 else if(strcmp(token,"uchar") == 0) {
891 t->type = UCHAR;
892 getTypeAttributes(in, t, unnamed_types, named_types);
893 t->size = 1;
894 getForwardslash(in);
895 getRAnglebracket(in);
896 }
897 else if(strcmp(token,"short") == 0) {
898 t->type = SHORT;
899 getTypeAttributes(in, t, unnamed_types, named_types);
900 t->size = 2;
901 getForwardslash(in);
902 getRAnglebracket(in);
903 }
904 else if(strcmp(token,"ushort") == 0) {
905 t->type = USHORT;
906 getTypeAttributes(in, t, unnamed_types, named_types);
907 t->size = 2;
908 getForwardslash(in);
909 getRAnglebracket(in);
910 }
911 else if(strcmp(token,"int") == 0) {
912 t->type = INT;
913 getTypeAttributes(in, t, unnamed_types, named_types);
914 getForwardslash(in);
915 getRAnglebracket(in);
916 }
917 else if(strcmp(token,"uint") == 0) {
918 t->type = UINT;
919 getTypeAttributes(in, t, unnamed_types, named_types);
920 getForwardslash(in);
921 getRAnglebracket(in);
922 }
923
924 else if(strcmp(token,"pointer") == 0) {
925 t->type = POINTER;
926 getTypeAttributes(in, t, unnamed_types, named_types);
927 getForwardslash(in);
928 getRAnglebracket(in);
929 }
930 else if(strcmp(token,"long") == 0) {
931 t->type = LONG;
932 getTypeAttributes(in, t, unnamed_types, named_types);
933 getForwardslash(in);
934 getRAnglebracket(in);
935 }
936 else if(strcmp(token,"ulong") == 0) {
937 t->type = ULONG;
938 getTypeAttributes(in, t, unnamed_types, named_types);
939 getForwardslash(in);
940 getRAnglebracket(in);
941 }
942 else if(strcmp(token,"size_t") == 0) {
943 t->type = SIZE_T;
944 getTypeAttributes(in, t, unnamed_types, named_types);
945 getForwardslash(in);
946 getRAnglebracket(in);
947 }
948 else if(strcmp(token,"ssize_t") == 0) {
949 t->type = SSIZE_T;
950 getTypeAttributes(in, t, unnamed_types, named_types);
951 getForwardslash(in);
952 getRAnglebracket(in);
953 }
954 else if(strcmp(token,"off_t") == 0) {
955 t->type = OFF_T;
956 getTypeAttributes(in, t, unnamed_types, named_types);
957 getForwardslash(in);
958 getRAnglebracket(in);
959 }
960 else if(strcmp(token,"float") == 0) {
961 t->type = FLOAT;
962 getTypeAttributes(in, t, unnamed_types, named_types);
963 getForwardslash(in);
964 getRAnglebracket(in);
965 }
966 else if(strcmp(token,"string") == 0) {
967 t->type = STRING;
968 getTypeAttributes(in, t, unnamed_types, named_types);
969 getForwardslash(in);
970 getRAnglebracket(in);
971 }
972 else if(strcmp(token,"typeref") == 0){
973 // Must be a named type
974 free(t);
975 sequence_pop(unnamed_types);
976 token = getNameAttribute(in);
977 t = find_named_type(token, named_types);
978 if(t == NULL) in->error(in,"Named referred to must be pre-declared.");
979 getForwardslash(in); //<typeref name=type_name/>
980 getRAnglebracket(in);
981 return t;
982 }else in->error(in,"not a valid type");
983
984 return t;
985 }
986
987 /*****************************************************************************
988 *Function name
989 * find_named_type : find a named type from hash table
990 *Input params
991 * name : type name
992 * named_types : array of named types
993 *Return values
994 * type_descriptor * : a type descriptor
995 *****************************************************************************/
996
997 type_descriptor_t * find_named_type(char *name, table_t * named_types)
998 {
999 type_descriptor_t *t;
1000
1001 t = table_find(named_types,name);
1002
1003 return t;
1004 }
1005
1006 type_descriptor_t * create_named_type(char *name, table_t * named_types)
1007 {
1008 type_descriptor_t *t;
1009
1010 t = (type_descriptor_t *)memAlloc(sizeof(type_descriptor_t));
1011 t->type_name = allocAndCopy(name);
1012 t->type = NONE;
1013 t->fmt = NULL;
1014 table_insert(named_types,t->type_name,t);
1015 // table_insert(named_types,allocAndCopy(name),t);
1016 return t;
1017 }
1018
1019 /*****************************************************************************
1020 *Function name
1021 * parseTypeDefinition : get type information from type definition
1022 *Input params
1023 * in : input file handle
1024 * unnamed_types : array of unamed types
1025 * named_types : array of named types
1026 *****************************************************************************/
1027
1028 void parseTypeDefinition(parse_file_t * in, sequence_t * unnamed_types,
1029 table_t * named_types)
1030 {
1031 char *token;
1032 type_descriptor_t *t;
1033
1034 token = getNameAttribute(in);
1035 if(token == NULL) in->error(in, "Type has empty name");
1036 t = create_named_type(token, named_types);
1037
1038 if(t->type != NONE) in->error(in,"redefinition of named type");
1039 getRAnglebracket(in); //<type name=type_name>
1040 getLAnglebracket(in); //<
1041 token = getName(in);
1042 //MD ??if(strcmp("struct",token))in->error(in,"not a valid type definition");
1043 ungetToken(in);
1044 parseType(in,t, unnamed_types, named_types);
1045
1046 //</type>
1047 getLAnglebracket(in);
1048 getForwardslash(in);
1049 token = getName(in);
1050 if(strcmp("type",token))in->error(in,"not a valid type definition");
1051 getRAnglebracket(in); //</type>
1052 }
1053
1054 /**************************************************************************
1055 * Function :
1056 * getComa, getName, getNumber, getEqual
1057 * Description :
1058 * Read a token from the input file, check its type, return it scontent.
1059 *
1060 * Parameters :
1061 * in , input file handle.
1062 *
1063 * Return values :
1064 * address of token content.
1065 *
1066 **************************************************************************/
1067
1068 char *getName(parse_file_t * in)
1069 {
1070 char *token;
1071
1072 token = getToken(in);
1073 // Optional descriptions
1074 // if(in->type != NAME) in->error(in,"Name token was expected");
1075 return token;
1076 }
1077
1078 int getNumber(parse_file_t * in)
1079 {
1080 char *token;
1081
1082 token = getToken(in);
1083 if(in->type != NUMBER) in->error(in, "Number token was expected");
1084 return atoi(token);
1085 }
1086
1087 char *getForwardslash(parse_file_t * in)
1088 {
1089 char *token;
1090
1091 token = getToken(in);
1092 //if(in->type != FORWARDSLASH) in->error(in, "forward slash token was expected");
1093 /* Mathieu : final / is optional now. */
1094 if(in->type != FORWARDSLASH) ungetToken(in);
1095
1096 return token;
1097 }
1098
1099 char *getLAnglebracket(parse_file_t * in)
1100 {
1101 char *token;
1102
1103 token = getToken(in);
1104 if(in->type != LANGLEBRACKET) in->error(in, "Left angle bracket was expected");
1105 return token;
1106 }
1107
1108 char *getRAnglebracket(parse_file_t * in)
1109 {
1110 char *token;
1111
1112 token = getToken(in);
1113 if(in->type != RANGLEBRACKET) in->error(in, "Right angle bracket was expected");
1114 return token;
1115 }
1116
1117 char *getQuotedString(parse_file_t * in)
1118 {
1119 char *token;
1120
1121 token = getToken(in);
1122 if(in->type != QUOTEDSTRING) in->error(in, "quoted string was expected");
1123 return token;
1124 }
1125
1126 char * getEqual(parse_file_t *in)
1127 {
1128 char *token;
1129
1130 token = getToken(in);
1131 if(in->type != EQUAL) in->error(in, "equal was expected");
1132 return token;
1133 }
1134
1135 int seekNextChar(parse_file_t *in)
1136 {
1137 int car;
1138 while((car = getc(in->fp)) != EOF) {
1139 if(!isspace(car)){
1140 ungetc(car,in->fp);
1141 return car;
1142 }
1143 }
1144 return EOF;
1145 }
1146
1147 /******************************************************************
1148 * Function :
1149 * getToken, ungetToken
1150 * Description :
1151 * Read a token from the input file and return its type and content.
1152 * Line numbers are accounted for and whitespace/comments are skipped.
1153 *
1154 * Parameters :
1155 * in, input file handle.
1156 *
1157 * Return values :
1158 * address of token content.
1159 *
1160 ******************************************************************/
1161
1162 void ungetToken(parse_file_t * in)
1163 {
1164 in->unget = 1;
1165 }
1166
1167 char *getToken(parse_file_t * in)
1168 {
1169 FILE *fp = in->fp;
1170 int car, car1;
1171 int pos = 0, escaped;
1172
1173 if(in->unget == 1) {
1174 in->unget = 0;
1175 return in->buffer;
1176 }
1177
1178 /* skip whitespace and comments */
1179
1180 while((car = getc(fp)) != EOF) {
1181 if(car == '/') {
1182 car1 = getc(fp);
1183 if(car1 == '*') skipComment(in);
1184 else if(car1 == '/') skipEOL(in);
1185 else {
1186 car1 = ungetc(car1,fp);
1187 break;
1188 }
1189 }
1190 else if(car == '\n') in->lineno++;
1191 else if(!isspace(car)) break;
1192 }
1193
1194 switch(car) {
1195 case EOF:
1196 in->type = ENDFILE;
1197 break;
1198 case '/':
1199 in->type = FORWARDSLASH;
1200 in->buffer[pos] = car;
1201 pos++;
1202 break;
1203 case '<':
1204 in->type = LANGLEBRACKET;
1205 in->buffer[pos] = car;
1206 pos++;
1207 break;
1208 case '>':
1209 in->type = RANGLEBRACKET;
1210 in->buffer[pos] = car;
1211 pos++;
1212 break;
1213 case '=':
1214 in->type = EQUAL;
1215 in->buffer[pos] = car;
1216 pos++;
1217 break;
1218 case '"':
1219 escaped = 0;
1220 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
1221 if(car == '\\' && escaped == 0) {
1222 in->buffer[pos] = car;
1223 pos++;
1224 escaped = 1;
1225 continue;
1226 }
1227 if(car == '"' && escaped == 0) break;
1228 if(car == '\n' && escaped == 0) {
1229 in->error(in, "non escaped newline inside quoted string");
1230 }
1231 if(car == '\n') in->lineno++;
1232 in->buffer[pos] = car;
1233 pos++;
1234 escaped = 0;
1235 }
1236 if(car == EOF) in->error(in,"no ending quotemark");
1237 if(pos == BUFFER_SIZE) in->error(in, "quoted string token too large");
1238 in->type = QUOTEDSTRING;
1239 break;
1240 default:
1241 if(isdigit(car)) {
1242 in->buffer[pos] = car;
1243 pos++;
1244 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
1245 if(!isdigit(car)) {
1246 ungetc(car,fp);
1247 break;
1248 }
1249 in->buffer[pos] = car;
1250 pos++;
1251 }
1252 if(car == EOF) ungetc(car,fp);
1253 if(pos == BUFFER_SIZE) in->error(in, "number token too large");
1254 in->type = NUMBER;
1255 }
1256 else if(isalnum(car) || car == '_' || car == '-') {
1257 in->buffer[0] = car;
1258 pos = 1;
1259 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
1260 if(!(isalnum(car) || car == '_' || car == '-')) {
1261 ungetc(car,fp);
1262 break;
1263 }
1264 in->buffer[pos] = car;
1265 pos++;
1266 }
1267 if(car == EOF) ungetc(car,fp);
1268 if(pos == BUFFER_SIZE) in->error(in, "name token too large");
1269 in->type = NAME;
1270 } else if(car == '?') {
1271 in->buffer[0] = car;
1272 pos++;
1273 }
1274 else in->error(in, "invalid character, unrecognized token");
1275 }
1276 in->buffer[pos] = 0;
1277 return in->buffer;
1278 }
1279
1280 void skipComment(parse_file_t * in)
1281 {
1282 int car;
1283 while((car = getc(in->fp)) != EOF) {
1284 if(car == '\n') in->lineno++;
1285 else if(car == '*') {
1286 car = getc(in->fp);
1287 if(car ==EOF) break;
1288 if(car == '/') return;
1289 ungetc(car,in->fp);
1290 }
1291 }
1292 if(car == EOF) in->error(in,"comment begining with '/*' has no ending '*/'");
1293 }
1294
1295 void skipEOL(parse_file_t * in)
1296 {
1297 int car;
1298 while((car = getc(in->fp)) != EOF) {
1299 if(car == '\n') {
1300 ungetc(car,in->fp);
1301 break;
1302 }
1303 }
1304 if(car == EOF)ungetc(car, in->fp);
1305 }
1306
1307 /*****************************************************************************
1308 *Function name
1309 * checkNamedTypesImplemented : check if all named types have definition
1310 ****************************************************************************/
1311
1312 void checkNamedTypesImplemented(table_t * named_types)
1313 {
1314 type_descriptor_t *t;
1315 int pos;
1316 char str[256];
1317
1318 for(pos = 0 ; pos < named_types->values.position; pos++) {
1319 t = (type_descriptor_t *) named_types->values.array[pos];
1320 if(t->type == NONE){
1321 sprintf(str,"named type '%s' has no definition",
1322 (char*)named_types->keys.array[pos]);
1323 error_callback(NULL,str);
1324 }
1325 }
1326 }
1327
1328
1329 /*****************************************************************************
1330 *Function name
1331 * generateChecksum : generate checksum for the facility
1332 *Input Params
1333 * facName : name of facility
1334 *Output Params
1335 * checksum : checksum for the facility
1336 ****************************************************************************/
1337
1338 void generateChecksum(char* facName,
1339 unsigned int * checksum, sequence_t * events)
1340 {
1341 unsigned long crc ;
1342 int pos;
1343 event_t * ev;
1344 unsigned int i;
1345
1346 crc = crc32(facName);
1347 for(pos = 0; pos < events->position; pos++){
1348 ev = (event_t *)(events->array[pos]);
1349 crc = partial_crc32(ev->name, crc);
1350 for(i = 0; i < ev->fields.position; i++) {
1351 field_t *f = (field_t*)ev->fields.array[i];
1352 crc = partial_crc32(f->name, crc);
1353 crc = getTypeChecksum(crc, f->type);
1354 }
1355 }
1356 *checksum = crc;
1357 }
1358
1359 /*****************************************************************************
1360 *Function name
1361 * getTypeChecksum : generate checksum by type info
1362 *Input Params
1363 * crc : checksum generated so far
1364 * type : type descriptor containing type info
1365 *Return value
1366 * unsigned long : checksum
1367 *****************************************************************************/
1368
1369 unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor_t * type)
1370 {
1371 unsigned long crc = aCrc;
1372 char * str = NULL, buf[16];
1373 int flag = 0, pos;
1374 field_t * fld;
1375
1376 switch(type->type){
1377 case INT_FIXED:
1378 str = intOutputTypes[getSizeindex(type->size)];
1379 break;
1380 case UINT_FIXED:
1381 str = uintOutputTypes[getSizeindex(type->size)];
1382 break;
1383 case POINTER:
1384 str = allocAndCopy("void *");
1385 flag = 1;
1386 break;
1387 case CHAR:
1388 str = allocAndCopy("signed char");
1389 flag = 1;
1390 break;
1391 case UCHAR:
1392 str = allocAndCopy("unsigned char");
1393 flag = 1;
1394 break;
1395 case SHORT:
1396 str = allocAndCopy("short");
1397 flag = 1;
1398 break;
1399 case USHORT:
1400 str = allocAndCopy("unsigned short");
1401 flag = 1;
1402 break;
1403 case INT:
1404 str = allocAndCopy("int");
1405 flag = 1;
1406 break;
1407 case UINT:
1408 str = allocAndCopy("uint");
1409 flag = 1;
1410 break;
1411 case LONG:
1412 str = allocAndCopy("long");
1413 flag = 1;
1414 break;
1415 case ULONG:
1416 str = allocAndCopy("unsigned long");
1417 flag = 1;
1418 break;
1419 case SIZE_T:
1420 str = allocAndCopy("size_t");
1421 flag = 1;
1422 break;
1423 case SSIZE_T:
1424 str = allocAndCopy("ssize_t");
1425 flag = 1;
1426 break;
1427 case OFF_T:
1428 str = allocAndCopy("off_t");
1429 flag = 1;
1430 break;
1431 case FLOAT:
1432 str = floatOutputTypes[getSizeindex(type->size)];
1433 break;
1434 case STRING:
1435 str = allocAndCopy("string");
1436 flag = 1;
1437 break;
1438 case ENUM:
1439 //str = appendString("enum ", uintOutputTypes[getSizeindex(type->size)]);
1440 str = allocAndCopy("enum");
1441 flag = 1;
1442 break;
1443 case ARRAY:
1444 sprintf(buf,"%zu", type->size);
1445 str = appendString("array ",buf);
1446 flag = 1;
1447 break;
1448 case SEQUENCE:
1449 str = allocAndCopy("sequence ");
1450 flag = 1;
1451 break;
1452 case STRUCT:
1453 str = allocAndCopy("struct");
1454 flag = 1;
1455 break;
1456 case UNION:
1457 str = allocAndCopy("union");
1458 flag = 1;
1459 break;
1460 default:
1461 error_callback(NULL, "named type has no definition");
1462 break;
1463 }
1464
1465 crc = partial_crc32(str,crc);
1466 if(flag) free(str);
1467
1468 if(type->fmt) crc = partial_crc32(type->fmt,crc);
1469
1470 if(type->type == ARRAY){
1471 crc = getTypeChecksum(crc,((field_t*)type->fields.array[0])->type);
1472 } else if(type->type ==SEQUENCE) {
1473 crc = getTypeChecksum(crc,((field_t*)type->fields.array[0])->type);
1474 crc = getTypeChecksum(crc,((field_t*)type->fields.array[1])->type);
1475 } else if(type->type == STRUCT || type->type == UNION){
1476 for(pos =0; pos < type->fields.position; pos++){
1477 fld = (field_t *) type->fields.array[pos];
1478 crc = partial_crc32(fld->name,crc);
1479 crc = getTypeChecksum(crc, fld->type);
1480 }
1481 }else if(type->type == ENUM){
1482 for(pos = 0; pos < type->labels.position; pos++)
1483 crc = partial_crc32((char*)type->labels.array[pos],crc);
1484 }
1485
1486 return crc;
1487 }
1488
1489
1490 /* Event type descriptors */
1491 void freeType(type_descriptor_t * tp)
1492 {
1493 int pos2;
1494 field_t *f;
1495
1496 if(tp->fmt != NULL) free(tp->fmt);
1497 if(tp->type == ENUM) {
1498 for(pos2 = 0; pos2 < tp->labels.position; pos2++) {
1499 free(tp->labels.array[pos2]);
1500 }
1501 sequence_dispose(&(tp->labels));
1502 for(pos2 = 0; pos2 < tp->labels_values.position; pos2++) {
1503 free(tp->labels_values.array[pos2]);
1504 }
1505 sequence_dispose(&(tp->labels_values));
1506 }
1507 if(tp->type == STRUCT) {
1508 for(pos2 = 0; pos2 < tp->fields.position; pos2++) {
1509 f = (field_t *) tp->fields.array[pos2];
1510 free(f->name);
1511 free(f->description);
1512 free(f);
1513 }
1514 sequence_dispose(&(tp->fields));
1515 }
1516 }
1517
1518 void freeNamedType(table_t * t)
1519 {
1520 int pos;
1521 type_descriptor_t * td;
1522
1523 for(pos = 0 ; pos < t->keys.position; pos++) {
1524 free((char *)t->keys.array[pos]);
1525 td = (type_descriptor_t*)t->values.array[pos];
1526 freeType(td);
1527 free(td);
1528 }
1529 }
1530
1531 void freeTypes(sequence_t *t)
1532 {
1533 int pos;
1534 type_descriptor_t *tp;
1535
1536 for(pos = 0 ; pos < t->position; pos++) {
1537 tp = (type_descriptor_t *)t->array[pos];
1538 freeType(tp);
1539 free(tp);
1540 }
1541 }
1542
1543 void freeEvents(sequence_t *t)
1544 {
1545 int pos;
1546 event_t *ev;
1547
1548 for(pos = 0 ; pos < t->position; pos++) {
1549 ev = (event_t *) t->array[pos];
1550 free(ev->name);
1551 free(ev->description);
1552 sequence_dispose(&ev->fields);
1553 free(ev);
1554 }
1555
1556 }
1557
1558
1559 /* Extensible array */
1560
1561 void sequence_init(sequence_t *t)
1562 {
1563 t->size = 10;
1564 t->position = 0;
1565 t->array = (void **)memAlloc(t->size * sizeof(void *));
1566 }
1567
1568 void sequence_dispose(sequence_t *t)
1569 {
1570 t->size = 0;
1571 free(t->array);
1572 t->array = NULL;
1573 }
1574
1575 void sequence_push(sequence_t *t, void *elem)
1576 {
1577 void **tmp;
1578
1579 if(t->position >= t->size) {
1580 tmp = t->array;
1581 t->array = (void **)memAlloc(t->size * 2 * sizeof(void *));
1582 memcpy(t->array, tmp, t->size * sizeof(void *));
1583 t->size = t->size * 2;
1584 free(tmp);
1585 }
1586 t->array[t->position] = elem;
1587 t->position++;
1588 }
1589
1590 void *sequence_pop(sequence_t *t)
1591 {
1592 if(t->position == 0) printf("Error : trying to pop an empty sequence");
1593 return t->array[--t->position];
1594 }
1595
1596
1597 /* Hash table API, implementation is just linear search for now */
1598
1599 void table_init(table_t *t)
1600 {
1601 sequence_init(&(t->keys));
1602 sequence_init(&(t->values));
1603 }
1604
1605 void table_dispose(table_t *t)
1606 {
1607 sequence_dispose(&(t->keys));
1608 sequence_dispose(&(t->values));
1609 }
1610
1611 void table_insert(table_t *t, char *key, void *value)
1612 {
1613 sequence_push(&(t->keys),key);
1614 sequence_push(&(t->values),value);
1615 }
1616
1617 void *table_find(table_t *t, char *key)
1618 {
1619 int pos;
1620 for(pos = 0 ; pos < t->keys.position; pos++) {
1621 if(strcmp((char *)key,(char *)t->keys.array[pos]) == 0)
1622 return(t->values.array[pos]);
1623 }
1624 return NULL;
1625 }
1626
1627 void table_insert_int(table_t *t, int *key, void *value)
1628 {
1629 sequence_push(&(t->keys),key);
1630 sequence_push(&(t->values),value);
1631 }
1632
1633 void *table_find_int(table_t *t, int *key)
1634 {
1635 int pos;
1636 for(pos = 0 ; pos < t->keys.position; pos++) {
1637 if(*key == *(int *)t->keys.array[pos])
1638 return(t->values.array[pos]);
1639 }
1640 return NULL;
1641 }
1642
1643
1644 /* Concatenate strings */
1645
1646 char *appendString(char *s, char *suffix)
1647 {
1648 char *tmp;
1649 if(suffix == NULL) return s;
1650
1651 tmp = (char *)memAlloc(strlen(s) + strlen(suffix) + 1);
1652 strcpy(tmp,s);
1653 strcat(tmp,suffix);
1654 return tmp;
1655 }
This page took 0.095912 seconds and 4 git commands to generate.