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