Add config.h support : will fix the LARGEFILE problem
[lttv.git] / ltt / branches / poly / ltt / parser.c
CommitLineData
6cd62ccf 1/*
2
3parser.c: Generate helper declarations and functions to trace events
4 from an event description file.
5
6Copyright (C) 2002, Xianxiu Yang
45e14832 7Copyright (C) 2002, Michel Dagenais
8Copyright (C) 2005, Mathieu Desnoyers
9
6cd62ccf 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
963b5f2d 24/* This program reads the ".xml" event definitions input files
25 and constructs structure for each event.
6cd62ccf 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
963b5f2d 35 information when the processing of an ".xml" file is finished. */
6cd62ccf 36
4e4d11b3 37#ifdef HAVE_CONFIG_H
38#include <config.h>
39#endif
40
6cd62ccf 41#include <stdlib.h>
42#include <string.h>
43#include <stdio.h>
44#include <stdarg.h>
8d1e6362 45#include <ctype.h>
0f7f40c1 46#include <linux/errno.h>
47#include <glib.h>
6cd62ccf 48
49
50#include "parser.h"
51
6cd62ccf 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
61int getSize(parse_file *in)
62{
45e14832 63 gchar *token;
6cd62ccf 64
65 token = getToken(in);
66 if(in->type == NUMBER) {
45e14832 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;
6cd62ccf 71 }
72 else if(in->type == NAME) {
45e14832 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;
6cd62ccf 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
89void error_callback(parse_file *in, char *msg)
90{
91 if(in)
45e14832 92 g_printf("Error in file %s, line %d: %s\n", in->name, in->lineno, msg);
6cd62ccf 93 else
94 printf("%s\n",msg);
6cd62ccf 95}
96
963b5f2d 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
45e14832 112gchar * getNameAttribute(parse_file *in)
963b5f2d 113{
45e14832 114 gchar * token;
115 gunichar car;
116 GIOStatus status;
117
963b5f2d 118 token = getName(in);
45e14832 119 if(g_ascii_strcasecmp("name",token))in->error(in,"name was expected");
963b5f2d 120 getEqual(in);
121
45e14832 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);
963b5f2d 126 else token = getName(in);
127 return token;
128}
129
130char * getFormatAttribute(parse_file *in)
131{
132 char * token;
133
134 //format is an option
135 token = getToken(in);
45e14832 136 if(g_ascii_strcasecmp("/",token) == 0 || g_ascii_strcasecmp(">",token) == 0){
963b5f2d 137 ungetToken(in);
138 return NULL;
139 }
140
45e14832 141 if(g_ascii_strcasecmp("format",token))in->error(in,"format was expected");
963b5f2d 142 getEqual(in);
143 token = getQuotedString(in);
144 return token;
145}
146
147int getSizeAttribute(parse_file *in)
148{
8d1e6362 149 /* skip name and equal */
963b5f2d 150 getName(in);
151 getEqual(in);
152
153 return getSize(in);
154}
155
156int getValueAttribute(parse_file *in)
157{
8d1e6362 158 /* skip name and equal */
963b5f2d 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
166char * getValueStrAttribute(parse_file *in)
167{
168 char * token;
169
170 token = getToken(in);
45e14832 171 if(g_ascii_strcasecmp("/",token) == 0){
963b5f2d 172 ungetToken(in);
173 return NULL;
174 }
175
45e14832 176 if(g_ascii_strcasecmp("value",token))in->error(in,"value was expected");
963b5f2d 177 getEqual(in);
178 token = getToken(in);
179 if(in->type != NUMBER) in->error(in,"number was expected");
180 return token;
181}
182
183char * getDescription(parse_file *in)
184{
45e14832 185 gint64 pos;
186 gchar * token, *str;
187 gunichar car;
188 GError * error = NULL;
963b5f2d 189
45e14832 190 pos = in->pos;
963b5f2d 191
192 getLAnglebracket(in);
193 token = getName(in);
45e14832 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
963b5f2d 201 return NULL;
202 }
203
204 getRAnglebracket(in);
205
206 pos = 0;
45e14832 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
963b5f2d 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
45e14832 222 str = g_strdup(in->buffer);
963b5f2d 223
224 getForwardslash(in);
225 token = getName(in);
45e14832 226 if(g_ascii_strcasecmp("description", token))in->error(in,"not a valid description");
963b5f2d 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
8d1e6362 242void parseFacility(parse_file *in, facility_t * fac)
963b5f2d 243{
244 char * token;
8d1e6362 245 event_t *ev;
963b5f2d 246
45e14832 247 fac->name = g_strdup(getNameAttribute(in));
963b5f2d 248 getRAnglebracket(in);
249
ed9d56bd 250 fac->description = getDescription(in);
963b5f2d 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
45e14832 259 if(g_ascii_strcasecmp("event",token) == 0){
260 ev = (event_t*) g_new(event_t,1);
963b5f2d 261 sequence_push(&(fac->events),ev);
262 parseEvent(in,ev, &(fac->unnamed_types), &(fac->named_types));
45e14832 263 }else if(g_ascii_strcasecmp("type",token) == 0){
963b5f2d 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);
45e14832 271 if(g_ascii_strcasecmp("facility",token)) in->error(in,"not the end of the facility");
963b5f2d 272 getRAnglebracket(in); //</facility>
273}
6cd62ccf 274
275/*****************************************************************************
276 *Function name
277 * parseEvent : generate event from event definition
278 *Input params
279 * in : input file handle
280 * ev : new event
963b5f2d 281 * unnamed_types : array of unamed types
282 * named_types : array of named types
6cd62ccf 283 *Output params
284 * ev : new event (parameters are passed to it)
285 ****************************************************************************/
286
8d1e6362 287void parseEvent(parse_file *in, event_t * ev, sequence * unnamed_types,
6cd62ccf 288 table * named_types)
289{
290 char *token;
6cd62ccf 291
963b5f2d 292 //<event name=eventtype_name>
45e14832 293 ev->name = g_strdup(getNameAttribute(in));
963b5f2d 294 getRAnglebracket(in);
6cd62ccf 295
963b5f2d 296 //<description>...</descriptio>
ed9d56bd 297 ev->description = getDescription(in);
6cd62ccf 298
963b5f2d 299 //event can have STRUCT, TYPEREF or NOTHING
300 getLAnglebracket(in);
6cd62ccf 301
963b5f2d 302 token = getToken(in);
303 if(in->type == FORWARDSLASH){ //</event> NOTHING
304 ev->type = NULL;
305 }else if(in->type == NAME){
45e14832 306 if(g_ascii_strcasecmp("struct",token)==0 || g_ascii_strcasecmp("typeref",token)==0){
963b5f2d 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);
6cd62ccf 315 }else in->error(in,"not a struct type");
316
963b5f2d 317 token = getName(in);
45e14832 318 if(g_ascii_strcasecmp("event",token))in->error(in,"not an event definition");
963b5f2d 319 getRAnglebracket(in); //</event>
6cd62ccf 320}
321
322/*****************************************************************************
323 *Function name
963b5f2d 324 * parseField : get field infomation from buffer
6cd62ccf 325 *Input params
963b5f2d 326 * in : input file handle
327 * t : type descriptor
328 * unnamed_types : array of unamed types
329 * named_types : array of named types
6cd62ccf 330 ****************************************************************************/
331
332void parseFields(parse_file *in, type_descriptor *t, sequence * unnamed_types,
333 table * named_types)
334{
335 char * token;
8d1e6362 336 type_fields *f;
6cd62ccf 337
45e14832 338 f = g_new(type_fields,1);
963b5f2d 339 sequence_push(&(t->fields),f);
6cd62ccf 340
963b5f2d 341 //<field name=field_name> <description> <type> </field>
45e14832 342 f->name = g_strdup(getNameAttribute(in));
963b5f2d 343 getRAnglebracket(in);
344
ed9d56bd 345 f->description = getDescription(in);
963b5f2d 346
347 //<int size=...>
348 getLAnglebracket(in);
349 f->type = parseType(in,NULL, unnamed_types, named_types);
6cd62ccf 350
963b5f2d 351 getLAnglebracket(in);
352 getForwardslash(in);
353 token = getName(in);
45e14832 354 if(g_ascii_strcasecmp("field",token))in->error(in,"not a valid field definition");
963b5f2d 355 getRAnglebracket(in); //</field>
6cd62ccf 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
963b5f2d 373 * unnamed_types : array of unamed types
374 * named_types : array of named types
6cd62ccf 375 *Return values
376 * type_descriptor* : a type descriptor
377 ****************************************************************************/
378
379type_descriptor *parseType(parse_file *in, type_descriptor *inType,
380 sequence * unnamed_types, table * named_types)
381{
963b5f2d 382 char *token;
6cd62ccf 383 type_descriptor *t;
384
385 if(inType == NULL) {
45e14832 386 t = g_new(type_descriptor,1);
6cd62ccf 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
45e14832 396 if(g_ascii_strcasecmp(token,"struct") == 0) {
6cd62ccf 397 t->type = STRUCT;
963b5f2d 398 getRAnglebracket(in); //<struct>
399 getLAnglebracket(in); //<field name=..>
400 token = getToken(in);
401 sequence_init(&(t->fields));
45e14832 402 while(g_ascii_strcasecmp("field",token) == 0){
963b5f2d 403 parseFields(in,t, unnamed_types, named_types);
404
405 //next field
406 getLAnglebracket(in);
407 token = getToken(in);
408 }
45e14832 409 if(g_ascii_strcasecmp("/",token))in->error(in,"not a valid structure definition");
963b5f2d 410 token = getName(in);
45e14832 411 if(g_ascii_strcasecmp("struct",token)!=0)
963b5f2d 412 in->error(in,"not a valid structure definition");
413 getRAnglebracket(in); //</struct>
414 }
45e14832 415 else if(g_ascii_strcasecmp(token,"union") == 0) {
963b5f2d 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));
45e14832 423 while(g_ascii_strcasecmp("field",token) == 0){
963b5f2d 424 parseFields(in,t, unnamed_types, named_types);
425
426 //next field
427 getLAnglebracket(in);
428 token = getToken(in);
429 }
45e14832 430 if(g_ascii_strcasecmp("/",token))in->error(in,"not a valid union definition");
963b5f2d 431 token = getName(in);
45e14832 432 if(g_ascii_strcasecmp("union",token)!=0)
963b5f2d 433 in->error(in,"not a valid union definition");
434 getRAnglebracket(in); //</union>
6cd62ccf 435 }
45e14832 436 else if(g_ascii_strcasecmp(token,"array") == 0) {
6cd62ccf 437 t->type = ARRAY;
963b5f2d 438 t->size = getValueAttribute(in);
439 getRAnglebracket(in); //<array size=n>
440
441 getLAnglebracket(in); //<type struct>
6cd62ccf 442 t->nested_type = parseType(in,NULL, unnamed_types, named_types);
963b5f2d 443
444 getLAnglebracket(in); //</array>
445 getForwardslash(in);
446 token = getName(in);
45e14832 447 if(g_ascii_strcasecmp("array",token))in->error(in,"not a valid array definition");
963b5f2d 448 getRAnglebracket(in); //</array>
6cd62ccf 449 }
45e14832 450 else if(g_ascii_strcasecmp(token,"sequence") == 0) {
6cd62ccf 451 t->type = SEQUENCE;
963b5f2d 452 t->size = getSizeAttribute(in);
453 getRAnglebracket(in); //<array lengthsize=isize>
454
455 getLAnglebracket(in); //<type struct>
6cd62ccf 456 t->nested_type = parseType(in,NULL, unnamed_types, named_types);
963b5f2d 457
458 getLAnglebracket(in); //</sequence>
459 getForwardslash(in);
460 token = getName(in);
45e14832 461 if(g_ascii_strcasecmp("sequence",token))in->error(in,"not a valid sequence definition");
963b5f2d 462 getRAnglebracket(in); //</sequence>
6cd62ccf 463 }
45e14832 464 else if(g_ascii_strcasecmp(token,"enum") == 0) {
963b5f2d 465 char * str, *str1;
6cd62ccf 466 t->type = ENUM;
467 sequence_init(&(t->labels));
963b5f2d 468 t->size = getSizeAttribute(in);
45e14832 469 t->fmt = g_strdup(getFormatAttribute(in));
963b5f2d 470 getRAnglebracket(in);
471
472 //<label name=label1 value=n/>
473 getLAnglebracket(in);
474 token = getToken(in); //"label" or "/"
45e14832 475 while(g_ascii_strcasecmp("label",token) == 0){
476 str1 = g_strdup(getNameAttribute(in));
963b5f2d 477 token = getValueStrAttribute(in);
478 if(token){
45e14832 479 str = g_strconcat(str1,"=",token,NULL);
480 g_free(str1);
481 sequence_push(&(t->labels),str);
963b5f2d 482 }else
45e14832 483 sequence_push(&(t->labels),str1);
963b5f2d 484
485 getForwardslash(in);
486 getRAnglebracket(in);
487
488 //next label definition
489 getLAnglebracket(in);
490 token = getToken(in); //"label" or "/"
491 }
45e14832 492 if(g_ascii_strcasecmp("/",token))in->error(in, "not a valid enum definition");
963b5f2d 493 token = getName(in);
45e14832 494 if(g_ascii_strcasecmp("enum",token))in->error(in, "not a valid enum definition");
963b5f2d 495 getRAnglebracket(in); //</label>
6cd62ccf 496 }
45e14832 497 else if(g_ascii_strcasecmp(token,"int") == 0) {
6cd62ccf 498 t->type = INT;
963b5f2d 499 t->size = getSizeAttribute(in);
45e14832 500 t->fmt = g_strdup(getFormatAttribute(in));
963b5f2d 501 getForwardslash(in);
502 getRAnglebracket(in);
6cd62ccf 503 }
45e14832 504 else if(g_ascii_strcasecmp(token,"uint") == 0) {
6cd62ccf 505 t->type = UINT;
963b5f2d 506 t->size = getSizeAttribute(in);
45e14832 507 t->fmt = g_strdup(getFormatAttribute(in));
963b5f2d 508 getForwardslash(in);
509 getRAnglebracket(in);
6cd62ccf 510 }
45e14832 511 else if(g_ascii_strcasecmp(token,"float") == 0) {
6cd62ccf 512 t->type = FLOAT;
963b5f2d 513 t->size = getSizeAttribute(in);
45e14832 514 t->fmt = g_strdup(getFormatAttribute(in));
963b5f2d 515 getForwardslash(in);
516 getRAnglebracket(in);
6cd62ccf 517 }
45e14832 518 else if(g_ascii_strcasecmp(token,"string") == 0) {
6cd62ccf 519 t->type = STRING;
45e14832 520 t->fmt = g_strdup(getFormatAttribute(in));
963b5f2d 521 getForwardslash(in);
522 getRAnglebracket(in);
6cd62ccf 523 }
45e14832 524 else if(g_ascii_strcasecmp(token,"typeref") == 0){
963b5f2d 525 // Must be a named type
6cd62ccf 526 if(inType != NULL)
527 in->error(in,"Named type cannot refer to a named type");
528 else {
45e14832 529 g_free(t);
6cd62ccf 530 sequence_pop(unnamed_types);
963b5f2d 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;
6cd62ccf 536 }
963b5f2d 537 }else in->error(in,"not a valid type");
6cd62ccf 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
963b5f2d 547 * named_types : array of named types
6cd62ccf 548 *Return values
549 * type_descriptor * : a type descriptor
550 *****************************************************************************/
551
45e14832 552type_descriptor * find_named_type(gchar *name, table * named_types)
6cd62ccf 553{
554 type_descriptor *t;
555
556 t = table_find(named_types,name);
557 if(t == NULL) {
45e14832 558 t = g_new(type_descriptor,1);
559 t->type_name = g_strdup(name);
6cd62ccf 560 t->type = NONE;
561 t->fmt = NULL;
908f42fa 562 table_insert(named_types,t->type_name,t);
45e14832 563 // table_insert(named_types,g_strdup(name),t);
6cd62ccf 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
963b5f2d 573 * unnamed_types : array of unamed types
574 * named_types : array of named types
6cd62ccf 575 *****************************************************************************/
576
577void parseTypeDefinition(parse_file * in, sequence * unnamed_types,
578 table * named_types)
579{
580 char *token;
581 type_descriptor *t;
582
963b5f2d 583 token = getNameAttribute(in);
6cd62ccf 584 t = find_named_type(token, named_types);
6cd62ccf 585
586 if(t->type != NONE) in->error(in,"redefinition of named type");
963b5f2d 587 getRAnglebracket(in); //<type name=type_name>
588 getLAnglebracket(in); //<struct>
589 token = getName(in);
45e14832 590 if(g_ascii_strcasecmp("struct",token))in->error(in,"not a valid type definition");
963b5f2d 591 ungetToken(in);
6cd62ccf 592 parseType(in,t, unnamed_types, named_types);
963b5f2d 593
594 //</type>
595 getLAnglebracket(in);
596 getForwardslash(in);
597 token = getName(in);
45e14832 598 if(g_ascii_strcasecmp("type",token))in->error(in,"not a valid type definition");
963b5f2d 599 getRAnglebracket(in); //</type>
6cd62ccf 600}
601
602/**************************************************************************
603 * Function :
963b5f2d 604 * getComa, getName, getNumber, getEqual
6cd62ccf 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
616char *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
625int 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
963b5f2d 634char *getForwardslash(parse_file * in)
6cd62ccf 635{
636 char *token;
637
638 token = getToken(in);
963b5f2d 639 if(in->type != FORWARDSLASH) in->error(in, "forward slash token was expected");
6cd62ccf 640 return token;
641}
642
963b5f2d 643char *getLAnglebracket(parse_file * in)
6cd62ccf 644{
645 char *token;
646
647 token = getToken(in);
963b5f2d 648 if(in->type != LANGLEBRACKET) in->error(in, "Left angle bracket was expected");
6cd62ccf 649 return token;
650}
651
963b5f2d 652char *getRAnglebracket(parse_file * in)
6cd62ccf 653{
654 char *token;
655
656 token = getToken(in);
963b5f2d 657 if(in->type != RANGLEBRACKET) in->error(in, "Right angle bracket was expected");
6cd62ccf 658 return token;
659}
660
661char *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
963b5f2d 670char * getEqual(parse_file *in)
6cd62ccf 671{
672 char *token;
673
674 token = getToken(in);
963b5f2d 675 if(in->type != EQUAL) in->error(in, "equal was expected");
6cd62ccf 676 return token;
677}
678
45e14832 679gunichar seekNextChar(parse_file *in, gunichar *car)
6cd62ccf 680{
45e14832 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;
963b5f2d 703 }
45e14832 704
705 } while(status != G_IO_STATUS_EOF && status != G_IO_STATUS_ERROR);
706
707 return status;
6cd62ccf 708}
709
45e14832 710
6cd62ccf 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
726void ungetToken(parse_file * in)
727{
728 in->unget = 1;
729}
730
45e14832 731gchar *getToken(parse_file * in)
6cd62ccf 732{
45e14832 733 gunichar car, car1;
6cd62ccf 734 int pos = 0, escaped;
45e14832 735 GError * error = NULL;
6cd62ccf 736
737 if(in->unget == 1) {
738 in->unget = 0;
739 return in->buffer;
740 }
741
742 /* skip whitespace and comments */
743
45e14832 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
6cd62ccf 752 if(car == '/') {
45e14832 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
6cd62ccf 759 if(car1 == '*') skipComment(in);
760 else if(car1 == '/') skipEOL(in);
45e14832 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--;
6cd62ccf 767 break;
768 }
769 }
770 else if(car == '\n') in->lineno++;
45e14832 771 else if(!g_unichar_isspace(car)) break;
6cd62ccf 772 }
6cd62ccf 773 switch(car) {
774 case EOF:
775 in->type = ENDFILE;
776 break;
963b5f2d 777 case '/':
778 in->type = FORWARDSLASH;
6cd62ccf 779 in->buffer[pos] = car;
780 pos++;
781 break;
963b5f2d 782 case '<':
783 in->type = LANGLEBRACKET;
6cd62ccf 784 in->buffer[pos] = car;
785 pos++;
786 break;
963b5f2d 787 case '>':
788 in->type = RANGLEBRACKET;
6cd62ccf 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;
45e14832 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
6cd62ccf 807 if(car == '\\' && escaped == 0) {
45e14832 808 in->buffer[pos] = car;
809 pos++;
6cd62ccf 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:
45e14832 827 if(g_unichar_isdigit(car)) {
6cd62ccf 828 in->buffer[pos] = car;
829 pos++;
45e14832 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
6cd62ccf 838 if(!isdigit(car)) {
45e14832 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--;
6cd62ccf 844 break;
845 }
846 in->buffer[pos] = car;
847 pos++;
848 }
45e14832 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 }
6cd62ccf 856 if(pos == BUFFER_SIZE) in->error(in, "number token too large");
857 in->type = NUMBER;
858 }
45e14832 859 else if(g_unichar_isalpha(car)) {
6cd62ccf 860 in->buffer[0] = car;
861 pos = 1;
45e14832 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--;
6cd62ccf 876 break;
877 }
878 in->buffer[pos] = car;
879 pos++;
880 }
45e14832 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 }
6cd62ccf 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
897void skipComment(parse_file * in)
898{
45e14832 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
6cd62ccf 910 if(car == '\n') in->lineno++;
911 else if(car == '*') {
45e14832 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
6cd62ccf 919 if(car ==EOF) break;
920 if(car == '/') return;
45e14832 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
6cd62ccf 928 }
929 }
930 if(car == EOF) in->error(in,"comment begining with '/*' has no ending '*/'");
931}
932
933void skipEOL(parse_file * in)
934{
45e14832 935 gunichar car;
936 GError * error = NULL;
937
938 while(g_io_channel_read_unichar(in->channel, &car, &error)
939 != G_IO_STATUS_EOF) {
6cd62ccf 940 if(car == '\n') {
45e14832 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--;
6cd62ccf 946 break;
947 }
948 }
45e14832 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 }
6cd62ccf 956}
957
6cd62ccf 958/*****************************************************************************
959 *Function name
960 * checkNamedTypesImplemented : check if all named types have definition
fc063e40 961 * returns -1 on error, 0 if ok
6cd62ccf 962 ****************************************************************************/
963
fc063e40 964int checkNamedTypesImplemented(table * named_types)
6cd62ccf 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){
fc063e40 973 sprintf(str,"named type '%s' has no definition",
974 (char*)named_types->keys.array[pos]);
975 error_callback(NULL,str);
976 return -1;
6cd62ccf 977 }
978 }
fc063e40 979 return 0;
6cd62ccf 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
0f7f40c1 992int generateChecksum(char* facName, guint32 * checksum, sequence * events)
6cd62ccf 993{
994 unsigned long crc ;
963b5f2d 995 int pos;
8d1e6362 996 event_t * ev;
6cd62ccf 997 char str[256];
998
999 crc = crc32(facName);
1000 for(pos = 0; pos < events->position; pos++){
8d1e6362 1001 ev = (event_t *)(events->array[pos]);
6cd62ccf 1002 crc = partial_crc32(ev->name,crc);
963b5f2d 1003 if(!ev->type) continue; //event without type
6cd62ccf 1004 if(ev->type->type != STRUCT){
1005 sprintf(str,"event '%s' has a type other than STRUCT",ev->name);
1006 error_callback(NULL, str);
fc063e40 1007 return -1;
6cd62ccf 1008 }
963b5f2d 1009 crc = getTypeChecksum(crc, ev->type);
6cd62ccf 1010 }
1011 *checksum = crc;
fc063e40 1012 return 0;
6cd62ccf 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
963b5f2d 1025unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor * type)
6cd62ccf 1026{
1027 unsigned long crc = aCrc;
1028 char * str = NULL, buf[16];
963b5f2d 1029 int flag = 0, pos;
8d1e6362 1030 type_fields * fld;
6cd62ccf 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:
45e14832 1043 str = g_strdup("string");
6cd62ccf 1044 flag = 1;
1045 break;
1046 case ENUM:
45e14832 1047 str = g_strconcat("enum ", uintOutputTypes[type->size], NULL);
6cd62ccf 1048 flag = 1;
1049 break;
1050 case ARRAY:
8d1e6362 1051 sprintf(buf,"%d",type->size);
45e14832 1052 str = g_strconcat("array ",buf, NULL);
6cd62ccf 1053 flag = 1;
1054 break;
1055 case SEQUENCE:
8d1e6362 1056 sprintf(buf,"%d",type->size);
45e14832 1057 str = g_strconcat("sequence ",buf, NULL);
6cd62ccf 1058 flag = 1;
1059 break;
1060 case STRUCT:
45e14832 1061 str = g_strdup("struct");
6cd62ccf 1062 flag = 1;
1063 break;
963b5f2d 1064 case UNION:
45e14832 1065 str = g_strdup("union");
963b5f2d 1066 flag = 1;
1067 break;
6cd62ccf 1068 default:
1069 error_callback(NULL, "named type has no definition");
1070 break;
1071 }
1072
1073 crc = partial_crc32(str,crc);
45e14832 1074 if(flag) g_free(str);
6cd62ccf 1075
1076 if(type->fmt) crc = partial_crc32(type->fmt,crc);
1077
1078 if(type->type == ARRAY || type->type == SEQUENCE){
963b5f2d 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++){
8d1e6362 1082 fld = (type_fields *) type->fields.array[pos];
963b5f2d 1083 crc = partial_crc32(fld->name,crc);
1084 crc = getTypeChecksum(crc, fld->type);
1085 }
6cd62ccf 1086 }else if(type->type == ENUM){
1087 for(pos = 0; pos < type->labels.position; pos++)
963b5f2d 1088 crc = partial_crc32((char*)type->labels.array[pos],crc);
6cd62ccf 1089 }
1090
1091 return crc;
1092}
1093
1094
1095/* Event type descriptors */
1096void freeType(type_descriptor * tp)
1097{
1098 int pos2;
8d1e6362 1099 type_fields *f;
6cd62ccf 1100
45e14832 1101 if(tp->fmt != NULL) g_free(tp->fmt);
6cd62ccf 1102 if(tp->type == ENUM) {
1103 for(pos2 = 0; pos2 < tp->labels.position; pos2++) {
45e14832 1104 g_free(tp->labels.array[pos2]);
6cd62ccf 1105 }
1106 sequence_dispose(&(tp->labels));
1107 }
1108 if(tp->type == STRUCT) {
1109 for(pos2 = 0; pos2 < tp->fields.position; pos2++) {
8d1e6362 1110 f = (type_fields *) tp->fields.array[pos2];
45e14832 1111 g_free(f->name);
1112 g_free(f->description);
1113 g_free(f);
6cd62ccf 1114 }
1115 sequence_dispose(&(tp->fields));
1116 }
1117}
1118
1119void freeNamedType(table * t)
1120{
1121 int pos;
1122 type_descriptor * td;
1123
1124 for(pos = 0 ; pos < t->keys.position; pos++) {
45e14832 1125 g_free((char *)t->keys.array[pos]);
6cd62ccf 1126 td = (type_descriptor*)t->values.array[pos];
1127 freeType(td);
45e14832 1128 g_free(td);
6cd62ccf 1129 }
1130}
1131
1132void freeTypes(sequence *t)
1133{
8d1e6362 1134 int pos;
6cd62ccf 1135 type_descriptor *tp;
6cd62ccf 1136
1137 for(pos = 0 ; pos < t->position; pos++) {
1138 tp = (type_descriptor *)t->array[pos];
1139 freeType(tp);
45e14832 1140 g_free(tp);
6cd62ccf 1141 }
1142}
1143
1144void freeEvents(sequence *t)
1145{
1146 int pos;
8d1e6362 1147 event_t *ev;
6cd62ccf 1148
1149 for(pos = 0 ; pos < t->position; pos++) {
8d1e6362 1150 ev = (event_t *) t->array[pos];
45e14832 1151 g_free(ev->name);
1152 g_free(ev->description);
1153 g_free(ev);
6cd62ccf 1154 }
1155
1156}
1157
1158
1159/* Extensible array */
1160
1161void sequence_init(sequence *t)
1162{
1163 t->size = 10;
1164 t->position = 0;
45e14832 1165 t->array = g_new(void*, t->size);
6cd62ccf 1166}
1167
1168void sequence_dispose(sequence *t)
1169{
1170 t->size = 0;
45e14832 1171 g_free(t->array);
6cd62ccf 1172 t->array = NULL;
1173}
1174
1175void sequence_push(sequence *t, void *elem)
1176{
1177 void **tmp;
1178
1179 if(t->position >= t->size) {
1180 tmp = t->array;
45e14832 1181 t->array = g_new(void*, 2*t->size);
6cd62ccf 1182 memcpy(t->array, tmp, t->size * sizeof(void *));
1183 t->size = t->size * 2;
45e14832 1184 g_free(tmp);
6cd62ccf 1185 }
1186 t->array[t->position] = elem;
1187 t->position++;
1188}
1189
1190void *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
1198void table_init(table *t)
1199{
1200 sequence_init(&(t->keys));
1201 sequence_init(&(t->values));
1202}
1203
1204void table_dispose(table *t)
1205{
1206 sequence_dispose(&(t->keys));
1207 sequence_dispose(&(t->values));
1208}
1209
1210void table_insert(table *t, char *key, void *value)
1211{
1212 sequence_push(&(t->keys),key);
1213 sequence_push(&(t->values),value);
1214}
1215
1216void *table_find(table *t, char *key)
1217{
1218 int pos;
1219 for(pos = 0 ; pos < t->keys.position; pos++) {
45e14832 1220 if(g_ascii_strcasecmp((char *)key,(char *)t->keys.array[pos]) == 0)
6cd62ccf 1221 return(t->values.array[pos]);
1222 }
1223 return NULL;
1224}
1225
1226void table_insert_int(table *t, int *key, void *value)
1227{
1228 sequence_push(&(t->keys),key);
1229 sequence_push(&(t->values),value);
1230}
1231
1232void *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.086534 seconds and 4 git commands to generate.