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