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