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