large files support
[lttv.git] / ltt / branches / poly / ltt / parser.c
... / ...
CommitLineData
1/*
2
3parser.c: Generate helper declarations and functions to trace events
4 from an event description file.
5
6Copyright (C) 2002, Xianxiu Yang
7Copyright (C) 2002, Michel Dagenais
8Copyright (C) 2005, Mathieu Desnoyers
9
10This 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
12the Free Software Foundation; version 2 of the License.
13
14This 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
57int 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
85void 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
108gchar * 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
126char * 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
143int getSizeAttribute(parse_file *in)
144{
145 /* skip name and equal */
146 getName(in);
147 getEqual(in);
148
149 return getSize(in);
150}
151
152int 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
162char * 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
179char * 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
238void 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
283void 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
328void 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
375type_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
548type_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
573void 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
612char *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
621int 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
630char *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
639char *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
648char *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
657char *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
666char * 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
675gunichar 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
722void ungetToken(parse_file * in)
723{
724 in->unget = 1;
725}
726
727gchar *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
893void 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
929void 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
960int 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
988int 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
1021unsigned 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 */
1092void 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
1115void 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
1128void 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
1140void 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
1157void sequence_init(sequence *t)
1158{
1159 t->size = 10;
1160 t->position = 0;
1161 t->array = g_new(void*, t->size);
1162}
1163
1164void sequence_dispose(sequence *t)
1165{
1166 t->size = 0;
1167 g_free(t->array);
1168 t->array = NULL;
1169}
1170
1171void 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
1186void *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
1194void table_init(table *t)
1195{
1196 sequence_init(&(t->keys));
1197 sequence_init(&(t->values));
1198}
1199
1200void table_dispose(table *t)
1201{
1202 sequence_dispose(&(t->keys));
1203 sequence_dispose(&(t->values));
1204}
1205
1206void table_insert(table *t, char *key, void *value)
1207{
1208 sequence_push(&(t->keys),key);
1209 sequence_push(&(t->values),value);
1210}
1211
1212void *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
1222void table_insert_int(table *t, int *key, void *value)
1223{
1224 sequence_push(&(t->keys),key);
1225 sequence_push(&(t->values),value);
1226}
1227
1228void *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.048544 seconds and 4 git commands to generate.