3 genevent.c: Generate helper declarations and functions to trace events
4 from an event description file.
6 Copyright (C) 2002, Xianxiu Yang
7 Copyright (C) 2002, Michel Dagenais
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.
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.
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
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.
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
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. */
42 #include <linux/errno.h>
49 /* Named types may be referenced from anywhere */
53 int main(int argc
, char** argv
)
57 char buffer
[BUFFER_SIZE
];
61 printf("At least one event definition file is needed\n");
66 in
.error
= error_callback
;
68 for(i
= 1 ; i
< argc
; i
++) {
70 in
.name
= allocAndCopy(argv
[i
]);
72 in
.fp
= fopen(in
.name
, "r");
74 in
.error(&in
,"cannot open facility input file");
78 token
= getToken(&in
);
79 if(in
.type
== ENDFILE
) break;
81 if(strcmp(token
, "<")) in
.error(&in
,"not a facility file");
84 if(strcmp("facility",token
) == 0) {
85 fac
= memAlloc(sizeof(facility
));
87 fac
->description
= NULL
;
88 sequence_init(&(fac
->events
));
89 table_init(&(fac
->named_types
));
90 sequence_init(&(fac
->unnamed_types
));
92 parseFacility(&in
, fac
);
94 //check if any namedType is not defined
95 checkNamedTypesImplemented(&fac
->named_types
);
97 else in
.error(&in
,"facility token was expected");
99 generateFile(argv
[i
]);
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
);
120 /*****************************************************************************
122 * generateFile : generate .c and .h file
124 * name : name of event definition file
125 ****************************************************************************/
126 void generateFile(char *name
){
127 char *cName
, *hName
, *tmp
;
130 unsigned long checksum
=0;
132 //remove .xml if it exists
133 tmp
= &name
[strlen(name
)-4];
134 if(strcmp(tmp
, ".xml") == 0){
138 tmp
= strrchr(name
,'/');
145 cName
= appendString(tmp
,".c");
146 hName
= appendString(tmp
,".h");
147 cFp
= fopen(cName
,"w");
149 printf("Cannot open the file : %s\n",cName
);
153 hFp
= fopen(hName
,"w");
155 printf("Cannot open the file : %s\n",hName
);
162 generateChecksum(fac
->name
, &checksum
, &(fac
->events
));
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
);
172 /* generate .c file, calls to register the facility at init time */
173 generateCfile(cFp
,fac
->name
,nbEvent
,checksum
);
180 /*****************************************************************************
182 * generateEnumEvent : output event enum to .h file
184 * fp : file to be written to
185 * facName : name of facility
187 * nbEvent : number of events in the facility
188 ****************************************************************************/
189 void generateEnumEvent(FILE *fp
, char *facName
, int * nbEvent
, unsigned long checksum
) {
192 fprintf(fp
,"#include <linux/ltt-log.h>\n\n");
194 fprintf(fp
,"/**** facility handle ****/\n\n");
195 fprintf(fp
,"extern trace_facility_t ltt_facility_%s_%X;\n\n\n",facName
, checksum
);
197 fprintf(fp
,"/**** event type ****/\n\n");
198 fprintf(fp
,"enum %s_event {\n",facName
);
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");
204 fprintf(fp
,"\n};\n\n\n");
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
;
212 /*****************************************************************************
214 * printStruct : Generic struct printing function
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 ****************************************************************************/
226 printStruct(FILE * fp
, int len
, void ** array
, char * name
, char * facName
,
227 int * whichTypeFirst
, int * hasStrSeq
, int * structCount
)
232 type_descriptor
* td
;
234 for (pos
= 0; pos
< len
; pos
++) {
235 fld
= (field
*)array
[pos
];
237 if( td
->type
!= STRING
&& td
->type
!= SEQUENCE
&&
239 if (*whichTypeFirst
== 0) {
240 *whichTypeFirst
= 1; //struct first
245 fprintf(fp
,"struct %s_%s",
248 fprintf(fp
, "_%d {\n",
254 fprintf(fp
, "\t%s %s; /* %s */\n",
255 getTypeStr(td
),fld
->name
,fld
->description
);
257 if (*whichTypeFirst
== 0) {
258 //string or sequence or array first
263 fprintf(fp
,"} __attribute__ ((packed));\n\n");
270 fprintf(fp
,"} __attribute__ ((packed));\n\n");
275 /*****************************************************************************
277 * generateHfile : Create the typedefs
279 * fp : file to be written to
280 ****************************************************************************/
282 generateTypeDefs(FILE * fp
)
286 fprintf(fp
, "/**** Basic Type Definitions ****/\n\n");
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
);
299 /*****************************************************************************
301 * generateEnumDefinition: generate enum definition if it exists
303 * fp : file to be written to
305 ****************************************************************************/
306 void generateEnumDefinition(FILE * fp
, type_descriptor
* type
){
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");
314 fprintf(fp
,"\n};\n\n\n");
317 /*****************************************************************************
319 * generateStrucTFunc: output structure and function to .h file
321 * fp : file to be written to
322 * facName : name of facility
323 ****************************************************************************/
324 void generateStructFunc(FILE * fp
, char * facName
, unsigned long checksum
){
327 type_descriptor
* td
;
329 int hasStrSeq
, flag
, structCount
, seqCount
,strCount
, whichTypeFirst
=0;
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");
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
);
348 //default: no string, array or sequence in the event
353 //structure for kernel
354 printStruct(fp
, ev
->type
->fields
.position
, ev
->type
->fields
.array
,
355 ev
->name
, facName
, &whichTypeFirst
, &hasStrSeq
, &structCount
);
357 //trace function : function name and parameters
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
];
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
,", ");
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
," + ");
382 //length of buffer : length of all arrays, sequences and strings
386 for(pos1
= 0; pos1
< ev
->type
->fields
.position
; pos1
++){
387 fld
= (field
*)ev
->type
->fields
.array
[pos1
];
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;
400 fprintf(fp
,"\tchar buff[bufLength];\n");
402 //declare a char pointer if needed
403 if(structCount
+ hasStrSeq
> 1) fprintf(fp
,"\tchar * ptr = buff;\n");
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);
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);
417 if(structCount
) fprintf(fp
,"\t//initialize structs\n");
420 for(pos1
= 0; pos1
< ev
->type
->fields
.position
; pos1
++){
421 fld
= (field
*)ev
->type
->fields
.array
[pos1
];
423 if(td
->type
!= ARRAY
&& td
->type
!= SEQUENCE
&& td
->type
!= STRING
){
427 if(structCount
> 1) fprintf(fp
,"\n");
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
);
433 if(structCount
) fprintf(fp
,"\n");
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
);
441 //copy struct, sequence and string to buffer
446 for(pos1
= 0; pos1
< ev
->type
->fields
.position
; pos1
++){
447 fld
= (field
*)ev
->type
->fields
.array
[pos1
];
449 if(td
->type
!= STRING
&& td
->type
!= SEQUENCE
&& td
->type
!= ARRAY
){
450 if(flag
== 0) structCount
++;
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
);
457 }else if(td
->type
== SEQUENCE
){
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
){
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
){
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
);
481 if(structCount
+ seqCount
> 1) fprintf(fp
,"\n");
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");
491 /*****************************************************************************
493 * getTypeStr : generate type string
495 * td : a type descriptor
497 * char * : type string
498 ****************************************************************************/
499 char * getTypeStr(type_descriptor
* td
){
500 type_descriptor
* t
;
504 return intOutputTypes
[td
->size
];
506 return uintOutputTypes
[td
->size
];
512 return "unsigned long";
520 return floatOutputTypes
[td
->size
];
524 return uintOutputTypes
[td
->size
];
530 return intOutputTypes
[t
->size
];
532 return uintOutputTypes
[t
->size
];
538 return "unsigned long";
546 return floatOutputTypes
[t
->size
];
550 return uintOutputTypes
[t
->size
];
552 error_callback(NULL
,"Nested struct is not supportted");
556 case STRUCT
: //for now we do not support nested struct
557 error_callback(NULL
,"Nested struct is not supportted");
560 error_callback(NULL
,"No type information");
566 /*****************************************************************************
568 * generateCfile : generate a .c file
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");
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
);
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
);
587 fprintf(fp
,"static void __exit facility_%s_exit(){\n",facName
);
590 fprintf(fp
,"module_init(facility_%s_init);\n",facName
);
591 fprintf(fp
,"module_exit(facility_%s_exit);\n",facName
);
This page took 0.059437 seconds and 5 git commands to generate.