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