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