Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP Path: utzoo!mnetor!seismo!ut-sally!pyramid!voder!kontron!bill From: bill@kontron.UUCP (Bill Cox) Newsgroups: net.sources Subject: Re: Rand's unifdef sources Message-ID: <956@kontron.UUCP> Date: Tue, 29-Jul-86 12:25:00 EDT Article-I.D.: kontron.956 Posted: Tue Jul 29 12:25:00 1986 Date-Received: Wed, 30-Jul-86 00:42:20 EDT References: <387@yetti.UUCP> Organization: Kontron Electronics, Mt. View, CA Lines: 738 > #!/bin/sh > # This is a shell archive, meaning: > # 1. Remove everything above the #!/bin/sh line. > # 2. Save the resulting text in a file. > # 3. Execute the file with /bin/sh (not csh) to create the files: > # unifdef.1 > # unifdef.c > # This archive created: Wed Jul 23 15:32:52 1986 > export PATH; PATH=/bin:$PATH > echo shar: extracting "'unifdef.1'" '(2591 characters)' > if test -f 'unifdef.1' > then > echo shar: over-writing existing file "'unifdef.1'" > fi > sed 's/^X//' << \SHAR_EOF > 'unifdef.1' > X.TH UNIFDEF 1 Rand > X.SH NAME > Xunifdef \- remove ifdef'ed lines > X.SH SYNOPSIS > X.B unifdef > X[ > X.B \-t > X.B \-l > X.B \-c > X.BI \-d sym > X.BI \-u sym > X.BI \-id sym > X.BI \-iu sym > X] ... [ file ] > X.SH DESCRIPTION > X.I Unifdef > Xis useful for removing ifdef'ed lines from a file while otherwise leaving the > Xfile alone. > X.I Unifdef > Xis like a stripped-down C preprocessor: > Xit is smart enough to deal with the nested ifdefs, comments, > Xsingle and double > Xquotes of C syntax so that it can do its job, but it doesn't do any including > Xor interpretation of macros. > XNeither does it strip out comments, though it recognizes and ignores them. > X.PP > XYou specify which symbols you want defined > X(\fB\-d\fIsym\fR) > Xor undefined > X(\fB\-u\fIsym\fR) > Xand the lines inside those ifdefs will be copied to the output or removed as > Xappropriate. > XThe ifdef, ifndef, else, and endif lines associated with > X.I sym > Xwill also be removed. > XIfdefs involving symbols you don't specify > Xand ``#if'' control lines > Xare untouched and copied out > Xalong with their associated > Xifdef, else, and endif lines. > XIf an ifdef X occurs nested inside another ifdef X, then the > Xinside ifdef is treated as if it were an unrecognized symbol. > XIf the same symbol appears in more than one argument, only the first > Xoccurrence is significant. > X.PP > XThe > X.B \-l > Xoption causes > X.I unifdef > Xto replace removed lines with blank lines > Xinstead of deleting them. > X.PP > XIf you use ifdefs to delimit non-C lines, such as comments > Xor code which is under construction, > Xthen you must tell > X.I unifdef > Xwhich symbols are used for that purpose so that it won't try to parse > Xfor quotes and comments > Xin those ifdef'ed lines. > XYou specify that you want the lines inside certain ifdefs to be ignored > Xbut copied out with > X.BI \-id sym > Xand > X.BI \-iu sym > Xsimilar to > X.BI \-d sym > Xand > X.BI \-u sym > Xabove. > X.PP > XIf you want to use > X.I unifdef > Xfor plain text (not C code), use the > X.B \-t > Xoption. > XThis makes > X.I unifdef > Xrefrain from attempting to recognize comments and single and double quotes. > X.PP > X.I Unifdef > Xcopies its output to > X.I stdout > Xand will take its input from > X.I stdin > Xif no > X.I file > Xargument is given. > XIf the > X.B \-c > Xargument is specified, then the operation of > X.I unifdef > Xis complemented, > Xi.e. the lines that would have been removed or blanked > Xare retained and vice versa. > X.PP > X.I Unifdef > Xworks nicely with the > X.BI \-i sym > Xoption recently added to > X.I diff > Xat Rand. > X.SH "SEE ALSO" > Xdiff(1) > X.SH DIAGNOSTICS > XPremature EOF, inappropriate else or endif. > X.PP > XExit status is 0 if output is exact copy of input, 1 if not, 2 if trouble. > X.SH AUTHOR > XDave Yost, The Rand Corporation > X.SH BUGS > XShould try to deal with ``#if'' lines. > SHAR_EOF > if test 2591 -ne "`wc -c 'unifdef.1'`" > then > echo shar: error transmitting "'unifdef.1'" '(should have been 2591 characters)' > fi > echo shar: extracting "'unifdef.c'" '(12319 characters)' > if test -f 'unifdef.c' > then > echo shar: over-writing existing file "'unifdef.c'" > fi > sed 's/^X//' << \SHAR_EOF > 'unifdef.c' > X#ifdef COMMENT > X > X unifdef - remove ifdef'ed lines > X > X Wishlist: > X provide an option which will append the name of the > X appropriate symbol after #else's and #endif's > X provide an option which will check symbols after > X #else's and #endif's to see that they match their > X corresponding #ifdef or #ifndef > X > X#endif > X > X#include > X#include > X#include > X > X#define BSS > XFILE *input; > X#ifndef YES > X#define YES 1 > X#define NO 0 > X#endif > Xtypedef int Bool; > X > Xchar *progname BSS; > Xchar *filename BSS; > Xchar text BSS; /* -t option in effect: this is a text file */ > Xchar lnblank BSS; /* -l option in effect: blank deleted lines */ > Xchar complement BSS; /* -c option in effect: complement the operation */ > X > X#define MAXSYMS 100 > Xchar *sym[MAXSYMS] BSS; /* symbol name */ > Xchar true[MAXSYMS] BSS; /* -dsym */ > Xchar ignore[MAXSYMS] BSS; /* -idsym or -iusym */ > Xchar insym[MAXSYMS] BSS; /* state: false, inactive, true */ > X#define SYM_INACTIVE 0 /* symbol is currently inactive */ > X#define SYM_FALSE 1 /* symbol is currently false */ > X#define SYM_TRUE 2 /* symbol is currently true */ > X > Xchar nsyms BSS; > Xchar incomment BSS; /* inside C comment */ > X > X#define QUOTE_NONE 0 > X#define QUOTE_SINGLE 1 > X#define QUOTE_DOUBLE 2 > Xchar inquote BSS; /* inside single or double quotes */ > X > Xint exitstat BSS; > Xchar *skipcomment (); > Xchar *skipquote (); > X > Xmain (argc, argv) > Xint argc; > Xchar **argv; > X{ > X char **curarg; > X register char *cp; > X register char *cp1; > X char ignorethis; > X > X progname = argv[0][0] ? argv[0] : "unifdef"; > X > X for (curarg = &argv[1]; --argc > 0; curarg++) { > X if (*(cp1 = cp = *curarg) != '-') > X break; > X if (*++cp1 == 'i') { > X ignorethis = YES; > X cp1++; > X } > X else > X ignorethis = NO; > X if ( ( *cp1 == 'd' > X || *cp1 == 'u' > X ) > X && cp1[1] != '\0' > X ) { > X if (nsyms >= MAXSYMS) { > X prname (); > X fprintf (stderr, "too many symbols.\n"); > X exit (2); > X } > X insym[nsyms] = SYM_INACTIVE; > X ignore[nsyms] = ignorethis; > X true[nsyms] = *cp1 == 'd' ? YES : NO; > X sym[nsyms++] = &cp1[1]; > X } > X else if (ignorethis) > X goto unrec; > X else if (strcmp (&cp[1], "t") == 0) > X text = YES; > X else if (strcmp (&cp[1], "l") == 0) > X lnblank = YES; > X else if (strcmp (&cp[1], "c") == 0) > X complement = YES; > X else { > X unrec: > X prname (); > X fprintf (stderr, "unrecognized option: %s\n", cp); > X goto usage; > X } > X } > X if (nsyms == 0) { > X usage: > X fprintf (stderr, "\ > XUsage: %s [-l] [-t] [-c] [[-dsym] [-usym] [-idsym] [-iusym]]... [file]\n\ > X At least one arg from [-d -u -id -iu] is required\n", progname); > X exit (2); > X } > X > X if (argc > 1) { > X prname (); > X fprintf (stderr, "can only do one file.\n"); > X } > X else if (argc == 1) { > X filename = *curarg; > X if ((input = fopen (filename, "r")) != NULL) { > X pfile(); > X (void) fclose (input); > X } > X else { > X prname (); > X fprintf (stderr, "can't open %s\n", *curarg); > X } > X } > X else { > X filename = "[stdin]"; > X input = stdin; > X pfile(); > X } > X > X (void) fflush (stdout); > X exit (exitstat); > X} > X > X/* types of input lines: */ > Xtypedef int Linetype; > X#define LT_PLAIN 0 /* ordinary line */ > X#define LT_TRUE 1 /* a true #ifdef of a symbol known to us */ > X#define LT_FALSE 2 /* a false #ifdef of a symbol known to us */ > X#define LT_OTHER 3 /* an #ifdef of a symbol not known to us */ > X#define LT_IF 4 /* an #ifdef of a symbol not known to us */ > X#define LT_ELSE 5 /* #else */ > X#define LT_ENDIF 6 /* #endif */ > X#define LT_LEOF 7 /* end of file */ > Xextern Linetype checkline (); > X > Xtypedef int Reject_level; > XReject_level reject BSS; /* 0 or 1: pass thru; 1 or 2: ignore comments */ > X#define REJ_NO 0 > X#define REJ_IGNORE 1 > X#define REJ_YES 2 > X > Xint linenum BSS; /* current line number */ > Xint stqcline BSS; /* start of current coment or quote */ > Xchar *errs[] = { > X#define NO_ERR 0 > X "", > X#define END_ERR 1 > X "", > X#define ELSE_ERR 2 > X "Inappropriate else", > X#define ENDIF_ERR 3 > X "Inappropriate endif", > X#define IEOF_ERR 4 > X "Premature EOF in ifdef", > X#define CEOF_ERR 5 > X "Premature EOF in comment", > X#define Q1EOF_ERR 6 > X "Premature EOF in quoted character", > X#define Q2EOF_ERR 7 > X "Premature EOF in quoted string" > X}; > X > X/* States for inif arg to doif */ > X#define IN_NONE 0 > X#define IN_IF 1 > X#define IN_ELSE 2 > X > Xpfile () > X{ > X reject = REJ_NO; > X (void) doif (-1, IN_NONE, reject, 0); > X return; > X} > X > Xdoif (thissym, inif, prevreject, depth) > Xregister int thissym; /* index of the symbol who was last ifdef'ed */ > Xint inif; /* YES or NO we are inside an ifdef */ > XReject_level prevreject;/* previous value of reject */ > Xint depth; /* depth of ifdef's */ > X{ > X register Linetype lineval; > X register Reject_level thisreject; > X int doret; /* tmp return value of doif */ > X int cursym; /* index of the symbol returned by checkline */ > X int stline; /* line number when called this time */ > X > X stline = linenum; > X for (;;) { > X switch (lineval = checkline (&cursym)) { > X case LT_PLAIN: > X flushline (YES); > X break; > X > X case LT_TRUE: > X case LT_FALSE: > X thisreject = reject; > X if (lineval == LT_TRUE) > X insym[cursym] = SYM_TRUE; > X else { > X if (reject != REJ_YES) > X reject = ignore[cursym] ? REJ_IGNORE : REJ_YES; > X insym[cursym] = SYM_FALSE; > X } > X if (ignore[cursym]) > X flushline (YES); > X else { > X exitstat = 1; > X flushline (NO); > X } > X if ((doret = doif (cursym, IN_IF, thisreject, depth + 1)) != NO_ERR) > X return error (doret, stline, depth); > X break; > X > X case LT_IF: > X case LT_OTHER: > X flushline (YES); > X if ((doret = doif (-1, IN_IF, reject, depth + 1)) != NO_ERR) > X return error (doret, stline, depth); > X break; > X > X case LT_ELSE: > X if (inif != IN_IF) > X return error (ELSE_ERR, linenum, depth); > X inif = IN_ELSE; > X if (thissym >= 0) { > X if (insym[thissym] == SYM_TRUE) { > X reject = ignore[thissym] ? REJ_IGNORE : REJ_YES; > X insym[thissym] = SYM_FALSE; > X } > X else { /* (insym[thissym] == SYM_FALSE) */ > X reject = prevreject; > X insym[thissym] = SYM_TRUE; > X } > X if (!ignore[thissym]) { > X flushline (NO); > X break; > X } > X } > X flushline (YES); > X break; > X > X case LT_ENDIF: > X if (inif == IN_NONE) > X return error (ENDIF_ERR, linenum, depth); > X if (thissym >= 0) { > X insym[thissym] = SYM_INACTIVE; > X reject = prevreject; > X if (!ignore[thissym]) { > X flushline (NO); > X return NO_ERR; > X } > X } > X flushline (YES); > X return NO_ERR; > X > X case LT_LEOF: { > X int err; > X err = incomment > X ? CEOF_ERR > X : inquote == QUOTE_SINGLE > X ? Q1EOF_ERR > X : inquote == QUOTE_DOUBLE > X ? Q2EOF_ERR > X : NO_ERR; > X if (inif != IN_NONE) { > X if (err != NO_ERR) > X (void) error (err, stqcline, depth); > X return error (IEOF_ERR, stline, depth); > X } > X else if (err != NO_ERR) > X return error (err, stqcline, depth); > X else > X return NO_ERR; > X } > X } > X } > X} > X > X#define endsym(c) (!isalpha (c) && !isdigit (c) && c != '_') > X > X#define MAXLINE 256 > Xchar tline[MAXLINE] BSS; > X > XLinetype > Xcheckline (cursym) > Xint *cursym; > X{ > X register char *cp; > X register char *symp; > X register char chr; > X char *scp; > X Linetype retval; > X int symind; > X# define KWSIZE 8 > X char keyword[KWSIZE]; > X > X linenum++; > X if (getlin (tline, sizeof tline, input, NO) == EOF) > X return LT_LEOF; > X > X retval = LT_PLAIN; > X if ( *(cp = tline) != '#' > X || incomment > X || inquote == QUOTE_SINGLE > X || inquote == QUOTE_DOUBLE > X ) > X goto eol; > X > X cp = skipcomment (++cp); > X symp = keyword; > X while (!endsym (*cp)) { > X *symp = *cp++; > X if (++symp >= &keyword[KWSIZE]) > X goto eol; > X } > X *symp = '\0'; > X > X if (strcmp (keyword, "ifdef") == 0) { > X retval = YES; > X goto ifdef; > X } > X else if (strcmp (keyword, "ifndef") == 0) { > X retval = NO; > X ifdef: > X scp = cp = skipcomment (++cp); > X if (incomment) { > X retval = LT_PLAIN; > X goto eol; > X } > X for (symind = 0; ; ) { > X if (insym[symind] == SYM_INACTIVE) { > X for ( symp = sym[symind], cp = scp > X ; *symp && *cp == *symp > X ; cp++, symp++ > X ) > X continue; > X chr = *cp; > X if (*symp == '\0' && endsym (chr)) { > X *cursym = symind; > X retval = (retval ^ true[symind]) ? LT_FALSE : LT_TRUE; > X break; > X } > X } > X if (++symind >= nsyms) { > X retval = LT_OTHER; > X break; > X } > X } > X } > X else if (strcmp (keyword, "if") == 0) > X retval = LT_IF; > X else if (strcmp (keyword, "else") == 0) > X retval = LT_ELSE; > X else if (strcmp (keyword, "endif") == 0) > X retval = LT_ENDIF; > X > X eol: > X if (!text && reject == REJ_NO) > X for (; *cp; ) { > X if (incomment) > X cp = skipcomment (cp); > X else if (inquote == QUOTE_SINGLE) > X cp = skipquote (cp, QUOTE_SINGLE); > X else if (inquote == QUOTE_DOUBLE) > X cp = skipquote (cp, QUOTE_DOUBLE); > X else if (*cp == '/' && cp[1] == '*') > X cp = skipcomment (cp); > X else if (*cp == '\'') > X cp = skipquote (cp, QUOTE_SINGLE); > X else if (*cp == '"') > X cp = skipquote (cp, QUOTE_DOUBLE); > X else > X cp++; > X } > X return retval; > X} > X > X/* Skip over comments and stop at the next charaacter > X/* position that is not whitespace. > X/**/ > Xchar * > Xskipcomment (cp) > Xregister char *cp; > X{ > X if (incomment) > X goto inside; > X for (;; cp++) { > X while (*cp == ' ' || *cp == '\t') > X cp++; > X if (text) > X return cp; > X if ( cp[0] != '/' > X || cp[1] != '*' > X ) > X return cp; > X cp += 2; > X if (!incomment) { > X incomment = YES; > X stqcline = linenum; > X } > X inside: > X for (;;) { > X for (; *cp != '*'; cp++) > X if (*cp == '\0') > X return cp; > X if (*++cp == '/') > X break; > X } > X incomment = NO; > X } > X} > X > X/* Skip over a quoted string or character and stop at the next charaacter > X/* position that is not whitespace. > X/**/ > Xchar * > Xskipquote (cp, type) > Xregister char *cp; > Xregister int type; > X{ > X register char qchar; > X > X qchar = type == QUOTE_SINGLE ? '\'' : '"'; > X > X if (inquote == type) > X goto inside; > X for (;; cp++) { > X if (*cp != qchar) > X return cp; > X cp++; > X inquote = type; > X stqcline = linenum; > X inside: > X for (; ; cp++) { > X if (*cp == qchar) > X break; > X if ( *cp == '\0' > X || *cp == '\\' > X && *++cp == '\0' > X ) > X return cp; > X } > X inquote = QUOTE_NONE; > X } > X} > X > X/* > X/* special getlin - treats form-feed as an end-of-line > X/* and expands tabs if asked for > X/* > X/**/ > Xgetlin (line, maxline, inp, expandtabs) > Xregister char *line; > Xint maxline; > XFILE *inp; > Xint expandtabs; > X{ > X int tmp; > X register int num; > X register int chr; > X#ifdef FFSPECIAL > X static char havechar = NO; /* have leftover char from last time */ > X static char svchar BSS; > X#endif > X > X num = 0; > X#ifdef FFSPECIAL > X if (havechar) { > X havechar = NO; > X chr = svchar; > X goto ent; > X } > X#endif > X while (num + 8 < maxline) { /* leave room for tab */ > X chr = getc (inp); > X if (isprint (chr)) { > X#ifdef FFSPECIAL > X ent: > X#endif > X *line++ = chr; > X num++; > X } > X else > X switch (chr) { > X case EOF: > X return EOF; > X > X case '\t': > X if (expandtabs) { > X num += tmp = 8 - (num & 7); > X do > X *line++ = ' '; > X while (--tmp); > X break; > X } > X default: > X *line++ = chr; > X num++; > X break; > X > X case '\n': > X *line = '\n'; > X num++; > X goto end; > X > X#ifdef FFSPECIAL > X case '\f': > X if (++num == 1) > X *line = '\f'; > X else { > X *line = '\n'; > X havechar = YES; > X svchar = chr; > X } > X goto end; > X#endif > X } > X } > X end: > X *++line = '\0'; > X return num; > X} > X > Xflushline (keep) > XBool keep; > X{ > X if ((keep && reject != REJ_YES) ^ complement) > X putlin (tline, stdout); > X else if (lnblank) > X putlin ("\n", stdout); > X return; > X} > X > X/* > X/* putlin - for tools > X/* > X/**/ > Xputlin (line, fio) > Xregister char *line; > Xregister FILE *fio; > X{ > X register char chr; > X > X while (chr = *line++) > X putc (chr, fio); > X return; > X} > X > Xprname () > X{ > X fprintf (stderr, "%s: ", progname); > X return; > X} > X > Xint > Xerror (err, line, depth) > X{ > X if (err == END_ERR) > X return err; > X > X prname (); > X > X#ifndef TESTING > X fprintf (stderr, "Error in %s line %d: %s.\n", > X filename, line, errs[err]); > X#endif > X > X#ifdef TESTING > X fprintf (stderr, "Error in %s line %d: %s. ", > X filename, line, errs[err]); > X fprintf (stderr, "ifdef depth: %d\n", depth); > X#endif > X > X exitstat = 2; > X return depth > 1 ? IEOF_ERR : END_ERR; > X} > SHAR_EOF > if test 12319 -ne "`wc -c 'unifdef.c'`" > then > echo shar: error transmitting "'unifdef.c'" '(should have been 12319 characters)' > fi > # End of shell archive > exit 0 > -- > The best way to have a Usenet: [decvax|ihnp4]!utzoo!yetti!oz > good idea is to have a Bitnet: oz@[yusol|yuyetti].BITNET > lot of ideas. Phonet: [416] 736-5053 x 3976 *** REPLACE THIS LINE WITH YOUR MESSAGE ***