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