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