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