apply patch by Gabriel Matni to add format string support for event fields
[lttv.git] / ltt / branches / poly / ltt / facility.c
CommitLineData
e8548639 1
449cb9d7 2/* This file is part of the Linux Trace Toolkit viewer
3 * Copyright (C) 2003-2004 Xiangxiu Yang
3aee1200 4 * 2005 Mathieu Desnoyers
449cb9d7 5 *
1b44b0b5 6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License Version 2.1 as published by the Free Software Foundation.
449cb9d7 9 *
1b44b0b5 10 * This library is distributed in the hope that it will be useful,
449cb9d7 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
1b44b0b5 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
449cb9d7 14 *
1b44b0b5 15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the
17 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18 * Boston, MA 02111-1307, USA.
449cb9d7 19 */
20
4e4d11b3 21#ifdef HAVE_CONFIG_H
22#include <config.h>
23#endif
24
6cd62ccf 25#include <stdlib.h>
26#include <string.h>
27#include <stdio.h>
cdf90f40 28#include <glib.h>
45e14832 29#include <sys/types.h>
30#include <sys/stat.h>
31#include <fcntl.h>
32
33
6cd62ccf 34
6cd62ccf 35#include "parser.h"
a5dcde2f 36#include <ltt/ltt.h>
37#include "ltt-private.h"
6cd62ccf 38#include <ltt/facility.h>
39
86005ded 40#ifndef g_open
41#define g_open open
42#endif
43
45e14832 44#define g_close close
45
6cd62ccf 46/* search for the (named) type in the table, if it does not exist
47 create a new one */
90699b2b 48LttType * lookup_named_type(LttFacility *fac, type_descriptor_t * td);
6cd62ccf 49
50/* construct directed acyclic graph for types, and tree for fields */
2312de30 51void construct_fields(LttFacility *fac,
c1161b10 52 LttField *field,
2312de30 53 field_t *fld);
6cd62ccf 54
55/* generate the facility according to the events belongin to it */
8d1e6362 56void generateFacility(LttFacility * f, facility_t * fac,
3aee1200 57 guint32 checksum);
6cd62ccf 58
59/* functions to release the memory occupied by a facility */
963b5f2d 60void freeFacility(LttFacility * facility);
61void freeEventtype(LttEventType * evType);
2312de30 62void freeLttType(LttType * type);
963b5f2d 63void freeLttField(LttField * fld);
908f42fa 64void freeLttNamedType(LttType * type);
6cd62ccf 65
66
e8548639 67/*****************************************************************************
68 *Function name
69 * parse_fmt : parses the format string
70 *Input params
71 * fmt : format string specified in the xml file
72 * header : points to the extracted header string
73 * separator : points to the extracted separator string
74 * footer : points to the extracted footer string
75 *
76 * Parses the format string in order to extract the header,
77 * the separator and the footer.
78 * The default fmt string is: { %S, %S }
79 * In this case:
80 * The header is: {
81 * The separator is: ,
82 * The footer
83 *
84 ****************************************************************************/
85
86parse_fmt(char *fmt, char **header, char **separator, char **footer){
87 int i;
88 unsigned int num = 0;
89
90 int header_index = 0;//header index
91 int separator_index = 0;//separator index
92 int footer_index = 0;//footer index
93 int fmt_length = strlen(fmt);
94
95 for(i=0; i<fmt_length; i++)
96 {
97 if(fmt[i]=='%')
98 {
99 num++;
100 if(num>=3)
101 g_error("More than 2 '%%' chars were encountered: %s\n",fmt);
102
103 //Detecting identifier
104 if(fmt[++i]!='S')
105 g_error("Unexpected format: %s\n",fmt);
106
107 if(i+1<strlen(fmt))
108 i = i+1;
109 else
110 g_error("Unexpected format: %s\n",fmt);
111
112 //Need to have at least on char after the %S
113 if(fmt[i]=='%')
114 g_error("Missing separator: %s\n",fmt);
115
116 if(separator_index==0)
117 separator_index = i;//index of separator inside the original string.
118 else if(footer_index==0)//the 'else' gives the priority to set the separator index first.
119 footer_index = i;//no break since an error should be generated if more than 2 '%' were encountered
120 }
121 }
122
123
124 //Create header String
125 num = separator_index-header_index-2;//(-2 due to '%S')
126 if(num<0)
127 g_error("Unexpected format");
128 //*header = malloc(num+1);//(+1 for EOS).
129 *header = g_new(gchar,num+1);//(+1 for EOS).
130 strncpy(*header,fmt,num);
131 (*header)[num] = '\0';//need EOS, not handled by strncopy
132
133 //Create seperator String
134 num =footer_index - separator_index - 2;
135 if(num<0)
136 g_error("Unexpected format");
137 //*separator = malloc(num+1);//+1 for EOS
138 *separator = g_new(gchar, num+1);//+1 for EOS
139 strncpy(*separator,fmt+separator_index*sizeof(char),num);
140 (*separator)[num] = '\0';//need EOS, not handled by strncopy
141
142 //Create footer String
143 num = strlen(fmt)-footer_index;
144 //*footer = malloc(num+1);
145 *footer = g_new(gchar, num+1);
146 strncpy(*footer,fmt+footer_index*sizeof(char),num);
147 (*footer)[num] = '\0';
148}
149
150/*****************************************************************************
151 *Function name
152 * verify_fmt_syntax : verifies the syntax of the format string
153 *Input params
154 * fmt : format string specified in the xml file
155 * fmt_type : points to the detected type in the fmt string
156 *
157 * Verifies the syntax of the format string sepcified in the xml file
158 * It allows fmt strings having the following syntax:
159 * "..header text... %12.20d ...footer text..."
160 * It sets the fmt_type accordingly. In the previous example
161 * fmt_type would point to the character 'd' inside fmt.
162 *
163 *returns 1 on success, and -1 or -2 on error.
164 *
165 ****************************************************************************/
166
167int verify_fmt_syntax(char *fmt, char **fmt_type){
168 int i;
169 int dot = 0;//number of dots encountered.
170 unsigned short counter = 0;
171 *fmt_type=NULL;
172
173
174 for(i=0; i<strlen(fmt); i++)
175 {
176 if(fmt[i]=='%')
177 {
178 if(++counter==2)
179 return -1;//should generate an error.
180
181 i = i+1;//go to next character
182
183 if(fmt[i]=='-' && i<(strlen(fmt)-1))
184 i++;//allow this character after the '%'
185
186 if(fmt[i]=='#' && i<(strlen(fmt)-1))
187 i++;//allow this character
188 }
189
190 if(counter ==1 && !isdigit(fmt[i]) && *fmt_type==NULL)
191 switch (fmt[i]){
192 case 'd':
193 case 'i':
194 case 'u':
195 case 'o':
196 case 'x':
197 case 'X':
198 case 'f':
199 case 'e':
200 case 'E':
201 case 's':
202 case 'p':
203 *fmt_type=&fmt[i];
204 break;
205 //do not return yet. may encounter another '%'
206 case '.':
207 if(++dot==2)
208 return -2;//generate error
209 break;
210 default:
211 return -1;
212 }
213
214 }
215
216 return 1;
217
218}
219
220/*****************************************************************************
221 *Function name
222 * append_ll : appends "ll" to the format string
223 *Input params
224 * fmt : format string specified in the xml file
225 * fmt_type : address of the format char inside fmt
226 *
227 * inserts "ll" just before the fmt_type
228 *
229 ****************************************************************************/
230
231void append_ll (char **fmt, char **fmt_type){
232 char *new_fmt;
233 int i;
234 int num;
235
236
237 //new_fmt = malloc(strlen(*fmt)*sizeof(char)+2);//the +2 corresponds the the "ll";
238 new_fmt = g_new(gchar, strlen(*fmt)+2);
239
240 num = *fmt_type - *fmt;
241
242 for(i=0; i<num;i++)
243 new_fmt[i] =(*fmt)[i];
244
245 new_fmt[i++] = 'l';
246 new_fmt[i++] = 'l';
247
248
249 while(i-2<strlen(*fmt))
250 {
251 new_fmt[i]=(*fmt)[i-2];
252 i++;
253 }
254
255 *fmt = new_fmt;
256 (*fmt)[i] = '\0';
257
258}
259
260
6cd62ccf 261/*****************************************************************************
262 *Function name
963b5f2d 263 * ltt_facility_open : open facilities
6cd62ccf 264 *Input params
963b5f2d 265 * t : the trace containing the facilities
6cd62ccf 266 * pathname : the path name of the facility
3aee1200 267 *
29e7c5b3 268 * Open the facility corresponding to the right checksum.
269 *
3aee1200 270 *returns 0 on success, 1 on error.
6cd62ccf 271 ****************************************************************************/
272
3aee1200 273int ltt_facility_open(LttFacility *f, LttTrace * t, gchar * pathname)
6cd62ccf 274{
a0c1f622 275 int ret = 0;
45e14832 276 gchar *token;
90699b2b 277 parse_file_t in;
8d1e6362 278 facility_t * fac;
2312de30 279 unsigned int checksum;
45e14832 280 gchar buffer[BUFFER_SIZE];
29e7c5b3 281 gboolean generated = FALSE;
6cd62ccf 282
45e14832 283 in.buffer = &(buffer[0]);
6cd62ccf 284 in.lineno = 0;
285 in.error = error_callback;
963b5f2d 286 in.name = pathname;
ba8a51cd 287 in.unget = 0;
6cd62ccf 288
90699b2b 289 in.fp = fopen(in.name, "r");
cb03932a 290 if(in.fp == NULL) {
3aee1200 291 g_warning("cannot open facility description file %s",
292 in.name);
a0c1f622 293 ret = 1;
294 goto open_error;
3aee1200 295 }
45e14832 296
6cd62ccf 297 while(1){
298 token = getToken(&in);
299 if(in.type == ENDFILE) break;
e6d018d4 300
c1161b10 301 if(g_ascii_strcasecmp(token, "<")) in.error(&in,"not a facility file");
302 token = getName(&in);
303 if(g_ascii_strcasecmp(token, "?")) in.error(&in,"not a facility file");
304 token = getName(&in);
305 if(g_ascii_strcasecmp(token, "xml")) in.error(&in,"not a facility file");
306 token = getName(&in);
307 if(g_ascii_strcasecmp(token, "version")) in.error(&in,"not a facility file");
308 token = getName(&in);
309 if(g_ascii_strcasecmp(token, "=")) in.error(&in,"not a facility file");
310 token = getQuotedString(&in);
311 if(g_ascii_strcasecmp(token, "1.0")) in.error(&in,"not a facility file");
312 token = getName(&in);
313 if(g_ascii_strcasecmp(token, "?")) in.error(&in,"not a facility file");
314 token = getToken(&in);
315 if(g_ascii_strcasecmp(token, ">")) in.error(&in,"not a facility file");
316
317 token = getToken(&in);
318
45e14832 319 if(g_ascii_strcasecmp(token, "<")) in.error(&in,"not a facility file");
963b5f2d 320 token = getName(&in);
45e14832 321
322 if(g_ascii_strcasecmp("facility",token) == 0) {
8d1e6362 323 fac = g_new(facility_t, 1);
963b5f2d 324 fac->name = NULL;
325 fac->description = NULL;
326 sequence_init(&(fac->events));
327 table_init(&(fac->named_types));
328 sequence_init(&(fac->unnamed_types));
329
330 parseFacility(&in, fac);
331
332 //check if any namedType is not defined
90699b2b 333 checkNamedTypesImplemented(&fac->named_types);
963b5f2d 334
90699b2b 335 generateChecksum(fac->name, &checksum, &fac->events);
cba098f3 336 // FIXME if(checksum == f->checksum) {
29e7c5b3 337 generateFacility(f, fac, checksum);
338 generated = TRUE;
cba098f3 339 //}
340 if (checksum != f->checksum)
341 g_warning("Facility checksum mismatch for facility %s : kernel 0x%X vs "
342 "XML 0x%X\n", fac->name, f->checksum, checksum);
963b5f2d 343
45e14832 344 g_free(fac->name);
d2ace3a9 345 free(fac->capname);
45e14832 346 g_free(fac->description);
963b5f2d 347 freeEvents(&fac->events);
348 sequence_dispose(&fac->events);
349 freeNamedType(&fac->named_types);
350 table_dispose(&fac->named_types);
351 freeTypes(&fac->unnamed_types);
352 sequence_dispose(&fac->unnamed_types);
cf1307af 353 g_free(fac);
129fd24a 354 if(generated) break; /* use the first good match */
6cd62ccf 355 }
3aee1200 356 else {
357 g_warning("facility token was expected in file %s", in.name);
a0c1f622 358 ret = 1;
3aee1200 359 goto parse_error;
360 }
6cd62ccf 361 }
29e7c5b3 362
3aee1200 363 parse_error:
90699b2b 364 fclose(in.fp);
a0c1f622 365open_error:
90699b2b 366
986e2a7c 367 if(!generated) {
368 g_warning("Cannot find facility %s, checksum 0x%X",
369 g_quark_to_string(f->name), f->checksum);
370 ret = 1;
371 }
29e7c5b3 372
a0c1f622 373 return ret;
6cd62ccf 374}
375
376
377/*****************************************************************************
378 *Function name
379 * generateFacility : generate facility, internal function
380 *Input params
963b5f2d 381 * facility : LttFacilty structure
382 * fac : facility structure
6cd62ccf 383 * checksum : checksum of the facility
6cd62ccf 384 ****************************************************************************/
385
3aee1200 386void generateFacility(LttFacility *f, facility_t *fac, guint32 checksum)
6cd62ccf 387{
963b5f2d 388 char * facilityName = fac->name;
90699b2b 389 sequence_t * events = &fac->events;
f104d082 390 unsigned int i, j;
963b5f2d 391 LttType * type;
f104d082 392 table_t *named_types = &fac->named_types;
6cd62ccf 393
3aee1200 394 g_assert(f->name == g_quark_from_string(facilityName));
cba098f3 395 //g_assert(f->checksum == checksum);
3aee1200 396
397 //f->event_number = events->position;
6cd62ccf 398
399 //initialize inner structures
3aee1200 400 f->events = g_array_sized_new (FALSE, TRUE, sizeof(LttEventType),
401 events->position);
402 //f->events = g_new(LttEventType*,f->event_number);
403 f->events = g_array_set_size(f->events, events->position);
404
405 g_datalist_init(&f->events_by_name);
2312de30 406 // g_datalist_init(&f->named_types);
f104d082 407#if 0
408 /* The first day, he created the named types */
409
410 for(i=0; i<named_types->keys.position; i++) {
411 GQuark name = g_quark_from_string((char*)named_types->keys.array[i]);
412 type_descriptor_t *td = (type_descriptor_t*)named_types->values.array[i];
413
414 /* Create the type */
415 type = g_new(LttType,1);
416 type->type_name = name;
417 type->type_class = td->type;
418 if(td->fmt) type->fmt = g_strdup(td->fmt);
419 else type->fmt = NULL;
420 type->size = td->size;
421 type->enum_strings = NULL;
422 type->element_type = NULL;
423 type->element_number = 0;
424
425 construct_types_and_fields(type, td, NULL, NULL, ...);
426
427 g_datalist_id_set_data_full(&fac->named_types, name,
428 type, (GDestroyNotify)freeLttNamedType);
429
430 }
431#endif //0
432 /* The second day, he created the event fields and types */
433 //for each event, construct field and type acyclic graph
6cd62ccf 434 for(i=0;i<events->position;i++){
c1161b10 435 event_t *parser_event = (event_t*)events->array[i];
f104d082 436 LttEventType *event_type = &g_array_index(f->events, LttEventType, i);
6cd62ccf 437
3aee1200 438 event_type->name =
f104d082 439 g_quark_from_string(parser_event->name);
3aee1200 440
441 g_datalist_id_set_data(&f->events_by_name, event_type->name,
442 event_type);
443
444 event_type->description =
f104d082 445 g_strdup(parser_event->description);
6cd62ccf 446
3aee1200 447 event_type->index = i;
f104d082 448 event_type->facility = f;
6cd62ccf 449
dd3a6d39 450 event_type->has_compact_data = parser_event->compact_data;
451
f104d082 452 event_type->fields = g_array_sized_new(FALSE, TRUE,
453 sizeof(LttField), parser_event->fields.position);
454 event_type->fields =
455 g_array_set_size(event_type->fields, parser_event->fields.position);
456 g_datalist_init(&event_type->fields_by_name);
457
458 for(j=0; j<parser_event->fields.position; j++) {
459 LttField *field = &g_array_index(event_type->fields, LttField, j);
460 field_t *parser_field = (field_t*)parser_event->fields.array[j];
461
2312de30 462 construct_fields(f, field, parser_field);
f104d082 463 g_datalist_id_set_data(&event_type->fields_by_name,
464 field->name,
465 field);
8710c6c7 466 }
f104d082 467 }
468
469 /* What about 2 days weeks ? */
6cd62ccf 470}
471
472
473/*****************************************************************************
474 *Function name
3aee1200 475 * construct_types_and_fields : construct field tree and type graph,
6cd62ccf 476 * internal recursion function
477 *Input params
478 * fac : facility struct
f104d082 479 * field : destination lttv field
480 * fld : source parser field
6cd62ccf 481 ****************************************************************************/
482
f104d082 483//DONE
484//make the change for arrays and sequences
485//no more root field. -> change this for an array of fields.
486// Compute the field size here.
487// Flag fields as "VARIABLE OFFSET" or "FIXED OFFSET" : as soon as
488// a field with a variable size is found, all the following fields must
489// be flagged with "VARIABLE OFFSET", this will be done by the offset
490// precomputation.
491
3aee1200 492
f104d082 493void construct_fields(LttFacility *fac,
c1161b10 494 LttField *field,
f104d082 495 field_t *fld)
496{
e8548639 497 char *fmt_type;//gaby
f104d082 498 guint len;
499 type_descriptor_t *td;
2312de30 500 LttType *type;
f104d082 501
c1161b10 502 if(fld->name)
503 field->name = g_quark_from_string(fld->name);
504 else
505 fld->name = 0;
ae3d0f50 506
f104d082 507 if(fld->description) {
508 len = strlen(fld->description);
509 field->description = g_new(gchar, len+1);
510 strcpy(field->description, fld->description);
511 }
512 field->dynamic_offsets = NULL;
513 type = &field->field_type;
514 td = fld->type;
515
516 type->enum_map = NULL;
517 type->fields = NULL;
518 type->fields_by_name = NULL;
c1161b10 519 type->network = td->network;
743e50fd 520
f104d082 521 switch(td->type) {
522 case INT_FIXED:
523 type->type_class = LTT_INT_FIXED;
524 type->size = td->size;
525 break;
526 case UINT_FIXED:
527 type->type_class = LTT_UINT_FIXED;
528 type->size = td->size;
529 break;
530 case POINTER:
531 type->type_class = LTT_POINTER;
532 type->size = fac->pointer_size;
533 break;
534 case CHAR:
535 type->type_class = LTT_CHAR;
536 type->size = td->size;
537 break;
538 case UCHAR:
539 type->type_class = LTT_UCHAR;
540 type->size = td->size;
743e50fd 541 g_assert(type->size != 0);
f104d082 542 break;
543 case SHORT:
544 type->type_class = LTT_SHORT;
545 type->size = td->size;
546 break;
547 case USHORT:
548 type->type_class = LTT_USHORT;
549 type->size = td->size;
550 break;
551 case INT:
552 type->type_class = LTT_INT;
553 type->size = fac->int_size;
554 break;
555 case UINT:
556 type->type_class = LTT_UINT;
557 type->size = fac->int_size;
743e50fd 558 g_assert(type->size != 0);
f104d082 559 break;
560 case LONG:
561 type->type_class = LTT_LONG;
562 type->size = fac->long_size;
563 break;
564 case ULONG:
565 type->type_class = LTT_ULONG;
566 type->size = fac->long_size;
567 break;
568 case SIZE_T:
569 type->type_class = LTT_SIZE_T;
570 type->size = fac->size_t_size;
571 break;
572 case SSIZE_T:
573 type->type_class = LTT_SSIZE_T;
574 type->size = fac->size_t_size;
575 break;
576 case OFF_T:
577 type->type_class = LTT_OFF_T;
578 type->size = fac->size_t_size;
579 break;
580 case FLOAT:
581 type->type_class = LTT_FLOAT;
582 type->size = td->size;
583 break;
584 case STRING:
585 type->type_class = LTT_STRING;
586 type->size = 0;
587 break;
588 case ENUM:
589 type->type_class = LTT_ENUM;
590 type->size = fac->int_size;
591 {
592 guint i;
743e50fd 593 type->enum_map = g_hash_table_new(g_direct_hash, g_direct_equal);
880fded3 594 type->lowest_value = G_MAXINT32;
595 type->highest_value = G_MININT32;
f104d082 596 for(i=0; i<td->labels.position; i++) {
2312de30 597 GQuark value = g_quark_from_string((char*)td->labels.array[i]);
598 gint key = *(int*)td->labels_values.array[i];
599 g_hash_table_insert(type->enum_map, (gpointer)key, (gpointer)value);
880fded3 600 type->highest_value = max(key, type->highest_value);
601 type->lowest_value = min(key, type->lowest_value);
f104d082 602 }
603 }
743e50fd 604 g_assert(type->size != 0);
f104d082 605 break;
606 case ARRAY:
607 type->type_class = LTT_ARRAY;
608 type->size = td->size;
609 type->fields = g_array_sized_new(FALSE, TRUE, sizeof(LttField),
610 td->fields.position);
611 type->fields = g_array_set_size(type->fields, td->fields.position);
612 {
613 guint i;
614
615 for(i=0; i<td->fields.position; i++) {
616 field_t *schild = (field_t*)td->fields.array[i];
617 LttField *dchild = &g_array_index(type->fields, LttField, i);
618
619 construct_fields(fac, dchild, schild);
620 }
621 }
622 break;
623 case SEQUENCE:
624 type->type_class = LTT_SEQUENCE;
625 type->size = 0;
626 type->fields = g_array_sized_new(FALSE, TRUE, sizeof(LttField),
627 td->fields.position);
628 type->fields = g_array_set_size(type->fields, td->fields.position);
629 {
630 guint i;
631
632 for(i=0; i<td->fields.position; i++) {
633 field_t *schild = (field_t*)td->fields.array[i];
634 LttField *dchild = &g_array_index(type->fields, LttField, i);
635
636 construct_fields(fac, dchild, schild);
637 }
638 }
639 break;
640 case STRUCT:
641 type->type_class = LTT_STRUCT;
642 type->size = 0; // Size not calculated by the parser.
643 type->fields = g_array_sized_new(FALSE, TRUE, sizeof(LttField),
644 td->fields.position);
645 type->fields = g_array_set_size(type->fields, td->fields.position);
646 g_datalist_init(&type->fields_by_name);
647 {
648 guint i;
649
650 for(i=0; i<td->fields.position; i++) {
651 field_t *schild = (field_t*)td->fields.array[i];
652 LttField *dchild = &g_array_index(type->fields, LttField, i);
653
654 construct_fields(fac, dchild, schild);
655 g_datalist_id_set_data(&type->fields_by_name,
656 dchild->name,
657 dchild);
658 }
659 }
660 break;
661 case UNION:
662 type->type_class = LTT_UNION;
663 type->size = 0; // Size not calculated by the parser.
664 type->fields = g_array_sized_new(FALSE, TRUE, sizeof(LttField),
665 td->fields.position);
666 type->fields = g_array_set_size(type->fields, td->fields.position);
667 g_datalist_init(&type->fields_by_name);
668 {
669 guint i;
670
671 for(i=0; i<td->fields.position; i++) {
672 field_t *schild = (field_t*)td->fields.array[i];
673 LttField *dchild = &g_array_index(type->fields, LttField, i);
674
675 construct_fields(fac, dchild, schild);
676 g_datalist_id_set_data(&type->fields_by_name,
677 dchild->name,
678 dchild);
679 }
680 }
681 break;
682 case NONE:
683 default:
684 g_error("construct_fields : unknown type");
685 }
686
687 field->field_size = type->size;
688
689 /* Put the fields as "variable" offset to root first. Then,
690 * the offset precomputation will only have to set the FIELD_FIXED until
691 * it reaches the first variable length field, then stop.
692 */
693 field->fixed_root = FIELD_VARIABLE;
694
695 if(td->fmt) {
696 len = strlen(td->fmt);
697 type->fmt = g_new(gchar, len+1);
698 strcpy(type->fmt, td->fmt);
699 }
e8548639 700 //here I should verify syntax based on type.
701 //if type is array or sequence or enum, parse_fmt.
702 //if type is basic, verify syntax, and allow or not the type format.
703 //the code can be integrated in the above code (after testing)
704
705
706
707 switch (type->type_class){
708 case LTT_ARRAY:
709 case LTT_UNION:
710 case LTT_STRUCT:
711 case LTT_SEQUENCE:
712 if(type->fmt==NULL)
713 {
714 //Assign a default format for these complex types
715 //type->fmt = malloc(11*sizeof(char));
716 type->fmt = g_new(gchar, 11);
717 type->fmt = g_strdup("{ %S, %S }");//set a default value for fmt. can directly set header and footer, but kept this way on purpose.
718 }
719 //Parse the fmt string in order to extract header, separator and footer
720 parse_fmt(type->fmt,&(type->header),&(type->separator),&(type->footer));
721
722 break;
723 case LTT_SHORT:
724 case LTT_INT:
725 case LTT_LONG:
726 case LTT_SSIZE_T:
727 case LTT_INT_FIXED:
728
729 if(type->fmt == NULL)
730 {
731 //Assign a default format string
732 //type->fmt = malloc(5*sizeof(char));
733 type->fmt = g_new(gchar, 5);
734 type->fmt=g_strdup("%lld");
735 break;
736 }
737 else
738 if(verify_fmt_syntax((type->fmt),&fmt_type)>0)
739 switch(fmt_type[0]){
740 case 'd':
741 case 'i':
742 case 'x':
743 case 'X':
744 append_ll(&(type->fmt),&fmt_type);//append 'll' to fmt
745 break;
746 default:
747 g_error("Format type '%c' not supported\n",fmt_type[0]);
748 break;
749 }
750 break;
751
752 case LTT_USHORT:
753 case LTT_UINT:
754 case LTT_ULONG:
755 case LTT_SIZE_T:
756 case LTT_OFF_T:
757 case LTT_UINT_FIXED:
758 if(type->fmt == NULL)
759 {
760 //Assign a default format string
761 //type->fmt= malloc(5*sizeof(char));
762 type->fmt = g_new(gchar, 5);
763 type->fmt=g_strdup("%lld");
764 break;
765 }
766 else
767 if(verify_fmt_syntax((type->fmt),&fmt_type)>0)
768 switch(fmt_type[0]){
769 case 'd':
770 case 'u':
771 case 'o':
772 case 'x':
773 case 'X':
774 append_ll(&(type->fmt),&fmt_type);
775 break;
776 default:
777 g_error("Format type '%c' not supported\n",fmt_type[0]);
778 }
779 break;
780
781 case LTT_CHAR:
782 case LTT_UCHAR:
783 if(type->fmt == NULL)
784 {
785 //Assign a default format string
786 //type->fmt = malloc(3*sizeof(char));
787 type->fmt = g_new(gchar, 3);
788 type->fmt = g_strdup("%c");
789 break;
790 }
791 else
792 if(verify_fmt_syntax((type->fmt),&fmt_type)>1)
793 switch(fmt_type[0]){
794 case 'c':
795 case 'd':
796 case 'u':
797 case 'x':
798 case 'X':
799 case 'o':
800 break;
801 default:
802 g_error("Format type '%c' not supported\n",fmt_type[0]);
803 }
804 break;
805
806 case LTT_FLOAT:
807 if(type->fmt == NULL)
808 {
809 //Assign a default format string
810 //type->fmt = malloc(3*sizeof(char));
811 type->fmt = g_new(gchar, 3);
812 type->fmt = g_strdup("%g");
813 break;
814 }
815 else
816 if(verify_fmt_syntax((type->fmt),&fmt_type)>0)
817 switch(fmt_type[0]){
818 case 'f':
819 case 'g':
820 case 'G':
821 case 'e':
822 case 'E':
823 break;
824 default:
825 g_error("Format type '%c' not supported\n",fmt_type[0]);
826 }
827 break;
828
829 case LTT_POINTER:
830 if(type->fmt == NULL)
831 {
832 //Assign a default format string
833 //type->fmt = malloc(7*sizeof(char));
834 type->fmt = g_new(gchar, 7);
835 type->fmt = g_strdup("0x%llx");
836 break;
837 }
838 else
839 if(verify_fmt_syntax((type->fmt),&fmt_type)>0)
840 switch(fmt_type[0]){
841 case 'p':
842 //type->fmt = malloc(7*sizeof(char));
843 type->fmt = g_new(gchar, 7);
844 type->fmt = g_strdup("0x%llx");
845 break;
846 case 'x':
847 case 'X':
848 case 'd':
849 append_ll(&(type->fmt),&fmt_type);
850 break;
851 default:
852 g_error("Format type '%c' not supported\n",fmt_type[0]);
853 }
854 break;
855
856 case LTT_STRING:
857 if(type->fmt == NULL)
858 {
859 //type->fmt = malloc(7*sizeof(char));
860 type->fmt = g_new(gchar, 5);
861 type->fmt = g_strdup("\"%s\"");//default value for fmt.
862 break;
863 }
864 else
865 if(verify_fmt_syntax((type->fmt),&fmt_type)>0)
866 switch(fmt_type[0]){
867 case 's':
868 break;
869 default:
870 g_error("Format type '%c' not supported\n", fmt_type[0]);
871 }
872 break;
873
874 default:
875 //missing enum
876 break;
877 }
f104d082 878
879
e8548639 880}
f104d082 881
882#if 0
90699b2b 883void construct_types_and_fields(LttFacility * fac, type_descriptor_t * td,
3aee1200 884 LttField * fld)
885{
a0c1f622 886 int i;
90699b2b 887 type_descriptor_t * tmpTd;
3aee1200 888
889 switch(td->type) {
cb03932a 890 case INT:
891 case UINT:
892 case FLOAT:
893 fld->field_type->size = td->size;
894 break;
895 case POINTER:
896 case LONG:
897 case ULONG:
898 case SIZE_T:
899 case SSIZE_T:
900 case OFF_T:
901 fld->field_type->size = 0;
902 break;
903 case STRING:
904 fld->field_type->size = 0;
905 break;
906 case ENUM:
907 fld->field_type->element_number = td->labels.position;
908 fld->field_type->enum_strings = g_new(GQuark,td->labels.position);
909 for(i=0;i<td->labels.position;i++){
910 fld->field_type->enum_strings[i]
911 = g_quark_from_string(((char*)(td->labels.array[i])));
912 }
913 fld->field_type->size = td->size;
914 break;
915
916 case ARRAY:
917 fld->field_type->element_number = (unsigned)td->size;
918 case SEQUENCE:
3aee1200 919 fld->field_type->element_type = g_new(LttType*,1);
920 tmpTd = td->nested_type;
921 fld->field_type->element_type[0] = lookup_named_type(fac, tmpTd);
922 fld->child = g_new(LttField*, 1);
923 fld->child[0] = g_new(LttField, 1);
924
925 fld->child[0]->field_type = fld->field_type->element_type[0];
926 fld->child[0]->offset_root = 0;
927 fld->child[0]->fixed_root = FIELD_UNKNOWN;
928 fld->child[0]->offset_parent = 0;
929 fld->child[0]->fixed_parent = FIELD_UNKNOWN;
930 fld->child[0]->field_size = 0;
931 fld->child[0]->fixed_size = FIELD_UNKNOWN;
932 fld->child[0]->parent = fld;
933 fld->child[0]->child = NULL;
934 fld->child[0]->current_element = 0;
935 construct_types_and_fields(fac, tmpTd, fld->child[0]);
936 break;
cb03932a 937
938 case STRUCT:
939 case UNION:
3aee1200 940 fld->field_type->element_number = td->fields.position;
941
942 g_assert(fld->field_type->element_type == NULL);
943 fld->field_type->element_type = g_new(LttType*, td->fields.position);
944
945 fld->child = g_new(LttField*, td->fields.position);
946 for(i=0;i<td->fields.position;i++){
90699b2b 947 tmpTd = ((field_t*)(td->fields.array[i]))->type;
3aee1200 948
c1161b10 949 fld->field_type->element_type[i] = lookup_named_type(fac, tmpTd);
3aee1200 950 fld->child[i] = g_new(LttField,1);
951
952 // fld->child[i]->field_pos = i;
953 fld->child[i]->field_type = fld->field_type->element_type[i];
954
955 fld->child[i]->field_type->element_name
c1161b10 956 = g_quark_from_string(((field_t*)(td->fields.array[i]))->name);
3aee1200 957
958 fld->child[i]->offset_root = 0;
959 fld->child[i]->fixed_root = FIELD_UNKNOWN;
960 fld->child[i]->offset_parent = 0;
961 fld->child[i]->fixed_parent = FIELD_UNKNOWN;
962 fld->child[i]->field_size = 0;
963 fld->child[i]->fixed_size = FIELD_UNKNOWN;
964 fld->child[i]->parent = fld;
965 fld->child[i]->child = NULL;
966 fld->child[i]->current_element = 0;
967 construct_types_and_fields(fac, tmpTd, fld->child[i]);
968 }
3aee1200 969 break;
cb03932a 970
3aee1200 971 default:
972 g_error("construct_types_and_fields : unknown type");
973 }
974
975
976}
977
f104d082 978#endif //0
3aee1200 979
980#if 0
981void construct_types_and_fields(LttFacility * fac, type_descriptor * td,
963b5f2d 982 LttField * fld)
6cd62ccf 983{
908f42fa 984 int i, flag;
6cd62ccf 985 type_descriptor * tmpTd;
986
987 // if(td->type == LTT_STRING || td->type == LTT_SEQUENCE)
988 // fld->field_size = 0;
989 // else fld->field_size = -1;
990
991 if(td->type == LTT_ENUM){
992 fld->field_type->element_number = td->labels.position;
3aee1200 993 fld->field_type->enum_strings = g_new(GQuark,td->labels.position);
6cd62ccf 994 for(i=0;i<td->labels.position;i++){
995 fld->field_type->enum_strings[i]
3aee1200 996 = g_quark_from_string(((char*)(td->labels.array[i])));
6cd62ccf 997 }
998 }else if(td->type == LTT_ARRAY || td->type == LTT_SEQUENCE){
999 if(td->type == LTT_ARRAY)
1000 fld->field_type->element_number = (unsigned)td->size;
963b5f2d 1001 fld->field_type->element_type = g_new(LttType*,1);
6cd62ccf 1002 tmpTd = td->nested_type;
1003 fld->field_type->element_type[0] = lookup_named_type(fac, tmpTd);
963b5f2d 1004 fld->child = g_new(LttField*, 1);
1005 fld->child[0] = g_new(LttField, 1);
6cd62ccf 1006
3aee1200 1007// fld->child[0]->field_pos = 0;
6cd62ccf 1008 fld->child[0]->field_type = fld->field_type->element_type[0];
1009 fld->child[0]->offset_root = fld->offset_root;
1010 fld->child[0]->fixed_root = fld->fixed_root;
1011 fld->child[0]->offset_parent = 0;
1012 fld->child[0]->fixed_parent = 1;
1013 // fld->child[0]->base_address = NULL;
1014 fld->child[0]->field_size = 0;
1015 fld->child[0]->field_fixed = -1;
1016 fld->child[0]->parent = fld;
1017 fld->child[0]->child = NULL;
1018 fld->child[0]->current_element = 0;
3aee1200 1019 construct_types_and_fields(fac, tmpTd, fld->child[0]);
6cd62ccf 1020 }else if(td->type == LTT_STRUCT){
1021 fld->field_type->element_number = td->fields.position;
908f42fa 1022
1023 if(fld->field_type->element_type == NULL){
1024 fld->field_type->element_type = g_new(LttType*, td->fields.position);
1025 flag = 1;
1026 }else{
1027 flag = 0;
1028 }
1029
963b5f2d 1030 fld->child = g_new(LttField*, td->fields.position);
6cd62ccf 1031 for(i=0;i<td->fields.position;i++){
8d1e6362 1032 tmpTd = ((type_fields*)(td->fields.array[i]))->type;
908f42fa 1033
1034 if(flag)
c1161b10 1035 fld->field_type->element_type[i] = lookup_named_type(fac, tmpTd);
963b5f2d 1036 fld->child[i] = g_new(LttField,1);
6cd62ccf 1037
1038 fld->child[i]->field_pos = i;
1039 fld->child[i]->field_type = fld->field_type->element_type[i];
908f42fa 1040
1041 if(flag){
c1161b10 1042 fld->child[i]->field_type->element_name
1043 = g_quark_from_string(((type_fields*)(td->fields.array[i]))->name);
908f42fa 1044 }
1045
6cd62ccf 1046 fld->child[i]->offset_root = -1;
1047 fld->child[i]->fixed_root = -1;
1048 fld->child[i]->offset_parent = -1;
1049 fld->child[i]->fixed_parent = -1;
1050 // fld->child[i]->base_address = NULL;
1051 fld->child[i]->field_size = 0;
1052 fld->child[i]->field_fixed = -1;
1053 fld->child[i]->parent = fld;
1054 fld->child[i]->child = NULL;
1055 fld->child[i]->current_element = 0;
3aee1200 1056 construct_types_and_fields(fac, tmpTd, fld->child[i]);
6cd62ccf 1057 }
1058 }
1059}
3aee1200 1060#endif //0
6cd62ccf 1061
f104d082 1062#if 0
6cd62ccf 1063/*****************************************************************************
1064 *Function name
1065 * lookup_named_type: search named type in the table
1066 * internal function
1067 *Input params
1068 * fac : facility struct
f104d082 1069 * name : type name
6cd62ccf 1070 *Return value
963b5f2d 1071 * : either find the named type, or create a new LttType
6cd62ccf 1072 ****************************************************************************/
1073
f104d082 1074LttType * lookup_named_type(LttFacility *fac, GQuark type_name)
6cd62ccf 1075{
cb03932a 1076 LttType *type = NULL;
6cd62ccf 1077
f104d082 1078 /* Named type */
1079 type = g_datalist_id_get_data(&fac->named_types, name);
1080
1081 g_assert(type != NULL);
1082#if 0
3aee1200 1083 if(type == NULL){
cb03932a 1084 /* Create the type */
3aee1200 1085 type = g_new(LttType,1);
1086 type->type_name = name;
3aee1200 1087 type->type_class = td->type;
1088 if(td->fmt) type->fmt = g_strdup(td->fmt);
1089 else type->fmt = NULL;
1090 type->size = td->size;
1091 type->enum_strings = NULL;
1092 type->element_type = NULL;
1093 type->element_number = 0;
cb03932a 1094
1095 if(td->type_name != NULL)
1096 g_datalist_id_set_data_full(&fac->named_types, name,
1097 type, (GDestroyNotify)freeLttNamedType);
6cd62ccf 1098 }
f104d082 1099#endif //0
3aee1200 1100 return type;
6cd62ccf 1101}
f104d082 1102#endif //0
6cd62ccf 1103
1104/*****************************************************************************
1105 *Function name
1106 * ltt_facility_close : close a facility, decrease its usage count,
1107 * if usage count = 0, release the memory
1108 *Input params
1109 * f : facility that will be closed
6cd62ccf 1110 ****************************************************************************/
1111
3aee1200 1112void ltt_facility_close(LttFacility *f)
6cd62ccf 1113{
6cd62ccf 1114 //release the memory it occupied
1115 freeFacility(f);
6cd62ccf 1116}
1117
1118/*****************************************************************************
1119 * Functions to release the memory occupied by the facility
1120 ****************************************************************************/
1121
963b5f2d 1122void freeFacility(LttFacility * fac)
6cd62ccf 1123{
3aee1200 1124 guint i;
1125 LttEventType *et;
6cd62ccf 1126
3aee1200 1127 for(i=0; i<fac->events->len; i++) {
1128 et = &g_array_index (fac->events, LttEventType, i);
1129 freeEventtype(et);
6cd62ccf 1130 }
3aee1200 1131 g_array_free(fac->events, TRUE);
6cd62ccf 1132
f104d082 1133 g_datalist_clear(&fac->events_by_name);
6cd62ccf 1134
f104d082 1135 // g_datalist_clear(&fac->named_types);
6cd62ccf 1136}
1137
963b5f2d 1138void freeEventtype(LttEventType * evType)
6cd62ccf 1139{
f104d082 1140 unsigned int i;
908f42fa 1141 LttType * root_type;
6cd62ccf 1142 if(evType->description)
f104d082 1143 g_free(evType->description);
1144
1145 for(i=0; i<evType->fields->len;i++) {
2312de30 1146 LttField *field = &g_array_index(evType->fields, LttField, i);
1147 freeLttField(field);
1417d990 1148 }
f104d082 1149 g_array_free(evType->fields, TRUE);
1150 g_datalist_clear(&evType->fields_by_name);
1151}
1152
1153void freeLttType(LttType * type)
1154{
1155 unsigned int i;
1156
1157 if(type->fmt)
1158 g_free(type->fmt);
1159
1160 if(type->enum_map)
2312de30 1161 g_hash_table_destroy(type->enum_map);
f104d082 1162
1163 if(type->fields) {
1164 for(i=0; i<type->fields->len; i++) {
1165 freeLttField(&g_array_index(type->fields, LttField, i));
1166 }
1167 g_array_free(type->fields, TRUE);
1168 }
1169 if(type->fields_by_name)
1170 g_datalist_clear(&type->fields_by_name);
e8548639 1171
1172 if(type->header)
1173 g_free(type->header);//no need for condition? if(type->header)
1174 if(type->separator)
1175 g_free(type->separator);
1176 if(type->footer)
1177 g_free(type->footer);
6cd62ccf 1178}
1179
908f42fa 1180void freeLttNamedType(LttType * type)
1181{
f104d082 1182 freeLttType(type);
908f42fa 1183}
1184
f104d082 1185void freeLttField(LttField * field)
1417d990 1186{
f104d082 1187 if(field->description)
1188 g_free(field->description);
1189 if(field->dynamic_offsets)
1190 g_array_free(field->dynamic_offsets, TRUE);
2312de30 1191 freeLttType(&field->field_type);
6cd62ccf 1192}
1193
1194/*****************************************************************************
1195 *Function name
1196 * ltt_facility_name : obtain the facility's name
1197 *Input params
3aee1200 1198 * f : the facility
6cd62ccf 1199 *Return value
3aee1200 1200 * GQuark : the facility's name
6cd62ccf 1201 ****************************************************************************/
1202
3aee1200 1203GQuark ltt_facility_name(LttFacility *f)
6cd62ccf 1204{
1205 return f->name;
1206}
1207
1208/*****************************************************************************
1209 *Function name
1210 * ltt_facility_checksum : obtain the facility's checksum
1211 *Input params
3aee1200 1212 * f : the facility
6cd62ccf 1213 *Return value
3aee1200 1214 * : the checksum of the facility
6cd62ccf 1215 ****************************************************************************/
1216
3aee1200 1217guint32 ltt_facility_checksum(LttFacility *f)
6cd62ccf 1218{
1219 return f->checksum;
1220}
1221
963b5f2d 1222/*****************************************************************************
1223 *Function name
1224 * ltt_facility_base_id : obtain the facility base id
1225 *Input params
1226 * f : the facility
1227 *Return value
1228 * : the base id of the facility
1229 ****************************************************************************/
1230
3aee1200 1231guint ltt_facility_id(LttFacility *f)
963b5f2d 1232{
3aee1200 1233 return f->id;
963b5f2d 1234}
1235
6cd62ccf 1236/*****************************************************************************
1237 *Function name
1238 * ltt_facility_eventtype_number: obtain the number of the event types
1239 *Input params
1240 * f : the facility that will be closed
1241 *Return value
3aee1200 1242 * : the number of the event types
6cd62ccf 1243 ****************************************************************************/
1244
3aee1200 1245guint8 ltt_facility_eventtype_number(LttFacility *f)
6cd62ccf 1246{
3aee1200 1247 return (f->events->len);
6cd62ccf 1248}
1249
1250/*****************************************************************************
1251 *Function name
1252 * ltt_facility_eventtype_get: obtain the event type according to event id
1253 * from 0 to event_number - 1
1254 *Input params
1255 * f : the facility that will be closed
1256 *Return value
963b5f2d 1257 * LttEventType * : the event type required
6cd62ccf 1258 ****************************************************************************/
1259
3aee1200 1260LttEventType *ltt_facility_eventtype_get(LttFacility *f, guint8 i)
6cd62ccf 1261{
c4afd5d8 1262 if(!f->exists) return NULL;
1263
3aee1200 1264 g_assert(i < f->events->len);
1265 return &g_array_index(f->events, LttEventType, i);
6cd62ccf 1266}
1267
1268/*****************************************************************************
1269 *Function name
1270 * ltt_facility_eventtype_get_by_name
1271 * : obtain the event type according to event name
1272 * event name is unique in the facility
1273 *Input params
cf74a6f1 1274 * f : the facility
6cd62ccf 1275 * name : the name of the event
1276 *Return value
963b5f2d 1277 * LttEventType * : the event type required
6cd62ccf 1278 ****************************************************************************/
1279
3aee1200 1280LttEventType *ltt_facility_eventtype_get_by_name(LttFacility *f, GQuark name)
6cd62ccf 1281{
cb03932a 1282 LttEventType *et = g_datalist_id_get_data(&f->events_by_name, name);
a0c1f622 1283 return et;
6cd62ccf 1284}
1285
This page took 0.107614 seconds and 4 git commands to generate.