sequence length type
[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);
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 ****************************************************************************/
539
540 void parseFields(parse_file_t *in, field_t *f,
541 sequence_t * unnamed_types,
542 table_t * named_types)
543 {
544 char * token;
545
546 //<field name=field_name> <description> <type> </field>
547 getFieldAttributes(in, f);
548 if(f->name == NULL) in->error(in, "Field not named");
549 getRAnglebracket(in);
550
551 f->description = getDescription(in);
552
553 //<int size=...>
554 getLAnglebracket(in);
555 f->type = parseType(in,NULL, unnamed_types, named_types);
556
557 getLAnglebracket(in);
558 getForwardslash(in);
559 token = getName(in);
560 if(strcmp("field",token))in->error(in,"not a valid field definition");
561 getRAnglebracket(in); //</field>
562 }
563
564
565 /*****************************************************************************
566 *Function name
567 * parseType : get type information, type can be :
568 * Primitive:
569 * int(size,fmt); uint(size,fmt); float(size,fmt);
570 * string(fmt); enum(size,fmt,(label1,label2...))
571 * Compound:
572 * array(arraySize, type); sequence(lengthSize,type)
573 * struct(field(name,type,description)...)
574 * type name:
575 * type(name,type)
576 *Input params
577 * in : input file handle
578 * inType : a type descriptor
579 * unnamed_types : array of unamed types
580 * named_types : array of named types
581 *Return values
582 * type_descriptor* : a type descriptor
583 ****************************************************************************/
584
585 type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType,
586 sequence_t * unnamed_types, table_t * named_types)
587 {
588 char *token;
589 type_descriptor_t *t;
590 field_t *f;
591
592 if(inType == NULL) {
593 t = (type_descriptor_t *) memAlloc(sizeof(type_descriptor_t));
594 t->type_name = NULL;
595 t->type = NONE;
596 t->fmt = NULL;
597 sequence_push(unnamed_types,t);
598 }
599 else t = inType;
600
601 token = getName(in);
602
603 if(strcmp(token,"struct") == 0) {
604 t->type = STRUCT;
605 getTypeAttributes(in, t, unnamed_types, named_types);
606 getRAnglebracket(in); //<struct>
607 getLAnglebracket(in); //<field name=..>
608 token = getToken(in);
609 sequence_init(&(t->fields));
610 while(strcmp("field",token) == 0){
611 f = (field_t *)memAlloc(sizeof(field_t));
612 sequence_push(&(t->fields),f);
613
614 parseFields(in, f, unnamed_types, named_types);
615
616 //next field
617 getLAnglebracket(in);
618 token = getToken(in);
619 }
620 if(strcmp("/",token))in->error(in,"not a valid structure definition");
621 token = getName(in);
622 if(strcmp("struct",token)!=0)
623 in->error(in,"not a valid structure definition");
624 getRAnglebracket(in); //</struct>
625 }
626 else if(strcmp(token,"union") == 0) {
627 t->type = UNION;
628 getTypeAttributes(in, t, unnamed_types, named_types);
629 getRAnglebracket(in); //<union>
630
631 getLAnglebracket(in); //<field name=..>
632 token = getToken(in);
633 sequence_init(&(t->fields));
634 while(strcmp("field",token) == 0){
635 f = (field_t *)memAlloc(sizeof(field_t));
636 sequence_push(&(t->fields),f);
637 parseFields(in, f, unnamed_types, named_types);
638
639 //next field
640 getLAnglebracket(in);
641 token = getToken(in);
642 }
643 if(strcmp("/",token))in->error(in,"not a valid union definition");
644 token = getName(in);
645 if(strcmp("union",token)!=0)
646 in->error(in,"not a valid union definition");
647 getRAnglebracket(in); //</union>
648 }
649 else if(strcmp(token,"array") == 0) {
650 t->type = ARRAY;
651 getTypeAttributes(in, t, unnamed_types, named_types);
652 if(t->size == 0) in->error(in, "Array has empty size");
653 getForwardslash(in);
654 getRAnglebracket(in); //<array size=n>
655
656 getLAnglebracket(in); //<type struct>
657 t->nested_type = parseType(in, NULL, unnamed_types, named_types);
658
659 getLAnglebracket(in); //</array>
660 getForwardslash(in);
661 token = getName(in);
662 if(strcmp("array",token))in->error(in,"not a valid array definition");
663 getRAnglebracket(in); //</array>
664 }
665 else if(strcmp(token,"sequence") == 0) {
666 t->type = SEQUENCE;
667 //getTypeAttributes(in, t, unnamed_types, named_types);
668 //getForwardslash(in);
669 getRAnglebracket(in); //<sequence>
670
671 getLAnglebracket(in); //<type sequence>
672 t->length_type = parseType(in, NULL, unnamed_types, named_types);
673
674 getLAnglebracket(in); //<type sequence>
675
676 t->nested_type = parseType(in, NULL, unnamed_types, named_types);
677
678 if(t->length_type == NULL) in->error(in, "Sequence has no length type");
679 switch(t->length_type->type) {
680 case UINT_FIXED :
681 case UCHAR :
682 case USHORT :
683 case UINT :
684 case ULONG :
685 case SIZE_T :
686 case OFF_T :
687 break;
688 default:
689 in->error(in, "Wrong length type for sequence");
690 }
691
692
693 if(t->nested_type == NULL) in->error(in, "Sequence has no nested type");
694 getLAnglebracket(in); //</sequence>
695 getForwardslash(in);
696 token = getName(in);
697 if(strcmp("sequence",token))in->error(in,"not a valid sequence definition");
698 getRAnglebracket(in); //</sequence>
699 }
700 else if(strcmp(token,"enum") == 0) {
701 char * str, *str1;
702 t->type = ENUM;
703 sequence_init(&(t->labels));
704 sequence_init(&(t->labels_description));
705 t->already_printed = 0;
706 getTypeAttributes(in, t, unnamed_types, named_types);
707 //if(t->size == 0) in->error(in, "Sequence has empty size");
708 //Mathieu : we fix enum size to 4 bytes. GCC is always like this.
709 //fox copy optimisation.
710 if(t->size != 0) in->error(in, "Enum has fixed size of 4.");
711 t->size = 4;
712 getRAnglebracket(in);
713
714 //<label name=label1 value=n/>
715 getLAnglebracket(in);
716 token = getToken(in); //"label" or "/"
717 while(strcmp("label",token) == 0){
718 str = allocAndCopy(getNameAttribute(in));
719 token = getValueStrAttribute(in);
720 if(token){
721 str1 = appendString(str,"=");
722 free(str);
723 str = appendString(str1,token);
724 free(str1);
725 sequence_push(&(t->labels),str);
726 }
727 else
728 sequence_push(&(t->labels),str);
729
730 getForwardslash(in);
731 getRAnglebracket(in);
732
733 //read description if any. May be NULL.
734 str = allocAndCopy(getDescription(in));
735 sequence_push(&(t->labels_description),str);
736
737 //next label definition
738 getLAnglebracket(in);
739 token = getToken(in); //"label" or "/"
740 }
741 if(strcmp("/",token))in->error(in, "not a valid enum definition");
742 token = getName(in);
743 if(strcmp("enum",token))in->error(in, "not a valid enum definition");
744 getRAnglebracket(in); //</label>
745 }
746 else if(strcmp(token,"int_fixed") == 0) {
747 t->type = INT_FIXED;
748 getTypeAttributes(in, t, unnamed_types, named_types);
749 if(t->size == 0) in->error(in, "int has empty size");
750 getForwardslash(in);
751 getRAnglebracket(in);
752 }
753 else if(strcmp(token,"uint_fixed") == 0) {
754 t->type = UINT_FIXED;
755 getTypeAttributes(in, t, unnamed_types, named_types);
756 if(t->size == 0) in->error(in, "uint has empty size");
757 getForwardslash(in);
758 getRAnglebracket(in);
759 }
760 else if(strcmp(token,"char") == 0) {
761 t->type = CHAR;
762 getTypeAttributes(in, t, unnamed_types, named_types);
763 getForwardslash(in);
764 getRAnglebracket(in);
765 }
766 else if(strcmp(token,"uchar") == 0) {
767 t->type = UCHAR;
768 getTypeAttributes(in, t, unnamed_types, named_types);
769 getForwardslash(in);
770 getRAnglebracket(in);
771 }
772 else if(strcmp(token,"short") == 0) {
773 t->type = SHORT;
774 getTypeAttributes(in, t, unnamed_types, named_types);
775 getForwardslash(in);
776 getRAnglebracket(in);
777 }
778 else if(strcmp(token,"ushort") == 0) {
779 t->type = USHORT;
780 getTypeAttributes(in, t, unnamed_types, named_types);
781 getForwardslash(in);
782 getRAnglebracket(in);
783 }
784 else if(strcmp(token,"int") == 0) {
785 t->type = INT;
786 getTypeAttributes(in, t, unnamed_types, named_types);
787 getForwardslash(in);
788 getRAnglebracket(in);
789 }
790 else if(strcmp(token,"uint") == 0) {
791 t->type = UINT;
792 getTypeAttributes(in, t, unnamed_types, named_types);
793 getForwardslash(in);
794 getRAnglebracket(in);
795 }
796
797 else if(strcmp(token,"pointer") == 0) {
798 t->type = POINTER;
799 getTypeAttributes(in, t, unnamed_types, named_types);
800 getForwardslash(in);
801 getRAnglebracket(in);
802 }
803 else if(strcmp(token,"long") == 0) {
804 t->type = LONG;
805 getTypeAttributes(in, t, unnamed_types, named_types);
806 getForwardslash(in);
807 getRAnglebracket(in);
808 }
809 else if(strcmp(token,"ulong") == 0) {
810 t->type = ULONG;
811 getTypeAttributes(in, t, unnamed_types, named_types);
812 getForwardslash(in);
813 getRAnglebracket(in);
814 }
815 else if(strcmp(token,"size_t") == 0) {
816 t->type = SIZE_T;
817 getTypeAttributes(in, t, unnamed_types, named_types);
818 getForwardslash(in);
819 getRAnglebracket(in);
820 }
821 else if(strcmp(token,"ssize_t") == 0) {
822 t->type = SSIZE_T;
823 getTypeAttributes(in, t, unnamed_types, named_types);
824 getForwardslash(in);
825 getRAnglebracket(in);
826 }
827 else if(strcmp(token,"off_t") == 0) {
828 t->type = OFF_T;
829 getTypeAttributes(in, t, unnamed_types, named_types);
830 getForwardslash(in);
831 getRAnglebracket(in);
832 }
833 else if(strcmp(token,"float") == 0) {
834 t->type = FLOAT;
835 getTypeAttributes(in, t, unnamed_types, named_types);
836 getForwardslash(in);
837 getRAnglebracket(in);
838 }
839 else if(strcmp(token,"string") == 0) {
840 t->type = STRING;
841 getTypeAttributes(in, t, unnamed_types, named_types);
842 getForwardslash(in);
843 getRAnglebracket(in);
844 }
845 else if(strcmp(token,"typeref") == 0){
846 // Must be a named type
847 if(inType != NULL)
848 in->error(in,"Named type cannot refer to a named type");
849 else {
850 free(t);
851 sequence_pop(unnamed_types);
852 token = getNameAttribute(in);
853 t = find_named_type(token, named_types);
854 getForwardslash(in); //<typeref name=type_name/>
855 getRAnglebracket(in);
856 return t;
857 }
858 }else in->error(in,"not a valid type");
859
860 return t;
861 }
862
863 /*****************************************************************************
864 *Function name
865 * find_named_type : find a named type from hash table
866 *Input params
867 * name : type name
868 * named_types : array of named types
869 *Return values
870 * type_descriptor * : a type descriptor
871 *****************************************************************************/
872
873 type_descriptor_t * find_named_type(char *name, table_t * named_types)
874 {
875 type_descriptor_t *t;
876
877 t = table_find(named_types,name);
878 if(t == NULL) {
879 t = (type_descriptor_t *)memAlloc(sizeof(type_descriptor_t));
880 t->type_name = allocAndCopy(name);
881 t->type = NONE;
882 t->fmt = NULL;
883 table_insert(named_types,t->type_name,t);
884 // table_insert(named_types,allocAndCopy(name),t);
885 }
886 return t;
887 }
888
889 /*****************************************************************************
890 *Function name
891 * parseTypeDefinition : get type information from type definition
892 *Input params
893 * in : input file handle
894 * unnamed_types : array of unamed types
895 * named_types : array of named types
896 *****************************************************************************/
897
898 void parseTypeDefinition(parse_file_t * in, sequence_t * unnamed_types,
899 table_t * named_types)
900 {
901 char *token;
902 type_descriptor_t *t;
903
904 token = getNameAttribute(in);
905 if(token == NULL) in->error(in, "Type has empty name");
906 t = find_named_type(token, named_types);
907
908 if(t->type != NONE) in->error(in,"redefinition of named type");
909 getRAnglebracket(in); //<type name=type_name>
910 getLAnglebracket(in); //<
911 token = getName(in);
912 //MD ??if(strcmp("struct",token))in->error(in,"not a valid type definition");
913 ungetToken(in);
914 parseType(in,t, unnamed_types, named_types);
915
916 //</type>
917 getLAnglebracket(in);
918 getForwardslash(in);
919 token = getName(in);
920 if(strcmp("type",token))in->error(in,"not a valid type definition");
921 getRAnglebracket(in); //</type>
922 }
923
924 /**************************************************************************
925 * Function :
926 * getComa, getName, getNumber, getEqual
927 * Description :
928 * Read a token from the input file, check its type, return it scontent.
929 *
930 * Parameters :
931 * in , input file handle.
932 *
933 * Return values :
934 * address of token content.
935 *
936 **************************************************************************/
937
938 char *getName(parse_file_t * in)
939 {
940 char *token;
941
942 token = getToken(in);
943 if(in->type != NAME) in->error(in,"Name token was expected");
944 return token;
945 }
946
947 int getNumber(parse_file_t * in)
948 {
949 char *token;
950
951 token = getToken(in);
952 if(in->type != NUMBER) in->error(in, "Number token was expected");
953 return atoi(token);
954 }
955
956 char *getForwardslash(parse_file_t * in)
957 {
958 char *token;
959
960 token = getToken(in);
961 //if(in->type != FORWARDSLASH) in->error(in, "forward slash token was expected");
962 /* Mathieu : final / is optional now. */
963 if(in->type != FORWARDSLASH) ungetToken(in);
964
965 return token;
966 }
967
968 char *getLAnglebracket(parse_file_t * in)
969 {
970 char *token;
971
972 token = getToken(in);
973 if(in->type != LANGLEBRACKET) in->error(in, "Left angle bracket was expected");
974 return token;
975 }
976
977 char *getRAnglebracket(parse_file_t * in)
978 {
979 char *token;
980
981 token = getToken(in);
982 if(in->type != RANGLEBRACKET) in->error(in, "Right angle bracket was expected");
983 return token;
984 }
985
986 char *getQuotedString(parse_file_t * in)
987 {
988 char *token;
989
990 token = getToken(in);
991 if(in->type != QUOTEDSTRING) in->error(in, "quoted string was expected");
992 return token;
993 }
994
995 char * getEqual(parse_file_t *in)
996 {
997 char *token;
998
999 token = getToken(in);
1000 if(in->type != EQUAL) in->error(in, "equal was expected");
1001 return token;
1002 }
1003
1004 char seekNextChar(parse_file_t *in)
1005 {
1006 char car;
1007 while((car = getc(in->fp)) != EOF) {
1008 if(!isspace(car)){
1009 ungetc(car,in->fp);
1010 return car;
1011 }
1012 }
1013 return EOF;
1014 }
1015
1016 /******************************************************************
1017 * Function :
1018 * getToken, ungetToken
1019 * Description :
1020 * Read a token from the input file and return its type and content.
1021 * Line numbers are accounted for and whitespace/comments are skipped.
1022 *
1023 * Parameters :
1024 * in, input file handle.
1025 *
1026 * Return values :
1027 * address of token content.
1028 *
1029 ******************************************************************/
1030
1031 void ungetToken(parse_file_t * in)
1032 {
1033 in->unget = 1;
1034 }
1035
1036 char *getToken(parse_file_t * in)
1037 {
1038 FILE *fp = in->fp;
1039 char car, car1;
1040 int pos = 0, escaped;
1041
1042 if(in->unget == 1) {
1043 in->unget = 0;
1044 return in->buffer;
1045 }
1046
1047 /* skip whitespace and comments */
1048
1049 while((car = getc(fp)) != EOF) {
1050 if(car == '/') {
1051 car1 = getc(fp);
1052 if(car1 == '*') skipComment(in);
1053 else if(car1 == '/') skipEOL(in);
1054 else {
1055 car1 = ungetc(car1,fp);
1056 break;
1057 }
1058 }
1059 else if(car == '\n') in->lineno++;
1060 else if(!isspace(car)) break;
1061 }
1062
1063 switch(car) {
1064 case EOF:
1065 in->type = ENDFILE;
1066 break;
1067 case '/':
1068 in->type = FORWARDSLASH;
1069 in->buffer[pos] = car;
1070 pos++;
1071 break;
1072 case '<':
1073 in->type = LANGLEBRACKET;
1074 in->buffer[pos] = car;
1075 pos++;
1076 break;
1077 case '>':
1078 in->type = RANGLEBRACKET;
1079 in->buffer[pos] = car;
1080 pos++;
1081 break;
1082 case '=':
1083 in->type = EQUAL;
1084 in->buffer[pos] = car;
1085 pos++;
1086 break;
1087 case '"':
1088 escaped = 0;
1089 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
1090 if(car == '\\' && escaped == 0) {
1091 in->buffer[pos] = car;
1092 pos++;
1093 escaped = 1;
1094 continue;
1095 }
1096 if(car == '"' && escaped == 0) break;
1097 if(car == '\n' && escaped == 0) {
1098 in->error(in, "non escaped newline inside quoted string");
1099 }
1100 if(car == '\n') in->lineno++;
1101 in->buffer[pos] = car;
1102 pos++;
1103 escaped = 0;
1104 }
1105 if(car == EOF) in->error(in,"no ending quotemark");
1106 if(pos == BUFFER_SIZE) in->error(in, "quoted string token too large");
1107 in->type = QUOTEDSTRING;
1108 break;
1109 default:
1110 if(isdigit(car)) {
1111 in->buffer[pos] = car;
1112 pos++;
1113 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
1114 if(!isdigit(car)) {
1115 ungetc(car,fp);
1116 break;
1117 }
1118 in->buffer[pos] = car;
1119 pos++;
1120 }
1121 if(car == EOF) ungetc(car,fp);
1122 if(pos == BUFFER_SIZE) in->error(in, "number token too large");
1123 in->type = NUMBER;
1124 }
1125 else if(isalpha(car)) {
1126 in->buffer[0] = car;
1127 pos = 1;
1128 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
1129 if(!(isalnum(car) || car == '_')) {
1130 ungetc(car,fp);
1131 break;
1132 }
1133 in->buffer[pos] = car;
1134 pos++;
1135 }
1136 if(car == EOF) ungetc(car,fp);
1137 if(pos == BUFFER_SIZE) in->error(in, "name token too large");
1138 in->type = NAME;
1139 }
1140 else in->error(in, "invalid character, unrecognized token");
1141 }
1142 in->buffer[pos] = 0;
1143 return in->buffer;
1144 }
1145
1146 void skipComment(parse_file_t * in)
1147 {
1148 char car;
1149 while((car = getc(in->fp)) != EOF) {
1150 if(car == '\n') in->lineno++;
1151 else if(car == '*') {
1152 car = getc(in->fp);
1153 if(car ==EOF) break;
1154 if(car == '/') return;
1155 ungetc(car,in->fp);
1156 }
1157 }
1158 if(car == EOF) in->error(in,"comment begining with '/*' has no ending '*/'");
1159 }
1160
1161 void skipEOL(parse_file_t * in)
1162 {
1163 char car;
1164 while((car = getc(in->fp)) != EOF) {
1165 if(car == '\n') {
1166 ungetc(car,in->fp);
1167 break;
1168 }
1169 }
1170 if(car == EOF)ungetc(car, in->fp);
1171 }
1172
1173 /*****************************************************************************
1174 *Function name
1175 * checkNamedTypesImplemented : check if all named types have definition
1176 ****************************************************************************/
1177
1178 void checkNamedTypesImplemented(table_t * named_types)
1179 {
1180 type_descriptor_t *t;
1181 int pos;
1182 char str[256];
1183
1184 for(pos = 0 ; pos < named_types->values.position; pos++) {
1185 t = (type_descriptor_t *) named_types->values.array[pos];
1186 if(t->type == NONE){
1187 sprintf(str,"named type '%s' has no definition",
1188 (char*)named_types->keys.array[pos]);
1189 error_callback(NULL,str);
1190 }
1191 }
1192 }
1193
1194
1195 /*****************************************************************************
1196 *Function name
1197 * generateChecksum : generate checksum for the facility
1198 *Input Params
1199 * facName : name of facility
1200 *Output Params
1201 * checksum : checksum for the facility
1202 ****************************************************************************/
1203
1204 void generateChecksum(char* facName,
1205 unsigned long * checksum, sequence_t * events)
1206 {
1207 unsigned long crc ;
1208 int pos;
1209 event_t * ev;
1210
1211 crc = crc32(facName);
1212 for(pos = 0; pos < events->position; pos++){
1213 ev = (event_t *)(events->array[pos]);
1214 crc = partial_crc32(ev->name, crc);
1215 for(unsigned int i = 0; i < ev->fields.position; i++) {
1216 field_t *f = (field_t*)ev->fields.array[i];
1217 crc = partial_crc32(f->name, crc);
1218 crc = getTypeChecksum(crc, f->type);
1219 }
1220 }
1221 *checksum = crc;
1222 }
1223
1224 /*****************************************************************************
1225 *Function name
1226 * getTypeChecksum : generate checksum by type info
1227 *Input Params
1228 * crc : checksum generated so far
1229 * type : type descriptor containing type info
1230 *Return value
1231 * unsigned long : checksum
1232 *****************************************************************************/
1233
1234 unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor_t * type)
1235 {
1236 unsigned long crc = aCrc;
1237 char * str = NULL, buf[16];
1238 int flag = 0, pos;
1239 field_t * fld;
1240
1241 switch(type->type){
1242 case INT_FIXED:
1243 str = intOutputTypes[getSizeindex(type->size)];
1244 break;
1245 case UINT_FIXED:
1246 str = uintOutputTypes[getSizeindex(type->size)];
1247 break;
1248 case POINTER:
1249 str = allocAndCopy("void *");
1250 flag = 1;
1251 break;
1252 case CHAR:
1253 str = allocAndCopy("signed char");
1254 flag = 1;
1255 break;
1256 case UCHAR:
1257 str = allocAndCopy("unsigned char");
1258 flag = 1;
1259 break;
1260 case SHORT:
1261 str = allocAndCopy("short");
1262 flag = 1;
1263 break;
1264 case USHORT:
1265 str = allocAndCopy("unsigned short");
1266 flag = 1;
1267 break;
1268 case INT:
1269 str = allocAndCopy("int");
1270 flag = 1;
1271 break;
1272 case UINT:
1273 str = allocAndCopy("uint");
1274 flag = 1;
1275 break;
1276 case LONG:
1277 str = allocAndCopy("long");
1278 flag = 1;
1279 break;
1280 case ULONG:
1281 str = allocAndCopy("unsigned long");
1282 flag = 1;
1283 break;
1284 case SIZE_T:
1285 str = allocAndCopy("size_t");
1286 flag = 1;
1287 break;
1288 case SSIZE_T:
1289 str = allocAndCopy("ssize_t");
1290 flag = 1;
1291 break;
1292 case OFF_T:
1293 str = allocAndCopy("off_t");
1294 flag = 1;
1295 break;
1296 case FLOAT:
1297 str = floatOutputTypes[getSizeindex(type->size)];
1298 break;
1299 case STRING:
1300 str = allocAndCopy("string");
1301 flag = 1;
1302 break;
1303 case ENUM:
1304 //str = appendString("enum ", uintOutputTypes[getSizeindex(type->size)]);
1305 str = allocAndCopy("enum");
1306 flag = 1;
1307 break;
1308 case ARRAY:
1309 sprintf(buf,"%llu", type->size);
1310 str = appendString("array ",buf);
1311 flag = 1;
1312 break;
1313 case SEQUENCE:
1314 sprintf(buf,"%llu", type->size);
1315 str = appendString("sequence ",buf);
1316 flag = 1;
1317 break;
1318 case STRUCT:
1319 str = allocAndCopy("struct");
1320 flag = 1;
1321 break;
1322 case UNION:
1323 str = allocAndCopy("union");
1324 flag = 1;
1325 break;
1326 default:
1327 error_callback(NULL, "named type has no definition");
1328 break;
1329 }
1330
1331 crc = partial_crc32(str,crc);
1332 if(flag) free(str);
1333
1334 if(type->fmt) crc = partial_crc32(type->fmt,crc);
1335
1336 if(type->type == ARRAY || type->type == SEQUENCE){
1337 crc = getTypeChecksum(crc,type->nested_type);
1338 }else if(type->type == STRUCT || type->type == UNION){
1339 for(pos =0; pos < type->fields.position; pos++){
1340 fld = (field_t *) type->fields.array[pos];
1341 crc = partial_crc32(fld->name,crc);
1342 crc = getTypeChecksum(crc, fld->type);
1343 }
1344 }else if(type->type == ENUM){
1345 for(pos = 0; pos < type->labels.position; pos++)
1346 crc = partial_crc32((char*)type->labels.array[pos],crc);
1347 }
1348
1349 return crc;
1350 }
1351
1352
1353 /* Event type descriptors */
1354 void freeType(type_descriptor_t * tp)
1355 {
1356 int pos2;
1357 field_t *f;
1358
1359 if(tp->fmt != NULL) free(tp->fmt);
1360 if(tp->type == ENUM) {
1361 for(pos2 = 0; pos2 < tp->labels.position; pos2++) {
1362 free(tp->labels.array[pos2]);
1363 }
1364 sequence_dispose(&(tp->labels));
1365 }
1366 if(tp->type == STRUCT) {
1367 for(pos2 = 0; pos2 < tp->fields.position; pos2++) {
1368 f = (field_t *) tp->fields.array[pos2];
1369 free(f->name);
1370 free(f->description);
1371 free(f);
1372 }
1373 sequence_dispose(&(tp->fields));
1374 }
1375 }
1376
1377 void freeNamedType(table_t * t)
1378 {
1379 int pos;
1380 type_descriptor_t * td;
1381
1382 for(pos = 0 ; pos < t->keys.position; pos++) {
1383 free((char *)t->keys.array[pos]);
1384 td = (type_descriptor_t*)t->values.array[pos];
1385 freeType(td);
1386 free(td);
1387 }
1388 }
1389
1390 void freeTypes(sequence_t *t)
1391 {
1392 int pos;
1393 type_descriptor_t *tp;
1394
1395 for(pos = 0 ; pos < t->position; pos++) {
1396 tp = (type_descriptor_t *)t->array[pos];
1397 freeType(tp);
1398 free(tp);
1399 }
1400 }
1401
1402 void freeEvents(sequence_t *t)
1403 {
1404 int pos;
1405 event_t *ev;
1406
1407 for(pos = 0 ; pos < t->position; pos++) {
1408 ev = (event_t *) t->array[pos];
1409 free(ev->name);
1410 free(ev->description);
1411 sequence_dispose(&ev->fields);
1412 free(ev);
1413 }
1414
1415 }
1416
1417
1418 /* Extensible array */
1419
1420 void sequence_init(sequence_t *t)
1421 {
1422 t->size = 10;
1423 t->position = 0;
1424 t->array = (void **)memAlloc(t->size * sizeof(void *));
1425 }
1426
1427 void sequence_dispose(sequence_t *t)
1428 {
1429 t->size = 0;
1430 free(t->array);
1431 t->array = NULL;
1432 }
1433
1434 void sequence_push(sequence_t *t, void *elem)
1435 {
1436 void **tmp;
1437
1438 if(t->position >= t->size) {
1439 tmp = t->array;
1440 t->array = (void **)memAlloc(t->size * 2 * sizeof(void *));
1441 memcpy(t->array, tmp, t->size * sizeof(void *));
1442 t->size = t->size * 2;
1443 free(tmp);
1444 }
1445 t->array[t->position] = elem;
1446 t->position++;
1447 }
1448
1449 void *sequence_pop(sequence_t *t)
1450 {
1451 return t->array[t->position--];
1452 }
1453
1454
1455 /* Hash table API, implementation is just linear search for now */
1456
1457 void table_init(table_t *t)
1458 {
1459 sequence_init(&(t->keys));
1460 sequence_init(&(t->values));
1461 }
1462
1463 void table_dispose(table_t *t)
1464 {
1465 sequence_dispose(&(t->keys));
1466 sequence_dispose(&(t->values));
1467 }
1468
1469 void table_insert(table_t *t, char *key, void *value)
1470 {
1471 sequence_push(&(t->keys),key);
1472 sequence_push(&(t->values),value);
1473 }
1474
1475 void *table_find(table_t *t, char *key)
1476 {
1477 int pos;
1478 for(pos = 0 ; pos < t->keys.position; pos++) {
1479 if(strcmp((char *)key,(char *)t->keys.array[pos]) == 0)
1480 return(t->values.array[pos]);
1481 }
1482 return NULL;
1483 }
1484
1485 void table_insert_int(table_t *t, int *key, void *value)
1486 {
1487 sequence_push(&(t->keys),key);
1488 sequence_push(&(t->values),value);
1489 }
1490
1491 void *table_find_int(table_t *t, int *key)
1492 {
1493 int pos;
1494 for(pos = 0 ; pos < t->keys.position; pos++) {
1495 if(*key == *(int *)t->keys.array[pos])
1496 return(t->values.array[pos]);
1497 }
1498 return NULL;
1499 }
1500
1501
1502 /* Concatenate strings */
1503
1504 char *appendString(char *s, char *suffix)
1505 {
1506 char *tmp;
1507 if(suffix == NULL) return s;
1508
1509 tmp = (char *)memAlloc(strlen(s) + strlen(suffix) + 1);
1510 strcpy(tmp,s);
1511 strcat(tmp,suffix);
1512 return tmp;
1513 }
1514
1515
This page took 0.090657 seconds and 4 git commands to generate.