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