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