1/* $NetBSD: main.c,v 1.16 2009/03/14 21:04:25 dsl Exp $ */ 2 3/* 4 * TODO: 5 * rewrite the command line stuff altogether - it's kludged beyond 6 * belief (as is the rest of the code...) 7 * 8 * DISCLAIMER DISCLAIMER DISCLAIMER 9 * This code is such a kludge that I don't want to put my name on it. 10 * It was a ridiculously fast hack and needs rewriting. 11 * However it does work... 12 */ 13 14#include <sys/cdefs.h> 15__KERNEL_RCSID(0, "$NetBSD: main.c,v 1.16 2009/03/14 21:04:25 dsl Exp $"); 16 17#include <stdlib.h> 18#include <stdio.h> 19#include <strings.h> 20#include <time.h> 21#include "malloc.h" 22#include "debug.h" 23#include "main.h" 24#include "procs.h" 25 26int debug[128]; 27 28int lineno = 1; 29 30FILE *statefile, *actfile, *eventfile_h, *statevalfile; 31FILE *infile, *astringfile; 32char *Transfilename; 33char *astringfile_name = DEBUGFILE; 34char *actfile_name = ACTFILE; 35char *statefile_name = STATEFILE; 36char *statevalfile_name = STATEVALFILE; 37char *eventfile_h_name = EVENTFILE_H; 38int print_trans = 0; 39int print_protoerrs = 0; 40int pgoption = 0; 41char kerneldirname[50] = "\0"; 42 43char protocol[50]; 44 45char *synonyms[] = { 46 "EVENT", 47 "PCB", 48 0 49}; 50 51void FakeFilename(); 52extern void llparse(); 53extern void initsets(); 54extern void init_alloc(); 55extern void dump_predtable(); 56extern void printprotoerrs(); 57 58void 59usage(char *a) 60{ 61 fprintf(stderr, 62 "usage: %s <transition file> {-D<debug options>} <other options>\n", 63 a); 64 fprintf(stderr, "\t<other options> is any combination of:\n"); 65 fprintf(stderr, "\t\t-A<action file name>\n"); 66 fprintf(stderr, "\t\t-E<event file name>\n"); 67 fprintf(stderr, "\t\t-S<state file name>\n"); 68 fprintf(stderr, "\t\t-I<initial values file name>\n"); 69 fprintf(stderr, "\t\t-X<debugging file name>\n"); 70 fprintf(stderr, "\t\t-K<directory name>\n"); 71 fprintf(stderr, 72 "\tThese names do NOT include the suffixes (.c, .h)\n"); 73 fprintf(stderr, 74 "\t\t-D<options> to turn on debug options for xebec itself\n"); 75 fprintf(stderr, "\t-<nn> for levels of debugging output\n"); 76 fprintf(stderr, "\t\t<nn> ranges from 1 to 3, 1 is default(everything)\n"); 77 fprintf(stderr, "\t\t-T to print transitions\n"); 78 fprintf(stderr, "\t\t-e to print list of combinations of\n"); 79 fprintf(stderr, "\t\t\t [event,old_state] that produce protocol errors\n"); 80 fprintf(stderr, "\t\t-g include profiling code in driver\n"); 81 Exit(-1); 82} 83 84void 85openfiles(register char *proto) 86{ 87 register char *junk; 88 register int lenp = strlen(proto); 89 90 IFDEBUG(b) 91 fprintf(OUT, "openfiles %s\n",proto); 92 ENDDEBUG 93 94#define DOIT(X)\ 95 /* GAG */\ 96 junk = Malloc( 2 + lenp + strlen(X ## _name) );\ 97 (void) sprintf(junk, "%s_", proto);\ 98 X ## _name = strcat(junk, X ## _name);\ 99 X = fopen(X ## _name, "w");\ 100 if((X)==(FILE *)0)\ 101 { fprintf(stderr,"Open failed: %s\n", "X"); Exit(-1); }\ 102 fprintf(X, "/* %cHeader%c */\n",'$', '$' );\ 103 fprintf(X, "/* %cSource%c */\n",'$', '$' ); 104 105 DOIT(eventfile_h); 106 107 IFDEBUG(X) 108#ifdef DEBUG 109 DOIT(astringfile); 110#endif /* DEBUG */ 111 fprintf(astringfile, 112 "#ifndef _NFILE\n#include <stdio.h>\n#endif /* _NFILE */\n" ); 113 ENDDEBUG 114 115 DOIT(statevalfile); 116 DOIT(statefile); 117 DOIT(actfile); 118 fprintf(actfile, 119 "#ifndef lint\nstatic char *rcsid = \"%cHeader%c\";\n#endif /* lint */\n", 120 '$', '$'); 121 122 if(pgoption) 123 putdriver(actfile, 15); 124 else 125 putdriver(actfile, 14); 126 127 FakeFilename(actfile, Transfilename, lineno); 128 putdriver(actfile, 1); 129 FakeFilename(actfile, Transfilename, lineno); 130 putdriver(actfile, 12); 131 fprintf(actfile, "#include \"%s%s\"\n", kerneldirname, statevalfile_name); 132 FakeFilename(actfile, Transfilename, lineno); 133 putdriver(actfile, 2); 134 135 initsets(eventfile_h, statefile); 136} 137 138void 139includecode(FILE *file, register char *f) 140{ 141 register int count=1; 142 static char o='{'; 143 static char c='}'; 144 register char *g; 145 146 IFDEBUG(a) 147 fprintf(stdout, "including: %s, f=%p", f,f); 148 ENDDEBUG 149 g = ++f; 150 while(count>0) { 151 if(*g == o) count++; 152 if(*g == c) count--; 153 g++; 154 } 155 *(--g) = '\0'; 156 IFDEBUG(a) 157 fprintf(stdout, "derived: %s", f); 158 ENDDEBUG 159 fprintf(file, "%s", f); 160 FakeFilename(file, Transfilename, lineno); 161} 162 163void 164putincludes(void) 165{ 166 FakeFilename(actfile, Transfilename, lineno); 167 fprintf(actfile, "\n#include \"%s%s\"\n", kerneldirname, eventfile_h_name); 168 IFDEBUG(X) 169 if( !debug['K'] ) 170 fprintf(actfile, "\n#include \"%s\"\n", astringfile_name); 171 /* not in kernel mode */ 172 ENDDEBUG 173 FakeFilename(actfile, Transfilename, lineno); 174} 175 176int 177main(int argc, char *argv[]) 178{ 179 register int i = 2; 180 extern char *strcpy(); 181 int start, finish; 182 extern int FirstEventAttribute; 183 extern int Nevents, Nstates; 184 185 start = time(0); 186 if(argc < 2) { 187 usage(argv[0]); 188 } 189 IFDEBUG(a) 190 fprintf(stdout, "infile = %s\n",argv[1]); 191 ENDDEBUG 192 Transfilename = argv[1]; 193 infile = fopen(argv[1], "r"); 194 195 if(argc > 2) while(i < argc) { 196 register int j=0; 197 char c; 198 char *name; 199 200 if(argv[i][j] == '-') j++; 201 switch(c = argv[i][j]) { 202 203 /* GROT */ 204 case 'A': 205 name = &argv[i][++j]; 206 actfile_name = Malloc( strlen(name)+4); 207 actfile_name = (char *)strcpy(actfile_name,name); 208#ifdef LINT 209 name = 210#endif /* LINT */ 211 strcat(actfile_name, ".c"); 212 fprintf(stdout, "debugging file is %s\n",actfile_name); 213 break; 214 case 'K': 215 debug[(unsigned char) c]=1; 216 fprintf(OUT, "option %c file %s\n",c, &argv[i][j+1]); 217 (void) strcpy(kerneldirname,&argv[i][++j]); 218 break; 219 case 'X': 220 debug[(unsigned char) c]=1; 221 name = &argv[i][++j]; 222 astringfile_name = Malloc( strlen(name)+4); 223 astringfile_name = (char *)strcpy(astringfile_name,name); 224#ifdef LINT 225 name = 226#endif /* LINT */ 227 strcat(astringfile_name, ".c"); 228 fprintf(OUT, "option %c, astringfile name %s\n",c, name); 229 break; 230 case 'E': 231 name = &argv[i][++j]; 232 eventfile_h_name = Malloc( strlen(name)+4); 233 eventfile_h_name = (char *)strcpy(eventfile_h_name,name); 234#ifdef LINT 235 name = 236#endif /* LINT */ 237 strcat(eventfile_h_name, ".h"); 238 fprintf(stdout, "event files is %s\n",eventfile_h_name); 239 break; 240 case 'I': 241 name = &argv[i][++j]; 242 statevalfile_name = Malloc( strlen(name)+4 ); 243 statevalfile_name = (char *)strcpy(statevalfile_name,name); 244#ifdef LINT 245 name = 246#endif /* LINT */ 247 strcat(statevalfile_name, ".init"); 248 fprintf(stdout, "state table initial values file is %s\n",statevalfile_name); 249 break; 250 case 'S': 251 name = &argv[i][++j]; 252 statefile_name = Malloc( strlen(name)+4); 253 statefile_name = (char *)strcpy(statefile_name,name); 254#ifdef LINT 255 name = 256#endif /* LINT */ 257 strcat(statefile_name, ".h"); 258 fprintf(stdout, "state file is %s\n",statefile_name); 259 break; 260 /* END GROT */ 261 case '1': 262 case '2': 263 case '3': 264 debug['X']= (int)argv[i][j] - (int) '0'; 265 fprintf(OUT, "value of debug['X'] is 0x%x,%d\n", debug['X'], 266 debug['X']); 267 break; 268 case 'D': 269 while((c = argv[i][++j])) { 270 if(c == 'X') { 271 fprintf(OUT, "debugging on"); 272 if(debug['X']) fprintf(OUT, 273 " - overrides any -%d flags used\n", debug['X']); 274 } 275 debug[(unsigned char) c]=1; 276 fprintf(OUT, "debug %c\n",c); 277 } 278 break; 279 case 'g': 280 pgoption = 1; 281 fprintf(stdout, "Profiling\n"); 282 break; 283 case 'e': 284 print_protoerrs = 1; 285 fprintf(stdout, "Protocol error table:\n"); 286 break; 287 288 case 'T': 289 print_trans = 1; 290 fprintf(stdout, "Transitions:\n"); 291 break; 292 default: 293 usage(argv[0]); 294 break; 295 } 296 i++; 297 } 298 if(kerneldirname[0]) { 299 char *c; 300#ifdef notdef 301 if(debug['X']) { 302 fprintf(OUT, "Option K overrides option X\n"); 303 debug['X'] = 0; 304 } 305#endif /* notdef */ 306 if(strlen(kerneldirname)<1) { 307 fprintf(OUT, "K option: dir name too short!\n"); 308 exit(1); 309 } 310 /* add ../name/ */ 311 c = (char *) Malloc(strlen(kerneldirname)+6) ; 312 if(c <= (char *)0) { 313 fprintf(OUT, "Cannot allocate %d bytes for kerneldirname\n", 314 strlen(kerneldirname + 6) ); 315 fprintf(OUT, "kerneldirname is %s\n", kerneldirname ); 316 exit(1); 317 } 318 *c = '.'; 319 *(c+1) = '.'; 320 *(c+2) = '/'; 321 (void) strcat(c, kerneldirname); 322 (void) strcat(c, "/\0"); 323 strcpy(kerneldirname, c); 324 } 325 326 init_alloc(); 327 328 (void) llparse(); 329 330 /* {{ */ 331 if( !FirstEventAttribute ) 332 fprintf(eventfile_h, "\t}ev_union;\n"); 333 fprintf(eventfile_h, "};/* end struct event */\n"); 334 fprintf(eventfile_h, "\n#define %s_NEVENTS 0x%x\n", protocol, Nevents); 335 fprintf(eventfile_h, 336 "\n#define ATTR(X)ev_union.%s ## X ## \n",EV_PREFIX); 337 (void) fclose(eventfile_h); 338 339 /* {{ */ fprintf(actfile, "\t}\nreturn 0;\n}\n"); /* end switch; end action() */ 340 dump_predtable(actfile); 341 342 putdriver(actfile, 3); 343 IFDEBUG(X) 344 if(!debug['K']) 345 putdriver(actfile, 4); 346 ENDDEBUG 347 putdriver(actfile, 6); 348 IFDEBUG(X) 349 /* 350 putdriver(actfile, 10); 351 */ 352 if(debug['K']) { 353 putdriver(actfile, 11); 354 } else { 355 switch(debug['X']) { 356 case 1: 357 default: 358 putdriver(actfile, 7); 359 break; 360 case 2: 361 putdriver(actfile, 13); 362 break; 363 case 3: 364 break; 365 } 366 } 367 ENDDEBUG 368 putdriver(actfile, 8); 369 (void) fclose(actfile); 370 IFDEBUG(X) 371 /* { */ 372 fprintf(astringfile, "};\n"); 373 (void) fclose(astringfile); 374 ENDDEBUG 375 376 (void) fclose(statevalfile); 377 378 fprintf(statefile, "\n#define %s_NSTATES 0x%x\n", protocol, Nstates); 379 (void) fclose(statefile); 380 381 finish = time(0); 382 fprintf(stdout, "%d seconds\n", finish - start); 383 if( print_protoerrs ) 384 printprotoerrs(); 385 386 exit(0); 387} 388 389int transno = 0; 390 391void 392Exit(int n) 393{ 394 fprintf(stderr, "Error at line %d\n",lineno); 395 if(transno) fprintf(stderr, "Transition number %d\n",transno); 396 (void) fflush(stdout); 397 (void) fflush(statefile); 398 (void) fflush(eventfile_h); 399 (void) fflush(actfile); 400 exit(n); 401} 402 403#if 0 404syntax(void) 405{ 406 static char *synt[] = { 407 "*PROTOCOL <string>\n", 408 "*PCB <string> <optional: SYNONYM synonymstring>\n", 409 "<optional: *INCLUDE {\n<C source>\n} >\n", 410 "*STATES <string>\n", 411 "*EVENTS <string>\n", 412 "*TRANSITIONS <string>\n", 413 }; 414} 415#endif 416 417void 418FakeFilename(FILE *outfile, char *name, int l) 419{ 420#if 0 421 doesn't work 422 fprintf(outfile, "\n\n\n\n# line %d \"%s\"\n", l, name); 423#else 424 (void)outfile; 425 (void)name; 426 (void)l; 427#endif 428} 429