UTF8 fix
[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
37#include <stdlib.h>
38#include <string.h>
39#include <stdio.h>
40#include <stdarg.h>
8d1e6362 41#include <ctype.h>
0f7f40c1 42#include <linux/errno.h>
43#include <glib.h>
6cd62ccf 44
45
46#include "parser.h"
47
6cd62ccf 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{
45e14832 59 gchar *token;
6cd62ccf 60
61 token = getToken(in);
62 if(in->type == NUMBER) {
45e14832 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;
6cd62ccf 67 }
68 else if(in->type == NAME) {
45e14832 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;
6cd62ccf 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)
45e14832 88 g_printf("Error in file %s, line %d: %s\n", in->name, in->lineno, msg);
6cd62ccf 89 else
90 printf("%s\n",msg);
6cd62ccf 91}
92
963b5f2d 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
45e14832 108gchar * getNameAttribute(parse_file *in)
963b5f2d 109{
45e14832 110 gchar * token;
111 gunichar car;
112 GIOStatus status;
113
963b5f2d 114 token = getName(in);
45e14832 115 if(g_ascii_strcasecmp("name",token))in->error(in,"name was expected");
963b5f2d 116 getEqual(in);
117
45e14832 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);
963b5f2d 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);
45e14832 132 if(g_ascii_strcasecmp("/",token) == 0 || g_ascii_strcasecmp(">",token) == 0){
963b5f2d 133 ungetToken(in);
134 return NULL;
135 }
136
45e14832 137 if(g_ascii_strcasecmp("format",token))in->error(in,"format was expected");
963b5f2d 138 getEqual(in);
139 token = getQuotedString(in);
140 return token;
141}
142
143int getSizeAttribute(parse_file *in)
144{
8d1e6362 145 /* skip name and equal */
963b5f2d 146 getName(in);
147 getEqual(in);
148
149 return getSize(in);
150}
151
152int getValueAttribute(parse_file *in)
153{
8d1e6362 154 /* skip name and equal */
963b5f2d 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);
45e14832 167 if(g_ascii_strcasecmp("/",token) == 0){
963b5f2d 168 ungetToken(in);
169 return NULL;
170 }
171
45e14832 172 if(g_ascii_strcasecmp("value",token))in->error(in,"value was expected");
963b5f2d 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{
45e14832 181 gint64 pos;
182 gchar * token, *str;
183 gunichar car;
184 GError * error = NULL;
963b5f2d 185
45e14832 186 pos = in->pos;
963b5f2d 187
188 getLAnglebracket(in);
189 token = getName(in);
45e14832 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
963b5f2d 197 return NULL;
198 }
199
200 getRAnglebracket(in);
201
202 pos = 0;
45e14832 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
963b5f2d 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
45e14832 218 str = g_strdup(in->buffer);
963b5f2d 219
220 getForwardslash(in);
221 token = getName(in);
45e14832 222 if(g_ascii_strcasecmp("description", token))in->error(in,"not a valid description");
963b5f2d 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
8d1e6362 238void parseFacility(parse_file *in, facility_t * fac)
963b5f2d 239{
240 char * token;
8d1e6362 241 event_t *ev;
963b5f2d 242
45e14832 243 fac->name = g_strdup(getNameAttribute(in));
963b5f2d 244 getRAnglebracket(in);
245
ed9d56bd 246 fac->description = getDescription(in);
963b5f2d 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
45e14832 255 if(g_ascii_strcasecmp("event",token) == 0){
256 ev = (event_t*) g_new(event_t,1);
963b5f2d 257 sequence_push(&(fac->events),ev);
258 parseEvent(in,ev, &(fac->unnamed_types), &(fac->named_types));
45e14832 259 }else if(g_ascii_strcasecmp("type",token) == 0){
963b5f2d 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);
45e14832 267 if(g_ascii_strcasecmp("facility",token)) in->error(in,"not the end of the facility");
963b5f2d 268 getRAnglebracket(in); //</facility>
269}
6cd62ccf 270
271/*****************************************************************************
272 *Function name
273 * parseEvent : generate event from event definition
274 *Input params
275 * in : input file handle
276 * ev : new event
963b5f2d 277 * unnamed_types : array of unamed types
278 * named_types : array of named types
6cd62ccf 279 *Output params
280 * ev : new event (parameters are passed to it)
281 ****************************************************************************/
282
8d1e6362 283void parseEvent(parse_file *in, event_t * ev, sequence * unnamed_types,
6cd62ccf 284 table * named_types)
285{
286 char *token;
6cd62ccf 287
963b5f2d 288 //<event name=eventtype_name>
45e14832 289 ev->name = g_strdup(getNameAttribute(in));
963b5f2d 290 getRAnglebracket(in);
6cd62ccf 291
963b5f2d 292 //<description>...</descriptio>
ed9d56bd 293 ev->description = getDescription(in);
6cd62ccf 294
963b5f2d 295 //event can have STRUCT, TYPEREF or NOTHING
296 getLAnglebracket(in);
6cd62ccf 297
963b5f2d 298 token = getToken(in);
299 if(in->type == FORWARDSLASH){ //</event> NOTHING
300 ev->type = NULL;
301 }else if(in->type == NAME){
45e14832 302 if(g_ascii_strcasecmp("struct",token)==0 || g_ascii_strcasecmp("typeref",token)==0){
963b5f2d 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);
6cd62ccf 311 }else in->error(in,"not a struct type");
312
963b5f2d 313 token = getName(in);
45e14832 314 if(g_ascii_strcasecmp("event",token))in->error(in,"not an event definition");
963b5f2d 315 getRAnglebracket(in); //</event>
6cd62ccf 316}
317
318/*****************************************************************************
319 *Function name
963b5f2d 320 * parseField : get field infomation from buffer
6cd62ccf 321 *Input params
963b5f2d 322 * in : input file handle
323 * t : type descriptor
324 * unnamed_types : array of unamed types
325 * named_types : array of named types
6cd62ccf 326 ****************************************************************************/
327
328void parseFields(parse_file *in, type_descriptor *t, sequence * unnamed_types,
329 table * named_types)
330{
331 char * token;
8d1e6362 332 type_fields *f;
6cd62ccf 333
45e14832 334 f = g_new(type_fields,1);
963b5f2d 335 sequence_push(&(t->fields),f);
6cd62ccf 336
963b5f2d 337 //<field name=field_name> <description> <type> </field>
45e14832 338 f->name = g_strdup(getNameAttribute(in));
963b5f2d 339 getRAnglebracket(in);
340
ed9d56bd 341 f->description = getDescription(in);
963b5f2d 342
343 //<int size=...>
344 getLAnglebracket(in);
345 f->type = parseType(in,NULL, unnamed_types, named_types);
6cd62ccf 346
963b5f2d 347 getLAnglebracket(in);
348 getForwardslash(in);
349 token = getName(in);
45e14832 350 if(g_ascii_strcasecmp("field",token))in->error(in,"not a valid field definition");
963b5f2d 351 getRAnglebracket(in); //</field>
6cd62ccf 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
963b5f2d 369 * unnamed_types : array of unamed types
370 * named_types : array of named types
6cd62ccf 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{
963b5f2d 378 char *token;
6cd62ccf 379 type_descriptor *t;
380
381 if(inType == NULL) {
45e14832 382 t = g_new(type_descriptor,1);
6cd62ccf 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
45e14832 392 if(g_ascii_strcasecmp(token,"struct") == 0) {
6cd62ccf 393 t->type = STRUCT;
963b5f2d 394 getRAnglebracket(in); //<struct>
395 getLAnglebracket(in); //<field name=..>
396 token = getToken(in);
397 sequence_init(&(t->fields));
45e14832 398 while(g_ascii_strcasecmp("field",token) == 0){
963b5f2d 399 parseFields(in,t, unnamed_types, named_types);
400
401 //next field
402 getLAnglebracket(in);
403 token = getToken(in);
404 }
45e14832 405 if(g_ascii_strcasecmp("/",token))in->error(in,"not a valid structure definition");
963b5f2d 406 token = getName(in);
45e14832 407 if(g_ascii_strcasecmp("struct",token)!=0)
963b5f2d 408 in->error(in,"not a valid structure definition");
409 getRAnglebracket(in); //</struct>
410 }
45e14832 411 else if(g_ascii_strcasecmp(token,"union") == 0) {
963b5f2d 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));
45e14832 419 while(g_ascii_strcasecmp("field",token) == 0){
963b5f2d 420 parseFields(in,t, unnamed_types, named_types);
421
422 //next field
423 getLAnglebracket(in);
424 token = getToken(in);
425 }
45e14832 426 if(g_ascii_strcasecmp("/",token))in->error(in,"not a valid union definition");
963b5f2d 427 token = getName(in);
45e14832 428 if(g_ascii_strcasecmp("union",token)!=0)
963b5f2d 429 in->error(in,"not a valid union definition");
430 getRAnglebracket(in); //</union>
6cd62ccf 431 }
45e14832 432 else if(g_ascii_strcasecmp(token,"array") == 0) {
6cd62ccf 433 t->type = ARRAY;
963b5f2d 434 t->size = getValueAttribute(in);
435 getRAnglebracket(in); //<array size=n>
436
437 getLAnglebracket(in); //<type struct>
6cd62ccf 438 t->nested_type = parseType(in,NULL, unnamed_types, named_types);
963b5f2d 439
440 getLAnglebracket(in); //</array>
441 getForwardslash(in);
442 token = getName(in);
45e14832 443 if(g_ascii_strcasecmp("array",token))in->error(in,"not a valid array definition");
963b5f2d 444 getRAnglebracket(in); //</array>
6cd62ccf 445 }
45e14832 446 else if(g_ascii_strcasecmp(token,"sequence") == 0) {
6cd62ccf 447 t->type = SEQUENCE;
963b5f2d 448 t->size = getSizeAttribute(in);
449 getRAnglebracket(in); //<array lengthsize=isize>
450
451 getLAnglebracket(in); //<type struct>
6cd62ccf 452 t->nested_type = parseType(in,NULL, unnamed_types, named_types);
963b5f2d 453
454 getLAnglebracket(in); //</sequence>
455 getForwardslash(in);
456 token = getName(in);
45e14832 457 if(g_ascii_strcasecmp("sequence",token))in->error(in,"not a valid sequence definition");
963b5f2d 458 getRAnglebracket(in); //</sequence>
6cd62ccf 459 }
45e14832 460 else if(g_ascii_strcasecmp(token,"enum") == 0) {
963b5f2d 461 char * str, *str1;
6cd62ccf 462 t->type = ENUM;
463 sequence_init(&(t->labels));
963b5f2d 464 t->size = getSizeAttribute(in);
45e14832 465 t->fmt = g_strdup(getFormatAttribute(in));
963b5f2d 466 getRAnglebracket(in);
467
468 //<label name=label1 value=n/>
469 getLAnglebracket(in);
470 token = getToken(in); //"label" or "/"
45e14832 471 while(g_ascii_strcasecmp("label",token) == 0){
472 str1 = g_strdup(getNameAttribute(in));
963b5f2d 473 token = getValueStrAttribute(in);
474 if(token){
45e14832 475 str = g_strconcat(str1,"=",token,NULL);
476 g_free(str1);
477 sequence_push(&(t->labels),str);
963b5f2d 478 }else
45e14832 479 sequence_push(&(t->labels),str1);
963b5f2d 480
481 getForwardslash(in);
482 getRAnglebracket(in);
483
484 //next label definition
485 getLAnglebracket(in);
486 token = getToken(in); //"label" or "/"
487 }
45e14832 488 if(g_ascii_strcasecmp("/",token))in->error(in, "not a valid enum definition");
963b5f2d 489 token = getName(in);
45e14832 490 if(g_ascii_strcasecmp("enum",token))in->error(in, "not a valid enum definition");
963b5f2d 491 getRAnglebracket(in); //</label>
6cd62ccf 492 }
45e14832 493 else if(g_ascii_strcasecmp(token,"int") == 0) {
6cd62ccf 494 t->type = INT;
963b5f2d 495 t->size = getSizeAttribute(in);
45e14832 496 t->fmt = g_strdup(getFormatAttribute(in));
963b5f2d 497 getForwardslash(in);
498 getRAnglebracket(in);
6cd62ccf 499 }
45e14832 500 else if(g_ascii_strcasecmp(token,"uint") == 0) {
6cd62ccf 501 t->type = UINT;
963b5f2d 502 t->size = getSizeAttribute(in);
45e14832 503 t->fmt = g_strdup(getFormatAttribute(in));
963b5f2d 504 getForwardslash(in);
505 getRAnglebracket(in);
6cd62ccf 506 }
45e14832 507 else if(g_ascii_strcasecmp(token,"float") == 0) {
6cd62ccf 508 t->type = FLOAT;
963b5f2d 509 t->size = getSizeAttribute(in);
45e14832 510 t->fmt = g_strdup(getFormatAttribute(in));
963b5f2d 511 getForwardslash(in);
512 getRAnglebracket(in);
6cd62ccf 513 }
45e14832 514 else if(g_ascii_strcasecmp(token,"string") == 0) {
6cd62ccf 515 t->type = STRING;
45e14832 516 t->fmt = g_strdup(getFormatAttribute(in));
963b5f2d 517 getForwardslash(in);
518 getRAnglebracket(in);
6cd62ccf 519 }
45e14832 520 else if(g_ascii_strcasecmp(token,"typeref") == 0){
963b5f2d 521 // Must be a named type
6cd62ccf 522 if(inType != NULL)
523 in->error(in,"Named type cannot refer to a named type");
524 else {
45e14832 525 g_free(t);
6cd62ccf 526 sequence_pop(unnamed_types);
963b5f2d 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;
6cd62ccf 532 }
963b5f2d 533 }else in->error(in,"not a valid type");
6cd62ccf 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
963b5f2d 543 * named_types : array of named types
6cd62ccf 544 *Return values
545 * type_descriptor * : a type descriptor
546 *****************************************************************************/
547
45e14832 548type_descriptor * find_named_type(gchar *name, table * named_types)
6cd62ccf 549{
550 type_descriptor *t;
551
552 t = table_find(named_types,name);
553 if(t == NULL) {
45e14832 554 t = g_new(type_descriptor,1);
555 t->type_name = g_strdup(name);
6cd62ccf 556 t->type = NONE;
557 t->fmt = NULL;
908f42fa 558 table_insert(named_types,t->type_name,t);
45e14832 559 // table_insert(named_types,g_strdup(name),t);
6cd62ccf 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
963b5f2d 569 * unnamed_types : array of unamed types
570 * named_types : array of named types
6cd62ccf 571 *****************************************************************************/
572
573void parseTypeDefinition(parse_file * in, sequence * unnamed_types,
574 table * named_types)
575{
576 char *token;
577 type_descriptor *t;
578
963b5f2d 579 token = getNameAttribute(in);
6cd62ccf 580 t = find_named_type(token, named_types);
6cd62ccf 581
582 if(t->type != NONE) in->error(in,"redefinition of named type");
963b5f2d 583 getRAnglebracket(in); //<type name=type_name>
584 getLAnglebracket(in); //<struct>
585 token = getName(in);
45e14832 586 if(g_ascii_strcasecmp("struct",token))in->error(in,"not a valid type definition");
963b5f2d 587 ungetToken(in);
6cd62ccf 588 parseType(in,t, unnamed_types, named_types);
963b5f2d 589
590 //</type>
591 getLAnglebracket(in);
592 getForwardslash(in);
593 token = getName(in);
45e14832 594 if(g_ascii_strcasecmp("type",token))in->error(in,"not a valid type definition");
963b5f2d 595 getRAnglebracket(in); //</type>
6cd62ccf 596}
597
598/**************************************************************************
599 * Function :
963b5f2d 600 * getComa, getName, getNumber, getEqual
6cd62ccf 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
963b5f2d 630char *getForwardslash(parse_file * in)
6cd62ccf 631{
632 char *token;
633
634 token = getToken(in);
963b5f2d 635 if(in->type != FORWARDSLASH) in->error(in, "forward slash token was expected");
6cd62ccf 636 return token;
637}
638
963b5f2d 639char *getLAnglebracket(parse_file * in)
6cd62ccf 640{
641 char *token;
642
643 token = getToken(in);
963b5f2d 644 if(in->type != LANGLEBRACKET) in->error(in, "Left angle bracket was expected");
6cd62ccf 645 return token;
646}
647
963b5f2d 648char *getRAnglebracket(parse_file * in)
6cd62ccf 649{
650 char *token;
651
652 token = getToken(in);
963b5f2d 653 if(in->type != RANGLEBRACKET) in->error(in, "Right angle bracket was expected");
6cd62ccf 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
963b5f2d 666char * getEqual(parse_file *in)
6cd62ccf 667{
668 char *token;
669
670 token = getToken(in);
963b5f2d 671 if(in->type != EQUAL) in->error(in, "equal was expected");
6cd62ccf 672 return token;
673}
674
45e14832 675gunichar seekNextChar(parse_file *in, gunichar *car)
6cd62ccf 676{
45e14832 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;
963b5f2d 699 }
45e14832 700
701 } while(status != G_IO_STATUS_EOF && status != G_IO_STATUS_ERROR);
702
703 return status;
6cd62ccf 704}
705
45e14832 706
6cd62ccf 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
45e14832 727gchar *getToken(parse_file * in)
6cd62ccf 728{
45e14832 729 gunichar car, car1;
6cd62ccf 730 int pos = 0, escaped;
45e14832 731 GError * error = NULL;
6cd62ccf 732
733 if(in->unget == 1) {
734 in->unget = 0;
735 return in->buffer;
736 }
737
738 /* skip whitespace and comments */
739
45e14832 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
6cd62ccf 748 if(car == '/') {
45e14832 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
6cd62ccf 755 if(car1 == '*') skipComment(in);
756 else if(car1 == '/') skipEOL(in);
45e14832 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--;
6cd62ccf 763 break;
764 }
765 }
766 else if(car == '\n') in->lineno++;
45e14832 767 else if(!g_unichar_isspace(car)) break;
6cd62ccf 768 }
6cd62ccf 769 switch(car) {
770 case EOF:
771 in->type = ENDFILE;
772 break;
963b5f2d 773 case '/':
774 in->type = FORWARDSLASH;
6cd62ccf 775 in->buffer[pos] = car;
776 pos++;
777 break;
963b5f2d 778 case '<':
779 in->type = LANGLEBRACKET;
6cd62ccf 780 in->buffer[pos] = car;
781 pos++;
782 break;
963b5f2d 783 case '>':
784 in->type = RANGLEBRACKET;
6cd62ccf 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;
45e14832 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
6cd62ccf 803 if(car == '\\' && escaped == 0) {
45e14832 804 in->buffer[pos] = car;
805 pos++;
6cd62ccf 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:
45e14832 823 if(g_unichar_isdigit(car)) {
6cd62ccf 824 in->buffer[pos] = car;
825 pos++;
45e14832 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
6cd62ccf 834 if(!isdigit(car)) {
45e14832 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--;
6cd62ccf 840 break;
841 }
842 in->buffer[pos] = car;
843 pos++;
844 }
45e14832 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 }
6cd62ccf 852 if(pos == BUFFER_SIZE) in->error(in, "number token too large");
853 in->type = NUMBER;
854 }
45e14832 855 else if(g_unichar_isalpha(car)) {
6cd62ccf 856 in->buffer[0] = car;
857 pos = 1;
45e14832 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--;
6cd62ccf 872 break;
873 }
874 in->buffer[pos] = car;
875 pos++;
876 }
45e14832 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 }
6cd62ccf 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{
45e14832 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
6cd62ccf 906 if(car == '\n') in->lineno++;
907 else if(car == '*') {
45e14832 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
6cd62ccf 915 if(car ==EOF) break;
916 if(car == '/') return;
45e14832 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
6cd62ccf 924 }
925 }
926 if(car == EOF) in->error(in,"comment begining with '/*' has no ending '*/'");
927}
928
929void skipEOL(parse_file * in)
930{
45e14832 931 gunichar car;
932 GError * error = NULL;
933
934 while(g_io_channel_read_unichar(in->channel, &car, &error)
935 != G_IO_STATUS_EOF) {
6cd62ccf 936 if(car == '\n') {
45e14832 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--;
6cd62ccf 942 break;
943 }
944 }
45e14832 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 }
6cd62ccf 952}
953
6cd62ccf 954/*****************************************************************************
955 *Function name
956 * checkNamedTypesImplemented : check if all named types have definition
fc063e40 957 * returns -1 on error, 0 if ok
6cd62ccf 958 ****************************************************************************/
959
fc063e40 960int checkNamedTypesImplemented(table * named_types)
6cd62ccf 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){
fc063e40 969 sprintf(str,"named type '%s' has no definition",
970 (char*)named_types->keys.array[pos]);
971 error_callback(NULL,str);
972 return -1;
6cd62ccf 973 }
974 }
fc063e40 975 return 0;
6cd62ccf 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
0f7f40c1 988int generateChecksum(char* facName, guint32 * checksum, sequence * events)
6cd62ccf 989{
990 unsigned long crc ;
963b5f2d 991 int pos;
8d1e6362 992 event_t * ev;
6cd62ccf 993 char str[256];
994
995 crc = crc32(facName);
996 for(pos = 0; pos < events->position; pos++){
8d1e6362 997 ev = (event_t *)(events->array[pos]);
6cd62ccf 998 crc = partial_crc32(ev->name,crc);
963b5f2d 999 if(!ev->type) continue; //event without type
6cd62ccf 1000 if(ev->type->type != STRUCT){
1001 sprintf(str,"event '%s' has a type other than STRUCT",ev->name);
1002 error_callback(NULL, str);
fc063e40 1003 return -1;
6cd62ccf 1004 }
963b5f2d 1005 crc = getTypeChecksum(crc, ev->type);
6cd62ccf 1006 }
1007 *checksum = crc;
fc063e40 1008 return 0;
6cd62ccf 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
963b5f2d 1021unsigned long getTypeChecksum(unsigned long aCrc, type_descriptor * type)
6cd62ccf 1022{
1023 unsigned long crc = aCrc;
1024 char * str = NULL, buf[16];
963b5f2d 1025 int flag = 0, pos;
8d1e6362 1026 type_fields * fld;
6cd62ccf 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:
45e14832 1039 str = g_strdup("string");
6cd62ccf 1040 flag = 1;
1041 break;
1042 case ENUM:
45e14832 1043 str = g_strconcat("enum ", uintOutputTypes[type->size], NULL);
6cd62ccf 1044 flag = 1;
1045 break;
1046 case ARRAY:
8d1e6362 1047 sprintf(buf,"%d",type->size);
45e14832 1048 str = g_strconcat("array ",buf, NULL);
6cd62ccf 1049 flag = 1;
1050 break;
1051 case SEQUENCE:
8d1e6362 1052 sprintf(buf,"%d",type->size);
45e14832 1053 str = g_strconcat("sequence ",buf, NULL);
6cd62ccf 1054 flag = 1;
1055 break;
1056 case STRUCT:
45e14832 1057 str = g_strdup("struct");
6cd62ccf 1058 flag = 1;
1059 break;
963b5f2d 1060 case UNION:
45e14832 1061 str = g_strdup("union");
963b5f2d 1062 flag = 1;
1063 break;
6cd62ccf 1064 default:
1065 error_callback(NULL, "named type has no definition");
1066 break;
1067 }
1068
1069 crc = partial_crc32(str,crc);
45e14832 1070 if(flag) g_free(str);
6cd62ccf 1071
1072 if(type->fmt) crc = partial_crc32(type->fmt,crc);
1073
1074 if(type->type == ARRAY || type->type == SEQUENCE){
963b5f2d 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++){
8d1e6362 1078 fld = (type_fields *) type->fields.array[pos];
963b5f2d 1079 crc = partial_crc32(fld->name,crc);
1080 crc = getTypeChecksum(crc, fld->type);
1081 }
6cd62ccf 1082 }else if(type->type == ENUM){
1083 for(pos = 0; pos < type->labels.position; pos++)
963b5f2d 1084 crc = partial_crc32((char*)type->labels.array[pos],crc);
6cd62ccf 1085 }
1086
1087 return crc;
1088}
1089
1090
1091/* Event type descriptors */
1092void freeType(type_descriptor * tp)
1093{
1094 int pos2;
8d1e6362 1095 type_fields *f;
6cd62ccf 1096
45e14832 1097 if(tp->fmt != NULL) g_free(tp->fmt);
6cd62ccf 1098 if(tp->type == ENUM) {
1099 for(pos2 = 0; pos2 < tp->labels.position; pos2++) {
45e14832 1100 g_free(tp->labels.array[pos2]);
6cd62ccf 1101 }
1102 sequence_dispose(&(tp->labels));
1103 }
1104 if(tp->type == STRUCT) {
1105 for(pos2 = 0; pos2 < tp->fields.position; pos2++) {
8d1e6362 1106 f = (type_fields *) tp->fields.array[pos2];
45e14832 1107 g_free(f->name);
1108 g_free(f->description);
1109 g_free(f);
6cd62ccf 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++) {
45e14832 1121 g_free((char *)t->keys.array[pos]);
6cd62ccf 1122 td = (type_descriptor*)t->values.array[pos];
1123 freeType(td);
45e14832 1124 g_free(td);
6cd62ccf 1125 }
1126}
1127
1128void freeTypes(sequence *t)
1129{
8d1e6362 1130 int pos;
6cd62ccf 1131 type_descriptor *tp;
6cd62ccf 1132
1133 for(pos = 0 ; pos < t->position; pos++) {
1134 tp = (type_descriptor *)t->array[pos];
1135 freeType(tp);
45e14832 1136 g_free(tp);
6cd62ccf 1137 }
1138}
1139
1140void freeEvents(sequence *t)
1141{
1142 int pos;
8d1e6362 1143 event_t *ev;
6cd62ccf 1144
1145 for(pos = 0 ; pos < t->position; pos++) {
8d1e6362 1146 ev = (event_t *) t->array[pos];
45e14832 1147 g_free(ev->name);
1148 g_free(ev->description);
1149 g_free(ev);
6cd62ccf 1150 }
1151
1152}
1153
1154
1155/* Extensible array */
1156
1157void sequence_init(sequence *t)
1158{
1159 t->size = 10;
1160 t->position = 0;
45e14832 1161 t->array = g_new(void*, t->size);
6cd62ccf 1162}
1163
1164void sequence_dispose(sequence *t)
1165{
1166 t->size = 0;
45e14832 1167 g_free(t->array);
6cd62ccf 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;
45e14832 1177 t->array = g_new(void*, 2*t->size);
6cd62ccf 1178 memcpy(t->array, tmp, t->size * sizeof(void *));
1179 t->size = t->size * 2;
45e14832 1180 g_free(tmp);
6cd62ccf 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++) {
45e14832 1216 if(g_ascii_strcasecmp((char *)key,(char *)t->keys.array[pos]) == 0)
6cd62ccf 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.087011 seconds and 4 git commands to generate.