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