network byte order + state multitraces fix
[lttv.git] / ltt / branches / poly / ltt / parser.c
1 /*
2
3 parser.c: Generate helper declarations and functions to trace events
4 from an event description file.
5
6 Copyright (C) 2005, Mathieu Desnoyers
7 Copyright (C) 2002, Xianxiu Yang
8 Copyright (C) 2002, Michel Dagenais
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 /* This program reads the ".xml" event definitions input files
24 and constructs structure for each event.
25
26 The program uses a very simple tokenizer, called from a hand written
27 recursive descent parser to fill a data structure describing the events.
28 The result is a sequence of events definitions which refer to type
29 definitions.
30
31 A table of named types is maintained to allow refering to types by name
32 when the same type is used at several places. Finally a sequence of
33 all types is maintained to facilitate the freeing of all type
34 information when the processing of an ".xml" file is finished. */
35
36 #include <stdlib.h>
37 #include <string.h>
38 #include <stdio.h>
39 #include <stdarg.h>
40 #include <linux/errno.h>
41 #include <assert.h>
42 #include <ctype.h>
43
44 #include "parser.h"
45
46
47 char *intOutputTypes[] = {
48 "int8_t", "int16_t", "int32_t", "int64_t" };
49
50 char *uintOutputTypes[] = {
51 "uint8_t", "uint16_t", "uint32_t", "uint64_t" };
52
53 char *floatOutputTypes[] = {
54 "undef", "undef", "float", "double" };
55
56
57
58
59 /* helper function */
60 void strupper(char *string)
61 {
62 char *ptr = string;
63
64 while(*ptr != '\0') {
65 *ptr = toupper(*ptr);
66 ptr++;
67 }
68 }
69
70
71 int getSizeindex(unsigned int value)
72 {
73 switch(value) {
74 case 1:
75 return 0;
76 case 2:
77 return 1;
78 case 4:
79 return 2;
80 case 8:
81 return 3;
82 default:
83 printf("Error : unknown value size %d\n", value);
84 exit(-1);
85 }
86 }
87
88 /*****************************************************************************
89 *Function name
90 * getSize : translate from string to integer
91 *Input params
92 * in : input file handle
93 *Return values
94 * size
95 *****************************************************************************/
96
97 unsigned long long int getSize(parse_file_t *in)
98 {
99 char *token;
100
101 token = getToken(in);
102 if(in->type == NUMBER) {
103 return strtoull(token, NULL, 0);
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
117 void error_callback(parse_file_t *in, char *msg)
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
136 void * 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
157 char *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
178 void getTypeAttributes(parse_file_t *in, type_descriptor_t *t,
179 sequence_t * unnamed_types, table_t * named_types)
180 {
181 char * token;
182
183 t->fmt = NULL;
184 t->size = 0;
185 t->custom_write = 0;
186 t->network = 0;
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);
207 } else if(!strcmp("custom_write", token)) {
208 t->custom_write = 1;
209 } else if(!strcmp("network", token)) {
210 t->network = 1;
211 }
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
227 void getEventAttributes(parse_file_t *in, event_t *ev)
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
270 void getFacilityAttributes(parse_file_t *in, facility_t *fac)
271 {
272 char * token;
273 char car;
274
275 fac->name = NULL;
276 fac->arch = NULL;
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));
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 }
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
312 void getFieldAttributes(parse_file_t *in, field_t *f)
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 }
333 }
334 }
335
336 char *getNameAttribute(parse_file_t *in)
337 {
338 char * token;
339 char *name = NULL;
340 char car;
341
342 while(1) {
343 token = getToken(in);
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));
350 } else {
351 ungetToken(in);
352 break;
353 }
354
355 }
356 if(name == NULL) in->error(in, "Name was expected");
357 return name;
358 }
359
360
361
362 //for <label name=label_name value=n format="..."/>, value is an option
363 char * getValueStrAttribute(parse_file_t *in)
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
380 char * getDescription(parse_file_t *in)
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
426 void parseFacility(parse_file_t *in, facility_t * fac)
427 {
428 char * token;
429 event_t *ev;
430
431 getFacilityAttributes(in, fac);
432 if(fac->name == NULL) in->error(in, "Attribute not named");
433
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){
448 ev = (event_t*) memAlloc(sizeof(event_t));
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
475 void parseEvent(parse_file_t *in, event_t * ev, sequence_t * unnamed_types,
476 table_t * named_types)
477 {
478 char *token;
479 field_t *f;
480
481 sequence_init(&(ev->fields));
482 //<event name=eventtype_name>
483 getEventAttributes(in, ev);
484 if(ev->name == NULL) in->error(in, "Event not named");
485 getRAnglebracket(in);
486
487 //<description>...</description>
488 ev->description = getDescription(in);
489
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
535 }
536
537 /*****************************************************************************
538 *Function name
539 * parseField : get field infomation from buffer
540 *Input params
541 * in : input file handle
542 * f : field
543 * unnamed_types : array of unamed types
544 * named_types : array of named types
545 * tag : is field surrounded by a <field> </field> tag ?
546 ****************************************************************************/
547
548 void parseFields(parse_file_t *in, field_t *f,
549 sequence_t * unnamed_types,
550 table_t * named_types,
551 int tag)
552 {
553 char * token;
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);
559
560 f->description = getDescription(in);
561 } else {
562 f->description = NULL;
563 }
564
565 //<int size=...>
566 getLAnglebracket(in);
567 f->type = parseType(in,NULL, unnamed_types, named_types);
568
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 }
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
599 type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType,
600 sequence_t * unnamed_types, table_t * named_types)
601 {
602 char *token;
603 type_descriptor_t *t;
604 field_t *f;
605
606 if(inType == NULL) {
607 t = (type_descriptor_t *) memAlloc(sizeof(type_descriptor_t));
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;
619 getTypeAttributes(in, t, unnamed_types, named_types);
620 getRAnglebracket(in); //<struct>
621 getLAnglebracket(in); //<field name=..>
622 token = getToken(in);
623 sequence_init(&(t->fields));
624 while(strcmp("field",token) == 0){
625 f = (field_t *)memAlloc(sizeof(field_t));
626 sequence_push(&(t->fields),f);
627
628 parseFields(in, f, unnamed_types, named_types, 1);
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;
642 getTypeAttributes(in, t, unnamed_types, named_types);
643 getRAnglebracket(in); //<union>
644
645 getLAnglebracket(in); //<field name=..>
646 token = getToken(in);
647 sequence_init(&(t->fields));
648 while(strcmp("field",token) == 0){
649 f = (field_t *)memAlloc(sizeof(field_t));
650 sequence_push(&(t->fields),f);
651 parseFields(in, f, unnamed_types, named_types, 1);
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;
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);
669 getRAnglebracket(in); //<array size=n>
670
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);
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;
688 sequence_init(&(t->fields));
689 getTypeAttributes(in, t, unnamed_types, named_types);
690 getForwardslash(in);
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 }
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) {
734 char * str;
735 int value = -1;
736
737 t->type = ENUM;
738 sequence_init(&(t->labels));
739 sequence_init(&(t->labels_values));
740 sequence_init(&(t->labels_description));
741 t->already_printed = 0;
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;
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){
754 int *label_value = malloc(sizeof(int));
755
756 str = allocAndCopy(getNameAttribute(in));
757 token = getValueStrAttribute(in);
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);
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 }
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;
799 getTypeAttributes(in, t, unnamed_types, named_types);
800 t->size = 1;
801 getForwardslash(in);
802 getRAnglebracket(in);
803 }
804 else if(strcmp(token,"uchar") == 0) {
805 t->type = UCHAR;
806 getTypeAttributes(in, t, unnamed_types, named_types);
807 t->size = 1;
808 getForwardslash(in);
809 getRAnglebracket(in);
810 }
811 else if(strcmp(token,"short") == 0) {
812 t->type = SHORT;
813 getTypeAttributes(in, t, unnamed_types, named_types);
814 t->size = 2;
815 getForwardslash(in);
816 getRAnglebracket(in);
817 }
818 else if(strcmp(token,"ushort") == 0) {
819 t->type = USHORT;
820 getTypeAttributes(in, t, unnamed_types, named_types);
821 t->size = 2;
822 getForwardslash(in);
823 getRAnglebracket(in);
824 }
825 else if(strcmp(token,"int") == 0) {
826 t->type = INT;
827 getTypeAttributes(in, t, unnamed_types, named_types);
828 getForwardslash(in);
829 getRAnglebracket(in);
830 }
831 else if(strcmp(token,"uint") == 0) {
832 t->type = UINT;
833 getTypeAttributes(in, t, unnamed_types, named_types);
834 getForwardslash(in);
835 getRAnglebracket(in);
836 }
837
838 else if(strcmp(token,"pointer") == 0) {
839 t->type = POINTER;
840 getTypeAttributes(in, t, unnamed_types, named_types);
841 getForwardslash(in);
842 getRAnglebracket(in);
843 }
844 else if(strcmp(token,"long") == 0) {
845 t->type = LONG;
846 getTypeAttributes(in, t, unnamed_types, named_types);
847 getForwardslash(in);
848 getRAnglebracket(in);
849 }
850 else if(strcmp(token,"ulong") == 0) {
851 t->type = ULONG;
852 getTypeAttributes(in, t, unnamed_types, named_types);
853 getForwardslash(in);
854 getRAnglebracket(in);
855 }
856 else if(strcmp(token,"size_t") == 0) {
857 t->type = SIZE_T;
858 getTypeAttributes(in, t, unnamed_types, named_types);
859 getForwardslash(in);
860 getRAnglebracket(in);
861 }
862 else if(strcmp(token,"ssize_t") == 0) {
863 t->type = SSIZE_T;
864 getTypeAttributes(in, t, unnamed_types, named_types);
865 getForwardslash(in);
866 getRAnglebracket(in);
867 }
868 else if(strcmp(token,"off_t") == 0) {
869 t->type = OFF_T;
870 getTypeAttributes(in, t, unnamed_types, named_types);
871 getForwardslash(in);
872 getRAnglebracket(in);
873 }
874 else if(strcmp(token,"float") == 0) {
875 t->type = FLOAT;
876 getTypeAttributes(in, t, unnamed_types, named_types);
877 getForwardslash(in);
878 getRAnglebracket(in);
879 }
880 else if(strcmp(token,"string") == 0) {
881 t->type = STRING;
882 getTypeAttributes(in, t, unnamed_types, named_types);
883 getForwardslash(in);
884 getRAnglebracket(in);
885 }
886 else if(strcmp(token,"typeref") == 0){
887 // Must be a named type
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;
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
911 type_descriptor_t * find_named_type(char *name, table_t * named_types)
912 {
913 type_descriptor_t *t;
914
915 t = table_find(named_types,name);
916
917 return t;
918 }
919
920 type_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 }
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
942 void parseTypeDefinition(parse_file_t * in, sequence_t * unnamed_types,
943 table_t * named_types)
944 {
945 char *token;
946 type_descriptor_t *t;
947
948 token = getNameAttribute(in);
949 if(token == NULL) in->error(in, "Type has empty name");
950 t = create_named_type(token, named_types);
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
982 char *getName(parse_file_t * in)
983 {
984 char *token;
985
986 token = getToken(in);
987 // Optional descriptions
988 // if(in->type != NAME) in->error(in,"Name token was expected");
989 return token;
990 }
991
992 int getNumber(parse_file_t * in)
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
1001 char *getForwardslash(parse_file_t * in)
1002 {
1003 char *token;
1004
1005 token = getToken(in);
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
1010 return token;
1011 }
1012
1013 char *getLAnglebracket(parse_file_t * in)
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
1022 char *getRAnglebracket(parse_file_t * in)
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
1031 char *getQuotedString(parse_file_t * in)
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
1040 char * getEqual(parse_file_t *in)
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
1049 char seekNextChar(parse_file_t *in)
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
1076 void ungetToken(parse_file_t * in)
1077 {
1078 in->unget = 1;
1079 }
1080
1081 char *getToken(parse_file_t * in)
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 }
1170 else if(isalnum(car) || car == '_' || car == '-') {
1171 in->buffer[0] = car;
1172 pos = 1;
1173 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
1174 if(!(isalnum(car) || car == '_' || car == '-')) {
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
1191 void skipComment(parse_file_t * in)
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
1206 void skipEOL(parse_file_t * in)
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
1223 void checkNamedTypesImplemented(table_t * named_types)
1224 {
1225 type_descriptor_t *t;
1226 int pos;
1227 char str[256];
1228
1229 for(pos = 0 ; pos < named_types->values.position; pos++) {
1230 t = (type_descriptor_t *) named_types->values.array[pos];
1231 if(t->type == NONE){
1232 sprintf(str,"named type '%s' has no definition",
1233 (char*)named_types->keys.array[pos]);
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
1249 void generateChecksum(char* facName,
1250 unsigned int * checksum, sequence_t * events)
1251 {
1252 unsigned long crc ;
1253 int pos;
1254 event_t * ev;
1255 unsigned int i;
1256
1257 crc = crc32(facName);
1258 for(pos = 0; pos < events->position; pos++){
1259 ev = (event_t *)(events->array[pos]);
1260 crc = partial_crc32(ev->name, crc);
1261 for(i = 0; i < ev->fields.position; i++) {
1262 field_t *f = (field_t*)ev->fields.array[i];
1263 crc = partial_crc32(f->name, crc);
1264 crc = getTypeChecksum(crc, f->type);
1265 }
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
1280 unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor_t * type)
1281 {
1282 unsigned long crc = aCrc;
1283 char * str = NULL, buf[16];
1284 int flag = 0, pos;
1285 field_t * fld;
1286
1287 switch(type->type){
1288 case INT_FIXED:
1289 str = intOutputTypes[getSizeindex(type->size)];
1290 break;
1291 case UINT_FIXED:
1292 str = uintOutputTypes[getSizeindex(type->size)];
1293 break;
1294 case POINTER:
1295 str = allocAndCopy("void *");
1296 flag = 1;
1297 break;
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;
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:
1343 str = floatOutputTypes[getSizeindex(type->size)];
1344 break;
1345 case STRING:
1346 str = allocAndCopy("string");
1347 flag = 1;
1348 break;
1349 case ENUM:
1350 //str = appendString("enum ", uintOutputTypes[getSizeindex(type->size)]);
1351 str = allocAndCopy("enum");
1352 flag = 1;
1353 break;
1354 case ARRAY:
1355 sprintf(buf,"%zu", type->size);
1356 str = appendString("array ",buf);
1357 flag = 1;
1358 break;
1359 case SEQUENCE:
1360 str = allocAndCopy("sequence ");
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
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){
1387 for(pos =0; pos < type->fields.position; pos++){
1388 fld = (field_t *) type->fields.array[pos];
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 */
1402 void freeType(type_descriptor_t * tp)
1403 {
1404 int pos2;
1405 field_t *f;
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));
1413 for(pos2 = 0; pos2 < tp->labels_values.position; pos2++) {
1414 free(tp->labels_values.array[pos2]);
1415 }
1416 sequence_dispose(&(tp->labels_values));
1417 }
1418 if(tp->type == STRUCT) {
1419 for(pos2 = 0; pos2 < tp->fields.position; pos2++) {
1420 f = (field_t *) tp->fields.array[pos2];
1421 free(f->name);
1422 free(f->description);
1423 free(f);
1424 }
1425 sequence_dispose(&(tp->fields));
1426 }
1427 }
1428
1429 void freeNamedType(table_t * t)
1430 {
1431 int pos;
1432 type_descriptor_t * td;
1433
1434 for(pos = 0 ; pos < t->keys.position; pos++) {
1435 free((char *)t->keys.array[pos]);
1436 td = (type_descriptor_t*)t->values.array[pos];
1437 freeType(td);
1438 free(td);
1439 }
1440 }
1441
1442 void freeTypes(sequence_t *t)
1443 {
1444 int pos;
1445 type_descriptor_t *tp;
1446
1447 for(pos = 0 ; pos < t->position; pos++) {
1448 tp = (type_descriptor_t *)t->array[pos];
1449 freeType(tp);
1450 free(tp);
1451 }
1452 }
1453
1454 void freeEvents(sequence_t *t)
1455 {
1456 int pos;
1457 event_t *ev;
1458
1459 for(pos = 0 ; pos < t->position; pos++) {
1460 ev = (event_t *) t->array[pos];
1461 free(ev->name);
1462 free(ev->description);
1463 sequence_dispose(&ev->fields);
1464 free(ev);
1465 }
1466
1467 }
1468
1469
1470 /* Extensible array */
1471
1472 void sequence_init(sequence_t *t)
1473 {
1474 t->size = 10;
1475 t->position = 0;
1476 t->array = (void **)memAlloc(t->size * sizeof(void *));
1477 }
1478
1479 void sequence_dispose(sequence_t *t)
1480 {
1481 t->size = 0;
1482 free(t->array);
1483 t->array = NULL;
1484 }
1485
1486 void sequence_push(sequence_t *t, void *elem)
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
1501 void *sequence_pop(sequence_t *t)
1502 {
1503 if(t->position == 0) printf("Error : trying to pop an empty sequence");
1504 return t->array[--t->position];
1505 }
1506
1507
1508 /* Hash table API, implementation is just linear search for now */
1509
1510 void table_init(table_t *t)
1511 {
1512 sequence_init(&(t->keys));
1513 sequence_init(&(t->values));
1514 }
1515
1516 void table_dispose(table_t *t)
1517 {
1518 sequence_dispose(&(t->keys));
1519 sequence_dispose(&(t->values));
1520 }
1521
1522 void table_insert(table_t *t, char *key, void *value)
1523 {
1524 sequence_push(&(t->keys),key);
1525 sequence_push(&(t->values),value);
1526 }
1527
1528 void *table_find(table_t *t, char *key)
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
1538 void table_insert_int(table_t *t, int *key, void *value)
1539 {
1540 sequence_push(&(t->keys),key);
1541 sequence_push(&(t->values),value);
1542 }
1543
1544 void *table_find_int(table_t *t, int *key)
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
1557 char *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.060917 seconds and 4 git commands to generate.