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