1 /* ifdef - remove #ifdefs Author: Warren Toomey */ 2 3 /* Copyright 1989 by Warren Toomey wkt@cs.adfa.oz.au[@uunet.uu.net] 4 * 5 * You may freely copy or distribute this code as long as this notice 6 * remains intact. 7 * 8 * You may modify this code, as long as this notice remains intact, and 9 * you add another notice indicating that the code has been modified. 10 * 11 * You may NOT sell this code or in any way profit from this code without 12 * prior agreement from the author. 13 */ 14 15 #include <sys/types.h> 16 #include <string.h> 17 #include <stdlib.h> 18 #include <stdio.h> 19 #include <unistd.h> 20 21 /* Definition of structures and constants used in ifdef.c */ 22 23 /* Types of symbols */ 24 #define DEF 1 /* Symbol is defined */ 25 #define UNDEF 2 /* Symbol isn't defined */ 26 #define IGN 3 /* Ignore this symbol unless defined */ 27 28 /* Redef mode values */ 29 #define MUTABLE 1 /* Symbol can change defined <-> undefined */ 30 #define IMMUTABLE 2 /* Symbol can't change as above */ 31 32 /* Processing modes */ 33 #define NO 0 /* Don't process */ 34 #define YES 1 /* Process */ 35 36 /* Ignore (IGN), ignore but process */ 37 struct DEFINE { 38 char *symbol; /* SLL of defined symbols. The redef */ 39 char type; /* field indicates if this symbol can */ 40 char redef; /* change from defined <-> undefined. */ 41 struct DEFINE *next; /* Type is DEF or UNDEF. */ 42 }; 43 44 /* Global variables & structures */ 45 FILE *zin; /* Input file for processing */ 46 struct DEFINE *defptr; /* Defined symbols SLL */ 47 struct DEFINE *defend; /* Ptr to last node in defptr */ 48 struct DEFINE *deftemp; /* Ptr to last found node */ 49 int line = 1; /* Current line number */ 50 int table = 0; /* Don't normally want a table */ 51 52 extern int optind; 53 extern char *optarg; 54 55 /* Prototypes. */ 56 int main(int argc, char **argv); 57 char fgetarg(FILE *stream, char *cbuf); 58 int find(char *symd); 59 void defit(char *sym, int redef, int typed); 60 void stop(void); 61 void gotoeoln(void); 62 void prteoln(void); 63 void printtable(void); 64 char getendif(void); 65 void gettable(void); 66 void parse(void); 67 void usage(void); 68 69 #ifdef __STDC__ 70 char fgetarg ( FILE *stream , char *cbuf ) 71 #else 72 char fgetarg(stream, cbuf) /* Get next arg from file into cbuf, */ 73 FILE *stream; /* returning the character that */ 74 char *cbuf; /* terminated it. Cbuf returns 0 */ 75 #endif 76 { /* if no arg. EOF is returned if no */ 77 int ch; /* args left in file. */ 78 int i; 79 80 i = 0; 81 cbuf[i] = 0; 82 83 while (((ch = fgetc(stream)) == ' ') || (ch == '\t') || (ch == '\n')) 84 if (ch == '\n') return(ch); /* Bypass leading */ 85 /* Whitespace */ 86 if (feof(stream)) return(EOF); 87 88 cbuf[i++] = ch; 89 90 while (((ch = fgetc(stream)) != ' ') && (ch != '\t') && (ch != '\n')) 91 cbuf[i++] = ch; /* Get the argument */ 92 93 cbuf[i] = 0; 94 return(ch); 95 } 96 97 98 #ifdef __STDC__ 99 int find ( char *sym ) 100 #else 101 int find(sym) 102 char *sym; 103 #endif 104 { /* Return DEF if defined else UNDEF */ 105 106 deftemp = defptr; 107 while (deftemp) { /* Search for the symbol */ 108 if (!strcmp(deftemp->symbol, sym)) 109 return(deftemp->type); /* Setting up the type */ 110 deftemp = deftemp->next; 111 } 112 return(0); 113 } 114 115 116 117 #define Define(x,y) defit(x,y,DEF) 118 #define Undefine(x,y) defit(x,y,UNDEF) 119 #define Ignore(x,y) defit(x,y,IGN) 120 121 #ifdef __STDC__ 122 void defit ( char *sym , int redef , int type ) 123 #else 124 void defit(sym, redef, type) /* Add symbol to the define list */ 125 char *sym; 126 char redef; /* Mode: MUTABLE etc */ 127 char type; /* Type: DEF, UNDEF, IGN */ 128 #endif 129 { 130 struct DEFINE *temp; 131 char c; 132 133 c = find(sym); /* First try finding the symbol */ 134 if (type == c) return; /* Return if already declared */ 135 if (c) { /* We have to move if from DEF <-> UNDEF */ 136 if (deftemp->redef == IMMUTABLE) 137 return; 138 else { 139 deftemp->type = type; 140 deftemp->redef = redef; 141 } 142 } else { /* We must create a struct & add it */ 143 /* Malloc room for the struct */ 144 if ((temp = (struct DEFINE *)malloc(sizeof(struct DEFINE))) == NULL) { 145 (void)fprintf(stderr, "ifdef: could not malloc\n"); 146 exit(1); 147 } 148 149 /* Malloc room for symbol */ 150 if ((temp->symbol = (char *)malloc(strlen(sym) + 1)) == NULL) { 151 (void)fprintf(stderr, "ifdef: could not malloc\n"); 152 exit(1); 153 } 154 (void)strcpy(temp->symbol, sym); /* Copy symbol into struct */ 155 temp->redef = redef; /* and set its redef mode too */ 156 temp->type = type; /* as well as making it defined */ 157 158 159 /* Now add to the SLL */ 160 if (defptr == NULL) /* If first node set */ 161 defptr = temp; /* the pointers to it */ 162 else 163 defend->next = temp; /* else add it to the */ 164 defend = temp; /* end of the list. */ 165 } 166 } 167 168 169 170 #ifdef __STDC__ 171 void stop ( void ) 172 #else 173 void stop() 174 #endif 175 { /* Stop: Tidy up at EOF */ 176 if (table) printtable(); 177 (void)fclose(zin); 178 exit(0); 179 } 180 181 #define Goto { line++; if (ch!='\n') gotoeoln(); } 182 #define Print { line++; if (ch!='\n') prteoln(); } 183 184 #ifdef __STDC__ 185 void gotoeoln ( void ) 186 #else 187 void gotoeoln() /* Go to the end of the line */ 188 #endif 189 { 190 int ch; 191 while ((ch = fgetc(zin)) != '\n') 192 if (ch == EOF) stop(); 193 } 194 195 196 #ifdef __STDC__ 197 void prteoln ( void ) 198 #else 199 void prteoln() /* Print to the end of the line */ 200 #endif 201 { 202 int ch; 203 while ((ch = fgetc(zin)) != '\n') 204 if (ch == EOF) 205 stop(); 206 else 207 (void)putchar(ch); 208 (void)putchar('\n'); 209 } 210 211 212 #ifdef __STDC__ 213 void printtable ( void ) 214 #else 215 void printtable() /* Print the defines in the SLL */ 216 #endif 217 { 218 struct DEFINE *temp; 219 220 (void)printf("Defined\n\n"); 221 222 temp = defptr; 223 while (temp) { 224 if (temp->type == DEF) (void)printf("%s\n", temp->symbol); 225 temp = temp->next; 226 } 227 228 (void)printf("\n\nUndefined\n\n"); 229 230 temp = defptr; 231 while (temp) { 232 if (temp->type == UNDEF) (void)printf("%s\n", temp->symbol); 233 temp = temp->next; 234 } 235 } 236 237 #ifdef __STDC__ 238 char getendif ( void ) 239 #else 240 char getendif() 241 #endif 242 { /* Find matching endif when ignoring */ 243 char word[80]; /* Buffer for symbols */ 244 int ch; 245 int skip; /* Number of skipped #ifdefs */ 246 247 skip = 1; 248 249 while (1) { 250 /* Scan through the file looking for starting lines */ 251 if ((ch = fgetc(zin)) == EOF) 252 stop(); /* Get first char on the line */ 253 if (ch != '#') { /* If not a # ignore line */ 254 (void)putchar(ch); 255 Print; 256 continue; 257 } 258 ch = fgetarg(zin, word); /* Get the word after the # */ 259 260 if (!strcmp(word, "ifdef") || !strcmp(word, "ifndef")) skip++; 261 /* Keep track of ifdefs & */ 262 if (!strcmp(word, "endif")) skip--; /* endifs */ 263 264 (void)printf("#%s%c", word, ch); /* Print the line out */ 265 Print; 266 if (!skip) return('\n'); /* If matching endif, return */ 267 } 268 } 269 270 271 #ifdef __STDC__ 272 void gettable ( void ) 273 #else 274 void gettable() /* Get & print a table of defines etc. */ 275 #endif 276 { 277 278 char word[80]; /* Buffer for symbols */ 279 int ch; 280 281 while (1) { 282 /* Scan through the file looking for starting lines */ 283 if ((ch = fgetc(zin)) == EOF) 284 stop(); /* Get first char on the line */ 285 if (ch != '#') { /* If not a # ignore line */ 286 Goto; 287 continue; 288 } 289 ch = fgetarg(zin, word); /* Get the word after the # */ 290 291 if (!strcmp(word, "define")) { /* Define: Define the */ 292 ch = fgetarg(zin, word); /* symbol, and goto */ 293 Define(word, MUTABLE); /* the end of line */ 294 Goto; 295 continue; 296 } 297 if (!strcmp(word, "undef")) { /* Undef: Undefine the */ 298 ch = fgetarg(zin, word); /* symbol, and goto */ 299 Undefine(word, MUTABLE); /* the end of line */ 300 Goto; 301 continue; 302 } /* Ifdef: */ 303 if (!strcmp(word, "ifdef") || !strcmp(word, "ifndef")) { 304 ch = fgetarg(zin, word); /* Get the symbol */ 305 if (find(word) != DEF) 306 Undefine(word, MUTABLE); /* undefine it */ 307 Goto; 308 continue; 309 } 310 Goto; /* else ignore the line */ 311 } 312 } 313 314 315 316 #ifdef __STDC__ 317 void parse ( void ) 318 #else 319 void parse() 320 #endif 321 { /* Parse & remove ifdefs from C source */ 322 char word[80]; /* Buffer for symbols */ 323 int ch; 324 int proc; /* Should we be processing this bit? */ 325 int skip; /* Number of skipped #ifdefs */ 326 327 proc = 1; 328 skip = 0; 329 330 while (1) { 331 /* Scan through the file looking for starting lines */ 332 if ((ch = fgetc(zin)) == EOF) 333 stop(); /* Get first char on the line */ 334 if (ch != '#') { 335 if (proc) { /* If not # and we're processing */ 336 (void)putchar(ch); /* then print the line */ 337 Print; 338 continue; 339 } else { 340 Goto; /* else just skip the line */ 341 continue; 342 } 343 } 344 345 ch = fgetarg(zin, word); /* Get the word after the # */ 346 347 if (!strcmp(word, "define") && proc) { /* Define: Define the */ 348 ch = fgetarg(zin, word); /* symbol, and goto */ 349 Define(word, MUTABLE); /* the end of line */ 350 (void)printf("#define %s%c", word, ch); 351 Print; 352 continue; 353 } 354 if (!strcmp(word, "undef") && proc) { /* Undef: Undefine the */ 355 ch = fgetarg(zin, word); /* symbol, and goto */ 356 Undefine(word, MUTABLE); /* the end of line */ 357 (void)printf("#undef %s%c", word, ch); 358 Print; 359 continue; 360 } 361 if (!strcmp(word, "if")) { /* If: we cannot handle these */ 362 if (!proc) /* at the moment, so just */ 363 skip++; /* treat them as an ignored */ 364 else { /* definition */ 365 (void)printf("#%s%c",word,ch); 366 Print; 367 ch = getendif(); /* Get matching endif */ 368 continue; 369 } 370 } 371 if (!strcmp(word, "ifdef")) { /* Ifdef: */ 372 if (!proc) /* If not processing */ 373 skip++; /* skip it */ 374 else { 375 ch = fgetarg(zin, word); /* Get the symbol */ 376 switch (find(word)) { 377 case DEF: 378 break; 379 case IGN: 380 (void)printf("#ifdef %s%c", word, ch); 381 Print; 382 ch = getendif(); /* Get matching endif */ 383 break; 384 /* If symbol undefined */ 385 default: 386 Undefine(word, MUTABLE); /* undefine it */ 387 proc = 0; /* & stop processing */ 388 } 389 } 390 Goto; 391 continue; 392 } 393 if (!strcmp(word, "ifndef")) { 394 /* Ifndef: */ 395 if (!proc) /* If not processing */ 396 skip++; /* skip the line */ 397 else { 398 ch = fgetarg(zin, word); /* Get the symbol */ 399 switch (find(word)) { /* If defined, stop */ 400 case DEF: 401 proc = 0; /* processing */ 402 break; 403 case IGN: 404 (void)printf("#ifdef %s%c", word, ch); 405 Print; 406 ch = getendif(); /* Get matching endif */ 407 break; 408 } 409 } 410 Goto; 411 continue; 412 } 413 if (!strcmp(word, "else") && !skip) { /* Else: Flip processing */ 414 proc = !proc; 415 Goto; 416 continue; 417 } 418 if (!strcmp(word, "endif")) { /* Endif: If no skipped */ 419 /* ifdefs turn processing */ 420 if (!skip) /* on, else decrement the */ 421 proc = 1; /* number of skips */ 422 else 423 skip--; 424 Goto; 425 continue; 426 } 427 /* The word fails all of the above tests, so if we're */ 428 /* processing, print the line. */ 429 if (proc) { 430 (void)printf("#%s%c", word, ch); 431 Print; 432 } else 433 Goto; 434 } 435 } 436 437 438 #ifdef __STDC__ 439 void usage ( void ) 440 #else 441 void usage() 442 #endif 443 { 444 (void)fprintf(stderr, "Usage: ifdef [-t] [-Dsymbol] [-dsymbol] [-Usymbol] [-Isymbol] <file>\n"); 445 exit(0); 446 } 447 448 449 #ifdef __STDC__ 450 int main(int argc , char *argv []) 451 #else 452 int main(argc, argv) 453 int argc; 454 char *argv[]; 455 #endif 456 { 457 char sym[80]; /* Temp symbol storage */ 458 int c; 459 460 if (argc == 1) usage(); /* Catch the curious user */ 461 while ((c = getopt(argc, argv, "tD:d:U:I:")) != EOF) { 462 switch (c) { 463 case 't': 464 table = 1; /* Get the various options */ 465 break; 466 467 case 'd': 468 (void)strcpy(sym, optarg); 469 Define(sym, MUTABLE); 470 break; 471 472 case 'D': 473 (void)strcpy(sym, optarg); 474 Define(sym, IMMUTABLE); 475 break; 476 477 case 'U': 478 (void)strcpy(sym, optarg); 479 Undefine(sym, IMMUTABLE); 480 break; 481 482 case 'I': 483 (void)strcpy(sym, optarg); 484 Ignore(sym, IMMUTABLE); 485 break; 486 487 default: usage(); 488 } 489 } 490 491 zin = stdin; /* If a C file is named */ 492 /* Open stdin with it */ 493 if (*argv[argc - 1] != '-') { 494 (void)fclose(zin); 495 if ((zin = fopen(argv[argc - 1], "r")) == NULL) { 496 perror("ifdef"); 497 exit(1); 498 } 499 } 500 if (table) 501 gettable(); /* Either generate a table or */ 502 else 503 parse(); /* parse & replace with the file */ 504 return(0); 505 } 506