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