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