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