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