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