Rand's unifdef sources
Bill Cox
bill at kontron.UUCP
Wed Jul 30 02:25:00 AEST 1986
> #!/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 <stdio.h>
> X#include <ctype.h>
> X#include <c_env.h>
> 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 ***
More information about the Comp.sources.unix
mailing list