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