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 ch = fgetarg(zin, word); /* Get the word after the # */ 345 346 if (!strcmp(word, "define") && proc) { /* Define: Define the */ 347 ch = fgetarg(zin, word); /* symbol, and goto */ 348 Define(word, MUTABLE); /* the end of line */ 349 (void)printf("#define %s%c", word, ch); 350 Print; 351 continue; 352 } 353 if (!strcmp(word, "undef") && proc) { /* Undef: Undefine the */ 354 ch = fgetarg(zin, word); /* symbol, and goto */ 355 Undefine(word, MUTABLE); /* the end of line */ 356 (void)printf("#undef %s%c", word, ch); 357 Print; 358 continue; 359 } 360 if (!strcmp(word, "if")) { /* If: we cannot handle these */ 361 if (!proc) /* at the moment, so just */ 362 skip++; /* treat them as an ignored */ 363 else { /* definition */ 364 (void)printf("#%s%c",word,ch); 365 Print; 366 ch = getendif(); /* Get matching endif */ 367 continue; 368 } 369 } 370 if (!strcmp(word, "ifdef")) { /* Ifdef: */ 371 if (!proc) /* If not processing */ 372 skip++; /* skip it */ 373 else { 374 ch = fgetarg(zin, word); /* Get the symbol */ 375 switch (find(word)) { 376 case DEF: 377 break; 378 case IGN: 379 (void)printf("#ifdef %s%c", word, ch); 380 Print; 381 ch = getendif(); /* Get matching endif */ 382 break; 383 /* If symbol undefined */ 384 default: 385 Undefine(word, MUTABLE); /* undefine it */ 386 proc = 0; /* & stop processing */ 387 } 388 } 389 Goto; 390 continue; 391 } 392 if (!strcmp(word, "ifndef")) { 393 /* Ifndef: */ 394 if (!proc) /* If not processing */ 395 skip++; /* skip the line */ 396 else { 397 ch = fgetarg(zin, word); /* Get the symbol */ 398 switch (find(word)) { /* If defined, stop */ 399 case DEF: 400 proc = 0; /* processing */ 401 break; 402 case IGN: 403 (void)printf("#ifdef %s%c", word, ch); 404 Print; 405 ch = getendif(); /* Get matching endif */ 406 break; 407 } 408 } 409 Goto; 410 continue; 411 } 412 if (!strcmp(word, "else") && !skip) { /* Else: Flip processing */ 413 proc = !proc; 414 Goto; 415 continue; 416 } 417 if (!strcmp(word, "endif")) { /* Endif: If no skipped */ 418 /* ifdefs turn processing */ 419 if (!skip) /* on, else decrement the */ 420 proc = 1; /* number of skips */ 421 else 422 skip--; 423 Goto; 424 continue; 425 } 426 /* The word fails all of the above tests, so if we're */ 427 /* processing, print the line. */ 428 if (proc) { 429 (void)printf("#%s%c", word, ch); 430 Print; 431 } else 432 Goto; 433 } 434 } 435 436 437 #ifdef __STDC__ 438 void usage ( void ) 439 #else 440 void usage() 441 #endif 442 { 443 (void)fprintf(stderr, "Usage: ifdef [-t] [-Dsymbol] [-dsymbol] [-Usymbol] [-Isymbol] <file>\n"); 444 exit(0); 445 } 446 447 448 #ifdef __STDC__ 449 int main(int argc , char *argv []) 450 #else 451 int main(argc, argv) 452 int argc; 453 char *argv[]; 454 #endif 455 { 456 char sym[80]; /* Temp symbol storage */ 457 int c; 458 459 if (argc == 1) usage(); /* Catch the curious user */ 460 while ((c = getopt(argc, argv, "tD:d:U:I:")) != EOF) { 461 switch (c) { 462 case 't': 463 table = 1; /* Get the various options */ 464 break; 465 466 case 'd': 467 (void)strcpy(sym, optarg); 468 Define(sym, MUTABLE); 469 break; 470 471 case 'D': 472 (void)strcpy(sym, optarg); 473 Define(sym, IMMUTABLE); 474 break; 475 476 case 'U': 477 (void)strcpy(sym, optarg); 478 Undefine(sym, IMMUTABLE); 479 break; 480 481 case 'I': 482 (void)strcpy(sym, optarg); 483 Ignore(sym, IMMUTABLE); 484 break; 485 486 default: usage(); 487 } 488 } 489 490 zin = stdin; /* If a C file is named */ 491 /* Open stdin with it */ 492 if (*argv[argc - 1] != '-') { 493 (void)fclose(zin); 494 if ((zin = fopen(argv[argc - 1], "r")) == NULL) { 495 perror("ifdef"); 496 exit(1); 497 } 498 } 499 if (table) 500 gettable(); /* Either generate a table or */ 501 else 502 parse(); /* parse & replace with the file */ 503 return(0); 504 } 505