Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

745 lines
23 KiB

  1. /***
  2. *ifstrip.c - Ifdef stripping tool
  3. *
  4. * Copyright (c) 1988-2001, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. * Strip in/out conditional code from sources.
  8. * Refer to ifstrip.doc for more information.
  9. *
  10. *Revision History:
  11. * ??-??-88 PHG Initial version
  12. * 05-10-90 JCR Accept .cxx/.hxx files, misc cleanup, etc.
  13. * 09-18-92 MAL Rewritten to cope with nested IFs, ELIFs etc.
  14. * 09-30-92 MAL Added support for IF expressions, modularized code
  15. * 10-13-93 SKS Recognize comments of the form /-*IFSTRIP=IGN*-/ to
  16. * override ifstrip behavior.
  17. * 09-01-94 SKS Add terseflag (-t) to suppress mesgs about directives
  18. * 10-05-94 SKS Fix bug: Add missing space to keyword "ifndef "
  19. * 01-04-99 GB Added support for internal CRT builds.
  20. *
  21. *******************************************************************************/
  22. #include <stdio.h>
  23. #include <stdlib.h>
  24. #include <ctype.h>
  25. #include <string.h>
  26. #include <search.h>
  27. #include <direct.h>
  28. #include <io.h>
  29. #include <errno.h>
  30. #include <fcntl.h>
  31. #include "constant.h" /* Program constants used by modules */
  32. #include "errormes.h" /* Error and warning reporting */
  33. #include "symtab.h" /* Symbol table handling */
  34. #include "eval.h" /* If expression evaluation */
  35. /* Global constants */
  36. /* CFW - added ifdef, ifndef asm keywords, added IFE, added IFDIF */
  37. char *syntaxstrings[2][maxkeyword + 1] =
  38. { {"#if ", "#elif ", "#else ", "#endif ", "#ifdef ", "#ifndef ", "", "", "", "", "", "", "" },
  39. {"if ", "", "else ", "endif ", "ifdef ", "ifndef ", "if1 ", "if2 ", "ifb ", "ifnb ", "ifidn ", "ifdif ", "ife " } };
  40. /* Language dependent if constructs, must be in the order c, asm and the keywords in the
  41. same order as the tokens stored in constant.h - All strings must be followed by a
  42. space, and those not available in a language should be empty */
  43. int syntaxlengths[2][maxkeyword + 1] = { {3, 5, 5, 6, 6, 7, 0, 0, 0, 0, 0, 0, 0},
  44. {2, 0, 4, 5, 5, 6, 3, 3, 3, 4, 5, 5, 3} };
  45. /* The lengths of the above strings minus spaces. Unused keywords marked with 0 */
  46. /* CFW - added comment stuff */
  47. char *commentstrings[2][maxcomment] = { {"/* ", "// "}, {"; ", ""} };
  48. int commentlengths[2][maxcomment] = { {2, 2 }, {1, 0} };
  49. /* must ignore comments in IF statements */
  50. /* Global variables */
  51. int terseFlag = FALSE; /* TRUE means do not echo forced directives */
  52. int warnings = TRUE; /* TRUE == print warnings */
  53. int currdir = FALSE; /* Put in current dir, use source extension */
  54. int isasm; /* TRUE == is assembler file */
  55. char **syntax; /* Language dependent syntax for output / matching */
  56. int *synlen; /* Lengths of above strings */
  57. char **comments; /* Language dependent comment strings */
  58. int *commlen; /* Lengths of above strings */
  59. char extension[5] = ".new"; /* Extension for output file */
  60. FILE *outfile; /* Current output file */
  61. char *curr_file; /* Name of current input file */
  62. FILE *infile; /* Current input file */
  63. FILE *errorfile; /* file to output error/warning messages */
  64. int linenum; /* Line number of current input file */
  65. int nonumbers; /* allow numeric expressions */
  66. enum {NOCOMMENT, CSTYLE, CPPSTYLE} commstyle = NOCOMMENT; /* type of comment to put after #else/#endif */
  67. enum {NON_CRT = 0, CRT=1} progtype = NON_CRT;
  68. char _inputline[MAXLINELEN];
  69. /* Functions */
  70. void setfiletype(char *);
  71. void makenewname(char *, char *);
  72. void usage(void);
  73. void stripprog(void);
  74. void putstring(char *);
  75. void putline(char *);
  76. char *getstring(char *, int, FILE *);
  77. char *cleanse(char *inputstring);
  78. void stripifdef(int, char *);
  79. void definedif(void);
  80. void undefinedif(void);
  81. void undefinedifsubpart(int, char *);
  82. void ignoredif(int, char *);
  83. void ignoredifsubpart(int, char *, char *);
  84. void skipto(int *, char *, int);
  85. void copyto(int *, char *, int);
  86. char *parseline(char *, int *);
  87. void stripif(int, char *);
  88. /* Print message and terminate */
  89. void error(reason, line)
  90. char *reason;
  91. char *line;
  92. {
  93. fprintf(errorfile, "%s(%d): %s\nfatal error: %s\n\n",
  94. curr_file, linenum, line, reason);
  95. exit(1);
  96. }
  97. /* Print message and return */
  98. void warning(reason, line)
  99. char *reason;
  100. char *line;
  101. {
  102. if (warnings)
  103. fprintf(errorfile, "%s(%d): %s\nwarning: %s\n\n", curr_file, linenum, line, reason);
  104. }
  105. /* Get a string from the input file, returns as fgets (MAL) */
  106. char *getstring(char *line, int n, FILE *fp)
  107. {
  108. char *returnvalue;
  109. int linelength;
  110. linenum++;
  111. returnvalue = fgets(line, n, fp);
  112. if (returnvalue != NULL)
  113. {
  114. linelength = strlen(line);
  115. if (line[linelength-1] == '\n')
  116. line[linelength-1] = '\0'; /* Strip trailing newline */
  117. else
  118. error("Line too long",line);
  119. }
  120. strcpy(_inputline, line);
  121. return returnvalue;
  122. }
  123. /* Put a string to the output file (MAL) */
  124. void putstring(char *string)
  125. {
  126. if ( fputs(string, outfile) == EOF )
  127. error("Fatal error writing output file","");
  128. }
  129. /* Put a line to the output file (MAL) */
  130. void putline(char *line)
  131. {
  132. putstring(line);
  133. if ( fputc('\n', outfile) == EOF )
  134. error("Fatal error writing output file","");
  135. }
  136. /* Put commented line like "#endif //CONDITION" based on comstytle flag
  137. * keyword = keyword to put
  138. * condition = condition to put
  139. */
  140. void putcommentedline(int keyword, char *condition)
  141. {
  142. if (progtype == CRT) {
  143. putline(_inputline);
  144. return;
  145. }
  146. putstring(syntax[keyword]);
  147. switch (commstyle) {
  148. case CSTYLE:
  149. if (isasm)
  150. putstring(" ; ");
  151. else
  152. putstring(" /* ");
  153. putstring(condition);
  154. if (isasm)
  155. putline("");
  156. else
  157. putline(" */");
  158. break;
  159. case CPPSTYLE:
  160. if (isasm)
  161. putstring(" ; ");
  162. else
  163. putstring(" // ");
  164. putline(condition);
  165. break;
  166. case NOCOMMENT:
  167. putline("");
  168. }
  169. }
  170. /* Set file type (assembler or C, treat C++ as C) */
  171. /* Language strings added (MAL) */
  172. void setfiletype(filename)
  173. char *filename;
  174. {
  175. char *p;
  176. p = strrchr(filename, '.');
  177. if (p == NULL)
  178. error("file must have an extension", "");
  179. if ( (_stricmp(p, ".c") == 0) || (_stricmp(p, ".h") == 0) ||
  180. (_stricmp(p, ".cpp") == 0) || (_stricmp(p, ".hpp") == 0) ||
  181. (_stricmp(p, ".cxx") == 0) || (_stricmp(p, ".hxx") == 0) ||
  182. (_stricmp(p, ".s") == 0) )
  183. isasm = FALSE;
  184. else if ( (_stricmp(p, ".asm") == 0) || (_stricmp(p, ".inc") == 0) )
  185. isasm = TRUE;
  186. else
  187. error("cannot determine file type", "");
  188. syntax = syntaxstrings[(isasm) ? 1 : 0]; /* Choose correct set of syntax strings */
  189. synlen = syntaxlengths[(isasm) ? 1 : 0]; /* and lengths */
  190. comments = commentstrings[(isasm) ? 1 : 0]; /* Choose correct comment set */
  191. commlen = commentlengths[(isasm) ? 1 : 0]; /* and lengths */
  192. }
  193. /* Make output file name */
  194. void makenewname(filename, newname)
  195. char *filename, *newname;
  196. {
  197. char *p;
  198. if (!currdir) {
  199. /* put on new extension */
  200. strcpy(newname, filename);
  201. p = strrchr(newname, '.');
  202. if (p == NULL)
  203. error("file must have an extension", "");
  204. strcpy(p, extension);
  205. }
  206. else {
  207. /* strip off directory specifier */
  208. p = strrchr(filename, '\\');
  209. if (p == NULL)
  210. error("file must not be in current directory", "");
  211. strcpy(newname, p+1);
  212. }
  213. }
  214. /* Strip the ifs within a program or block of program text (MAL) */
  215. void stripprog()
  216. {
  217. char inputline[MAXLINELEN], *condition;
  218. int linetype;
  219. while ( getstring(inputline, MAXLINELEN, infile) != NULL )
  220. {
  221. condition = parseline(inputline, &linetype); /* Get the line token and condition pointer */
  222. switch (linetype)
  223. {
  224. case NORMAL:
  225. putline(inputline);
  226. break;
  227. case IFDEF:
  228. case IFNDEF:
  229. stripifdef(linetype, condition);
  230. break;
  231. case IF:
  232. case IFE:
  233. stripif(linetype, condition);
  234. break;
  235. case IF1:
  236. case IF2:
  237. case IFB:
  238. case IFNB:
  239. case IFIDN:
  240. /* CFW - ignore special assembler directives */
  241. ignoredif(linetype, condition);
  242. break;
  243. default:
  244. error("Error in program structure - ELSE / ELIF / ENDIF before IF","");
  245. }
  246. }
  247. }
  248. // CFW - cleanse condition strings of any trailing junk such as comments
  249. char *cleanse(char *inputstring)
  250. {
  251. char *linepointer = inputstring;
  252. while (__iscsym(*linepointer))
  253. linepointer++;
  254. *linepointer = '\0';
  255. return inputstring;
  256. }
  257. /* Strip an if depending on the statement if(n)def and the value of its condition (MAL) */
  258. void stripifdef(int iftype, char *condition)
  259. {
  260. int condvalue;
  261. condvalue = lookupsym(cleanse(condition)); /* Find the value of the condition from the symbol table */
  262. if (iftype == IFNDEF)
  263. condvalue = negatecondition(condvalue); /* Negate the condition for IFNDEFs */
  264. switch (condvalue)
  265. {
  266. case DEFINED:
  267. definedif();
  268. break;
  269. case UNDEFINED:
  270. undefinedif(); /* CFW - changed definedif to undefinedif call */
  271. break;
  272. case NOTPRESENT:
  273. warning("Switch unlisted - ignoring", condition);
  274. /* Drop through to IGNORE case */
  275. case IGNORE:
  276. ignoredif(iftype, condition);
  277. }
  278. }
  279. void stripif(int linetype, char *condition)
  280. {
  281. char newcondition[MAXLINELEN]; /* IGNORE conditions can be MAXLINELEN long */
  282. int truth;
  283. evaluate(newcondition, &truth, condition); /* Get the truth value and new condition. */
  284. /* CFW - added IFE */
  285. if (linetype == IFE)
  286. truth = negatecondition(truth);
  287. switch (truth)
  288. {
  289. case DEFINED:
  290. definedif();
  291. break;
  292. case UNDEFINED:
  293. undefinedif();
  294. break;
  295. case IGNORE:
  296. ignoredif(linetype, newcondition);
  297. break;
  298. }
  299. }
  300. /* Strip a defined if (MAL) */
  301. void definedif()
  302. {
  303. char condition[MAXCONDLEN];
  304. int keyword;
  305. copyto(&keyword, condition, KEYWORD); /* Copy up to the ELSE / ELIF / ENDIF */
  306. if (keyword != ENDIF)
  307. skipto(&keyword, condition, ENDIF); /* Skip forward to the ENDIF if not there already */
  308. }
  309. /* Strip an undefined if (MAL) */
  310. void undefinedif()
  311. {
  312. char condition[MAXCONDLEN];
  313. int keyword;
  314. skipto(&keyword, condition, KEYWORD); /* Skip to the ELSE / ELIF / ENDIF */
  315. if (keyword != ENDIF) /* No need to recurse if at ENDIF */
  316. undefinedifsubpart(keyword, condition); /* Deal with the ELSE / ELIF */
  317. }
  318. /* Deal with the subparts of an undefined if (MAL) */
  319. void undefinedifsubpart(int keyword, char *condition)
  320. {
  321. int nextkeyword, condvalue;
  322. char newcondition[MAXCONDLEN];
  323. char nextcondition[MAXCONDLEN];
  324. switch (keyword)
  325. {
  326. case ELIF:
  327. evaluate(newcondition, &condvalue, condition);
  328. switch (condvalue)
  329. {
  330. case DEFINED:
  331. copyto(&nextkeyword, nextcondition, KEYWORD);
  332. if (nextkeyword != ENDIF)
  333. skipto(&nextkeyword, nextcondition, ENDIF);
  334. break;
  335. case UNDEFINED:
  336. skipto(&nextkeyword, nextcondition, KEYWORD);
  337. if (keyword != ENDIF) /* No need to recurse at ENDIF */
  338. undefinedifsubpart(nextkeyword, nextcondition);
  339. break;
  340. case IGNORE:
  341. stripifdef(IFDEF, newcondition);
  342. }
  343. break;
  344. case ELSE:
  345. copyto(&nextkeyword, nextcondition, ENDIF);
  346. }
  347. }
  348. /* Strip an ignored if (MAL) */
  349. void ignoredif(int linetype, char *condition)
  350. {
  351. char *controlcondition;
  352. int nextkeyword;
  353. char nextcondition[MAXLINELEN]; /* IGNORE conditions may be a line long */
  354. if ( progtype == CRT){
  355. putline(_inputline);
  356. } else {
  357. putstring(syntax[linetype]); /* Use IF to cope with any expression */
  358. putline(condition);
  359. }
  360. controlcondition = _strdup(condition);
  361. copyto(&nextkeyword, nextcondition, KEYWORD);
  362. ignoredifsubpart(nextkeyword, nextcondition, controlcondition);
  363. free(controlcondition);
  364. }
  365. /* Deal with the subparts of an ignored if (MAL) */
  366. /* See design document for explanation of actions! */
  367. /* controlcondition is controlling condition of the if */
  368. void ignoredifsubpart(int keyword, char *condition, char *controlcondition)
  369. {
  370. int nextkeyword, condvalue;
  371. char newcondition[MAXLINELEN]; /* IGNORE conditions may be a line long */
  372. char nextcondition[MAXLINELEN]; /* IGNORE conditions may be a line long */
  373. switch (keyword)
  374. {
  375. case ELIF:
  376. /* CFW - replaced lookupsym with evaluate */
  377. evaluate(newcondition, &condvalue, condition);
  378. switch (condvalue)
  379. {
  380. case DEFINED:
  381. putcommentedline(ELSE, controlcondition); /* ELSIF DEFINED == ELSE */
  382. copyto(&nextkeyword, nextcondition, KEYWORD);
  383. if (nextkeyword != ENDIF)
  384. skipto(&nextkeyword, nextcondition, ENDIF);
  385. if (progtype == CRT)
  386. putline(_inputline);
  387. else
  388. putline(syntax[ENDIF]);
  389. break;
  390. case UNDEFINED: /* ELSIF UNDEFINED skipped */
  391. skipto(&nextkeyword, nextcondition, KEYWORD);
  392. ignoredifsubpart(nextkeyword, nextcondition, controlcondition);
  393. break;
  394. case IGNORE:
  395. if ( progtype == CRT)
  396. putline(_inputline);
  397. else {
  398. putstring(syntax[ELIF]); /* ELSIF IGNORED copied like IF */
  399. putline(newcondition);
  400. }
  401. controlcondition = _strdup(newcondition); // new controlling condition.
  402. copyto(&nextkeyword, nextcondition, KEYWORD);
  403. ignoredifsubpart(nextkeyword, nextcondition, controlcondition);
  404. free(controlcondition);
  405. }
  406. break;
  407. case ELSE:
  408. putcommentedline(ELSE, controlcondition);
  409. copyto(&nextkeyword, nextcondition, ENDIF);
  410. putcommentedline(ENDIF, controlcondition);
  411. break;
  412. case ENDIF:
  413. putcommentedline(ENDIF, controlcondition);
  414. }
  415. }
  416. /* Skip to the target keyword. Returns the keyword found and any condition following it. (MAL) */
  417. void skipto(int *keyword, char *condition, int target)
  418. {
  419. char currline[MAXLINELEN], *conditioninline;
  420. int linetype, ifdepth = 0, found = FALSE;
  421. while (!found)
  422. if ( getstring(currline, MAXLINELEN, infile) != NULL )
  423. {
  424. conditioninline = parseline(currline, &linetype);
  425. switch (linetype)
  426. {
  427. case NORMAL:
  428. break; /* Ignore a normal line */
  429. case IFDEF:
  430. case IFNDEF:
  431. case IF:
  432. case IF1:
  433. case IF2:
  434. case IFB:
  435. case IFNB:
  436. case IFIDN:
  437. case IFE:
  438. ifdepth++;
  439. break; /* Register nested if, do not need to test for stripping */
  440. case ENDIF:
  441. if (ifdepth > 0)
  442. {
  443. ifdepth--; /* Back up a level if in a nested if */
  444. break;
  445. }
  446. /* Else drop through to default case */
  447. default:
  448. if ( (ifdepth == 0) && ((linetype == target) || (target == KEYWORD)) )
  449. found = TRUE;
  450. }
  451. }
  452. else
  453. error("Error in program structure - EOF before ENDIF", "");
  454. *keyword = linetype; /* Return keyword token */
  455. strcpy(condition, conditioninline);
  456. }
  457. /* Copy to the target keyword. Returns the keyword found and any condition following it.
  458. Any if statements inside the area being copied are stripped as usual. (MAL) */
  459. void copyto(int *keyword, char *condition, int target)
  460. {
  461. char currline[MAXLINELEN], *conditioninline;
  462. int linetype, found = FALSE;
  463. while (!found)
  464. if ( getstring(currline, MAXLINELEN, infile) != NULL )
  465. {
  466. conditioninline = parseline(currline, &linetype);
  467. switch (linetype)
  468. {
  469. case NORMAL:
  470. putline(currline); /* Copy a normal line */
  471. break;
  472. case IFDEF:
  473. case IFNDEF:
  474. stripifdef(linetype, conditioninline); /* Strip a nested if(n)def */
  475. break;
  476. case IF:
  477. case IFE:
  478. stripif(linetype, conditioninline);
  479. break;
  480. case IF1:
  481. case IF2:
  482. case IFB:
  483. case IFNB:
  484. case IFIDN:
  485. /* CFW - ignore special assembler directives */
  486. ignoredif(linetype, conditioninline);
  487. break;
  488. default:
  489. if ( (linetype == target) || (target == KEYWORD) )
  490. found = TRUE;
  491. }
  492. }
  493. else
  494. error("Error in program structure - EOF before ENDIF", "");
  495. *keyword = linetype; /* Return line token */
  496. strcpy(condition, conditioninline);
  497. }
  498. /* Parse a line of text returning a condition pointer into the line and placing a line type in
  499. the integer location supplied (MAL) */
  500. char *parseline(char *inputline, int *linetype)
  501. {
  502. int numofwhitespace, comparetoken = 0, found = FALSE;
  503. char *linepointer = inputline;
  504. numofwhitespace = strspn(inputline, " \t");
  505. if (*(numofwhitespace + inputline) == '\0')
  506. {
  507. *linetype = NORMAL; /* Empty line */
  508. return NULL;
  509. }
  510. linepointer += numofwhitespace;
  511. do
  512. {
  513. if (synlen[comparetoken] != 0)
  514. {
  515. if ( (!_strnicmp(linepointer, syntax[comparetoken], (size_t) synlen[comparetoken])) &&
  516. ( isspace( *(linepointer + synlen[comparetoken]) ) || !*(linepointer + synlen[comparetoken]) ) )
  517. found = TRUE;
  518. else
  519. comparetoken++;
  520. }
  521. else
  522. comparetoken++;
  523. } while ( (!found) && (comparetoken <= maxkeyword) );
  524. if (found)
  525. {
  526. linepointer += synlen[comparetoken];
  527. if (*linepointer)
  528. linepointer += strspn(linepointer, " \t");
  529. *linetype = comparetoken;
  530. return linepointer;
  531. }
  532. else
  533. {
  534. *linetype = NORMAL;
  535. return NULL;
  536. }
  537. }
  538. /* Print program usage and quit */
  539. void usage()
  540. {
  541. fprintf(stderr, "Usage: ifstrip [-n] [-w] [-x[ext]] [-f switchfile] file ...\n");
  542. fprintf(stderr, "\n");
  543. fprintf(stderr, " -n produce no output files\n");
  544. fprintf(stderr, " -w suppresses warning levels\n");
  545. fprintf(stderr, " -f next argument is the switch file\n");
  546. fprintf(stderr, " -e next argument is the error/warning file\n");
  547. fprintf(stderr, " -c comment retained else/endifs with switch condition\n");
  548. fprintf(stderr, " -C save as -C, but C++ style (//) comments\n");
  549. fprintf(stderr, " -z treat numbers (e.g., #if 0) like identifiers\n");
  550. fprintf(stderr, " -x specify extension to use on output files\n");
  551. fprintf(stderr, " none means use source extension but put in\n");
  552. fprintf(stderr, " current directory (source must be in other dir)\n");
  553. fprintf(stderr, "\n");
  554. fprintf(stderr, " file list may contain wild cards\n");
  555. exit(1);
  556. }
  557. int exclude(struct _finddata_t f_data)
  558. {
  559. if ( f_data.attrib & _A_SUBDIR )
  560. {
  561. printf("%s is a directory\n", f_data.name);
  562. return 1;
  563. }
  564. return 0;
  565. }
  566. void gdir( char * dst, char * src)
  567. {
  568. int i;
  569. for ( i = strlen(src) -1; i >= 0 && (src[i] != '\\'); i--);
  570. strncpy(dst, src, i);
  571. dst[i] = 0;
  572. }
  573. /* Main program - parse command line, process each file */
  574. void main(argc, argv)
  575. int argc;
  576. char *argv[];
  577. {
  578. char *errorfilename;
  579. char *switchfilename = "switches";
  580. char outfilename[MAXFILENAMELEN];
  581. int ferrorfile = FALSE;
  582. int nooutput = FALSE;
  583. struct _finddata_t f_data;
  584. long h_find;
  585. char base_dir[256], curr_dir[256];
  586. int i;
  587. for (i = 1; i < argc; ++i) {
  588. if (argv[i][0] != '-')
  589. break;
  590. switch (argv[i][1]) {
  591. case 'w':
  592. warnings = FALSE;
  593. break;
  594. case 'f':
  595. ++i;
  596. switchfilename = argv[i];
  597. break;
  598. case 't':
  599. ++ terseFlag;
  600. break;
  601. case 'z':
  602. nonumbers = TRUE;
  603. break;
  604. case 'e':
  605. ++i;
  606. errorfilename = argv[i];
  607. ferrorfile = TRUE;
  608. break;
  609. case 'x':
  610. if (argv[i][2] == '\0')
  611. currdir = TRUE;
  612. else if (argv[i][2] == '.')
  613. strncpy(extension, argv[i]+2, 4);
  614. /* period was supplied */
  615. else
  616. strncpy(extension+1, argv[i]+2, 3);
  617. /* period not supplied */
  618. break;
  619. case 'n':
  620. nooutput = TRUE;
  621. break;
  622. case 'c':
  623. commstyle = CSTYLE;
  624. break;
  625. case 'C':
  626. commstyle = CPPSTYLE;
  627. break;
  628. case 'a':
  629. progtype = CRT;
  630. break;
  631. default:
  632. fprintf(errorfile, "unknown switch \"%s\"\n", argv[i]);
  633. usage();
  634. }
  635. }
  636. if (i >= argc)
  637. usage();
  638. if (ferrorfile)
  639. {
  640. errorfile = fopen(errorfilename, "a");
  641. if (errorfile == NULL)
  642. {
  643. fprintf(stderr, "cannot open \"%s\" for error, using stderr\n",
  644. errorfilename);
  645. ferrorfile = FALSE;
  646. errorfile = stderr;
  647. }
  648. }
  649. else
  650. errorfile = stderr;
  651. readsyms(switchfilename);
  652. if ( _getcwd(base_dir, 255) == NULL)
  653. exit(0);
  654. for ( ; i < argc; ++i) {
  655. gdir(curr_dir, argv[i]);
  656. if (_chdir(curr_dir) == -1) {
  657. printf("%s: %s\n", curr_dir, strerror(errno));
  658. exit(0);
  659. }
  660. if ( (h_find = _findfirst(argv[i], &f_data)) == -1)
  661. continue;
  662. do
  663. {
  664. if ( exclude(f_data) != 1)
  665. {
  666. curr_file = f_data.name;
  667. linenum = 0;
  668. setfiletype(curr_file);
  669. if (nooutput)
  670. strcpy(outfilename, "nul");
  671. else
  672. makenewname(curr_file, outfilename);
  673. infile = fopen(curr_file, "r");
  674. if (infile == NULL) {
  675. printf("%s which is %s is somewhat wrong, and the length is %d\n",f_data.name, strerror(errno), strlen(f_data.name));
  676. error("cannot open file for input", "");
  677. }
  678. outfile = fopen(outfilename, "w");
  679. if (outfile == NULL) {
  680. fprintf(stderr, "cannot open \"%s\" for output\n",
  681. outfilename);
  682. exit(1);
  683. }
  684. stripprog();
  685. fclose(infile);
  686. fclose(outfile);
  687. }
  688. } while ( _findnext(h_find, &f_data) == 0);
  689. _findclose(h_find);
  690. if (_chdir(base_dir) == -1) {
  691. printf("%s: %s\n", curr_dir, strerror(errno));
  692. exit(0);
  693. }
  694. }
  695. if (ferrorfile)
  696. fclose(errorfile);
  697. exit(0);
  698. }