Add a test script to do profiling. Some cleaning as well.
[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 <stdio.h>
40 #include <stdarg.h>
41 #include <linux/errno.h>
42
43
44 #include "parser.h"
45 #include "genevent.h"
46
47 /* Named types may be referenced from anywhere */
48
49 facility * fac;
50
51 int main(int argc, char** argv)
52 {
53 char *token;
54 parse_file in;
55 char buffer[BUFFER_SIZE];
56 int i;
57
58 if(argc < 2){
59 printf("At least one event definition file is needed\n");
60 exit(1);
61 }
62
63 in.buffer = buffer;
64 in.error = error_callback;
65
66 for(i = 1 ; i < argc ; i++) {
67 in.lineno = 0;
68 in.name = allocAndCopy(argv[i]);
69
70 in.fp = fopen(in.name, "r");
71 if(!in.fp ){
72 in.error(&in,"cannot open facility input file");
73 }
74
75 while(1){
76 token = getToken(&in);
77 if(in.type == ENDFILE) break;
78
79 if(strcmp(token, "<")) in.error(&in,"not a facility file");
80 token = getName(&in);
81
82 if(strcmp("facility",token) == 0) {
83 fac = memAlloc(sizeof(facility));
84 fac->name = NULL;
85 fac->description = NULL;
86 sequence_init(&(fac->events));
87 table_init(&(fac->named_types));
88 sequence_init(&(fac->unnamed_types));
89
90 parseFacility(&in, fac);
91
92 //check if any namedType is not defined
93 checkNamedTypesImplemented(&fac->named_types);
94 }else in.error(&in,"facility token was expected");
95
96 generateFile(argv[i]);
97
98 free(fac->name);
99 free(fac->description);
100 freeEvents(&fac->events);
101 sequence_dispose(&fac->events);
102 freeNamedType(&fac->named_types);
103 table_dispose(&fac->named_types);
104 freeTypes(&fac->unnamed_types);
105 sequence_dispose(&fac->unnamed_types);
106 free(fac);
107 }
108
109 free(in.name);
110 fclose(in.fp);
111
112 }
113 return 0;
114 }
115
116
117 /*****************************************************************************
118 *Function name
119 * generateFile : generate .c and .h file
120 *Input Params
121 * name : name of event definition file
122 ****************************************************************************/
123 void generateFile(char *name){
124 char *cName, *hName, *tmp;
125 FILE * cFp, *hFp;
126 int nbEvent;
127 unsigned long checksum=0;
128
129 //remove .xml if it exists
130 tmp = &name[strlen(name)-4];
131 if(strcmp(tmp, ".xml") == 0){
132 *tmp = '\0';
133 }
134
135 tmp = strrchr(name,'/');
136 if(tmp){
137 tmp++;
138 }else{
139 tmp = name;
140 }
141
142 cName = appendString(tmp,".c");
143 hName = appendString(tmp,".h");
144 cFp = fopen(cName,"w");
145 if(!cFp){
146 printf("Cannot open the file : %s\n",cName);
147 exit(1);
148 }
149
150 hFp = fopen(hName,"w");
151 if(!hFp){
152 printf("Cannot open the file : %s\n",hName);
153 exit(1);
154 }
155
156 free(cName);
157 free(hName);
158
159 generateChecksum(fac->name, &checksum, &(fac->events));
160
161 /* generate .h file, event enumeration then structures and functions */
162 generateEnumEvent(hFp, fac->name, &nbEvent);
163 generateStructFunc(hFp, fac->name);
164
165 /* generate .c file, calls to register the facility at init time */
166 generateCfile(cFp,fac->name,nbEvent,checksum);
167
168 fclose(hFp);
169 fclose(cFp);
170 }
171
172
173 /*****************************************************************************
174 *Function name
175 * generateEnumEvent : output event enum to .h file
176 *Input Params
177 * fp : file to be written to
178 * facName : name of facility
179 *Output Params
180 * nbEvent : number of events in the facility
181 ****************************************************************************/
182 void generateEnumEvent(FILE *fp, char *facName, int * nbEvent) {
183 int pos = 0;
184
185 //will be removed later
186 fprintf(fp,"typedef unsigned int trace_facility_t;\n\n");
187 fprintf(fp,"extern int trace_new(trace_facility_t fID, u8 eID, int length, char * buf);\n\n");
188
189
190 fprintf(fp,"/**** facility handle ****/\n\n");
191 fprintf(fp,"extern trace_facility_t facility_%s;\n\n\n",facName);
192
193 fprintf(fp,"/**** event type ****/\n\n");
194 fprintf(fp,"enum %s_event {\n",facName);
195
196 for(pos = 0; pos < fac->events.position;pos++) {
197 fprintf(fp," %s", ((event *)(fac->events.array[pos]))->name);
198 if(pos != fac->events.position-1) fprintf(fp,",\n");
199 }
200 fprintf(fp,"\n};\n\n\n");
201
202 // fprintf(fp,"/**** number of events in the facility ****/\n\n");
203 // fprintf(fp,"int nbEvents_%s = %d;\n\n\n",facName, fac->events.position);
204 *nbEvent = fac->events.position;
205 }
206
207
208 /*****************************************************************************
209 *Function name
210 * generateEnumDefinition: generate enum definition if it exists
211 *Input Params
212 * fp : file to be written to
213 * fHead : enum type
214 ****************************************************************************/
215 void generateEnumDefinition(FILE * fp, type_descriptor * type){
216 int pos;
217
218 fprintf(fp,"enum {\n");
219 for(pos = 0; pos < type->labels.position; pos++){
220 fprintf(fp," %s", type->labels.array[pos]);
221 if (pos != type->labels.position - 1) fprintf(fp,",\n");
222 }
223 fprintf(fp,"\n};\n\n\n");
224 }
225
226 /*****************************************************************************
227 *Function name
228 * generateStrucTFunc: output structure and function to .h file
229 *Input Params
230 * fp : file to be written to
231 * facName : name of facility
232 ****************************************************************************/
233 void generateStructFunc(FILE * fp, char * facName){
234 event * ev;
235 field * fld;
236 type_descriptor * td;
237 int pos, pos1;
238 int hasStrSeq, flag, structCount, seqCount,strCount, whichTypeFirst=0;
239
240 for(pos = 0; pos < fac->events.position; pos++){
241 ev = (event *) fac->events.array[pos];
242 //yxx if(ev->nested)continue;
243 fprintf(fp,"/**** structure and trace function for event: %s ****/\n\n",ev->name);
244 if(ev->type == 0){ // event without type
245 fprintf(fp,"static inline void trace_%s_%s(void){\n",facName,ev->name);
246 fprintf(fp," trace_new(facility_%s, %s, 0, NULL);\n",facName,ev->name);
247 fprintf(fp,"};\n\n\n");
248 continue;
249 }
250
251 //if fields contain enum, print out enum definition
252 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
253 fld = (field *)ev->type->fields.array[pos1];
254 if(fld->type->type == ENUM) generateEnumDefinition(fp, fld->type);
255 }
256
257 //default: no string, array or sequence in the event
258 hasStrSeq = 0;
259 whichTypeFirst = 0;
260
261 //structure for kernel
262 flag = 0;
263 structCount = 0;
264 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
265 fld = (field *)ev->type->fields.array[pos1];
266 td = fld->type;
267 if( td->type != STRING && td->type != SEQUENCE && td->type != ARRAY){
268 if(whichTypeFirst == 0) whichTypeFirst = 1; //struct first
269 if(flag == 0){
270 flag = 1;
271 fprintf(fp,"struct %s_%s_%d{\n",ev->name,facName,++structCount);
272 }
273 fprintf(fp, " %s %s; /* %s */\n",getTypeStr(td),fld->name,fld->description );
274 }else{
275 if(whichTypeFirst == 0) whichTypeFirst = 2; //string or sequence or array first
276 hasStrSeq++;
277 if(flag)
278 fprintf(fp,"} __attribute__ ((packed));\n\n");
279 flag = 0;
280 }
281 }
282 if(flag)
283 fprintf(fp,"} __attribute__ ((packed));\n\n");
284
285 //trace function : function name and parameters
286 seqCount = 0;
287 strCount = 0;
288 fprintf(fp,"static inline void trace_%s_%s(",facName,ev->name);
289 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
290 fld = (field *)ev->type->fields.array[pos1];
291 td = fld->type;
292 if(td->type == ARRAY ){
293 fprintf(fp,"%s * %s",getTypeStr(td), fld->name);
294 }else if(td->type == STRING){
295 fprintf(fp,"short int strLength_%d, %s * %s",++strCount, getTypeStr(td), fld->name);
296 }else if(td->type == SEQUENCE){
297 fprintf(fp,"%s seqLength_%d, %s * %s",uintOutputTypes[td->size], ++seqCount,getTypeStr(td), fld->name);
298 }else fprintf(fp,"%s %s",getTypeStr(td), fld->name);
299 if(pos1 != ev->type->fields.position -1)fprintf(fp,", ");
300 }
301 fprintf(fp,"){\n");
302
303 //length of buffer : length of all structures
304 fprintf(fp," int bufLength = ");
305 for(pos1=0;pos1<structCount;pos1++){
306 fprintf(fp,"sizeof(struct %s_%s_%d)",ev->name, facName,pos1+1);
307 if(pos1 != structCount-1) fprintf(fp," + ");
308 }
309
310 //length of buffer : length of all arrays, sequences and strings
311 seqCount = 0;
312 strCount = 0;
313 flag = 0;
314 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
315 fld = (field *)ev->type->fields.array[pos1];
316 td = fld->type;
317 if(td->type == SEQUENCE || td->type==STRING ||td->type==ARRAY){
318 if(structCount || flag > 0) fprintf(fp," + ");
319 if(td->type == SEQUENCE) fprintf(fp,"sizeof(%s) + sizeof(%s) * seqLength_%d",uintOutputTypes[td->size], getTypeStr(td), ++seqCount);
320 else if(td->type==STRING) fprintf(fp,"strLength_%d + 1", ++strCount);
321 else if(td->type==ARRAY) fprintf(fp,"sizeof(%s) * %d", getTypeStr(td),td->size);
322 if(structCount == 0) flag = 1;
323 }
324 }
325 fprintf(fp,";\n");
326
327 //allocate buffer
328 fprintf(fp," char buff[bufLength];\n");
329
330 //declare a char pointer if needed
331 if(structCount + hasStrSeq > 1) fprintf(fp," char * ptr = buff;\n");
332
333 //allocate memory for new struct and initialize it
334 if(whichTypeFirst == 1){ //struct first
335 for(pos1=0;pos1<structCount;pos1++){
336 if(pos1==0) fprintf(fp," struct %s_%s_1 * __1 = (struct %s_%s_1 *)buff;\n",ev->name, facName,ev->name, facName);
337 else fprintf(fp," struct %s_%s_%d __%d;\n",ev->name, facName,pos1+1,pos1+1);
338 }
339 }else if(whichTypeFirst == 2){
340 for(pos1=0;pos1<structCount;pos1++)
341 fprintf(fp," struct %s_%s_%d __%d;\n",ev->name, facName,pos1+1,pos1+1);
342 }
343 fprintf(fp,"\n");
344
345 if(structCount) fprintf(fp," //initialize structs\n");
346 flag = 0;
347 structCount = 0;
348 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
349 fld = (field *)ev->type->fields.array[pos1];
350 td = fld->type;
351 if(td->type != ARRAY && td->type != SEQUENCE && td->type != STRING){
352 if(flag == 0){
353 flag = 1;
354 structCount++;
355 if(structCount > 1) fprintf(fp,"\n");
356 }
357 if(structCount == 1 && whichTypeFirst == 1) fprintf(fp, " __1->%s = %s;\n",fld->name,fld->name );
358 else fprintf(fp, " __%d.%s = %s;\n",structCount ,fld->name,fld->name);
359 }else flag = 0;
360 }
361 if(structCount) fprintf(fp,"\n");
362
363 //set ptr to the end of first struct if needed;
364 if(whichTypeFirst == 1 && structCount + hasStrSeq > 1){
365 fprintf(fp,"\n //set ptr to the end of the first struct\n");
366 fprintf(fp," ptr += sizeof(struct %s_%s_1);\n\n",ev->name, facName);
367 }
368
369 //copy struct, sequence and string to buffer
370 seqCount = 0;
371 strCount = 0;
372 flag = 0;
373 structCount = 0;
374 for(pos1 = 0; pos1 < ev->type->fields.position; pos1++){
375 fld = (field *)ev->type->fields.array[pos1];
376 td = fld->type;
377 if(td->type != STRING && td->type != SEQUENCE && td->type != ARRAY){
378 if(flag == 0) structCount++;
379 flag++;
380 if((structCount > 1 || whichTypeFirst == 2) && flag == 1){
381 fprintf(fp," //copy struct to buffer\n");
382 fprintf(fp," memcpy(ptr, &__%d, sizeof(struct %s_%s_%d));\n",structCount, ev->name, facName,structCount);
383 fprintf(fp," ptr += sizeof(struct %s_%s_%d);\n\n",ev->name, facName,structCount);
384 }
385 }else if(td->type == SEQUENCE){
386 flag = 0;
387 fprintf(fp," //copy sequence length and sequence to buffer\n");
388 fprintf(fp," *ptr = seqLength_%d;\n",++seqCount);
389 fprintf(fp," ptr += sizeof(%s);\n",uintOutputTypes[td->size]);
390 fprintf(fp," memcpy(ptr, %s, sizeof(%s) * seqLength_%d);\n",fld->name, getTypeStr(td), seqCount);
391 fprintf(fp," ptr += sizeof(%s) * seqLength_%d;\n\n",getTypeStr(td), seqCount );
392 }else if(td->type==STRING){
393 flag = 0;
394 fprintf(fp," //copy string to buffer\n");
395 fprintf(fp," if(strLength_%d > 0){\n",++strCount);
396 fprintf(fp," memcpy(ptr, %s, strLength_%d + 1);\n", fld->name, strCount);
397 fprintf(fp," ptr += strLength_%d + 1;\n",strCount);
398 fprintf(fp," }else{\n");
399 fprintf(fp," *ptr = '\\0';\n");
400 fprintf(fp," ptr += 1;\n");
401 fprintf(fp," }\n\n");
402 }else if(td->type==ARRAY){
403 flag = 0;
404 fprintf(fp," //copy array to buffer\n");
405 fprintf(fp," memcpy(ptr, %s, sizeof(%s) * %d);\n", fld->name, getTypeStr(td), td->size);
406 fprintf(fp," ptr += sizeof(%s) * %d;\n\n",getTypeStr(td), td->size);
407 }
408 }
409 if(structCount + seqCount > 1) fprintf(fp,"\n");
410
411 //call trace function
412 fprintf(fp,"\n //call trace function\n");
413 fprintf(fp," trace_new(facility_%s, %s, bufLength, buff);\n",facName,ev->name);
414 fprintf(fp,"};\n\n\n");
415 }
416
417 }
418
419 /*****************************************************************************
420 *Function name
421 * getTypeStr : generate type string
422 *Input Params
423 * td : a type descriptor
424 *Return Values
425 * char * : type string
426 ****************************************************************************/
427 char * getTypeStr(type_descriptor * td){
428 type_descriptor * t ;
429
430 switch(td->type){
431 case INT:
432 return intOutputTypes[td->size];
433 case UINT:
434 return uintOutputTypes[td->size];
435 case FLOAT:
436 return floatOutputTypes[td->size];
437 case STRING:
438 return "char";
439 case ENUM:
440 return uintOutputTypes[td->size];
441 case ARRAY:
442 case SEQUENCE:
443 t = td->nested_type;
444 switch(t->type){
445 case INT:
446 return intOutputTypes[t->size];
447 case UINT:
448 return uintOutputTypes[t->size];
449 case FLOAT:
450 return floatOutputTypes[t->size];
451 case STRING:
452 return "char";
453 case ENUM:
454 return uintOutputTypes[t->size];
455 default :
456 error_callback(NULL,"Nested struct is not supportted");
457 break;
458 }
459 break;
460 case STRUCT: //for now we do not support nested struct
461 error_callback(NULL,"Nested struct is not supportted");
462 break;
463 default:
464 error_callback(NULL,"No type information");
465 break;
466 }
467 return NULL;
468 }
469
470 /*****************************************************************************
471 *Function name
472 * generateCfile : generate a .c file
473 *Input Params
474 * fp : file to be written to
475 * facName : name of facility
476 * nbEvent : number of events in the facility
477 * checksum : checksum for the facility
478 ****************************************************************************/
479 void generateCfile(FILE * fp, char * facName, int nbEvent, unsigned long checksum){
480 //will be removed later
481 fprintf(fp,"typedef unsigned int trace_facility_t;\n\n");
482
483 fprintf(fp,"static unsigned long checksum = %lu;\n\n",checksum);
484 fprintf(fp,"/* facility handle */\n");
485 fprintf(fp,"trace_facility_t facility_%s;\n\n",facName);
486
487 fprintf(fp,"static void __init facility_%s_init(){\n",facName);
488 fprintf(fp," facility_%s = trace_register_facility_by_checksum(\"%s\", checksum,%d);\n",facName,facName,nbEvent);
489 fprintf(fp,"}\n\n");
490
491 fprintf(fp,"static void __exit facility_%s_exit(){\n",facName);
492 fprintf(fp,"}\n\n");
493
494 fprintf(fp,"module_init(facility_%s_init);\n",facName);
495 fprintf(fp,"module_exit(facility_%s_exit);\n",facName);
496 }
497
498
This page took 0.041814 seconds and 4 git commands to generate.