genevent type enhancements and xml split
[lttv.git] / genevent / genevent.c
1 /*
2
3 genevent.c: Generate helper declarations and functions to trace events
4 from an event description file.
5
6 Copyright (C) 2002, Xianxiu Yang
7 Copyright (C) 2002, Michel Dagenais
8
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; version 2 of the License.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 */
22
23 /* This program reads the ".event" event definitions input files
24 specified as command line arguments and generates corresponding
25 ".c" and ".h" files required to trace such events in the kernel.
26
27 The program uses a very simple tokenizer, called from a hand written
28 recursive descent parser to fill a data structure describing the events.
29 The result is a sequence of events definitions which refer to type
30 definitions.
31
32 A table of named types is maintained to allow refering to types by name
33 when the same type is used at several places. Finally a sequence of
34 all types is maintained to facilitate the freeing of all type
35 information when the processing of an ".event" file is finished. */
36
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include <stdio.h>
41 #include <stdarg.h>
42 #include <linux/errno.h>
43
44
45 #include "parser.h"
46 #include "genevent.h"
47
48
49 /* Named types may be referenced from anywhere */
50
51 facility * fac;
52
53 int main(int argc, char** argv)
54 {
55 char *token;
56 parse_file in;
57 char buffer[BUFFER_SIZE];
58 int i;
59
60 if(argc < 2){
61 printf("At least one event definition file is needed\n");
62 exit(1);
63 }
64
65 in.buffer = buffer;
66 in.error = error_callback;
67
68 for(i = 1 ; i < argc ; i++) {
69 in.lineno = 0;
70 in.name = allocAndCopy(argv[i]);
71
72 in.fp = fopen(in.name, "r");
73 if(!in.fp ){
74 in.error(&in,"cannot open facility input file");
75 }
76
77 while(1){
78 token = getToken(&in);
79 if(in.type == ENDFILE) break;
80
81 if(strcmp(token, "<")) in.error(&in,"not a facility file");
82 token = getName(&in);
83
84 if(strcmp("facility",token) == 0) {
85 fac = memAlloc(sizeof(facility));
86 fac->name = NULL;
87 fac->description = NULL;
88 sequence_init(&(fac->events));
89 table_init(&(fac->named_types));
90 sequence_init(&(fac->unnamed_types));
91
92 parseFacility(&in, fac);
93
94 //check if any namedType is not defined
95 checkNamedTypesImplemented(&fac->named_types);
96 }
97 else in.error(&in,"facility token was expected");
98
99 generateFile(argv[i]);
100
101 free(fac->name);
102 free(fac->description);
103 freeEvents(&fac->events);
104 sequence_dispose(&fac->events);
105 freeNamedType(&fac->named_types);
106 table_dispose(&fac->named_types);
107 freeTypes(&fac->unnamed_types);
108 sequence_dispose(&fac->unnamed_types);
109 free(fac);
110 }
111
112 free(in.name);
113 fclose(in.fp);
114
115 }
116 return 0;
117 }
118
119
120 /*****************************************************************************
121 *Function name
122 * generateFile : generate .c and .h file
123 *Input Params
124 * name : name of event definition file
125 ****************************************************************************/
126 void generateFile(char *name){
127 char *cName, *hName, *tmp;
128 FILE * cFp, *hFp;
129 int nbEvent;
130 unsigned long checksum=0;
131
132 //remove .xml if it exists
133 tmp = &name[strlen(name)-4];
134 if(strcmp(tmp, ".xml") == 0){
135 *tmp = '\0';
136 }
137
138 tmp = strrchr(name,'/');
139 if(tmp){
140 tmp++;
141 }else{
142 tmp = name;
143 }
144
145 cName = appendString(tmp,".c");
146 hName = appendString(tmp,".h");
147 cFp = fopen(cName,"w");
148 if(!cFp){
149 printf("Cannot open the file : %s\n",cName);
150 exit(1);
151 }
152
153 hFp = fopen(hName,"w");
154 if(!hFp){
155 printf("Cannot open the file : %s\n",hName);
156 exit(1);
157 }
158
159 free(cName);
160 free(hName);
161
162 generateChecksum(fac->name, &checksum, &(fac->events));
163
164 /* generate .h file, event enumeration then structures and functions */
165 fprintf(hFp, "#ifndef _LTT_FACILITY_%s_H_\n",fac->capname);
166 fprintf(hFp, "#define _LTT_FACILITY_%s_H_\n\n",fac->capname);
167 generateEnumEvent(hFp, fac->name, &nbEvent, checksum);
168 generateTypeDefs(hFp);
169 generateStructFunc(hFp, fac->name,checksum);
170 fprintf(hFp, "#endif //_LTT_FACILITY_%s_H_\n",fac->capname);
171
172 /* generate .c file, calls to register the facility at init time */
173 generateCfile(cFp,fac->name,nbEvent,checksum);
174
175 fclose(hFp);
176 fclose(cFp);
177 }
178
179
180 /*****************************************************************************
181 *Function name
182 * generateEnumEvent : output event enum to .h file
183 *Input Params
184 * fp : file to be written to
185 * facName : name of facility
186 *Output Params
187 * nbEvent : number of events in the facility
188 ****************************************************************************/
189 void generateEnumEvent(FILE *fp, char *facName, int * nbEvent, unsigned long checksum) {
190 int pos = 0;
191
192 fprintf(fp,"#include <linux/ltt-log.h>\n\n");
193
194 fprintf(fp,"/**** facility handle ****/\n\n");
195 fprintf(fp,"extern trace_facility_t ltt_facility_%s_%X;\n\n\n",facName, checksum);
196
197 fprintf(fp,"/**** event type ****/\n\n");
198 fprintf(fp,"enum %s_event {\n",facName);
199
200 for(pos = 0; pos < fac->events.position;pos++) {
201 fprintf(fp,"\t%s", ((event *)(fac->events.array[pos]))->name);
202 if(pos != fac->events.position-1) fprintf(fp,",\n");
203 }
204 fprintf(fp,"\n};\n\n\n");
205
206 // fprintf(fp,"/**** number of events in the facility ****/\n\n");
207 // fprintf(fp,"int nbEvents_%s = %d;\n\n\n",facName, fac->events.position);
208 *nbEvent = fac->events.position;
209 }
210
211
212 /*****************************************************************************
213 *Function name
214 * printStruct : Generic struct printing function
215 *Input Params
216 * fp : file to be written to
217 * len : number of fields
218 * array : array of field info
219 * name : basic struct name
220 * facName : name of facility
221 * whichTypeFirst : struct or array/sequence first
222 * hasStrSeq : string or sequence present?
223 * structCount : struct postfix
224 ****************************************************************************/
225 static void
226 printStruct(FILE * fp, int len, void ** array, char * name, char * facName,
227 int * whichTypeFirst, int * hasStrSeq, int * structCount)
228 {
229 int flag = 0;
230 int pos;
231 field * fld;
232 type_descriptor * td;
233
234 for (pos = 0; pos < len; pos++) {
235 fld = (field *)array[pos];
236 td = fld->type;
237 if( td->type != STRING && td->type != SEQUENCE &&
238 td->type != ARRAY) {
239 if (*whichTypeFirst == 0) {
240 *whichTypeFirst = 1; //struct first
241 }
242 if (flag == 0) {
243 flag = 1;
244
245 fprintf(fp,"struct %s_%s",
246 name, facName);
247 if (structCount) {
248 fprintf(fp, "_%d {\n",
249 ++*structCount);
250 } else {
251 fprintf(fp, " {\n");
252 }
253 }
254 fprintf(fp, "\t%s %s; /* %s */\n",
255 getTypeStr(td),fld->name,fld->description );
256 } else {
257 if (*whichTypeFirst == 0) {
258 //string or sequence or array first
259 *whichTypeFirst = 2;
260 }
261 (*hasStrSeq)++;
262 if(flag) {
263 fprintf(fp,"} __attribute__ ((packed));\n\n");
264 }
265 flag = 0;
266 }
267 }
268
269 if(flag) {
270 fprintf(fp,"} __attribute__ ((packed));\n\n");
271 }
272 }
273
274
275 /*****************************************************************************
276 *Function name
277 * generateHfile : Create the typedefs
278 *Input Params
279 * fp : file to be written to
280 ****************************************************************************/
281 void
282 generateTypeDefs(FILE * fp)
283 {
284 int pos, tmp = 1;
285
286 fprintf(fp, "/**** Basic Type Definitions ****/\n\n");
287
288 for (pos = 0; pos < fac->named_types.values.position; pos++) {
289 type_descriptor * type =
290 (type_descriptor*)fac->named_types.values.array[pos];
291 printStruct(fp, type->fields.position, type->fields.array,
292 "", type->type_name, &tmp, &tmp, NULL);
293 fprintf(fp, "typedef struct _%s %s;\n\n",
294 type->type_name, type->type_name);
295 }
296 }
297
298
299 /*****************************************************************************
300 *Function name
301 * generateEnumDefinition: generate enum definition if it exists
302 *Input Params
303 * fp : file to be written to
304 * fHead : enum type
305 ****************************************************************************/
306 void generateEnumDefinition(FILE * fp, type_descriptor * type){
307 int pos;
308
309 fprintf(fp,"enum {\n");
310 for(pos = 0; pos < type->labels.position; pos++){
311 fprintf(fp,"\t%s", type->labels.array[pos]);
312 if (pos != type->labels.position - 1) fprintf(fp,",\n");
313 }
314 fprintf(fp,"\n};\n\n\n");
315 }
316
317 /*****************************************************************************
318 *Function name
319 * generateStrucTFunc: output structure and function to .h file
320 *Input Params
321 * fp : file to be written to
322 * facName : name of facility
323 ****************************************************************************/
324 void generateStructFunc(FILE * fp, char * facName, unsigned long checksum){
325 event * ev;
326 field * fld;
327 type_descriptor * td;
328 int pos, pos1;
329 int hasStrSeq, flag, structCount, seqCount,strCount, whichTypeFirst=0;
330
331 for(pos = 0; pos < fac->events.position; pos++){
332 ev = (event *) fac->events.array[pos];
333 //yxx if(ev->nested)continue;
334 fprintf(fp,"/**** structure and trace function for event: %s ****/\n\n",ev->name);
335 if(ev->type == 0){ // event without type
336 fprintf(fp,"static inline void trace_%s_%s(void){\n",facName,ev->name);
337 fprintf(fp,"\tltt_log_event(ltt_facility_%s_%X, %s, 0, NULL);\n",facName,checksum,ev->name);
338 fprintf(fp,"};\n\n\n");
339 continue;
340 }
341
342 //if fields contain enum, print out enum definition
343 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
344 fld = (field *)ev->type->fields.array[pos1];
345 if(fld->type->type == ENUM) generateEnumDefinition(fp, fld->type);
346 }
347
348 //default: no string, array or sequence in the event
349 hasStrSeq = 0;
350 whichTypeFirst = 0;
351 structCount = 0;
352
353 //structure for kernel
354 printStruct(fp, ev->type->fields.position, ev->type->fields.array,
355 ev->name, facName, &whichTypeFirst, &hasStrSeq, &structCount);
356
357 //trace function : function name and parameters
358 seqCount = 0;
359 strCount = 0;
360 fprintf(fp,"static inline void trace_%s_%s(",facName,ev->name);
361 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
362 fld = (field *)ev->type->fields.array[pos1];
363 td = fld->type;
364 if(td->type == ARRAY ){
365 fprintf(fp,"%s * %s",getTypeStr(td), fld->name);
366 }else if(td->type == STRING){
367 fprintf(fp,"short int strLength_%d, %s * %s",++strCount, getTypeStr(td), fld->name);
368 }else if(td->type == SEQUENCE){
369 fprintf(fp,"%s seqLength_%d, %s * %s",uintOutputTypes[td->size], ++seqCount,getTypeStr(td), fld->name);
370 }else fprintf(fp,"%s %s",getTypeStr(td), fld->name);
371 if(pos1 != ev->type->fields.position -1)fprintf(fp,", ");
372 }
373 fprintf(fp,"){\n");
374
375 //length of buffer : length of all structures
376 fprintf(fp,"\tint bufLength = ");
377 for(pos1=0;pos1<structCount;pos1++){
378 fprintf(fp,"sizeof(struct %s_%s_%d)",ev->name, facName,pos1+1);
379 if(pos1 != structCount-1) fprintf(fp," + ");
380 }
381
382 //length of buffer : length of all arrays, sequences and strings
383 seqCount = 0;
384 strCount = 0;
385 flag = 0;
386 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
387 fld = (field *)ev->type->fields.array[pos1];
388 td = fld->type;
389 if(td->type == SEQUENCE || td->type==STRING ||td->type==ARRAY){
390 if(structCount || flag > 0) fprintf(fp," + ");
391 if(td->type == SEQUENCE) fprintf(fp,"sizeof(%s) + sizeof(%s) * seqLength_%d",uintOutputTypes[td->size], getTypeStr(td), ++seqCount);
392 else if(td->type==STRING) fprintf(fp,"strLength_%d + 1", ++strCount);
393 else if(td->type==ARRAY) fprintf(fp,"sizeof(%s) * %d", getTypeStr(td),td->size);
394 if(structCount == 0) flag = 1;
395 }
396 }
397 fprintf(fp,";\n");
398
399 //allocate buffer
400 fprintf(fp,"\tchar buff[bufLength];\n");
401
402 //declare a char pointer if needed
403 if(structCount + hasStrSeq > 1) fprintf(fp,"\tchar * ptr = buff;\n");
404
405 //allocate memory for new struct and initialize it
406 if(whichTypeFirst == 1){ //struct first
407 for(pos1=0;pos1<structCount;pos1++){
408 if(pos1==0) fprintf(fp,"\tstruct %s_%s_1 * __1 = (struct %s_%s_1 *)buff;\n",ev->name, facName,ev->name, facName);
409 else fprintf(fp,"\tstruct %s_%s_%d __%d;\n",ev->name, facName,pos1+1,pos1+1);
410 }
411 }else if(whichTypeFirst == 2){
412 for(pos1=0;pos1<structCount;pos1++)
413 fprintf(fp,"\tstruct %s_%s_%d __%d;\n",ev->name, facName,pos1+1,pos1+1);
414 }
415 fprintf(fp,"\n");
416
417 if(structCount) fprintf(fp,"\t//initialize structs\n");
418 flag = 0;
419 structCount = 0;
420 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
421 fld = (field *)ev->type->fields.array[pos1];
422 td = fld->type;
423 if(td->type != ARRAY && td->type != SEQUENCE && td->type != STRING){
424 if(flag == 0){
425 flag = 1;
426 structCount++;
427 if(structCount > 1) fprintf(fp,"\n");
428 }
429 if(structCount == 1 && whichTypeFirst == 1) fprintf(fp, "\t__1->%s = %s;\n",fld->name,fld->name );
430 else fprintf(fp, "\t__%d.%s = %s;\n",structCount ,fld->name,fld->name);
431 }else flag = 0;
432 }
433 if(structCount) fprintf(fp,"\n");
434
435 //set ptr to the end of first struct if needed;
436 if(whichTypeFirst == 1 && structCount + hasStrSeq > 1){
437 fprintf(fp,"\n\t//set ptr to the end of the first struct\n");
438 fprintf(fp,"\tptr += sizeof(struct %s_%s_1);\n\n",ev->name, facName);
439 }
440
441 //copy struct, sequence and string to buffer
442 seqCount = 0;
443 strCount = 0;
444 flag = 0;
445 structCount = 0;
446 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
447 fld = (field *)ev->type->fields.array[pos1];
448 td = fld->type;
449 if(td->type != STRING && td->type != SEQUENCE && td->type != ARRAY){
450 if(flag == 0) structCount++;
451 flag++;
452 if((structCount > 1 || whichTypeFirst == 2) && flag == 1){
453 fprintf(fp,"\t//copy struct to buffer\n");
454 fprintf(fp,"\tmemcpy(ptr, &__%d, sizeof(struct %s_%s_%d));\n",structCount, ev->name, facName,structCount);
455 fprintf(fp,"\tptr += sizeof(struct %s_%s_%d);\n\n",ev->name, facName,structCount);
456 }
457 }else if(td->type == SEQUENCE){
458 flag = 0;
459 fprintf(fp,"\t//copy sequence length and sequence to buffer\n");
460 fprintf(fp,"\t*ptr = seqLength_%d;\n",++seqCount);
461 fprintf(fp,"\tptr += sizeof(%s);\n",uintOutputTypes[td->size]);
462 fprintf(fp,"\tmemcpy(ptr, %s, sizeof(%s) * seqLength_%d);\n",fld->name, getTypeStr(td), seqCount);
463 fprintf(fp,"\tptr += sizeof(%s) * seqLength_%d;\n\n",getTypeStr(td), seqCount );
464 }else if(td->type==STRING){
465 flag = 0;
466 fprintf(fp,"\t//copy string to buffer\n");
467 fprintf(fp,"\tif(strLength_%d > 0){\n",++strCount);
468 fprintf(fp,"\t\tmemcpy(ptr, %s, strLength_%d + 1);\n", fld->name, strCount);
469 fprintf(fp,"\t\tptr += strLength_%d + 1;\n",strCount);
470 fprintf(fp,"\t}else{\n");
471 fprintf(fp,"\t\t*ptr = '\\0';\n");
472 fprintf(fp,"\t\tptr += 1;\n");
473 fprintf(fp,"\t}\n\n");
474 }else if(td->type==ARRAY){
475 flag = 0;
476 fprintf(fp,"\t//copy array to buffer\n");
477 fprintf(fp,"\tmemcpy(ptr, %s, sizeof(%s) * %d);\n", fld->name, getTypeStr(td), td->size);
478 fprintf(fp,"\tptr += sizeof(%s) * %d;\n\n",getTypeStr(td), td->size);
479 }
480 }
481 if(structCount + seqCount > 1) fprintf(fp,"\n");
482
483 //call trace function
484 fprintf(fp,"\n\t//call trace function\n");
485 fprintf(fp,"\tltt_log_event(ltt_facility_%s_%X, %s, bufLength, buff);\n",facName,checksum,ev->name);
486 fprintf(fp,"};\n\n\n");
487 }
488
489 }
490
491 /*****************************************************************************
492 *Function name
493 * getTypeStr : generate type string
494 *Input Params
495 * td : a type descriptor
496 *Return Values
497 * char * : type string
498 ****************************************************************************/
499 char * getTypeStr(type_descriptor * td){
500 type_descriptor * t ;
501
502 switch(td->type){
503 case INT:
504 return intOutputTypes[td->size];
505 case UINT:
506 return uintOutputTypes[td->size];
507 case POINTER:
508 return "void *";
509 case LONG:
510 return "long";
511 case ULONG:
512 return "unsigned long";
513 case SIZE_T:
514 return "size_t";
515 case SSIZE_T:
516 return "ssize_t";
517 case OFF_T:
518 return "off_t";
519 case FLOAT:
520 return floatOutputTypes[td->size];
521 case STRING:
522 return "char";
523 case ENUM:
524 return uintOutputTypes[td->size];
525 case ARRAY:
526 case SEQUENCE:
527 t = td->nested_type;
528 switch(t->type){
529 case INT:
530 return intOutputTypes[t->size];
531 case UINT:
532 return uintOutputTypes[t->size];
533 case POINTER:
534 return "void *";
535 case LONG:
536 return "long";
537 case ULONG:
538 return "unsigned long";
539 case SIZE_T:
540 return "size_t";
541 case SSIZE_T:
542 return "ssize_t";
543 case OFF_T:
544 return "off_t";
545 case FLOAT:
546 return floatOutputTypes[t->size];
547 case STRING:
548 return "char";
549 case ENUM:
550 return uintOutputTypes[t->size];
551 default :
552 error_callback(NULL,"Nested struct is not supportted");
553 break;
554 }
555 break;
556 case STRUCT: //for now we do not support nested struct
557 error_callback(NULL,"Nested struct is not supportted");
558 break;
559 default:
560 error_callback(NULL,"No type information");
561 break;
562 }
563 return NULL;
564 }
565
566 /*****************************************************************************
567 *Function name
568 * generateCfile : generate a .c file
569 *Input Params
570 * fp : file to be written to
571 * facName : name of facility
572 * nbEvent : number of events in the facility
573 * checksum : checksum for the facility
574 ****************************************************************************/
575 void generateCfile(FILE * fp, char * facName, int nbEvent, unsigned long checksum){
576 //will be removed later
577 fprintf(fp,"typedef unsigned int trace_facility_t;\n\n");
578
579 fprintf(fp,"static unsigned long checksum = %lu;\n\n",checksum);
580 fprintf(fp,"/* facility handle */\n");
581 fprintf(fp,"trace_facility_t facility_%s;\n\n",facName);
582
583 fprintf(fp,"static void __init facility_%s_init(){\n",facName);
584 fprintf(fp,"\tfacility_%s = trace_register_facility_by_checksum(\"%s\", checksum,%d);\n",facName,facName,nbEvent);
585 fprintf(fp,"}\n\n");
586
587 fprintf(fp,"static void __exit facility_%s_exit(){\n",facName);
588 fprintf(fp,"}\n\n");
589
590 fprintf(fp,"module_init(facility_%s_init);\n",facName);
591 fprintf(fp,"module_exit(facility_%s_exit);\n",facName);
592 }
593
594
This page took 0.047105 seconds and 5 git commands to generate.