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