⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 unifdef.c

📁 早期freebsd实现
💻 C
字号:
/* * Copyright (c) 1985, 1993 *	The Regents of the University of California.  All rights reserved. * * This code is derived from software contributed to Berkeley by * Dave Yost. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char copyright[] ="@(#) Copyright (c) 1985, 1993\n\	The Regents of the University of California.  All rights reserved.\n";#endif /* not lint */#ifndef lintstatic char sccsid[] = "@(#)unifdef.c	8.1 (Berkeley) 6/6/93";#endif /* not lint *//* * unifdef - remove ifdef'ed lines * *  Warning: will not work correctly if input contains null characters. * *  Wishlist: *      provide an option which will append the name of the *        appropriate symbol after #else's and #endif's *      provide an option which will check symbols after *        #else's and #endif's to see that they match their *        corresponding #ifdef or #ifndef */#include <stdio.h>#include <ctype.h>#define BSSFILE *input;#ifndef YES#define YES 1#define NO  0#endif/*YES */typedef int Bool;char *progname BSS;char *filename BSS;char text BSS;          /* -t option in effect: this is a text file */char lnblank BSS;       /* -l option in effect: blank deleted lines */char complement BSS;    /* -c option in effect: complement the operation */#define MAXSYMS 100char *symname[MAXSYMS] BSS; /* symbol name */char true[MAXSYMS] BSS;     /* -Dsym */char ignore[MAXSYMS] BSS;   /* -iDsym or -iUsym */char insym[MAXSYMS] BSS;    /* state: false, inactive, true */#define SYM_INACTIVE 0      /* symbol is currently inactive */#define SYM_FALSE    1      /* symbol is currently false */#define SYM_TRUE     2      /* symbol is currently true  */char nsyms BSS;char incomment BSS;         /* inside C comment */#define QUOTE_NONE   0#define QUOTE_SINGLE 1#define QUOTE_DOUBLE 2char inquote BSS;           /* inside single or double quotes */int exitstat BSS;char *skipcomment ();char *skipquote ();main (argc, argv)int argc;char **argv;{    char **curarg;    register char *cp;    register char *cp1;    char ignorethis;    progname = argv[0][0] ? argv[0] : "unifdef";    for (curarg = &argv[1]; --argc > 0; curarg++) {	if (*(cp1 = cp = *curarg) != '-')	    break;	if (*++cp1 == 'i') {	    ignorethis = YES;	    cp1++;	} else	    ignorethis = NO;	if (   (   *cp1 == 'D'		|| *cp1 == 'U'	       )	    && cp1[1] != '\0'	   ) {	    register int symind;	    if ((symind = findsym (&cp1[1])) < 0) {		if (nsyms >= MAXSYMS) {		    prname ();		    fprintf (stderr, "too many symbols.\n");		    exit (2);		}		symind = nsyms++;		symname[symind] = &cp1[1];		insym[symind] = SYM_INACTIVE;	    }	    ignore[symind] = ignorethis;	    true[symind] = *cp1 == 'D' ? YES : NO;	} else if (ignorethis)	    goto unrec;	else if (strcmp (&cp[1], "t") == 0)	    text = YES;	else if (strcmp (&cp[1], "l") == 0)	    lnblank = YES;	else if (strcmp (&cp[1], "c") == 0)	    complement = YES;	else { unrec:	    prname ();	    fprintf (stderr, "unrecognized option: %s\n", cp);	    goto usage;	}    }    if (nsyms == 0) { usage:	fprintf (stderr, "\Usage: %s [-l] [-t] [-c] [[-Dsym] [-Usym] [-iDsym] [-iUsym]]... [file]\n\    At least one arg from [-D -U -iD -iU] is required\n", progname);	exit (2);    }    if (argc > 1) {	prname ();	fprintf (stderr, "can only do one file.\n");    } else if (argc == 1) {	filename = *curarg;	if ((input = fopen (filename, "r")) != NULL) {	    pfile();	    (void) fclose (input);	} else {	    prname ();	    fprintf (stderr, "can't open ");	    perror(*curarg);	}    } else {	filename = "[stdin]";	input = stdin;	pfile();    }    (void) fflush (stdout);    exit (exitstat);}/* types of input lines: */typedef int Linetype;#define LT_PLAIN       0   /* ordinary line */#define LT_TRUE        1   /* a true  #ifdef of a symbol known to us */#define LT_FALSE       2   /* a false #ifdef of a symbol known to us */#define LT_OTHER       3   /* an #ifdef of a symbol not known to us */#define LT_IF          4   /* an #ifdef of a symbol not known to us */#define LT_ELSE        5   /* #else */#define LT_ENDIF       6   /* #endif */#define LT_LEOF        7   /* end of file */extern Linetype checkline ();typedef int Reject_level;Reject_level reject BSS;    /* 0 or 1: pass thru; 1 or 2: ignore comments */#define REJ_NO          0#define REJ_IGNORE      1#define REJ_YES         2int linenum BSS;    /* current line number */int stqcline BSS;   /* start of current coment or quote */char *errs[] = {#define NO_ERR      0			"",#define END_ERR     1			"",#define ELSE_ERR    2			"Inappropriate else",#define ENDIF_ERR   3			"Inappropriate endif",#define IEOF_ERR    4			"Premature EOF in ifdef",#define CEOF_ERR    5			"Premature EOF in comment",#define Q1EOF_ERR   6			"Premature EOF in quoted character",#define Q2EOF_ERR   7			"Premature EOF in quoted string"};/* States for inif arg to doif */#define IN_NONE 0#define IN_IF   1#define IN_ELSE 2pfile (){    reject = REJ_NO;    (void) doif (-1, IN_NONE, reject, 0);    return;}intdoif (thissym, inif, prevreject, depth)register int thissym;   /* index of the symbol who was last ifdef'ed */int inif;               /* YES or NO we are inside an ifdef */Reject_level prevreject;/* previous value of reject */int depth;              /* depth of ifdef's */{    register Linetype lineval;    register Reject_level thisreject;    int doret;          /* tmp return value of doif */    int cursym;         /* index of the symbol returned by checkline */    int stline;         /* line number when called this time */    stline = linenum;    for (;;) {	switch (lineval = checkline (&cursym)) {	case LT_PLAIN:	    flushline (YES);	    break;	case LT_TRUE:	case LT_FALSE:	    thisreject = reject;	    if (lineval == LT_TRUE)		insym[cursym] = SYM_TRUE;	    else {		if (reject != REJ_YES)		    reject = ignore[cursym] ? REJ_IGNORE : REJ_YES;		insym[cursym] = SYM_FALSE;	    }	    if (ignore[cursym])		flushline (YES);	    else {		exitstat = 1;		flushline (NO);	    }	    if ((doret = doif (cursym, IN_IF, thisreject, depth + 1)) != NO_ERR)		return error (doret, stline, depth);	    break;	case LT_IF:	case LT_OTHER:	    flushline (YES);	    if ((doret = doif (-1, IN_IF, reject, depth + 1)) != NO_ERR)		return error (doret, stline, depth);	    break;	case LT_ELSE:	    if (inif != IN_IF)		return error (ELSE_ERR, linenum, depth);	    inif = IN_ELSE;	    if (thissym >= 0) {		if (insym[thissym] == SYM_TRUE) {		    reject = ignore[thissym] ? REJ_IGNORE : REJ_YES;		    insym[thissym] = SYM_FALSE;		} else { /* (insym[thissym] == SYM_FALSE) */		    reject = prevreject;		    insym[thissym] = SYM_TRUE;		}		if (!ignore[thissym]) {		    flushline (NO);		    break;		}	    }	    flushline (YES);	    break;	case LT_ENDIF:	    if (inif == IN_NONE)		return error (ENDIF_ERR, linenum, depth);	    if (thissym >= 0) {		insym[thissym] = SYM_INACTIVE;		reject = prevreject;		if (!ignore[thissym]) {		    flushline (NO);		    return NO_ERR;		}	    }	    flushline (YES);	    return NO_ERR;	case LT_LEOF: {	    int err;	    err =   incomment		  ? CEOF_ERR		  : inquote == QUOTE_SINGLE		  ? Q1EOF_ERR		  : inquote == QUOTE_DOUBLE		  ? Q2EOF_ERR		  : NO_ERR;	    if (inif != IN_NONE) {		if (err != NO_ERR)		    (void) error (err, stqcline, depth);		return error (IEOF_ERR, stline, depth);	    } else if (err != NO_ERR)		return error (err, stqcline, depth);	    else		return NO_ERR;	    }	}    }}#define endsym(c) (!isalpha (c) && !isdigit (c) && c != '_')#define MAXLINE 256char tline[MAXLINE] BSS;Linetypecheckline (cursym)int *cursym;    /* if LT_TRUE or LT_FALSE returned, set this to sym index */{    register char *cp;    register char *symp;    char *scp;    Linetype retval;#   define KWSIZE 8    char keyword[KWSIZE];    linenum++;    if (getlin (tline, sizeof tline, input, NO) == EOF)	return LT_LEOF;    retval = LT_PLAIN;    if (   *(cp = tline) != '#'	|| incomment	|| inquote == QUOTE_SINGLE	|| inquote == QUOTE_DOUBLE       )	goto eol;    cp = skipcomment (++cp);    symp = keyword;    while (!endsym (*cp)) {	*symp = *cp++;	if (++symp >= &keyword[KWSIZE])	    goto eol;    }    *symp = '\0';    if (strcmp (keyword, "ifdef") == 0) {	retval = YES;	goto ifdef;    } else if (strcmp (keyword, "ifndef") == 0) {	retval = NO; ifdef:	scp = cp = skipcomment (++cp);	if (incomment) {	    retval = LT_PLAIN;	    goto eol;	}	{	    int symind;	    if ((symind = findsym (scp)) >= 0)		retval = (retval ^ true[*cursym = symind])			 ? LT_FALSE : LT_TRUE;	    else		retval = LT_OTHER;	}    } else if (strcmp (keyword, "if") == 0)	retval = LT_IF;    else if (strcmp (keyword, "else") == 0)	retval = LT_ELSE;    else if (strcmp (keyword, "endif") == 0)	retval = LT_ENDIF; eol:    if (!text && reject != REJ_IGNORE)	for (; *cp; ) {	    if (incomment)		cp = skipcomment (cp);	    else if (inquote == QUOTE_SINGLE)		cp = skipquote (cp, QUOTE_SINGLE);	    else if (inquote == QUOTE_DOUBLE)		cp = skipquote (cp, QUOTE_DOUBLE);	    else if (*cp == '/' && cp[1] == '*')		cp = skipcomment (cp);	    else if (*cp == '\'')		cp = skipquote (cp, QUOTE_SINGLE);	    else if (*cp == '"')		cp = skipquote (cp, QUOTE_DOUBLE);	    else		cp++;	}    return retval;}/* *  Skip over comments and stop at the next charaacter *  position that is not whitespace. */char *skipcomment (cp)register char *cp;{    if (incomment)	goto inside;    for (;; cp++) {	while (*cp == ' ' || *cp == '\t')	    cp++;	if (text)	    return cp;	if (   cp[0] != '/'	    || cp[1] != '*'	   )	    return cp;	cp += 2;	if (!incomment) {	    incomment = YES;	    stqcline = linenum;	} inside:	for (;;) {	    for (; *cp != '*'; cp++)		if (*cp == '\0')		    return cp;	    if (*++cp == '/') {		incomment = NO;		break;	    }	}    }}/* *  Skip over a quoted string or character and stop at the next charaacter *  position that is not whitespace. */char *skipquote (cp, type)register char *cp;register int type;{    register char qchar;    qchar = type == QUOTE_SINGLE ? '\'' : '"';    if (inquote == type)	goto inside;    for (;; cp++) {	if (*cp != qchar)	    return cp;	cp++;	inquote = type;	stqcline = linenum; inside:	for (; ; cp++) {	    if (*cp == qchar)		break;	    if (   *cp == '\0'		|| *cp == '\\' && *++cp == '\0'	       )		return cp;	}	inquote = QUOTE_NONE;    }}/* *  findsym - look for the symbol in the symbol table. *            if found, return symbol table index, *            else return -1. */intfindsym (str)char *str;{    register char *cp;    register char *symp;    register int symind;    register char chr;    for (symind = 0; symind < nsyms; ++symind) {	if (insym[symind] == SYM_INACTIVE) {	    for ( symp = symname[symind], cp = str		; *symp && *cp == *symp		; cp++, symp++		)		continue;	    chr = *cp;	    if (*symp == '\0' && endsym (chr))		return symind;	}    }    return -1;}/* *   getlin - expands tabs if asked for *            and (if compiled in) treats form-feed as an end-of-line */intgetlin (line, maxline, inp, expandtabs)register char *line;int maxline;FILE *inp;int expandtabs;{    int tmp;    register int num;    register int chr;#ifdef  FFSPECIAL    static char havechar = NO;  /* have leftover char from last time */    static char svchar BSS;#endif/*FFSPECIAL */    num = 0;#ifdef  FFSPECIAL    if (havechar) {	havechar = NO;	chr = svchar;	goto ent;    }#endif/*FFSPECIAL */    while (num + 8 < maxline) {   /* leave room for tab */	chr = getc (inp);	if (isprint (chr)) {#ifdef  FFSPECIAL ent:#endif/*FFSPECIAL */	    *line++ = chr;	    num++;	} else	    switch (chr) {	    case EOF:		return EOF;	    case '\t':		if (expandtabs) {		    num += tmp = 8 - (num & 7);		    do			*line++ = ' ';		    while (--tmp);		    break;		}	    default:		*line++ = chr;		num++;		break;	    case '\n':		*line = '\n';		num++;		goto end;#ifdef  FFSPECIAL	    case '\f':		if (++num == 1)		    *line = '\f';		else {		    *line = '\n';		    havechar = YES;		    svchar = chr;		}		goto end;#endif/*FFSPECIAL */	    }    } end:    *++line = '\0';    return num;}flushline (keep)Bool keep;{    if ((keep && reject != REJ_YES) ^ complement) {	register char *line = tline;	register FILE *out = stdout;	register char chr;	while (chr = *line++)	    putc (chr, out);    } else if (lnblank)	putc ('\n', stdout);    return;}prname (){    fprintf (stderr, "%s: ", progname);    return;}interror (err, line, depth)int err;        /* type of error & index into error string array */int line;       /* line number */int depth;      /* how many ifdefs we are inside */{    if (err == END_ERR)	return err;    prname ();#ifndef TESTING    fprintf (stderr, "Error in %s line %d: %s.\n", filename, line, errs[err]);#else/* TESTING */    fprintf (stderr, "Error in %s line %d: %s. ", filename, line, errs[err]);    fprintf (stderr, "ifdef depth: %d\n", depth);#endif/*TESTING */    exitstat = 2;    return depth > 1 ? IEOF_ERR : END_ERR;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -