enhance .h
[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 fprintf(lFp, "#ifndef _LTT_FACILITY_LOADER_%s_H_\n",fac->capname);
179 fprintf(lFp, "#define _LTT_FACILITY_LOADER_%s_H_\n\n",fac->capname);
180 generateLoaderfile(lFp,fac->name,nbEvent,checksum);
181 fprintf(lFp, "#endif //_LTT_FACILITY_LOADER_%s_H_\n",fac->capname);
182
183 fclose(hFp);
184 fclose(lFp);
185 }
186
187
188 /*****************************************************************************
189 *Function name
190 * generateEnumEvent : output event enum to .h file
191 *Input Params
192 * fp : file to be written to
193 * facName : name of facility
194 *Output Params
195 * nbEvent : number of events in the facility
196 ****************************************************************************/
197 void generateEnumEvent(FILE *fp, char *facName, int * nbEvent, unsigned long checksum) {
198 int pos = 0;
199
200 fprintf(fp,"#include <linux/ltt-log.h>\n\n");
201
202 fprintf(fp,"/**** facility handle ****/\n\n");
203 fprintf(fp,"extern trace_facility_t ltt_facility_%s_%X;\n\n\n",facName, checksum);
204
205 fprintf(fp,"/**** event type ****/\n\n");
206 fprintf(fp,"enum %s_event {\n",facName);
207
208 for(pos = 0; pos < fac->events.position;pos++) {
209 fprintf(fp,"\t%s", ((event *)(fac->events.array[pos]))->name);
210 if(pos != fac->events.position-1) fprintf(fp,",\n");
211 }
212 fprintf(fp,"\n};\n\n\n");
213
214 // fprintf(fp,"/**** number of events in the facility ****/\n\n");
215 // fprintf(fp,"int nbEvents_%s = %d;\n\n\n",facName, fac->events.position);
216 *nbEvent = fac->events.position;
217 }
218
219
220 /*****************************************************************************
221 *Function name
222 * printStruct : Generic struct printing function
223 *Input Params
224 * fp : file to be written to
225 * len : number of fields
226 * array : array of field info
227 * name : basic struct name
228 * facName : name of facility
229 * whichTypeFirst : struct or array/sequence first
230 * hasStrSeq : string or sequence present?
231 * structCount : struct postfix
232 ****************************************************************************/
233
234 static void
235 printStruct(FILE * fp, int len, void ** array, char * name, char * facName,
236 int * whichTypeFirst, int * hasStrSeq, int * structCount)
237 {
238 int flag = 0;
239 int pos;
240 field * fld;
241 type_descriptor * td;
242
243 for (pos = 0; pos < len; pos++) {
244 fld = (field *)array[pos];
245 td = fld->type;
246 if( td->type != STRING && td->type != SEQUENCE &&
247 td->type != ARRAY) {
248 if (*whichTypeFirst == 0) {
249 *whichTypeFirst = 1; //struct first
250 }
251 if (flag == 0) {
252 flag = 1;
253
254 fprintf(fp,"struct %s_%s",name, facName);
255 if (structCount) {
256 fprintf(fp, "_%d {\n",++*structCount);
257 } else {
258 fprintf(fp, " {\n");
259 }
260 }
261 fprintf(fp, "\t%s %s; /* %s */\n",
262 getTypeStr(td),fld->name,fld->description );
263 } else {
264 if (*whichTypeFirst == 0) {
265 //string or sequence or array first
266 *whichTypeFirst = 2;
267 }
268 (*hasStrSeq)++;
269 if(flag) {
270 fprintf(fp,"} __attribute__ ((packed));\n\n");
271 }
272 flag = 0;
273 }
274 }
275
276 if(flag) {
277 fprintf(fp,"} __attribute__ ((packed));\n\n");
278 }
279 }
280
281
282 /*****************************************************************************
283 *Function name
284 * generateHfile : Create the typedefs
285 *Input Params
286 * fp : file to be written to
287 ****************************************************************************/
288 void
289 generateTypeDefs(FILE * fp)
290 {
291 int pos, tmp = 1;
292
293 fprintf(fp, "/**** Basic Type Definitions ****/\n\n");
294
295 for (pos = 0; pos < fac->named_types.values.position; pos++) {
296 type_descriptor * type =
297 (type_descriptor*)fac->named_types.values.array[pos];
298 printStruct(fp, type->fields.position, type->fields.array,
299 "", type->type_name, &tmp, &tmp, NULL);
300 fprintf(fp, "typedef struct _%s %s;\n\n",
301 type->type_name, type->type_name);
302 }
303 }
304
305
306 /*****************************************************************************
307 *Function name
308 * generateEnumDefinition: generate enum definition if it exists
309 *Input Params
310 * fp : file to be written to
311 * fHead : enum type
312 ****************************************************************************/
313 void generateEnumDefinition(FILE * fp, type_descriptor * type){
314 int pos;
315
316 fprintf(fp,"enum {\n");
317 for(pos = 0; pos < type->labels.position; pos++){
318 fprintf(fp,"\t%s", type->labels.array[pos]);
319 if (pos != type->labels.position - 1) fprintf(fp,",\n");
320 }
321 fprintf(fp,"\n};\n\n\n");
322 }
323
324 /*****************************************************************************
325 *Function name
326 * generateStrucTFunc: output structure and function to .h file
327 *Input Params
328 * fp : file to be written to
329 * facName : name of facility
330 ****************************************************************************/
331 void generateStructFunc(FILE * fp, char * facName, unsigned long checksum){
332 event * ev;
333 field * fld;
334 type_descriptor * td;
335 int pos, pos1;
336 int hasStrSeq, flag, structCount, seqCount,strCount, whichTypeFirst=0;
337
338 for(pos = 0; pos < fac->events.position; pos++){
339 ev = (event *) fac->events.array[pos];
340 //yxx if(ev->nested)continue;
341 fprintf(fp,"/**** structure and trace function for event: %s ****/\n\n",ev->name);
342 if(ev->type == 0){ // event without type
343 fprintf(fp,"static inline void trace_%s_%s(void){\n",facName,ev->name);
344 fprintf(fp,"\tltt_log_event(ltt_facility_%s_%X, %s, 0, NULL);\n",facName,checksum,ev->name);
345 fprintf(fp,"};\n\n\n");
346 continue;
347 }
348
349 //if fields contain enum, print out enum definition
350 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
351 fld = (field *)ev->type->fields.array[pos1];
352 if(fld->type->type == ENUM) generateEnumDefinition(fp, fld->type);
353 }
354
355 //default: no string, array or sequence in the event
356 hasStrSeq = 0;
357 whichTypeFirst = 0;
358 structCount = 0;
359
360 //structure for kernel
361 printStruct(fp, ev->type->fields.position, ev->type->fields.array,
362 ev->name, facName, &whichTypeFirst, &hasStrSeq, &structCount);
363
364 //trace function : function name and parameters
365 seqCount = 0;
366 strCount = 0;
367 fprintf(fp,"static inline void trace_%s_%s(",facName,ev->name);
368 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
369 fld = (field *)ev->type->fields.array[pos1];
370 td = fld->type;
371 if(td->type == ARRAY ){
372 fprintf(fp,"%s * %s",getTypeStr(td), fld->name);
373 }else if(td->type == STRING){
374 fprintf(fp,"short int strLength_%d, %s * %s",++strCount, getTypeStr(td), fld->name);
375 }else if(td->type == SEQUENCE){
376 fprintf(fp,"%s seqLength_%d, %s * %s",uintOutputTypes[td->size], ++seqCount,getTypeStr(td), fld->name);
377 }else fprintf(fp,"%s %s",getTypeStr(td), fld->name);
378 if(pos1 != ev->type->fields.position -1)fprintf(fp,", ");
379 }
380 fprintf(fp,"){\n");
381
382 //length of buffer : length of all structures
383 fprintf(fp,"\tint bufLength = ");
384 for(pos1=0;pos1<structCount;pos1++){
385 fprintf(fp,"sizeof(struct %s_%s_%d)",ev->name, facName,pos1+1);
386 if(pos1 != structCount-1) fprintf(fp," + ");
387 }
388
389 //length of buffer : length of all arrays, sequences and strings
390 seqCount = 0;
391 strCount = 0;
392 flag = 0;
393 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
394 fld = (field *)ev->type->fields.array[pos1];
395 td = fld->type;
396 if(td->type == SEQUENCE || td->type==STRING ||td->type==ARRAY){
397 if(structCount || flag > 0) fprintf(fp," + ");
398 if(td->type == SEQUENCE) fprintf(fp,"sizeof(%s) + sizeof(%s) * seqLength_%d",uintOutputTypes[td->size], getTypeStr(td), ++seqCount);
399 else if(td->type==STRING) fprintf(fp,"strLength_%d + 1", ++strCount);
400 else if(td->type==ARRAY) fprintf(fp,"sizeof(%s) * %d", getTypeStr(td),td->size);
401 if(structCount == 0) flag = 1;
402 }
403 }
404 fprintf(fp,";\n");
405
406 //allocate buffer
407 fprintf(fp,"\tchar buff[bufLength];\n");
408
409 //declare a char pointer if needed
410 if(structCount + hasStrSeq > 1) fprintf(fp,"\tchar * ptr = buff;\n");
411
412 //allocate memory for new struct and initialize it
413 if(whichTypeFirst == 1){ //struct first
414 for(pos1=0;pos1<structCount;pos1++){
415 if(pos1==0) fprintf(fp,"\tstruct %s_%s_1 * __1 = (struct %s_%s_1 *)buff;\n",ev->name, facName,ev->name, facName);
416 else fprintf(fp,"\tstruct %s_%s_%d __%d;\n",ev->name, facName,pos1+1,pos1+1);
417 }
418 }else if(whichTypeFirst == 2){
419 for(pos1=0;pos1<structCount;pos1++)
420 fprintf(fp,"\tstruct %s_%s_%d __%d;\n",ev->name, facName,pos1+1,pos1+1);
421 }
422 fprintf(fp,"\n");
423
424 if(structCount) fprintf(fp,"\t//initialize structs\n");
425 flag = 0;
426 structCount = 0;
427 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
428 fld = (field *)ev->type->fields.array[pos1];
429 td = fld->type;
430 if(td->type != ARRAY && td->type != SEQUENCE && td->type != STRING){
431 if(flag == 0){
432 flag = 1;
433 structCount++;
434 if(structCount > 1) fprintf(fp,"\n");
435 }
436 if(structCount == 1 && whichTypeFirst == 1) fprintf(fp, "\t__1->%s = %s;\n",fld->name,fld->name );
437 else fprintf(fp, "\t__%d.%s = %s;\n",structCount ,fld->name,fld->name);
438 }else flag = 0;
439 }
440 if(structCount) fprintf(fp,"\n");
441
442 //set ptr to the end of first struct if needed;
443 if(whichTypeFirst == 1 && structCount + hasStrSeq > 1){
444 fprintf(fp,"\n\t//set ptr to the end of the first struct\n");
445 fprintf(fp,"\tptr += sizeof(struct %s_%s_1);\n\n",ev->name, facName);
446 }
447
448 //copy struct, sequence and string to buffer
449 seqCount = 0;
450 strCount = 0;
451 flag = 0;
452 structCount = 0;
453 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
454 fld = (field *)ev->type->fields.array[pos1];
455 td = fld->type;
456 if(td->type != STRING && td->type != SEQUENCE && td->type != ARRAY){
457 if(flag == 0) structCount++;
458 flag++;
459 if((structCount > 1 || whichTypeFirst == 2) && flag == 1){
460 fprintf(fp,"\t//copy struct to buffer\n");
461 fprintf(fp,"\tmemcpy(ptr, &__%d, sizeof(struct %s_%s_%d));\n",structCount, ev->name, facName,structCount);
462 fprintf(fp,"\tptr += sizeof(struct %s_%s_%d);\n\n",ev->name, facName,structCount);
463 }
464 }else if(td->type == SEQUENCE){
465 flag = 0;
466 fprintf(fp,"\t//copy sequence length and sequence to buffer\n");
467 fprintf(fp,"\t*ptr = seqLength_%d;\n",++seqCount);
468 fprintf(fp,"\tptr += sizeof(%s);\n",uintOutputTypes[td->size]);
469 fprintf(fp,"\tmemcpy(ptr, %s, sizeof(%s) * seqLength_%d);\n",fld->name, getTypeStr(td), seqCount);
470 fprintf(fp,"\tptr += sizeof(%s) * seqLength_%d;\n\n",getTypeStr(td), seqCount );
471 }else if(td->type==STRING){
472 flag = 0;
473 fprintf(fp,"\t//copy string to buffer\n");
474 fprintf(fp,"\tif(strLength_%d > 0){\n",++strCount);
475 fprintf(fp,"\t\tmemcpy(ptr, %s, strLength_%d + 1);\n", fld->name, strCount);
476 fprintf(fp,"\t\tptr += strLength_%d + 1;\n",strCount);
477 fprintf(fp,"\t}else{\n");
478 fprintf(fp,"\t\t*ptr = '\\0';\n");
479 fprintf(fp,"\t\tptr += 1;\n");
480 fprintf(fp,"\t}\n\n");
481 }else if(td->type==ARRAY){
482 flag = 0;
483 fprintf(fp,"\t//copy array to buffer\n");
484 fprintf(fp,"\tmemcpy(ptr, %s, sizeof(%s) * %d);\n", fld->name, getTypeStr(td), td->size);
485 fprintf(fp,"\tptr += sizeof(%s) * %d;\n\n",getTypeStr(td), td->size);
486 }
487 }
488 if(structCount + seqCount > 1) fprintf(fp,"\n");
489
490 //call trace function
491 fprintf(fp,"\n\t//call trace function\n");
492 fprintf(fp,"\tltt_log_event(ltt_facility_%s_%X, %s, bufLength, buff);\n",facName,checksum,ev->name);
493 fprintf(fp,"};\n\n\n");
494 }
495
496 }
497
498 /*****************************************************************************
499 *Function name
500 * getTypeStr : generate type string
501 *Input Params
502 * td : a type descriptor
503 *Return Values
504 * char * : type string
505 ****************************************************************************/
506 char * getTypeStr(type_descriptor * td){
507 type_descriptor * t ;
508
509 switch(td->type){
510 case INT:
511 return intOutputTypes[td->size];
512 case UINT:
513 return uintOutputTypes[td->size];
514 case POINTER:
515 return "void *";
516 case LONG:
517 return "long";
518 case ULONG:
519 return "unsigned long";
520 case SIZE_T:
521 return "size_t";
522 case SSIZE_T:
523 return "ssize_t";
524 case OFF_T:
525 return "off_t";
526 case FLOAT:
527 return floatOutputTypes[td->size];
528 case STRING:
529 return "char";
530 case ENUM:
531 return uintOutputTypes[td->size];
532 case ARRAY:
533 case SEQUENCE:
534 t = td->nested_type;
535 switch(t->type){
536 case INT:
537 return intOutputTypes[t->size];
538 case UINT:
539 return uintOutputTypes[t->size];
540 case POINTER:
541 return "void *";
542 case LONG:
543 return "long";
544 case ULONG:
545 return "unsigned long";
546 case SIZE_T:
547 return "size_t";
548 case SSIZE_T:
549 return "ssize_t";
550 case OFF_T:
551 return "off_t";
552 case FLOAT:
553 return floatOutputTypes[t->size];
554 case STRING:
555 return "char";
556 case ENUM:
557 return uintOutputTypes[t->size];
558 default :
559 error_callback(NULL,"Nested struct is not supportted");
560 break;
561 }
562 break;
563 case STRUCT: //for now we do not support nested struct
564 error_callback(NULL,"Nested struct is not supportted");
565 break;
566 default:
567 error_callback(NULL,"No type information");
568 break;
569 }
570 return NULL;
571 }
572
573 /*****************************************************************************
574 *Function name
575 * generateLoaderfile: generate a facility loaded .h file
576 *Input Params
577 * fp : file to be written to
578 * facName : name of facility
579 * nbEvent : number of events in the facility
580 * checksum : checksum for the facility
581 ****************************************************************************/
582 void generateLoaderfile(FILE * fp, char * facName, int nbEvent, unsigned long checksum){
583 //will be removed later
584 fprintf(fp,"ltt_facility_t\tltt_facility_%s_%X;\n\n", facName, checksum);
585
586 fprintf(fp,"EXPORT_SYMBOL(ltt_facility_%s_%X);\n\n",facName, checksum);
587 fprintf(fp,"#define LTT_FACILITY_SYMBOL\t\t\t\tltt_facility_%s_%X\n",
588 facName, checksum);
589 fprintf(fp,"#define LTT_FACILITY_CHECKSUM\t\t\t0x%X\n", checksum);
590 fprintf(fp,"#define LTT_FACILITY_NAME\t\t\t\t\t\"%s\"\n", facName);
591 fprintf(fp,"#define LTT_FACILITY_NUM_EVENTS\t\t%d\n\n", nbEvent);
592 }
593
594
This page took 0.05065 seconds and 5 git commands to generate.