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
745 lines
23 KiB
/***
|
|
*ifstrip.c - Ifdef stripping tool
|
|
*
|
|
* Copyright (c) 1988-2001, Microsoft Corporation. All rights reserved.
|
|
*
|
|
*Purpose:
|
|
* Strip in/out conditional code from sources.
|
|
* Refer to ifstrip.doc for more information.
|
|
*
|
|
*Revision History:
|
|
* ??-??-88 PHG Initial version
|
|
* 05-10-90 JCR Accept .cxx/.hxx files, misc cleanup, etc.
|
|
* 09-18-92 MAL Rewritten to cope with nested IFs, ELIFs etc.
|
|
* 09-30-92 MAL Added support for IF expressions, modularized code
|
|
* 10-13-93 SKS Recognize comments of the form /-*IFSTRIP=IGN*-/ to
|
|
* override ifstrip behavior.
|
|
* 09-01-94 SKS Add terseflag (-t) to suppress mesgs about directives
|
|
* 10-05-94 SKS Fix bug: Add missing space to keyword "ifndef "
|
|
* 01-04-99 GB Added support for internal CRT builds.
|
|
*
|
|
*******************************************************************************/
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <ctype.h>
|
|
#include <string.h>
|
|
#include <search.h>
|
|
#include <direct.h>
|
|
#include <io.h>
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include "constant.h" /* Program constants used by modules */
|
|
#include "errormes.h" /* Error and warning reporting */
|
|
#include "symtab.h" /* Symbol table handling */
|
|
#include "eval.h" /* If expression evaluation */
|
|
|
|
/* Global constants */
|
|
/* CFW - added ifdef, ifndef asm keywords, added IFE, added IFDIF */
|
|
char *syntaxstrings[2][maxkeyword + 1] =
|
|
{ {"#if ", "#elif ", "#else ", "#endif ", "#ifdef ", "#ifndef ", "", "", "", "", "", "", "" },
|
|
{"if ", "", "else ", "endif ", "ifdef ", "ifndef ", "if1 ", "if2 ", "ifb ", "ifnb ", "ifidn ", "ifdif ", "ife " } };
|
|
/* Language dependent if constructs, must be in the order c, asm and the keywords in the
|
|
same order as the tokens stored in constant.h - All strings must be followed by a
|
|
space, and those not available in a language should be empty */
|
|
int syntaxlengths[2][maxkeyword + 1] = { {3, 5, 5, 6, 6, 7, 0, 0, 0, 0, 0, 0, 0},
|
|
{2, 0, 4, 5, 5, 6, 3, 3, 3, 4, 5, 5, 3} };
|
|
/* The lengths of the above strings minus spaces. Unused keywords marked with 0 */
|
|
|
|
/* CFW - added comment stuff */
|
|
char *commentstrings[2][maxcomment] = { {"/* ", "// "}, {"; ", ""} };
|
|
int commentlengths[2][maxcomment] = { {2, 2 }, {1, 0} };
|
|
/* must ignore comments in IF statements */
|
|
|
|
/* Global variables */
|
|
int terseFlag = FALSE; /* TRUE means do not echo forced directives */
|
|
int warnings = TRUE; /* TRUE == print warnings */
|
|
int currdir = FALSE; /* Put in current dir, use source extension */
|
|
int isasm; /* TRUE == is assembler file */
|
|
char **syntax; /* Language dependent syntax for output / matching */
|
|
int *synlen; /* Lengths of above strings */
|
|
char **comments; /* Language dependent comment strings */
|
|
int *commlen; /* Lengths of above strings */
|
|
char extension[5] = ".new"; /* Extension for output file */
|
|
FILE *outfile; /* Current output file */
|
|
char *curr_file; /* Name of current input file */
|
|
FILE *infile; /* Current input file */
|
|
FILE *errorfile; /* file to output error/warning messages */
|
|
int linenum; /* Line number of current input file */
|
|
int nonumbers; /* allow numeric expressions */
|
|
enum {NOCOMMENT, CSTYLE, CPPSTYLE} commstyle = NOCOMMENT; /* type of comment to put after #else/#endif */
|
|
enum {NON_CRT = 0, CRT=1} progtype = NON_CRT;
|
|
char _inputline[MAXLINELEN];
|
|
|
|
/* Functions */
|
|
void setfiletype(char *);
|
|
void makenewname(char *, char *);
|
|
void usage(void);
|
|
void stripprog(void);
|
|
void putstring(char *);
|
|
void putline(char *);
|
|
char *getstring(char *, int, FILE *);
|
|
char *cleanse(char *inputstring);
|
|
void stripifdef(int, char *);
|
|
void definedif(void);
|
|
void undefinedif(void);
|
|
void undefinedifsubpart(int, char *);
|
|
void ignoredif(int, char *);
|
|
void ignoredifsubpart(int, char *, char *);
|
|
void skipto(int *, char *, int);
|
|
void copyto(int *, char *, int);
|
|
char *parseline(char *, int *);
|
|
void stripif(int, char *);
|
|
|
|
/* Print message and terminate */
|
|
void error(reason, line)
|
|
char *reason;
|
|
char *line;
|
|
{
|
|
fprintf(errorfile, "%s(%d): %s\nfatal error: %s\n\n",
|
|
curr_file, linenum, line, reason);
|
|
exit(1);
|
|
}
|
|
|
|
/* Print message and return */
|
|
void warning(reason, line)
|
|
char *reason;
|
|
char *line;
|
|
{
|
|
if (warnings)
|
|
fprintf(errorfile, "%s(%d): %s\nwarning: %s\n\n", curr_file, linenum, line, reason);
|
|
}
|
|
|
|
/* Get a string from the input file, returns as fgets (MAL) */
|
|
char *getstring(char *line, int n, FILE *fp)
|
|
{
|
|
char *returnvalue;
|
|
int linelength;
|
|
linenum++;
|
|
returnvalue = fgets(line, n, fp);
|
|
if (returnvalue != NULL)
|
|
{
|
|
linelength = strlen(line);
|
|
if (line[linelength-1] == '\n')
|
|
line[linelength-1] = '\0'; /* Strip trailing newline */
|
|
else
|
|
error("Line too long",line);
|
|
}
|
|
strcpy(_inputline, line);
|
|
return returnvalue;
|
|
}
|
|
|
|
/* Put a string to the output file (MAL) */
|
|
void putstring(char *string)
|
|
{
|
|
if ( fputs(string, outfile) == EOF )
|
|
error("Fatal error writing output file","");
|
|
}
|
|
|
|
/* Put a line to the output file (MAL) */
|
|
void putline(char *line)
|
|
{
|
|
putstring(line);
|
|
if ( fputc('\n', outfile) == EOF )
|
|
error("Fatal error writing output file","");
|
|
}
|
|
|
|
/* Put commented line like "#endif //CONDITION" based on comstytle flag
|
|
* keyword = keyword to put
|
|
* condition = condition to put
|
|
*/
|
|
void putcommentedline(int keyword, char *condition)
|
|
{
|
|
if (progtype == CRT) {
|
|
putline(_inputline);
|
|
return;
|
|
}
|
|
putstring(syntax[keyword]);
|
|
switch (commstyle) {
|
|
case CSTYLE:
|
|
if (isasm)
|
|
putstring(" ; ");
|
|
else
|
|
putstring(" /* ");
|
|
putstring(condition);
|
|
if (isasm)
|
|
putline("");
|
|
else
|
|
putline(" */");
|
|
break;
|
|
case CPPSTYLE:
|
|
if (isasm)
|
|
putstring(" ; ");
|
|
else
|
|
putstring(" // ");
|
|
putline(condition);
|
|
break;
|
|
case NOCOMMENT:
|
|
putline("");
|
|
}
|
|
}
|
|
|
|
/* Set file type (assembler or C, treat C++ as C) */
|
|
/* Language strings added (MAL) */
|
|
void setfiletype(filename)
|
|
char *filename;
|
|
{
|
|
char *p;
|
|
|
|
p = strrchr(filename, '.');
|
|
if (p == NULL)
|
|
error("file must have an extension", "");
|
|
if ( (_stricmp(p, ".c") == 0) || (_stricmp(p, ".h") == 0) ||
|
|
(_stricmp(p, ".cpp") == 0) || (_stricmp(p, ".hpp") == 0) ||
|
|
(_stricmp(p, ".cxx") == 0) || (_stricmp(p, ".hxx") == 0) ||
|
|
(_stricmp(p, ".s") == 0) )
|
|
isasm = FALSE;
|
|
else if ( (_stricmp(p, ".asm") == 0) || (_stricmp(p, ".inc") == 0) )
|
|
isasm = TRUE;
|
|
else
|
|
error("cannot determine file type", "");
|
|
syntax = syntaxstrings[(isasm) ? 1 : 0]; /* Choose correct set of syntax strings */
|
|
synlen = syntaxlengths[(isasm) ? 1 : 0]; /* and lengths */
|
|
comments = commentstrings[(isasm) ? 1 : 0]; /* Choose correct comment set */
|
|
commlen = commentlengths[(isasm) ? 1 : 0]; /* and lengths */
|
|
}
|
|
|
|
/* Make output file name */
|
|
void makenewname(filename, newname)
|
|
char *filename, *newname;
|
|
{
|
|
char *p;
|
|
|
|
if (!currdir) {
|
|
/* put on new extension */
|
|
strcpy(newname, filename);
|
|
p = strrchr(newname, '.');
|
|
if (p == NULL)
|
|
error("file must have an extension", "");
|
|
strcpy(p, extension);
|
|
}
|
|
else {
|
|
/* strip off directory specifier */
|
|
p = strrchr(filename, '\\');
|
|
if (p == NULL)
|
|
error("file must not be in current directory", "");
|
|
strcpy(newname, p+1);
|
|
}
|
|
}
|
|
|
|
/* Strip the ifs within a program or block of program text (MAL) */
|
|
void stripprog()
|
|
{
|
|
char inputline[MAXLINELEN], *condition;
|
|
int linetype;
|
|
while ( getstring(inputline, MAXLINELEN, infile) != NULL )
|
|
{
|
|
condition = parseline(inputline, &linetype); /* Get the line token and condition pointer */
|
|
switch (linetype)
|
|
{
|
|
case NORMAL:
|
|
putline(inputline);
|
|
break;
|
|
case IFDEF:
|
|
case IFNDEF:
|
|
stripifdef(linetype, condition);
|
|
break;
|
|
case IF:
|
|
case IFE:
|
|
stripif(linetype, condition);
|
|
break;
|
|
case IF1:
|
|
case IF2:
|
|
case IFB:
|
|
case IFNB:
|
|
case IFIDN:
|
|
/* CFW - ignore special assembler directives */
|
|
ignoredif(linetype, condition);
|
|
break;
|
|
default:
|
|
error("Error in program structure - ELSE / ELIF / ENDIF before IF","");
|
|
}
|
|
}
|
|
}
|
|
|
|
// CFW - cleanse condition strings of any trailing junk such as comments
|
|
char *cleanse(char *inputstring)
|
|
{
|
|
char *linepointer = inputstring;
|
|
|
|
while (__iscsym(*linepointer))
|
|
linepointer++;
|
|
|
|
*linepointer = '\0';
|
|
|
|
return inputstring;
|
|
}
|
|
|
|
|
|
/* Strip an if depending on the statement if(n)def and the value of its condition (MAL) */
|
|
void stripifdef(int iftype, char *condition)
|
|
{
|
|
int condvalue;
|
|
condvalue = lookupsym(cleanse(condition)); /* Find the value of the condition from the symbol table */
|
|
if (iftype == IFNDEF)
|
|
condvalue = negatecondition(condvalue); /* Negate the condition for IFNDEFs */
|
|
switch (condvalue)
|
|
{
|
|
case DEFINED:
|
|
definedif();
|
|
break;
|
|
case UNDEFINED:
|
|
undefinedif(); /* CFW - changed definedif to undefinedif call */
|
|
break;
|
|
case NOTPRESENT:
|
|
warning("Switch unlisted - ignoring", condition);
|
|
/* Drop through to IGNORE case */
|
|
case IGNORE:
|
|
ignoredif(iftype, condition);
|
|
}
|
|
}
|
|
|
|
void stripif(int linetype, char *condition)
|
|
{
|
|
char newcondition[MAXLINELEN]; /* IGNORE conditions can be MAXLINELEN long */
|
|
int truth;
|
|
evaluate(newcondition, &truth, condition); /* Get the truth value and new condition. */
|
|
/* CFW - added IFE */
|
|
if (linetype == IFE)
|
|
truth = negatecondition(truth);
|
|
switch (truth)
|
|
{
|
|
case DEFINED:
|
|
definedif();
|
|
break;
|
|
case UNDEFINED:
|
|
undefinedif();
|
|
break;
|
|
case IGNORE:
|
|
ignoredif(linetype, newcondition);
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Strip a defined if (MAL) */
|
|
void definedif()
|
|
{
|
|
char condition[MAXCONDLEN];
|
|
int keyword;
|
|
copyto(&keyword, condition, KEYWORD); /* Copy up to the ELSE / ELIF / ENDIF */
|
|
if (keyword != ENDIF)
|
|
skipto(&keyword, condition, ENDIF); /* Skip forward to the ENDIF if not there already */
|
|
}
|
|
|
|
/* Strip an undefined if (MAL) */
|
|
void undefinedif()
|
|
{
|
|
char condition[MAXCONDLEN];
|
|
int keyword;
|
|
skipto(&keyword, condition, KEYWORD); /* Skip to the ELSE / ELIF / ENDIF */
|
|
if (keyword != ENDIF) /* No need to recurse if at ENDIF */
|
|
undefinedifsubpart(keyword, condition); /* Deal with the ELSE / ELIF */
|
|
}
|
|
|
|
/* Deal with the subparts of an undefined if (MAL) */
|
|
void undefinedifsubpart(int keyword, char *condition)
|
|
{
|
|
int nextkeyword, condvalue;
|
|
char newcondition[MAXCONDLEN];
|
|
char nextcondition[MAXCONDLEN];
|
|
switch (keyword)
|
|
{
|
|
case ELIF:
|
|
evaluate(newcondition, &condvalue, condition);
|
|
switch (condvalue)
|
|
{
|
|
case DEFINED:
|
|
copyto(&nextkeyword, nextcondition, KEYWORD);
|
|
if (nextkeyword != ENDIF)
|
|
skipto(&nextkeyword, nextcondition, ENDIF);
|
|
break;
|
|
case UNDEFINED:
|
|
skipto(&nextkeyword, nextcondition, KEYWORD);
|
|
if (keyword != ENDIF) /* No need to recurse at ENDIF */
|
|
undefinedifsubpart(nextkeyword, nextcondition);
|
|
break;
|
|
case IGNORE:
|
|
stripifdef(IFDEF, newcondition);
|
|
}
|
|
break;
|
|
case ELSE:
|
|
copyto(&nextkeyword, nextcondition, ENDIF);
|
|
}
|
|
}
|
|
|
|
/* Strip an ignored if (MAL) */
|
|
void ignoredif(int linetype, char *condition)
|
|
{
|
|
char *controlcondition;
|
|
int nextkeyword;
|
|
char nextcondition[MAXLINELEN]; /* IGNORE conditions may be a line long */
|
|
if ( progtype == CRT){
|
|
putline(_inputline);
|
|
} else {
|
|
putstring(syntax[linetype]); /* Use IF to cope with any expression */
|
|
putline(condition);
|
|
}
|
|
controlcondition = _strdup(condition);
|
|
copyto(&nextkeyword, nextcondition, KEYWORD);
|
|
ignoredifsubpart(nextkeyword, nextcondition, controlcondition);
|
|
free(controlcondition);
|
|
}
|
|
|
|
/* Deal with the subparts of an ignored if (MAL) */
|
|
/* See design document for explanation of actions! */
|
|
/* controlcondition is controlling condition of the if */
|
|
void ignoredifsubpart(int keyword, char *condition, char *controlcondition)
|
|
{
|
|
int nextkeyword, condvalue;
|
|
char newcondition[MAXLINELEN]; /* IGNORE conditions may be a line long */
|
|
char nextcondition[MAXLINELEN]; /* IGNORE conditions may be a line long */
|
|
switch (keyword)
|
|
{
|
|
case ELIF:
|
|
/* CFW - replaced lookupsym with evaluate */
|
|
evaluate(newcondition, &condvalue, condition);
|
|
switch (condvalue)
|
|
{
|
|
case DEFINED:
|
|
putcommentedline(ELSE, controlcondition); /* ELSIF DEFINED == ELSE */
|
|
copyto(&nextkeyword, nextcondition, KEYWORD);
|
|
if (nextkeyword != ENDIF)
|
|
skipto(&nextkeyword, nextcondition, ENDIF);
|
|
if (progtype == CRT)
|
|
putline(_inputline);
|
|
else
|
|
putline(syntax[ENDIF]);
|
|
break;
|
|
case UNDEFINED: /* ELSIF UNDEFINED skipped */
|
|
skipto(&nextkeyword, nextcondition, KEYWORD);
|
|
ignoredifsubpart(nextkeyword, nextcondition, controlcondition);
|
|
break;
|
|
case IGNORE:
|
|
if ( progtype == CRT)
|
|
putline(_inputline);
|
|
else {
|
|
putstring(syntax[ELIF]); /* ELSIF IGNORED copied like IF */
|
|
putline(newcondition);
|
|
}
|
|
controlcondition = _strdup(newcondition); // new controlling condition.
|
|
copyto(&nextkeyword, nextcondition, KEYWORD);
|
|
ignoredifsubpart(nextkeyword, nextcondition, controlcondition);
|
|
free(controlcondition);
|
|
}
|
|
break;
|
|
case ELSE:
|
|
putcommentedline(ELSE, controlcondition);
|
|
copyto(&nextkeyword, nextcondition, ENDIF);
|
|
putcommentedline(ENDIF, controlcondition);
|
|
break;
|
|
case ENDIF:
|
|
putcommentedline(ENDIF, controlcondition);
|
|
}
|
|
}
|
|
|
|
/* Skip to the target keyword. Returns the keyword found and any condition following it. (MAL) */
|
|
void skipto(int *keyword, char *condition, int target)
|
|
{
|
|
char currline[MAXLINELEN], *conditioninline;
|
|
int linetype, ifdepth = 0, found = FALSE;
|
|
while (!found)
|
|
if ( getstring(currline, MAXLINELEN, infile) != NULL )
|
|
{
|
|
conditioninline = parseline(currline, &linetype);
|
|
switch (linetype)
|
|
{
|
|
case NORMAL:
|
|
break; /* Ignore a normal line */
|
|
case IFDEF:
|
|
case IFNDEF:
|
|
case IF:
|
|
case IF1:
|
|
case IF2:
|
|
case IFB:
|
|
case IFNB:
|
|
case IFIDN:
|
|
case IFE:
|
|
ifdepth++;
|
|
break; /* Register nested if, do not need to test for stripping */
|
|
case ENDIF:
|
|
if (ifdepth > 0)
|
|
{
|
|
ifdepth--; /* Back up a level if in a nested if */
|
|
break;
|
|
}
|
|
/* Else drop through to default case */
|
|
default:
|
|
if ( (ifdepth == 0) && ((linetype == target) || (target == KEYWORD)) )
|
|
found = TRUE;
|
|
}
|
|
}
|
|
else
|
|
error("Error in program structure - EOF before ENDIF", "");
|
|
*keyword = linetype; /* Return keyword token */
|
|
strcpy(condition, conditioninline);
|
|
}
|
|
|
|
/* Copy to the target keyword. Returns the keyword found and any condition following it.
|
|
Any if statements inside the area being copied are stripped as usual. (MAL) */
|
|
void copyto(int *keyword, char *condition, int target)
|
|
{
|
|
char currline[MAXLINELEN], *conditioninline;
|
|
int linetype, found = FALSE;
|
|
while (!found)
|
|
if ( getstring(currline, MAXLINELEN, infile) != NULL )
|
|
{
|
|
conditioninline = parseline(currline, &linetype);
|
|
switch (linetype)
|
|
{
|
|
case NORMAL:
|
|
putline(currline); /* Copy a normal line */
|
|
break;
|
|
case IFDEF:
|
|
case IFNDEF:
|
|
stripifdef(linetype, conditioninline); /* Strip a nested if(n)def */
|
|
break;
|
|
case IF:
|
|
case IFE:
|
|
stripif(linetype, conditioninline);
|
|
break;
|
|
case IF1:
|
|
case IF2:
|
|
case IFB:
|
|
case IFNB:
|
|
case IFIDN:
|
|
/* CFW - ignore special assembler directives */
|
|
ignoredif(linetype, conditioninline);
|
|
break;
|
|
default:
|
|
if ( (linetype == target) || (target == KEYWORD) )
|
|
found = TRUE;
|
|
}
|
|
}
|
|
else
|
|
error("Error in program structure - EOF before ENDIF", "");
|
|
*keyword = linetype; /* Return line token */
|
|
strcpy(condition, conditioninline);
|
|
}
|
|
|
|
/* Parse a line of text returning a condition pointer into the line and placing a line type in
|
|
the integer location supplied (MAL) */
|
|
char *parseline(char *inputline, int *linetype)
|
|
{
|
|
int numofwhitespace, comparetoken = 0, found = FALSE;
|
|
char *linepointer = inputline;
|
|
numofwhitespace = strspn(inputline, " \t");
|
|
if (*(numofwhitespace + inputline) == '\0')
|
|
{
|
|
*linetype = NORMAL; /* Empty line */
|
|
return NULL;
|
|
}
|
|
linepointer += numofwhitespace;
|
|
do
|
|
{
|
|
if (synlen[comparetoken] != 0)
|
|
{
|
|
if ( (!_strnicmp(linepointer, syntax[comparetoken], (size_t) synlen[comparetoken])) &&
|
|
( isspace( *(linepointer + synlen[comparetoken]) ) || !*(linepointer + synlen[comparetoken]) ) )
|
|
found = TRUE;
|
|
else
|
|
comparetoken++;
|
|
}
|
|
else
|
|
comparetoken++;
|
|
} while ( (!found) && (comparetoken <= maxkeyword) );
|
|
if (found)
|
|
{
|
|
linepointer += synlen[comparetoken];
|
|
if (*linepointer)
|
|
linepointer += strspn(linepointer, " \t");
|
|
*linetype = comparetoken;
|
|
return linepointer;
|
|
}
|
|
else
|
|
{
|
|
*linetype = NORMAL;
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
/* Print program usage and quit */
|
|
void usage()
|
|
{
|
|
fprintf(stderr, "Usage: ifstrip [-n] [-w] [-x[ext]] [-f switchfile] file ...\n");
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, " -n produce no output files\n");
|
|
fprintf(stderr, " -w suppresses warning levels\n");
|
|
fprintf(stderr, " -f next argument is the switch file\n");
|
|
fprintf(stderr, " -e next argument is the error/warning file\n");
|
|
fprintf(stderr, " -c comment retained else/endifs with switch condition\n");
|
|
fprintf(stderr, " -C save as -C, but C++ style (//) comments\n");
|
|
fprintf(stderr, " -z treat numbers (e.g., #if 0) like identifiers\n");
|
|
fprintf(stderr, " -x specify extension to use on output files\n");
|
|
fprintf(stderr, " none means use source extension but put in\n");
|
|
fprintf(stderr, " current directory (source must be in other dir)\n");
|
|
fprintf(stderr, "\n");
|
|
fprintf(stderr, " file list may contain wild cards\n");
|
|
exit(1);
|
|
}
|
|
|
|
|
|
|
|
int exclude(struct _finddata_t f_data)
|
|
{
|
|
if ( f_data.attrib & _A_SUBDIR )
|
|
{
|
|
printf("%s is a directory\n", f_data.name);
|
|
return 1;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
void gdir( char * dst, char * src)
|
|
{
|
|
int i;
|
|
for ( i = strlen(src) -1; i >= 0 && (src[i] != '\\'); i--);
|
|
strncpy(dst, src, i);
|
|
dst[i] = 0;
|
|
}
|
|
|
|
|
|
|
|
/* Main program - parse command line, process each file */
|
|
void main(argc, argv)
|
|
int argc;
|
|
char *argv[];
|
|
{
|
|
char *errorfilename;
|
|
char *switchfilename = "switches";
|
|
char outfilename[MAXFILENAMELEN];
|
|
int ferrorfile = FALSE;
|
|
int nooutput = FALSE;
|
|
struct _finddata_t f_data;
|
|
long h_find;
|
|
char base_dir[256], curr_dir[256];
|
|
int i;
|
|
|
|
for (i = 1; i < argc; ++i) {
|
|
if (argv[i][0] != '-')
|
|
break;
|
|
switch (argv[i][1]) {
|
|
case 'w':
|
|
warnings = FALSE;
|
|
break;
|
|
case 'f':
|
|
++i;
|
|
switchfilename = argv[i];
|
|
break;
|
|
case 't':
|
|
++ terseFlag;
|
|
break;
|
|
case 'z':
|
|
nonumbers = TRUE;
|
|
break;
|
|
|
|
case 'e':
|
|
++i;
|
|
errorfilename = argv[i];
|
|
ferrorfile = TRUE;
|
|
break;
|
|
case 'x':
|
|
if (argv[i][2] == '\0')
|
|
currdir = TRUE;
|
|
else if (argv[i][2] == '.')
|
|
strncpy(extension, argv[i]+2, 4);
|
|
/* period was supplied */
|
|
else
|
|
strncpy(extension+1, argv[i]+2, 3);
|
|
/* period not supplied */
|
|
break;
|
|
case 'n':
|
|
nooutput = TRUE;
|
|
break;
|
|
case 'c':
|
|
commstyle = CSTYLE;
|
|
break;
|
|
case 'C':
|
|
commstyle = CPPSTYLE;
|
|
break;
|
|
case 'a':
|
|
progtype = CRT;
|
|
break;
|
|
default:
|
|
fprintf(errorfile, "unknown switch \"%s\"\n", argv[i]);
|
|
usage();
|
|
}
|
|
}
|
|
|
|
if (i >= argc)
|
|
usage();
|
|
|
|
if (ferrorfile)
|
|
{
|
|
errorfile = fopen(errorfilename, "a");
|
|
if (errorfile == NULL)
|
|
{
|
|
fprintf(stderr, "cannot open \"%s\" for error, using stderr\n",
|
|
errorfilename);
|
|
ferrorfile = FALSE;
|
|
errorfile = stderr;
|
|
}
|
|
}
|
|
else
|
|
errorfile = stderr;
|
|
|
|
readsyms(switchfilename);
|
|
|
|
if ( _getcwd(base_dir, 255) == NULL)
|
|
exit(0);
|
|
for ( ; i < argc; ++i) {
|
|
gdir(curr_dir, argv[i]);
|
|
if (_chdir(curr_dir) == -1) {
|
|
printf("%s: %s\n", curr_dir, strerror(errno));
|
|
exit(0);
|
|
}
|
|
if ( (h_find = _findfirst(argv[i], &f_data)) == -1)
|
|
continue;
|
|
do
|
|
{
|
|
if ( exclude(f_data) != 1)
|
|
{
|
|
curr_file = f_data.name;
|
|
linenum = 0;
|
|
setfiletype(curr_file);
|
|
if (nooutput)
|
|
strcpy(outfilename, "nul");
|
|
else
|
|
makenewname(curr_file, outfilename);
|
|
infile = fopen(curr_file, "r");
|
|
if (infile == NULL) {
|
|
printf("%s which is %s is somewhat wrong, and the length is %d\n",f_data.name, strerror(errno), strlen(f_data.name));
|
|
error("cannot open file for input", "");
|
|
}
|
|
outfile = fopen(outfilename, "w");
|
|
if (outfile == NULL) {
|
|
fprintf(stderr, "cannot open \"%s\" for output\n",
|
|
outfilename);
|
|
exit(1);
|
|
}
|
|
stripprog();
|
|
fclose(infile);
|
|
fclose(outfile);
|
|
}
|
|
} while ( _findnext(h_find, &f_data) == 0);
|
|
_findclose(h_find);
|
|
if (_chdir(base_dir) == -1) {
|
|
printf("%s: %s\n", curr_dir, strerror(errno));
|
|
exit(0);
|
|
}
|
|
}
|
|
if (ferrorfile)
|
|
fclose(errorfile);
|
|
|
|
exit(0);
|
|
}
|