add func instrumentation
[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) 2005, Mathieu Desnoyers
7 Copyright (C) 2002, Xianxiu Yang
8 Copyright (C) 2002, Michel Dagenais
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 /* This program reads the ".xml" event definitions input files
24 and constructs structure for each event.
25
26 The program uses a very simple tokenizer, called from a hand written
27 recursive descent parser to fill a data structure describing the events.
28 The result is a sequence of events definitions which refer to type
29 definitions.
30
31 A table of named types is maintained to allow refering to types by name
32 when the same type is used at several places. Finally a sequence of
33 all types is maintained to facilitate the freeing of all type
34 information when the processing of an ".xml" file is finished. */
35
36 #include <stdlib.h>
37 #include <string.h>
38 #include <stdio.h>
39 #include <stdarg.h>
40 #include <linux/errno.h>
41 #include <assert.h>
42 #include <ctype.h>
43
44 #include "parser.h"
45
46
47 char *intOutputTypes[] = {
48 "int8_t", "int16_t", "int32_t", "int64_t" };
49
50 char *uintOutputTypes[] = {
51 "uint8_t", "uint16_t", "uint32_t", "uint64_t" };
52
53 char *floatOutputTypes[] = {
54 "undef", "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(unsigned 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 unsigned long long int getSize(parse_file_t *in)
98 {
99 char *token;
100 int has_quotes = 0;
101 unsigned long long int ret;
102
103 token = getToken(in);
104 if(token[0] == '"') {
105 has_quotes = 1;
106 token = getToken(in);
107 }
108 if(in->type == NUMBER) {
109 ret = strtoull(token, NULL, 0);
110 } else {
111 goto error;
112 }
113 if(has_quotes) {
114 token = getToken(in);
115 if(token[0] != '"') goto error;
116 }
117
118 return ret;
119 error:
120 in->error(in,"incorrect size specification");
121 return -1;
122 }
123
124 /*****************************************************************************
125 *Function name
126 * error_callback : print out error info
127 *Input params
128 * in : input file handle
129 * msg : message to be printed
130 ****************************************************************************/
131
132 void error_callback(parse_file_t *in, char *msg)
133 {
134 if(in)
135 printf("Error in file %s, line %d: %s\n", in->name, in->lineno, msg);
136 else
137 printf("%s\n",msg);
138 assert(0);
139 exit(1);
140 }
141
142 /*****************************************************************************
143 *Function name
144 * memAlloc : allocate memory
145 *Input params
146 * size : required memory size
147 *return value
148 * void * : pointer to allocate memory or NULL
149 ****************************************************************************/
150
151 void * memAlloc(int size)
152 {
153 void * addr;
154 if(size == 0) return NULL;
155 addr = malloc(size);
156 if(!addr){
157 printf("Failed to allocate memory");
158 exit(1);
159 }
160 return addr;
161 }
162
163 /*****************************************************************************
164 *Function name
165 * allocAndCopy : allocate memory and initialize it
166 *Input params
167 * str : string to be put in memory
168 *return value
169 * char * : pointer to allocate memory or NULL
170 ****************************************************************************/
171
172 char *allocAndCopy(char *str)
173 {
174 char * addr;
175 if(str == NULL) return NULL;
176 addr = (char *)memAlloc(strlen(str)+1);
177 strcpy(addr,str);
178 return addr;
179 }
180
181 /**************************************************************************
182 * Function :
183 * getTypeAttributes
184 * Description :
185 * Read the attribute from the input file.
186 *
187 * Parameters :
188 * in , input file handle.
189 * t , the type descriptor to fill.
190 *
191 **************************************************************************/
192
193 void getTypeAttributes(parse_file_t *in, type_descriptor_t *t,
194 sequence_t * unnamed_types, table_t * named_types)
195 {
196 char * token;
197
198 t->fmt = NULL;
199 t->size = 0;
200 t->custom_write = 0;
201 t->network = 0;
202
203 while(1) {
204 token = getToken(in);
205 if(strcmp("/",token) == 0 || strcmp(">",token) == 0){
206 ungetToken(in);
207 break;
208 }
209
210 if(!strcmp("format",token)) {
211 getEqual(in);
212 t->fmt = allocAndCopy(getQuotedString(in));
213 //} else if(!strcmp("name",token)) {
214 // getEqual(in);
215 // car = seekNextChar(in);
216 // if(car == EOF) in->error(in,"name was expected");
217 // else if(car == '\"') t->type_name = allocAndCopy(getQuotedString(in));
218 // else t->type_name = allocAndCopy(getName(in));
219 } else if(!strcmp("size",token)) {
220 getEqual(in);
221 t->size = getSize(in);
222 } else if(!strcmp("custom_write", token)) {
223 t->custom_write = 1;
224 } else if(!strcmp("network", token)) {
225 t->network = 1;
226 }
227 }
228 }
229
230 /**************************************************************************
231 * Function :
232 * getEventAttributes
233 * Description :
234 * Read the attribute from the input file.
235 *
236 * Parameters :
237 * in , input file handle.
238 * ev , the event to fill.
239 *
240 **************************************************************************/
241
242 void getEventAttributes(parse_file_t *in, event_t *ev)
243 {
244 char * token;
245 char car;
246
247 ev->name = NULL;
248 ev->per_trace = 0;
249 ev->per_tracefile = 0;
250 ev->param_buffer = 0;
251 ev->no_instrument_function = 0;
252
253 while(1) {
254 token = getToken(in);
255 if(strcmp("/",token) == 0 || strcmp(">",token) == 0){
256 ungetToken(in);
257 break;
258 }
259
260 if(!strcmp("name",token)) {
261 getEqual(in);
262 car = seekNextChar(in);
263 if(car == EOF) in->error(in,"name was expected");
264 else if(car == '\"') ev->name = allocAndCopy(getQuotedString(in));
265 else ev->name = allocAndCopy(getName(in));
266 } else if(!strcmp("per_trace", token)) {
267 ev->per_trace = 1;
268 } else if(!strcmp("per_tracefile", token)) {
269 ev->per_tracefile = 1;
270 } else if(!strcmp("param_buffer", token)) {
271 ev->param_buffer = 1;
272 } else if(!strcmp("no_instrument_function", token)) {
273 ev->no_instrument_function = 1;
274 }
275
276 }
277 }
278
279 /**************************************************************************
280 * Function :
281 * getFacilityAttributes
282 * Description :
283 * Read the attribute from the input file.
284 *
285 * Parameters :
286 * in , input file handle.
287 * fac , the facility to fill.
288 *
289 **************************************************************************/
290
291 void getFacilityAttributes(parse_file_t *in, facility_t *fac)
292 {
293 char * token;
294 char car;
295
296 fac->name = NULL;
297 fac->arch = NULL;
298 fac->user = 0;
299
300 while(1) {
301 token = getToken(in);
302 if(strcmp("/",token) == 0 || strcmp(">",token) == 0){
303 ungetToken(in);
304 break;
305 }
306
307 if(!strcmp("name",token)) {
308 getEqual(in);
309 car = seekNextChar(in);
310 if(car == EOF) in->error(in,"name was expected");
311 else if(car == '\"') fac->name = allocAndCopy(getQuotedString(in));
312 else fac->name = allocAndCopy(getName(in));
313 if(!strncmp(fac->name, "user_", sizeof("user_")) == 0)
314 fac->user = 1;
315 } else if(!strcmp("arch", token)) {
316 getEqual(in);
317 car = seekNextChar(in);
318 if(car == '\"') fac->name = allocAndCopy(getQuotedString(in));
319 else fac->arch = allocAndCopy(getName(in));
320 }
321 }
322 }
323
324 /**************************************************************************
325 * Function :
326 * getFieldAttributes
327 * Description :
328 * Read the attribute from the input file.
329 *
330 * Parameters :
331 * in , input file handle.
332 * f , the field to fill.
333 *
334 **************************************************************************/
335
336 void getFieldAttributes(parse_file_t *in, field_t *f)
337 {
338 char * token;
339 char car;
340
341 f->name = NULL;
342
343 while(1) {
344 token = getToken(in);
345 if(strcmp("/",token) == 0 || strcmp(">",token) == 0){
346 ungetToken(in);
347 break;
348 }
349
350 if(!strcmp("name",token)) {
351 getEqual(in);
352 car = seekNextChar(in);
353 if(car == EOF) in->error(in,"name was expected");
354 else if(car == '\"') f->name = allocAndCopy(getQuotedString(in));
355 else f->name = allocAndCopy(getName(in));
356 }
357 }
358 }
359
360 char *getNameAttribute(parse_file_t *in)
361 {
362 char * token;
363 char *name = NULL;
364 char car;
365
366 while(1) {
367 token = getToken(in);
368 if(!strcmp("name",token)) {
369 getEqual(in);
370 car = seekNextChar(in);
371 if(car == EOF) in->error(in,"name was expected");
372 else if(car == '\"') name = allocAndCopy(getQuotedString(in));
373 else name = allocAndCopy(getName(in));
374 } else {
375 ungetToken(in);
376 break;
377 }
378
379 }
380 if(name == NULL) in->error(in, "Name was expected");
381 return name;
382 }
383
384
385
386 //for <label name=label_name value=n format="..."/>, value is an option
387 //Return value : 0 : no value, 1 : has a value
388 int getValueAttribute(parse_file_t *in, long long *value)
389 {
390 char * token;
391 int has_quotes = 0;
392
393 token = getToken(in);
394 if(strcmp("/",token) == 0){
395 ungetToken(in);
396 return 0;
397 }
398
399 if(strcmp("value",token))in->error(in,"value was expected");
400 getEqual(in);
401 token = getToken(in);
402
403 if(token[0] == '"') {
404 has_quotes = 1;
405 token = getToken(in);
406 }
407 if(in->type == NUMBER) {
408 *value = strtoll(token, NULL, 0);
409 } else {
410 goto error;
411 }
412 if(has_quotes) {
413 token = getToken(in);
414 if(token[0] != '"') goto error;
415 }
416 return 1;
417
418 error:
419 in->error(in,"incorrect size specification");
420 return 0;
421 }
422
423 char * getDescription(parse_file_t *in)
424 {
425 long int pos;
426 char * token, car, *str;
427
428 pos = ftell(in->fp);
429
430 getLAnglebracket(in);
431 token = getName(in);
432 if(strcmp("description",token)){
433 fseek(in->fp, pos, SEEK_SET);
434 return NULL;
435 }
436
437 getRAnglebracket(in);
438
439 pos = 0;
440 while((car = getc(in->fp)) != EOF) {
441 if(car == '<') break;
442 if(car == '\0') continue;
443 in->buffer[pos] = car;
444 pos++;
445 }
446 if(car == EOF)in->error(in,"not a valid description");
447 in->buffer[pos] = '\0';
448
449 str = allocAndCopy(in->buffer);
450
451 getForwardslash(in);
452 token = getName(in);
453 if(strcmp("description", token))in->error(in,"not a valid description");
454 getRAnglebracket(in);
455
456 return str;
457 }
458
459 /*****************************************************************************
460 *Function name
461 * parseFacility : generate event list
462 *Input params
463 * in : input file handle
464 * fac : empty facility
465 *Output params
466 * fac : facility filled with event list
467 ****************************************************************************/
468
469 void parseFacility(parse_file_t *in, facility_t * fac)
470 {
471 char * token;
472 event_t *ev;
473
474 getFacilityAttributes(in, fac);
475 if(fac->name == NULL) in->error(in, "Attribute not named");
476
477 fac->capname = allocAndCopy(fac->name);
478 strupper(fac->capname);
479 getRAnglebracket(in);
480
481 fac->description = getDescription(in);
482
483 while(1){
484 getLAnglebracket(in);
485
486 token = getToken(in);
487 if(in->type == ENDFILE)
488 in->error(in,"the definition of the facility is not finished");
489
490 if(strcmp("event",token) == 0){
491 ev = (event_t*) memAlloc(sizeof(event_t));
492 sequence_push(&(fac->events),ev);
493 parseEvent(in,ev, &(fac->unnamed_types), &(fac->named_types));
494 }else if(strcmp("type",token) == 0){
495 parseTypeDefinition(in, &(fac->unnamed_types), &(fac->named_types));
496 }else if(in->type == FORWARDSLASH){
497 break;
498 }else in->error(in,"event or type token expected\n");
499 }
500
501 token = getName(in);
502 if(strcmp("facility",token)) in->error(in,"not the end of the facility");
503 getRAnglebracket(in); //</facility>
504 }
505
506 /*****************************************************************************
507 *Function name
508 * parseEvent : generate event from event definition
509 *Input params
510 * in : input file handle
511 * ev : new event
512 * unnamed_types : array of unamed types
513 * named_types : array of named types
514 *Output params
515 * ev : new event (parameters are passed to it)
516 ****************************************************************************/
517
518 void parseEvent(parse_file_t *in, event_t * ev, sequence_t * unnamed_types,
519 table_t * named_types)
520 {
521 char *token;
522 field_t *f;
523
524 sequence_init(&(ev->fields));
525 //<event name=eventtype_name>
526 getEventAttributes(in, ev);
527 if(ev->name == NULL) in->error(in, "Event not named");
528 getRAnglebracket(in);
529
530 //<description>...</description>
531 ev->description = getDescription(in);
532
533 int got_end = 0;
534 /* Events can have multiple fields. each field form at least a function
535 * parameter of the logging function. */
536 while(!got_end) {
537 getLAnglebracket(in);
538 token = getToken(in);
539
540 switch(in->type) {
541 case FORWARDSLASH: /* </event> */
542 token = getName(in);
543 if(strcmp("event",token))in->error(in,"not an event definition");
544 getRAnglebracket(in); //</event>
545 got_end = 1;
546 break;
547 case NAME: /* a field */
548 if(strcmp("field",token))in->error(in,"expecting a field");
549 f = (field_t *)memAlloc(sizeof(field_t));
550 sequence_push(&(ev->fields),f);
551 parseFields(in, f, unnamed_types, named_types, 1);
552 break;
553 default:
554 in->error(in, "expecting </event> or <field >");
555 break;
556 }
557 }
558 #if 0
559 if(in->type == FORWARDSLASH){ //</event> NOTHING
560 ev->type = NULL;
561 }else if(in->type == NAME){
562 if(strcmp("struct",token)==0 || strcmp("typeref",token)==0){
563 ungetToken(in);
564 ev->type = parseType(in,NULL, unnamed_types, named_types);
565 if(ev->type->type != STRUCT && ev->type->type != NONE)
566 in->error(in,"type must be a struct");
567 }else in->error(in, "not a valid type");
568
569 getLAnglebracket(in);
570 getForwardslash(in);
571 }else in->error(in,"not a struct type");
572 getLAnglebracket(in);
573 getForwardslash(in);
574 token = getName(in);
575 if(strcmp("event",token))in->error(in,"not an event definition");
576 getRAnglebracket(in); //</event>
577 #endif //0
578 }
579
580 /*****************************************************************************
581 *Function name
582 * parseField : get field infomation from buffer
583 *Input params
584 * in : input file handle
585 * f : field
586 * unnamed_types : array of unamed types
587 * named_types : array of named types
588 * tag : is field surrounded by a <field> </field> tag ?
589 ****************************************************************************/
590
591 void parseFields(parse_file_t *in, field_t *f,
592 sequence_t * unnamed_types,
593 table_t * named_types,
594 int tag)
595 {
596 char * token;
597 if(tag) {
598 //<field name=field_name> <description> <type> </field>
599 getFieldAttributes(in, f);
600 if(f->name == NULL) in->error(in, "Field not named");
601 getRAnglebracket(in);
602
603 f->description = getDescription(in);
604 } else {
605 f->description = NULL;
606 }
607
608 //<int size=...>
609 getLAnglebracket(in);
610 f->type = parseType(in,NULL, unnamed_types, named_types);
611
612 if(tag) {
613 getLAnglebracket(in);
614 getForwardslash(in);
615 token = getName(in);
616 if(strcmp("field",token))in->error(in,"not a valid field definition");
617 getRAnglebracket(in); //</field>
618 }
619 }
620
621
622 /*****************************************************************************
623 *Function name
624 * parseType : get type information, type can be :
625 * Primitive:
626 * int(size,fmt); uint(size,fmt); float(size,fmt);
627 * string(fmt); enum(size,fmt,(label1,label2...))
628 * Compound:
629 * array(arraySize, type); sequence(lengthSize,type)
630 * struct(field(name,type,description)...)
631 * type name:
632 * type(name,type)
633 *Input params
634 * in : input file handle
635 * inType : a type descriptor
636 * unnamed_types : array of unamed types
637 * named_types : array of named types
638 *Return values
639 * type_descriptor* : a type descriptor
640 ****************************************************************************/
641
642 type_descriptor_t *parseType(parse_file_t *in, type_descriptor_t *inType,
643 sequence_t * unnamed_types, table_t * named_types)
644 {
645 char *token;
646 type_descriptor_t *t;
647 field_t *f;
648
649 if(inType == NULL) {
650 t = (type_descriptor_t *) memAlloc(sizeof(type_descriptor_t));
651 t->type_name = NULL;
652 t->type = NONE;
653 t->fmt = NULL;
654 sequence_push(unnamed_types,t);
655 }
656 else t = inType;
657
658 token = getName(in);
659
660 if(strcmp(token,"struct") == 0) {
661 t->type = STRUCT;
662 getTypeAttributes(in, t, unnamed_types, named_types);
663 getRAnglebracket(in); //<struct>
664 getLAnglebracket(in); //<field name=..>
665 token = getToken(in);
666 sequence_init(&(t->fields));
667 while(strcmp("field",token) == 0){
668 f = (field_t *)memAlloc(sizeof(field_t));
669 sequence_push(&(t->fields),f);
670
671 parseFields(in, f, unnamed_types, named_types, 1);
672
673 //next field
674 getLAnglebracket(in);
675 token = getToken(in);
676 }
677 if(strcmp("/",token))in->error(in,"not a valid structure definition");
678 token = getName(in);
679 if(strcmp("struct",token)!=0)
680 in->error(in,"not a valid structure definition");
681 getRAnglebracket(in); //</struct>
682 }
683 else if(strcmp(token,"union") == 0) {
684 t->type = UNION;
685 getTypeAttributes(in, t, unnamed_types, named_types);
686 getRAnglebracket(in); //<union>
687
688 getLAnglebracket(in); //<field name=..>
689 token = getToken(in);
690 sequence_init(&(t->fields));
691 while(strcmp("field",token) == 0){
692 f = (field_t *)memAlloc(sizeof(field_t));
693 sequence_push(&(t->fields),f);
694 parseFields(in, f, unnamed_types, named_types, 1);
695
696 //next field
697 getLAnglebracket(in);
698 token = getToken(in);
699 }
700 if(strcmp("/",token))in->error(in,"not a valid union definition");
701 token = getName(in);
702 if(strcmp("union",token)!=0)
703 in->error(in,"not a valid union definition");
704 getRAnglebracket(in); //</union>
705 }
706 else if(strcmp(token,"array") == 0) {
707 t->type = ARRAY;
708 sequence_init(&(t->fields));
709 getTypeAttributes(in, t, unnamed_types, named_types);
710 if(t->size == 0) in->error(in, "Array has empty size");
711 getForwardslash(in);
712 getRAnglebracket(in); //<array size=n>
713
714 //getLAnglebracket(in); //<subtype>
715 /* subfield */
716 f = (field_t *)memAlloc(sizeof(field_t));
717 sequence_push(&(t->fields),f);
718 parseFields(in, f, unnamed_types, named_types, 0);
719
720 //getLAnglebracket(in); //<type struct>
721 //t->nested_type = parseType(in, NULL, unnamed_types, named_types);
722
723 getLAnglebracket(in); //</array>
724 getForwardslash(in);
725 token = getName(in);
726 if(strcmp("array",token))in->error(in,"not a valid array definition");
727 getRAnglebracket(in); //</array>
728 }
729 else if(strcmp(token,"sequence") == 0) {
730 t->type = SEQUENCE;
731 sequence_init(&(t->fields));
732 getTypeAttributes(in, t, unnamed_types, named_types);
733 getForwardslash(in);
734 getRAnglebracket(in); //<sequence>
735
736 //getLAnglebracket(in); //<sequence size type>
737 /* subfield */
738 f = (field_t *)memAlloc(sizeof(field_t));
739 sequence_push(&(t->fields),f);
740 parseFields(in, f, unnamed_types, named_types, 0);
741
742 //getLAnglebracket(in); //<subtype>
743 /* subfield */
744 f = (field_t *)memAlloc(sizeof(field_t));
745 sequence_push(&(t->fields),f);
746 parseFields(in, f, unnamed_types, named_types, 0);
747
748 //getLAnglebracket(in); //<type sequence>
749 //t->length_type = parseType(in, NULL, unnamed_types, named_types);
750
751 //getLAnglebracket(in); //<type sequence>
752
753 //t->nested_type = parseType(in, NULL, unnamed_types, named_types);
754
755 if(t->fields.position < 1) in->error(in, "Sequence has no length type");
756 if(t->fields.position < 2) in->error(in, "Sequence has no subtype");
757 switch(((field_t*)t->fields.array[0])->type->type) {
758 case UINT_FIXED :
759 case UCHAR :
760 case USHORT :
761 case UINT :
762 case ULONG :
763 case SIZE_T :
764 case OFF_T :
765 break;
766 default:
767 in->error(in, "Wrong length type for sequence");
768 }
769
770 getLAnglebracket(in); //</sequence>
771 getForwardslash(in);
772 token = getName(in);
773 if(strcmp("sequence",token))in->error(in,"not a valid sequence definition");
774 getRAnglebracket(in); //</sequence>
775 }
776 else if(strcmp(token,"enum") == 0) {
777 char * str;
778 long long value = -1;
779
780 t->type = ENUM;
781 sequence_init(&(t->labels));
782 sequence_init(&(t->labels_values));
783 sequence_init(&(t->labels_description));
784 t->already_printed = 0;
785 getTypeAttributes(in, t, unnamed_types, named_types);
786 //if(t->size == 0) in->error(in, "Sequence has empty size");
787 //Mathieu : we fix enum size to target int size. GCC is always like this.
788 //fox copy optimisation.
789 if(t->size != 0) in->error(in, "Enum has fixed size of target int.");
790 t->size = 0;
791 getRAnglebracket(in);
792
793 //<label name=label1 value=n/>
794 getLAnglebracket(in);
795 token = getToken(in); //"label" or "/"
796 while(strcmp("label",token) == 0){
797 int *label_value = malloc(sizeof(int));
798 int has_value = 0;
799 long long loc_value;
800
801 str = allocAndCopy(getNameAttribute(in));
802 has_value = getValueAttribute(in, &loc_value);
803
804 sequence_push(&(t->labels),str);
805
806 if(has_value) value = loc_value;
807 else value++;
808
809 *label_value = value;
810 sequence_push(&(t->labels_values), label_value);
811
812 getForwardslash(in);
813 getRAnglebracket(in);
814
815 //read description if any. May be NULL.
816 str = allocAndCopy(getDescription(in));
817 sequence_push(&(t->labels_description),str);
818
819 //next label definition
820 getLAnglebracket(in);
821 token = getToken(in); //"label" or "/"
822 }
823 if(strcmp("/",token))in->error(in, "not a valid enum definition");
824 token = getName(in);
825 if(strcmp("enum",token))in->error(in, "not a valid enum definition");
826 getRAnglebracket(in); //</label>
827 }
828 else if(strcmp(token,"int_fixed") == 0) {
829 t->type = INT_FIXED;
830 getTypeAttributes(in, t, unnamed_types, named_types);
831 if(t->size == 0) in->error(in, "int has empty size");
832 getForwardslash(in);
833 getRAnglebracket(in);
834 }
835 else if(strcmp(token,"uint_fixed") == 0) {
836 t->type = UINT_FIXED;
837 getTypeAttributes(in, t, unnamed_types, named_types);
838 if(t->size == 0) in->error(in, "uint has empty size");
839 getForwardslash(in);
840 getRAnglebracket(in);
841 }
842 else if(strcmp(token,"char") == 0) {
843 t->type = CHAR;
844 getTypeAttributes(in, t, unnamed_types, named_types);
845 t->size = 1;
846 getForwardslash(in);
847 getRAnglebracket(in);
848 }
849 else if(strcmp(token,"uchar") == 0) {
850 t->type = UCHAR;
851 getTypeAttributes(in, t, unnamed_types, named_types);
852 t->size = 1;
853 getForwardslash(in);
854 getRAnglebracket(in);
855 }
856 else if(strcmp(token,"short") == 0) {
857 t->type = SHORT;
858 getTypeAttributes(in, t, unnamed_types, named_types);
859 t->size = 2;
860 getForwardslash(in);
861 getRAnglebracket(in);
862 }
863 else if(strcmp(token,"ushort") == 0) {
864 t->type = USHORT;
865 getTypeAttributes(in, t, unnamed_types, named_types);
866 t->size = 2;
867 getForwardslash(in);
868 getRAnglebracket(in);
869 }
870 else if(strcmp(token,"int") == 0) {
871 t->type = INT;
872 getTypeAttributes(in, t, unnamed_types, named_types);
873 getForwardslash(in);
874 getRAnglebracket(in);
875 }
876 else if(strcmp(token,"uint") == 0) {
877 t->type = UINT;
878 getTypeAttributes(in, t, unnamed_types, named_types);
879 getForwardslash(in);
880 getRAnglebracket(in);
881 }
882
883 else if(strcmp(token,"pointer") == 0) {
884 t->type = POINTER;
885 getTypeAttributes(in, t, unnamed_types, named_types);
886 getForwardslash(in);
887 getRAnglebracket(in);
888 }
889 else if(strcmp(token,"long") == 0) {
890 t->type = LONG;
891 getTypeAttributes(in, t, unnamed_types, named_types);
892 getForwardslash(in);
893 getRAnglebracket(in);
894 }
895 else if(strcmp(token,"ulong") == 0) {
896 t->type = ULONG;
897 getTypeAttributes(in, t, unnamed_types, named_types);
898 getForwardslash(in);
899 getRAnglebracket(in);
900 }
901 else if(strcmp(token,"size_t") == 0) {
902 t->type = SIZE_T;
903 getTypeAttributes(in, t, unnamed_types, named_types);
904 getForwardslash(in);
905 getRAnglebracket(in);
906 }
907 else if(strcmp(token,"ssize_t") == 0) {
908 t->type = SSIZE_T;
909 getTypeAttributes(in, t, unnamed_types, named_types);
910 getForwardslash(in);
911 getRAnglebracket(in);
912 }
913 else if(strcmp(token,"off_t") == 0) {
914 t->type = OFF_T;
915 getTypeAttributes(in, t, unnamed_types, named_types);
916 getForwardslash(in);
917 getRAnglebracket(in);
918 }
919 else if(strcmp(token,"float") == 0) {
920 t->type = FLOAT;
921 getTypeAttributes(in, t, unnamed_types, named_types);
922 getForwardslash(in);
923 getRAnglebracket(in);
924 }
925 else if(strcmp(token,"string") == 0) {
926 t->type = STRING;
927 getTypeAttributes(in, t, unnamed_types, named_types);
928 getForwardslash(in);
929 getRAnglebracket(in);
930 }
931 else if(strcmp(token,"typeref") == 0){
932 // Must be a named type
933 free(t);
934 sequence_pop(unnamed_types);
935 token = getNameAttribute(in);
936 t = find_named_type(token, named_types);
937 if(t == NULL) in->error(in,"Named referred to must be pre-declared.");
938 getForwardslash(in); //<typeref name=type_name/>
939 getRAnglebracket(in);
940 return t;
941 }else in->error(in,"not a valid type");
942
943 return t;
944 }
945
946 /*****************************************************************************
947 *Function name
948 * find_named_type : find a named type from hash table
949 *Input params
950 * name : type name
951 * named_types : array of named types
952 *Return values
953 * type_descriptor * : a type descriptor
954 *****************************************************************************/
955
956 type_descriptor_t * find_named_type(char *name, table_t * named_types)
957 {
958 type_descriptor_t *t;
959
960 t = table_find(named_types,name);
961
962 return t;
963 }
964
965 type_descriptor_t * create_named_type(char *name, table_t * named_types)
966 {
967 type_descriptor_t *t;
968
969 t = (type_descriptor_t *)memAlloc(sizeof(type_descriptor_t));
970 t->type_name = allocAndCopy(name);
971 t->type = NONE;
972 t->fmt = NULL;
973 table_insert(named_types,t->type_name,t);
974 // table_insert(named_types,allocAndCopy(name),t);
975 return t;
976 }
977
978 /*****************************************************************************
979 *Function name
980 * parseTypeDefinition : get type information from type definition
981 *Input params
982 * in : input file handle
983 * unnamed_types : array of unamed types
984 * named_types : array of named types
985 *****************************************************************************/
986
987 void parseTypeDefinition(parse_file_t * in, sequence_t * unnamed_types,
988 table_t * named_types)
989 {
990 char *token;
991 type_descriptor_t *t;
992
993 token = getNameAttribute(in);
994 if(token == NULL) in->error(in, "Type has empty name");
995 t = create_named_type(token, named_types);
996
997 if(t->type != NONE) in->error(in,"redefinition of named type");
998 getRAnglebracket(in); //<type name=type_name>
999 getLAnglebracket(in); //<
1000 token = getName(in);
1001 //MD ??if(strcmp("struct",token))in->error(in,"not a valid type definition");
1002 ungetToken(in);
1003 parseType(in,t, unnamed_types, named_types);
1004
1005 //</type>
1006 getLAnglebracket(in);
1007 getForwardslash(in);
1008 token = getName(in);
1009 if(strcmp("type",token))in->error(in,"not a valid type definition");
1010 getRAnglebracket(in); //</type>
1011 }
1012
1013 /**************************************************************************
1014 * Function :
1015 * getComa, getName, getNumber, getEqual
1016 * Description :
1017 * Read a token from the input file, check its type, return it scontent.
1018 *
1019 * Parameters :
1020 * in , input file handle.
1021 *
1022 * Return values :
1023 * address of token content.
1024 *
1025 **************************************************************************/
1026
1027 char *getName(parse_file_t * in)
1028 {
1029 char *token;
1030
1031 token = getToken(in);
1032 // Optional descriptions
1033 // if(in->type != NAME) in->error(in,"Name token was expected");
1034 return token;
1035 }
1036
1037 int getNumber(parse_file_t * in)
1038 {
1039 char *token;
1040
1041 token = getToken(in);
1042 if(in->type != NUMBER) in->error(in, "Number token was expected");
1043 return atoi(token);
1044 }
1045
1046 char *getForwardslash(parse_file_t * in)
1047 {
1048 char *token;
1049
1050 token = getToken(in);
1051 //if(in->type != FORWARDSLASH) in->error(in, "forward slash token was expected");
1052 /* Mathieu : final / is optional now. */
1053 if(in->type != FORWARDSLASH) ungetToken(in);
1054
1055 return token;
1056 }
1057
1058 char *getLAnglebracket(parse_file_t * in)
1059 {
1060 char *token;
1061
1062 token = getToken(in);
1063 if(in->type != LANGLEBRACKET) in->error(in, "Left angle bracket was expected");
1064 return token;
1065 }
1066
1067 char *getRAnglebracket(parse_file_t * in)
1068 {
1069 char *token;
1070
1071 token = getToken(in);
1072 if(in->type != RANGLEBRACKET) in->error(in, "Right angle bracket was expected");
1073 return token;
1074 }
1075
1076 char *getQuotedString(parse_file_t * in)
1077 {
1078 char *token;
1079
1080 token = getToken(in);
1081 if(in->type != QUOTEDSTRING) in->error(in, "quoted string was expected");
1082 return token;
1083 }
1084
1085 char * getEqual(parse_file_t *in)
1086 {
1087 char *token;
1088
1089 token = getToken(in);
1090 if(in->type != EQUAL) in->error(in, "equal was expected");
1091 return token;
1092 }
1093
1094 char seekNextChar(parse_file_t *in)
1095 {
1096 char car;
1097 while((car = getc(in->fp)) != EOF) {
1098 if(!isspace(car)){
1099 ungetc(car,in->fp);
1100 return car;
1101 }
1102 }
1103 return EOF;
1104 }
1105
1106 /******************************************************************
1107 * Function :
1108 * getToken, ungetToken
1109 * Description :
1110 * Read a token from the input file and return its type and content.
1111 * Line numbers are accounted for and whitespace/comments are skipped.
1112 *
1113 * Parameters :
1114 * in, input file handle.
1115 *
1116 * Return values :
1117 * address of token content.
1118 *
1119 ******************************************************************/
1120
1121 void ungetToken(parse_file_t * in)
1122 {
1123 in->unget = 1;
1124 }
1125
1126 char *getToken(parse_file_t * in)
1127 {
1128 FILE *fp = in->fp;
1129 char car, car1;
1130 int pos = 0, escaped;
1131
1132 if(in->unget == 1) {
1133 in->unget = 0;
1134 return in->buffer;
1135 }
1136
1137 /* skip whitespace and comments */
1138
1139 while((car = getc(fp)) != EOF) {
1140 if(car == '/') {
1141 car1 = getc(fp);
1142 if(car1 == '*') skipComment(in);
1143 else if(car1 == '/') skipEOL(in);
1144 else {
1145 car1 = ungetc(car1,fp);
1146 break;
1147 }
1148 }
1149 else if(car == '\n') in->lineno++;
1150 else if(!isspace(car)) break;
1151 }
1152
1153 switch(car) {
1154 case EOF:
1155 in->type = ENDFILE;
1156 break;
1157 case '/':
1158 in->type = FORWARDSLASH;
1159 in->buffer[pos] = car;
1160 pos++;
1161 break;
1162 case '<':
1163 in->type = LANGLEBRACKET;
1164 in->buffer[pos] = car;
1165 pos++;
1166 break;
1167 case '>':
1168 in->type = RANGLEBRACKET;
1169 in->buffer[pos] = car;
1170 pos++;
1171 break;
1172 case '=':
1173 in->type = EQUAL;
1174 in->buffer[pos] = car;
1175 pos++;
1176 break;
1177 case '"':
1178 escaped = 0;
1179 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
1180 if(car == '\\' && escaped == 0) {
1181 in->buffer[pos] = car;
1182 pos++;
1183 escaped = 1;
1184 continue;
1185 }
1186 if(car == '"' && escaped == 0) break;
1187 if(car == '\n' && escaped == 0) {
1188 in->error(in, "non escaped newline inside quoted string");
1189 }
1190 if(car == '\n') in->lineno++;
1191 in->buffer[pos] = car;
1192 pos++;
1193 escaped = 0;
1194 }
1195 if(car == EOF) in->error(in,"no ending quotemark");
1196 if(pos == BUFFER_SIZE) in->error(in, "quoted string token too large");
1197 in->type = QUOTEDSTRING;
1198 break;
1199 default:
1200 if(isdigit(car)) {
1201 in->buffer[pos] = car;
1202 pos++;
1203 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
1204 if(!isdigit(car)) {
1205 ungetc(car,fp);
1206 break;
1207 }
1208 in->buffer[pos] = car;
1209 pos++;
1210 }
1211 if(car == EOF) ungetc(car,fp);
1212 if(pos == BUFFER_SIZE) in->error(in, "number token too large");
1213 in->type = NUMBER;
1214 }
1215 else if(isalnum(car) || car == '_' || car == '-') {
1216 in->buffer[0] = car;
1217 pos = 1;
1218 while((car = getc(fp)) != EOF && pos < BUFFER_SIZE) {
1219 if(!(isalnum(car) || car == '_' || car == '-')) {
1220 ungetc(car,fp);
1221 break;
1222 }
1223 in->buffer[pos] = car;
1224 pos++;
1225 }
1226 if(car == EOF) ungetc(car,fp);
1227 if(pos == BUFFER_SIZE) in->error(in, "name token too large");
1228 in->type = NAME;
1229 }
1230 else in->error(in, "invalid character, unrecognized token");
1231 }
1232 in->buffer[pos] = 0;
1233 return in->buffer;
1234 }
1235
1236 void skipComment(parse_file_t * in)
1237 {
1238 char car;
1239 while((car = getc(in->fp)) != EOF) {
1240 if(car == '\n') in->lineno++;
1241 else if(car == '*') {
1242 car = getc(in->fp);
1243 if(car ==EOF) break;
1244 if(car == '/') return;
1245 ungetc(car,in->fp);
1246 }
1247 }
1248 if(car == EOF) in->error(in,"comment begining with '/*' has no ending '*/'");
1249 }
1250
1251 void skipEOL(parse_file_t * in)
1252 {
1253 char car;
1254 while((car = getc(in->fp)) != EOF) {
1255 if(car == '\n') {
1256 ungetc(car,in->fp);
1257 break;
1258 }
1259 }
1260 if(car == EOF)ungetc(car, in->fp);
1261 }
1262
1263 /*****************************************************************************
1264 *Function name
1265 * checkNamedTypesImplemented : check if all named types have definition
1266 ****************************************************************************/
1267
1268 void checkNamedTypesImplemented(table_t * named_types)
1269 {
1270 type_descriptor_t *t;
1271 int pos;
1272 char str[256];
1273
1274 for(pos = 0 ; pos < named_types->values.position; pos++) {
1275 t = (type_descriptor_t *) named_types->values.array[pos];
1276 if(t->type == NONE){
1277 sprintf(str,"named type '%s' has no definition",
1278 (char*)named_types->keys.array[pos]);
1279 error_callback(NULL,str);
1280 }
1281 }
1282 }
1283
1284
1285 /*****************************************************************************
1286 *Function name
1287 * generateChecksum : generate checksum for the facility
1288 *Input Params
1289 * facName : name of facility
1290 *Output Params
1291 * checksum : checksum for the facility
1292 ****************************************************************************/
1293
1294 void generateChecksum(char* facName,
1295 unsigned int * checksum, sequence_t * events)
1296 {
1297 unsigned long crc ;
1298 int pos;
1299 event_t * ev;
1300 unsigned int i;
1301
1302 crc = crc32(facName);
1303 for(pos = 0; pos < events->position; pos++){
1304 ev = (event_t *)(events->array[pos]);
1305 crc = partial_crc32(ev->name, crc);
1306 for(i = 0; i < ev->fields.position; i++) {
1307 field_t *f = (field_t*)ev->fields.array[i];
1308 crc = partial_crc32(f->name, crc);
1309 crc = getTypeChecksum(crc, f->type);
1310 }
1311 }
1312 *checksum = crc;
1313 }
1314
1315 /*****************************************************************************
1316 *Function name
1317 * getTypeChecksum : generate checksum by type info
1318 *Input Params
1319 * crc : checksum generated so far
1320 * type : type descriptor containing type info
1321 *Return value
1322 * unsigned long : checksum
1323 *****************************************************************************/
1324
1325 unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor_t * type)
1326 {
1327 unsigned long crc = aCrc;
1328 char * str = NULL, buf[16];
1329 int flag = 0, pos;
1330 field_t * fld;
1331
1332 switch(type->type){
1333 case INT_FIXED:
1334 str = intOutputTypes[getSizeindex(type->size)];
1335 break;
1336 case UINT_FIXED:
1337 str = uintOutputTypes[getSizeindex(type->size)];
1338 break;
1339 case POINTER:
1340 str = allocAndCopy("void *");
1341 flag = 1;
1342 break;
1343 case CHAR:
1344 str = allocAndCopy("signed char");
1345 flag = 1;
1346 break;
1347 case UCHAR:
1348 str = allocAndCopy("unsigned char");
1349 flag = 1;
1350 break;
1351 case SHORT:
1352 str = allocAndCopy("short");
1353 flag = 1;
1354 break;
1355 case USHORT:
1356 str = allocAndCopy("unsigned short");
1357 flag = 1;
1358 break;
1359 case INT:
1360 str = allocAndCopy("int");
1361 flag = 1;
1362 break;
1363 case UINT:
1364 str = allocAndCopy("uint");
1365 flag = 1;
1366 break;
1367 case LONG:
1368 str = allocAndCopy("long");
1369 flag = 1;
1370 break;
1371 case ULONG:
1372 str = allocAndCopy("unsigned long");
1373 flag = 1;
1374 break;
1375 case SIZE_T:
1376 str = allocAndCopy("size_t");
1377 flag = 1;
1378 break;
1379 case SSIZE_T:
1380 str = allocAndCopy("ssize_t");
1381 flag = 1;
1382 break;
1383 case OFF_T:
1384 str = allocAndCopy("off_t");
1385 flag = 1;
1386 break;
1387 case FLOAT:
1388 str = floatOutputTypes[getSizeindex(type->size)];
1389 break;
1390 case STRING:
1391 str = allocAndCopy("string");
1392 flag = 1;
1393 break;
1394 case ENUM:
1395 //str = appendString("enum ", uintOutputTypes[getSizeindex(type->size)]);
1396 str = allocAndCopy("enum");
1397 flag = 1;
1398 break;
1399 case ARRAY:
1400 sprintf(buf,"%zu", type->size);
1401 str = appendString("array ",buf);
1402 flag = 1;
1403 break;
1404 case SEQUENCE:
1405 str = allocAndCopy("sequence ");
1406 flag = 1;
1407 break;
1408 case STRUCT:
1409 str = allocAndCopy("struct");
1410 flag = 1;
1411 break;
1412 case UNION:
1413 str = allocAndCopy("union");
1414 flag = 1;
1415 break;
1416 default:
1417 error_callback(NULL, "named type has no definition");
1418 break;
1419 }
1420
1421 crc = partial_crc32(str,crc);
1422 if(flag) free(str);
1423
1424 if(type->fmt) crc = partial_crc32(type->fmt,crc);
1425
1426 if(type->type == ARRAY){
1427 crc = getTypeChecksum(crc,((field_t*)type->fields.array[0])->type);
1428 } else if(type->type ==SEQUENCE) {
1429 crc = getTypeChecksum(crc,((field_t*)type->fields.array[0])->type);
1430 crc = getTypeChecksum(crc,((field_t*)type->fields.array[1])->type);
1431 } else if(type->type == STRUCT || type->type == UNION){
1432 for(pos =0; pos < type->fields.position; pos++){
1433 fld = (field_t *) type->fields.array[pos];
1434 crc = partial_crc32(fld->name,crc);
1435 crc = getTypeChecksum(crc, fld->type);
1436 }
1437 }else if(type->type == ENUM){
1438 for(pos = 0; pos < type->labels.position; pos++)
1439 crc = partial_crc32((char*)type->labels.array[pos],crc);
1440 }
1441
1442 return crc;
1443 }
1444
1445
1446 /* Event type descriptors */
1447 void freeType(type_descriptor_t * tp)
1448 {
1449 int pos2;
1450 field_t *f;
1451
1452 if(tp->fmt != NULL) free(tp->fmt);
1453 if(tp->type == ENUM) {
1454 for(pos2 = 0; pos2 < tp->labels.position; pos2++) {
1455 free(tp->labels.array[pos2]);
1456 }
1457 sequence_dispose(&(tp->labels));
1458 for(pos2 = 0; pos2 < tp->labels_values.position; pos2++) {
1459 free(tp->labels_values.array[pos2]);
1460 }
1461 sequence_dispose(&(tp->labels_values));
1462 }
1463 if(tp->type == STRUCT) {
1464 for(pos2 = 0; pos2 < tp->fields.position; pos2++) {
1465 f = (field_t *) tp->fields.array[pos2];
1466 free(f->name);
1467 free(f->description);
1468 free(f);
1469 }
1470 sequence_dispose(&(tp->fields));
1471 }
1472 }
1473
1474 void freeNamedType(table_t * t)
1475 {
1476 int pos;
1477 type_descriptor_t * td;
1478
1479 for(pos = 0 ; pos < t->keys.position; pos++) {
1480 free((char *)t->keys.array[pos]);
1481 td = (type_descriptor_t*)t->values.array[pos];
1482 freeType(td);
1483 free(td);
1484 }
1485 }
1486
1487 void freeTypes(sequence_t *t)
1488 {
1489 int pos;
1490 type_descriptor_t *tp;
1491
1492 for(pos = 0 ; pos < t->position; pos++) {
1493 tp = (type_descriptor_t *)t->array[pos];
1494 freeType(tp);
1495 free(tp);
1496 }
1497 }
1498
1499 void freeEvents(sequence_t *t)
1500 {
1501 int pos;
1502 event_t *ev;
1503
1504 for(pos = 0 ; pos < t->position; pos++) {
1505 ev = (event_t *) t->array[pos];
1506 free(ev->name);
1507 free(ev->description);
1508 sequence_dispose(&ev->fields);
1509 free(ev);
1510 }
1511
1512 }
1513
1514
1515 /* Extensible array */
1516
1517 void sequence_init(sequence_t *t)
1518 {
1519 t->size = 10;
1520 t->position = 0;
1521 t->array = (void **)memAlloc(t->size * sizeof(void *));
1522 }
1523
1524 void sequence_dispose(sequence_t *t)
1525 {
1526 t->size = 0;
1527 free(t->array);
1528 t->array = NULL;
1529 }
1530
1531 void sequence_push(sequence_t *t, void *elem)
1532 {
1533 void **tmp;
1534
1535 if(t->position >= t->size) {
1536 tmp = t->array;
1537 t->array = (void **)memAlloc(t->size * 2 * sizeof(void *));
1538 memcpy(t->array, tmp, t->size * sizeof(void *));
1539 t->size = t->size * 2;
1540 free(tmp);
1541 }
1542 t->array[t->position] = elem;
1543 t->position++;
1544 }
1545
1546 void *sequence_pop(sequence_t *t)
1547 {
1548 if(t->position == 0) printf("Error : trying to pop an empty sequence");
1549 return t->array[--t->position];
1550 }
1551
1552
1553 /* Hash table API, implementation is just linear search for now */
1554
1555 void table_init(table_t *t)
1556 {
1557 sequence_init(&(t->keys));
1558 sequence_init(&(t->values));
1559 }
1560
1561 void table_dispose(table_t *t)
1562 {
1563 sequence_dispose(&(t->keys));
1564 sequence_dispose(&(t->values));
1565 }
1566
1567 void table_insert(table_t *t, char *key, void *value)
1568 {
1569 sequence_push(&(t->keys),key);
1570 sequence_push(&(t->values),value);
1571 }
1572
1573 void *table_find(table_t *t, char *key)
1574 {
1575 int pos;
1576 for(pos = 0 ; pos < t->keys.position; pos++) {
1577 if(strcmp((char *)key,(char *)t->keys.array[pos]) == 0)
1578 return(t->values.array[pos]);
1579 }
1580 return NULL;
1581 }
1582
1583 void table_insert_int(table_t *t, int *key, void *value)
1584 {
1585 sequence_push(&(t->keys),key);
1586 sequence_push(&(t->values),value);
1587 }
1588
1589 void *table_find_int(table_t *t, int *key)
1590 {
1591 int pos;
1592 for(pos = 0 ; pos < t->keys.position; pos++) {
1593 if(*key == *(int *)t->keys.array[pos])
1594 return(t->values.array[pos]);
1595 }
1596 return NULL;
1597 }
1598
1599
1600 /* Concatenate strings */
1601
1602 char *appendString(char *s, char *suffix)
1603 {
1604 char *tmp;
1605 if(suffix == NULL) return s;
1606
1607 tmp = (char *)memAlloc(strlen(s) + strlen(suffix) + 1);
1608 strcpy(tmp,s);
1609 strcat(tmp,suffix);
1610 return tmp;
1611 }
This page took 0.064285 seconds and 5 git commands to generate.