apply patch by Gabriel Matni to add format string support for event fields
[lttv.git] / ltt / branches / poly / ltt / facility.c
1
2 /* This file is part of the Linux Trace Toolkit viewer
3 * Copyright (C) 2003-2004 Xiangxiu Yang
4 * 2005 Mathieu Desnoyers
5 *
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.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
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.
19 */
20
21 #ifdef HAVE_CONFIG_H
22 #include <config.h>
23 #endif
24
25 #include <stdlib.h>
26 #include <string.h>
27 #include <stdio.h>
28 #include <glib.h>
29 #include <sys/types.h>
30 #include <sys/stat.h>
31 #include <fcntl.h>
32
33
34
35 #include "parser.h"
36 #include <ltt/ltt.h>
37 #include "ltt-private.h"
38 #include <ltt/facility.h>
39
40 #ifndef g_open
41 #define g_open open
42 #endif
43
44 #define g_close close
45
46 /* search for the (named) type in the table, if it does not exist
47 create a new one */
48 LttType * lookup_named_type(LttFacility *fac, type_descriptor_t * td);
49
50 /* construct directed acyclic graph for types, and tree for fields */
51 void construct_fields(LttFacility *fac,
52 LttField *field,
53 field_t *fld);
54
55 /* generate the facility according to the events belongin to it */
56 void generateFacility(LttFacility * f, facility_t * fac,
57 guint32 checksum);
58
59 /* functions to release the memory occupied by a facility */
60 void freeFacility(LttFacility * facility);
61 void freeEventtype(LttEventType * evType);
62 void freeLttType(LttType * type);
63 void freeLttField(LttField * fld);
64 void freeLttNamedType(LttType * type);
65
66
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
86 parse_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
167 int 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
231 void 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
261 /*****************************************************************************
262 *Function name
263 * ltt_facility_open : open facilities
264 *Input params
265 * t : the trace containing the facilities
266 * pathname : the path name of the facility
267 *
268 * Open the facility corresponding to the right checksum.
269 *
270 *returns 0 on success, 1 on error.
271 ****************************************************************************/
272
273 int ltt_facility_open(LttFacility *f, LttTrace * t, gchar * pathname)
274 {
275 int ret = 0;
276 gchar *token;
277 parse_file_t in;
278 facility_t * fac;
279 unsigned int checksum;
280 gchar buffer[BUFFER_SIZE];
281 gboolean generated = FALSE;
282
283 in.buffer = &(buffer[0]);
284 in.lineno = 0;
285 in.error = error_callback;
286 in.name = pathname;
287 in.unget = 0;
288
289 in.fp = fopen(in.name, "r");
290 if(in.fp == NULL) {
291 g_warning("cannot open facility description file %s",
292 in.name);
293 ret = 1;
294 goto open_error;
295 }
296
297 while(1){
298 token = getToken(&in);
299 if(in.type == ENDFILE) break;
300
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
319 if(g_ascii_strcasecmp(token, "<")) in.error(&in,"not a facility file");
320 token = getName(&in);
321
322 if(g_ascii_strcasecmp("facility",token) == 0) {
323 fac = g_new(facility_t, 1);
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
333 checkNamedTypesImplemented(&fac->named_types);
334
335 generateChecksum(fac->name, &checksum, &fac->events);
336 // FIXME if(checksum == f->checksum) {
337 generateFacility(f, fac, checksum);
338 generated = TRUE;
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);
343
344 g_free(fac->name);
345 free(fac->capname);
346 g_free(fac->description);
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);
353 g_free(fac);
354 if(generated) break; /* use the first good match */
355 }
356 else {
357 g_warning("facility token was expected in file %s", in.name);
358 ret = 1;
359 goto parse_error;
360 }
361 }
362
363 parse_error:
364 fclose(in.fp);
365 open_error:
366
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 }
372
373 return ret;
374 }
375
376
377 /*****************************************************************************
378 *Function name
379 * generateFacility : generate facility, internal function
380 *Input params
381 * facility : LttFacilty structure
382 * fac : facility structure
383 * checksum : checksum of the facility
384 ****************************************************************************/
385
386 void generateFacility(LttFacility *f, facility_t *fac, guint32 checksum)
387 {
388 char * facilityName = fac->name;
389 sequence_t * events = &fac->events;
390 unsigned int i, j;
391 LttType * type;
392 table_t *named_types = &fac->named_types;
393
394 g_assert(f->name == g_quark_from_string(facilityName));
395 //g_assert(f->checksum == checksum);
396
397 //f->event_number = events->position;
398
399 //initialize inner structures
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);
406 // g_datalist_init(&f->named_types);
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
434 for(i=0;i<events->position;i++){
435 event_t *parser_event = (event_t*)events->array[i];
436 LttEventType *event_type = &g_array_index(f->events, LttEventType, i);
437
438 event_type->name =
439 g_quark_from_string(parser_event->name);
440
441 g_datalist_id_set_data(&f->events_by_name, event_type->name,
442 event_type);
443
444 event_type->description =
445 g_strdup(parser_event->description);
446
447 event_type->index = i;
448 event_type->facility = f;
449
450 event_type->has_compact_data = parser_event->compact_data;
451
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
462 construct_fields(f, field, parser_field);
463 g_datalist_id_set_data(&event_type->fields_by_name,
464 field->name,
465 field);
466 }
467 }
468
469 /* What about 2 days weeks ? */
470 }
471
472
473 /*****************************************************************************
474 *Function name
475 * construct_types_and_fields : construct field tree and type graph,
476 * internal recursion function
477 *Input params
478 * fac : facility struct
479 * field : destination lttv field
480 * fld : source parser field
481 ****************************************************************************/
482
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
492
493 void construct_fields(LttFacility *fac,
494 LttField *field,
495 field_t *fld)
496 {
497 char *fmt_type;//gaby
498 guint len;
499 type_descriptor_t *td;
500 LttType *type;
501
502 if(fld->name)
503 field->name = g_quark_from_string(fld->name);
504 else
505 fld->name = 0;
506
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;
519 type->network = td->network;
520
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;
541 g_assert(type->size != 0);
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;
558 g_assert(type->size != 0);
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;
593 type->enum_map = g_hash_table_new(g_direct_hash, g_direct_equal);
594 type->lowest_value = G_MAXINT32;
595 type->highest_value = G_MININT32;
596 for(i=0; i<td->labels.position; i++) {
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);
600 type->highest_value = max(key, type->highest_value);
601 type->lowest_value = min(key, type->lowest_value);
602 }
603 }
604 g_assert(type->size != 0);
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 }
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 }
878
879
880 }
881
882 #if 0
883 void construct_types_and_fields(LttFacility * fac, type_descriptor_t * td,
884 LttField * fld)
885 {
886 int i;
887 type_descriptor_t * tmpTd;
888
889 switch(td->type) {
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:
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;
937
938 case STRUCT:
939 case UNION:
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++){
947 tmpTd = ((field_t*)(td->fields.array[i]))->type;
948
949 fld->field_type->element_type[i] = lookup_named_type(fac, tmpTd);
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
956 = g_quark_from_string(((field_t*)(td->fields.array[i]))->name);
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 }
969 break;
970
971 default:
972 g_error("construct_types_and_fields : unknown type");
973 }
974
975
976 }
977
978 #endif //0
979
980 #if 0
981 void construct_types_and_fields(LttFacility * fac, type_descriptor * td,
982 LttField * fld)
983 {
984 int i, flag;
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;
993 fld->field_type->enum_strings = g_new(GQuark,td->labels.position);
994 for(i=0;i<td->labels.position;i++){
995 fld->field_type->enum_strings[i]
996 = g_quark_from_string(((char*)(td->labels.array[i])));
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;
1001 fld->field_type->element_type = g_new(LttType*,1);
1002 tmpTd = td->nested_type;
1003 fld->field_type->element_type[0] = lookup_named_type(fac, tmpTd);
1004 fld->child = g_new(LttField*, 1);
1005 fld->child[0] = g_new(LttField, 1);
1006
1007 // fld->child[0]->field_pos = 0;
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;
1019 construct_types_and_fields(fac, tmpTd, fld->child[0]);
1020 }else if(td->type == LTT_STRUCT){
1021 fld->field_type->element_number = td->fields.position;
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
1030 fld->child = g_new(LttField*, td->fields.position);
1031 for(i=0;i<td->fields.position;i++){
1032 tmpTd = ((type_fields*)(td->fields.array[i]))->type;
1033
1034 if(flag)
1035 fld->field_type->element_type[i] = lookup_named_type(fac, tmpTd);
1036 fld->child[i] = g_new(LttField,1);
1037
1038 fld->child[i]->field_pos = i;
1039 fld->child[i]->field_type = fld->field_type->element_type[i];
1040
1041 if(flag){
1042 fld->child[i]->field_type->element_name
1043 = g_quark_from_string(((type_fields*)(td->fields.array[i]))->name);
1044 }
1045
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;
1056 construct_types_and_fields(fac, tmpTd, fld->child[i]);
1057 }
1058 }
1059 }
1060 #endif //0
1061
1062 #if 0
1063 /*****************************************************************************
1064 *Function name
1065 * lookup_named_type: search named type in the table
1066 * internal function
1067 *Input params
1068 * fac : facility struct
1069 * name : type name
1070 *Return value
1071 * : either find the named type, or create a new LttType
1072 ****************************************************************************/
1073
1074 LttType * lookup_named_type(LttFacility *fac, GQuark type_name)
1075 {
1076 LttType *type = NULL;
1077
1078 /* Named type */
1079 type = g_datalist_id_get_data(&fac->named_types, name);
1080
1081 g_assert(type != NULL);
1082 #if 0
1083 if(type == NULL){
1084 /* Create the type */
1085 type = g_new(LttType,1);
1086 type->type_name = name;
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;
1094
1095 if(td->type_name != NULL)
1096 g_datalist_id_set_data_full(&fac->named_types, name,
1097 type, (GDestroyNotify)freeLttNamedType);
1098 }
1099 #endif //0
1100 return type;
1101 }
1102 #endif //0
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
1110 ****************************************************************************/
1111
1112 void ltt_facility_close(LttFacility *f)
1113 {
1114 //release the memory it occupied
1115 freeFacility(f);
1116 }
1117
1118 /*****************************************************************************
1119 * Functions to release the memory occupied by the facility
1120 ****************************************************************************/
1121
1122 void freeFacility(LttFacility * fac)
1123 {
1124 guint i;
1125 LttEventType *et;
1126
1127 for(i=0; i<fac->events->len; i++) {
1128 et = &g_array_index (fac->events, LttEventType, i);
1129 freeEventtype(et);
1130 }
1131 g_array_free(fac->events, TRUE);
1132
1133 g_datalist_clear(&fac->events_by_name);
1134
1135 // g_datalist_clear(&fac->named_types);
1136 }
1137
1138 void freeEventtype(LttEventType * evType)
1139 {
1140 unsigned int i;
1141 LttType * root_type;
1142 if(evType->description)
1143 g_free(evType->description);
1144
1145 for(i=0; i<evType->fields->len;i++) {
1146 LttField *field = &g_array_index(evType->fields, LttField, i);
1147 freeLttField(field);
1148 }
1149 g_array_free(evType->fields, TRUE);
1150 g_datalist_clear(&evType->fields_by_name);
1151 }
1152
1153 void freeLttType(LttType * type)
1154 {
1155 unsigned int i;
1156
1157 if(type->fmt)
1158 g_free(type->fmt);
1159
1160 if(type->enum_map)
1161 g_hash_table_destroy(type->enum_map);
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);
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);
1178 }
1179
1180 void freeLttNamedType(LttType * type)
1181 {
1182 freeLttType(type);
1183 }
1184
1185 void freeLttField(LttField * field)
1186 {
1187 if(field->description)
1188 g_free(field->description);
1189 if(field->dynamic_offsets)
1190 g_array_free(field->dynamic_offsets, TRUE);
1191 freeLttType(&field->field_type);
1192 }
1193
1194 /*****************************************************************************
1195 *Function name
1196 * ltt_facility_name : obtain the facility's name
1197 *Input params
1198 * f : the facility
1199 *Return value
1200 * GQuark : the facility's name
1201 ****************************************************************************/
1202
1203 GQuark ltt_facility_name(LttFacility *f)
1204 {
1205 return f->name;
1206 }
1207
1208 /*****************************************************************************
1209 *Function name
1210 * ltt_facility_checksum : obtain the facility's checksum
1211 *Input params
1212 * f : the facility
1213 *Return value
1214 * : the checksum of the facility
1215 ****************************************************************************/
1216
1217 guint32 ltt_facility_checksum(LttFacility *f)
1218 {
1219 return f->checksum;
1220 }
1221
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
1231 guint ltt_facility_id(LttFacility *f)
1232 {
1233 return f->id;
1234 }
1235
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
1242 * : the number of the event types
1243 ****************************************************************************/
1244
1245 guint8 ltt_facility_eventtype_number(LttFacility *f)
1246 {
1247 return (f->events->len);
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
1257 * LttEventType * : the event type required
1258 ****************************************************************************/
1259
1260 LttEventType *ltt_facility_eventtype_get(LttFacility *f, guint8 i)
1261 {
1262 if(!f->exists) return NULL;
1263
1264 g_assert(i < f->events->len);
1265 return &g_array_index(f->events, LttEventType, i);
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
1274 * f : the facility
1275 * name : the name of the event
1276 *Return value
1277 * LttEventType * : the event type required
1278 ****************************************************************************/
1279
1280 LttEventType *ltt_facility_eventtype_get_by_name(LttFacility *f, GQuark name)
1281 {
1282 LttEventType *et = g_datalist_id_get_data(&f->events_by_name, name);
1283 return et;
1284 }
1285
This page took 0.05647 seconds and 4 git commands to generate.