home *** CD-ROM | disk | FTP | other *** search
- From: genrad!masscomp!tektronix!tekig4!bradn
- Subject: scpp - a selective C preprocessor (Part 1 of 2)
- Newsgroups: mod.sources
- Approved: jpn@panda.UUCP
-
- Mod.sources: Volume 3, Issue 13
- Submitted by: decvax!tektronix!tekig4!bradn
-
-
- In response to the net.lang.c comments about the misuses of the preprocessor,
- I offer this program that interprets selected macros in a file without
- disturbing anything else. I wrote it after trying to read Bourne's
- "Algol-like" adb.
-
- Scpp is also the most thorough conditional-code remover I've seen -- very
- useful for making sense out of heavily "ifdef'ed" code like UUCP.
-
- Scpp should run at least under 4.2BSD, SYSIII and SYSV. Please let me know
- if you have any trouble getting it running.
-
- Brad Needham
- Tektronix, Inc.
- ...decvax!tektronix!tekig4!bradn
-
- -------------- cut along the dashed line -------
- #! /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:
- # scpp.1
- # Makefile
- # lex.l
- # ctrl.c
- # interp
- # io.c
- # This archive created: Thu Sep 19 12:35:36 1985
- export PATH; PATH=/bin:$PATH
- echo shar: extracting "'scpp.1'" '(2992 characters)'
- if test -f 'scpp.1'
- then
- echo shar: will not over-write existing file "'scpp.1'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'scpp.1'
- X.TH SCPP 1 "28 September 1983"
- X.SH NAME
- Xscpp \- selective C preprocessor
- X.SH SYNOPSIS
- X.B scpp
- X[
- X.BI \-M macro
- X] [
- X.BI \-D macro
- X] [
- X.BI \-D macro=def
- X] [
- X.B \-C
- X]
- X.ti +5
- X[
- X.BI \-I incdir
- X] [
- X.I file...
- X]
- X.SH DESCRIPTION
- X.B Scpp
- Xconcatenates the input
- X.I files
- X(or reads standard-in, if no
- X.I file
- Xis given),
- Xinterprets all references to given macros,
- Xleaving the rest of the
- X.IR file "(s)"
- Xunaltered,
- Xthen writes the result to standard-out.
- XIt is helpful in removing conditionally compiled code or misleading
- Xmacros from a file.
- X.PP
- XThe
- X.I file
- Xname "\fB-\fP" refers to standard-in.
- X.PP
- XThe following options are available.
- XEach option can appear as frequently as desired.
- X.RS
- X.TP
- X.SM \-M
- XInterpret all references to the given
- X.I macro.
- X.I Macro
- Xcan be either a single macro name or a whitespace-separated list of
- Xmacro names (e.g. -MMAXINT or -M"MAXINT MININT INTWID").
- XAll occurrences of the macro and all instances of the intrinsic macro
- X\&"defined()" referring to this macro are expanded.
- XAll preprocessor directives referring to this macro (except
- X.BR #if )
- Xperform their usual function and do not appear in the output.
- X.B #if
- Xdirectives are interpreted only if their value is not dependent on macros
- Xwhich are not to be interpreted.
- X.TP
- X.SM \-D
- XDefine the
- X.I macro
- Xto have the value
- X.I def,
- Xor "1" if no
- X.I def
- Xis given.
- XUnlike the C preprocessor,
- X.B scpp
- Xdoes not implicitly define certain macros that describe the environment in
- Xwhich the code will be running (e.g. "vax" or "unix").
- X.B \-D
- Ximplies
- X.B \-M.
- X.TP
- X.SM \-C
- XPreserve comments and whitespace in interpreted macro definitions.
- XNormally, comments and leading and trailing whitespace are stripped from
- Xinterpreted macro definitions.
- X.TP
- X.SM \-I
- XAdd
- X.I incdir
- Xto the list of directories to be searched for include files.
- X.B Scpp
- Xsearches directories in the same order as the C preprocessor:
- Xif the include filename is enclosed in double-quotes ("...")
- Xrather than angle-brackets (<...>),
- Xthe directory containing the current file being processed;
- Xthe directories given by -I, left-to-right;
- Xthe standard directory, /usr/include.
- X.RE
- X.SH AUTHOR
- XBrad Needham, Tektronix, Inc.
- X.SH "SEE ALSO"
- Xcc(1).
- X.SH BUGS
- XVery long identifiers (those over 100 characters long) will crash
- X.B scpp.
- X.PP
- XBecause
- X.B scpp
- Xinterprets only the given macros, the meaning of some code will change.
- XE.g. "scpp -MBOO" of
- X.br
- X #define BOO hello,there
- X.br
- X #define twopar(a,b) a b
- X.br
- X twopar(BOO,folks)
- X.br
- Xwill generate
- X.br
- X #define twopar(a,b) a b
- X.br
- X twopar(hello,there,folks)
- X.br
- Xcausing an argument mismatch when the output is compiled.
- X.PP
- XBecause uninterpreted "#if"s, "ifdef"s, and "ifndef"s, have no effect
- Xon the output, the following example, when processed via "scpp -MLEFT",
- Xwill generate an error message complaining about
- Xmultiple definitions of "LEFT".
- X.br
- X #ifdef ZULU
- X.br
- X #define LEFT 20
- X.br
- X #else
- X.br
- X #define LEFT 347
- X.br
- X #endif
- X.PP
- XThe C preprocessor macros "\fB__FILE__\fP" and "\fB__LINE__\fP" have no
- Xspecial meaning to
- X.B scpp.
- SHAR_EOF
- if test 2992 -ne "`wc -c < 'scpp.1'`"
- then
- echo shar: error transmitting "'scpp.1'" '(should have been 2992 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'Makefile'" '(1086 characters)'
- if test -f 'Makefile'
- then
- echo shar: will not over-write existing file "'Makefile'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'Makefile'
- X# Makefile for the selective C preprocessor, scpp.
- X#
- X# Copyright (c) 1985 by
- X# Tektronix, Incorporated Beaverton, Oregon 97077
- X# All rights reserved.
- X#
- X# Permission is hereby granted for personal, non-commercial
- X# reproduction and use of this program, provided that this
- X# notice and all copyright notices are included in any copy.
- X
- XDEFS=
- XCFLAGS= -O $(DEFS)
- XHDRS= scpp.h
- X
- XSOURCES= ctrl.c io.c lex.l parse.y scpp.c
- XOBJECTS= ctrl.o io.o lex.o parse.o scpp.o
- X
- Xall: scpp scpp.cat
- Xscpp: $(OBJECTS)
- X $(CC) $(CFLAGS) -o scpp $(OBJECTS) -ll
- Xscpp.cat: scpp.1
- X nroff -man scpp.1 >scpp.cat
- X
- Xscpp.o: scpp.c y.tab.h scpp.h
- Xctrl.o: ctrl.c y.tab.h scpp.h
- Xio.o: io.c scpp.h
- Xlex.o: lex.c y.tab.h scpp.h
- Xparse.o: parse.c scpp.h
- X
- Xlex.c: lex.l
- X lex lex.l
- X sed -e '/yylex/s//xxlex/g' <lex.yy.c >lex.c
- X rm lex.yy.c
- Xy.tab.h parse.c: parse.y
- X yacc -d parse.y
- X mv y.tab.c parse.c
- X
- Xclean:
- X -rm -f lex.yy.c lex.c y.tab.c y.tab.h y.output parse.c
- X -rm -f $(OBJECTS)
- X
- Xtags: $(SOURCES)
- X ctags $(SOURCES)
- Xmail:
- X shar -a scpp.1 Makefile lex.l ctrl.c interp io.c >scpp.shar1
- X shar -a parse.y scpp.c scpp.h >scpp.shar2
- SHAR_EOF
- if test 1086 -ne "`wc -c < 'Makefile'`"
- then
- echo shar: error transmitting "'Makefile'" '(should have been 1086 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'lex.l'" '(2334 characters)'
- if test -f 'lex.l'
- then
- echo shar: will not over-write existing file "'lex.l'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'lex.l'
- X%{
- X/*
- X * scpp - selective C preprocessor
- X * Lexical scanner
- X *
- X * Copyright (c) 1985 by
- X * Tektronix, Incorporated Beaverton, Oregon 97077
- X * All rights reserved.
- X *
- X * Permission is hereby granted for personal, non-commercial
- X * reproduction and use of this program, provided that this
- X * notice and all copyright notices are included in any copy.
- X */
- X
- X# include <stdio.h>
- X
- X# undef input
- X# undef unput
- X# define input() (*nxtin == ATTN ? nxtc() : *nxtin++)
- X# define unput(c) unc(c)
- X
- X# include "scpp.h"
- X# include "y.tab.h"
- X
- Xint lasttok = NL; /* used to detect ^# when lex can't */
- X# define yield(t) lasttok = t; questr(yytext, yyleng); return(t)
- X
- X/*
- X * All input to higher levels of scpp is provided exclusively by this
- X * lexical analyzer, xxlex().
- X * This routine is called xxlex() rather than yylex() because the "#if"
- X * expression parser uses a slightly different lexical analyzer (which
- X * calls xxlex()).
- X */
- X
- X%}
- X%%
- X
- X"<" {yield(LT);}
- X"<=" {yield(LE);}
- X">" {yield(GT);}
- X">=" {yield(GE);}
- X"," {yield(CM);}
- X"/" {yield(DIV);}
- X"%" {yield(MOD);}
- X"+" {yield(PLUS);}
- X"-" {yield(MINUS);}
- X"<<" {yield(LS);}
- X">>" {yield(RS);}
- X"*" {yield(MUL);}
- X"==" {yield(EQ);}
- X"!=" {yield(NE);}
- X"&" {yield(AND);}
- X"|" {yield(OR);}
- X"^" {yield(ER);}
- X"&&" {yield(ANDAND);}
- X"||" {yield(OROR);}
- X"?" {yield(QUEST);}
- X":" {yield(COLON);}
- X"!" {yield(NOT);}
- X"~" {yield(COMPL);}
- X"(" {yield(LP);}
- X")" {yield(RP);}
- X"," {yield(CM);}
- X[ \t]+ {yield(WHITE); /* whitespace */}
- X\\\n {/* escaped newline */
- X if (curfile->af_raw) {
- X curfile->af_line++;
- X }
- X yield(QNL);
- X }
- X\n {/* unescaped newline */
- X if (curfile->af_raw) {
- X curfile->af_line++;
- X }
- X yield(NL);
- X }
- X0x[0-9a-fA-F]+[Ll]? {yield(INT); /* hex constant */}
- X[0-9]+[Ll]? {yield(INT); /* decimal or octal constant */}
- X[0-9]+[Ee]([+-][0-9])?[0-9]* |
- X\.[0-9]+([Ee]([+-][0-9])?[0-9]*)? |
- X[0-9]+\.[0-9]*([Ee]([+-][0-9])?[0-9]*)? {yield(FLOAT); /* floating constant */}
- X[a-zA-Z_][a-zA-Z0-9_]* {yield(IDENT); /* identifier */}
- X\' {yield(QUOTE);}
- X\" {yield(DQUOTE);}
- X\\ {yield(BACKS);}
- X"/*" {yield(OPENC); /* start (open) comment */}
- X"*/" {yield(CLOSEC);/* finish (close) comment */}
- X# {/*
- X * a control line if preceeded immediately by a newline,
- X * even if that newline was the result of macro interpretation.
- X */
- X if (lasttok == NL) {
- X yield(POUNDLINE);
- X }
- X yield(OTHER);
- X }
- X. {yield(OTHER);}
- X
- X%%
- SHAR_EOF
- if test 2334 -ne "`wc -c < 'lex.l'`"
- then
- echo shar: error transmitting "'lex.l'" '(should have been 2334 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'ctrl.c'" '(19059 characters)'
- if test -f 'ctrl.c'
- then
- echo shar: will not over-write existing file "'ctrl.c'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'ctrl.c'
- X/*
- X * ctrl - interpretation of preprocessor control lines (e.g. #define...)
- X * for the selective C preprocessor, scpp.
- X *
- X * Copyright (c) 1985 by
- X * Tektronix, Incorporated Beaverton, Oregon 97077
- X * All rights reserved.
- X *
- X * Permission is hereby granted for personal, non-commercial
- X * reproduction and use of this program, provided that this
- X * notice and all copyright notices are included in any copy.
- X */
- X
- X# include <stdio.h>
- X# include "scpp.h"
- X# include "y.tab.h"
- X
- X/*
- X * valbuf[] the buffer in which to build the value of a macro which has
- X * parameters.
- X */
- X
- X# define VALLEN 1000 /* max # of chars in a macro value string */
- Xchar valbuf[VALLEN];
- Xchar *valend; /*
- X * always points to the null-terminator
- X * of the value while the value is being built
- X */
- X
- X/*
- X * form[] the array of formal parameters for a macro.
- X * Each formal argument of a macro acts as a "local variable" during the
- X * scan for the value of the macro. The form[] array contains
- X * pointers to each argument's slot in the symbol table (used to recognize
- X * the formal argument in the value) and the previous value of that slot
- X * (so that the symbol table can be restored to normal after the value
- X * of the macro has been scanned.
- X */
- X
- Xstruct aformal {
- X struct amacro *fm_sym; /* symbol table slot for this formal */
- X struct amacro fm_copy; /* copy of the old contents of that slot */
- X};
- X# define FORMSIZ 40 /* max number of parameters to a macro */
- Xstruct aformal form[FORMSIZ];
- Xstruct aformal *formtop; /* points to the next empty slot in form[] */
- X
- X/*
- X * do_xxx() - functions for processing preprocessor control lines.
- X */
- X
- Xint do_line();
- Xint do_include();
- Xint do_define();
- Xint do_undef();
- Xint do_ifdef();
- Xint do_ifndef();
- Xint do_if();
- Xint do_else();
- Xint do_endif();
- X
- X/*
- X * key - the array of preprocessor keywords.
- X */
- X
- Xstruct akeyword key[] = {
- X {"line", do_line, 0},
- X {"include", do_include, 0},
- X {"define", do_define, 0},
- X {"undef", do_undef, 0},
- X {"ifdef", do_ifdef, 0},
- X {"ifndef", do_ifndef, 0},
- X {"if", do_if, 0},
- X {"else", do_else, 0},
- X {"endif", do_endif, 0},
- X {0,0,0} /* a zero ak_name marks the end of the list */
- X};
- X
- X/*
- X * ikeywords() - initialize the preprocessor keywords.
- X * For each keyword, set its ak_sym field and act as if it has been -M'ed.
- X */
- X
- Xikeywords()
- X{
- X struct akeyword *kp;
- X
- X
- X for (kp = &key[0]; kp->ak_name; ++kp) {
- X kp->ak_sym = findmac(kp->ak_name,
- X kp->ak_name + strlen(kp->ak_name));
- X if (kp->ak_sym->am_name) {
- X bomb("INTERNAL: identical keywords in key[]");
- X }
- X
- X kp->ak_sym->am_name = kp->ak_name;
- X kp->ak_sym->am_npar = -1;
- X /* leave am_val as 0 */
- X }
- X}
- X
- X/*
- X * findkey() - find the keyword corresponding to the given symbol table entry,
- X * returning a pointer to that keyword in key[],
- X * or zero if no match.
- X */
- X
- Xstruct akeyword *
- Xfindkey(mac)
- Xstruct amacro *mac;
- X{
- X struct akeyword *kp;
- X
- X for (kp = &key[0]; kp->ak_name && kp->ak_sym != mac; ++kp)
- X ;
- X if (!kp->ak_name) {
- X return((struct akeyword *) 0);
- X }
- X return(kp);
- X}
- X
- X/*
- X * doctrl() - process a control line (a line beginning with '#').
- X */
- X
- Xint /* returned token (NL or 0) */
- Xdoctrl(f) /* process control lines */
- Xchar *f; /* first char of this line (the '#' token) in pend[] */
- X{
- X int tok; /* the current token */
- X struct amacro *cmd; /* the preprocessor command (symbol table) */
- X struct akeyword *kp; /* the preprocessor command (keyword table) */
- X
- X
- X /*
- X * skip initial whitespace and comments (if any);
- X * ignore empty command lines;
- X * print warnings for garbled command lines;
- X * switch on the command name.
- X */
- X
- X if ((tok = nonwhite(gintok)) == 0 || tok == NL) {
- X return(tok);
- X }
- X
- X if (tok != IDENT) {
- X warnf("undefined control");
- X tok = endline();
- X return(tok);
- X }
- X
- X cmd = findmac(curtext, nxtout);
- X if (!cmd->am_name || !(kp = findkey(cmd))) {
- X /* name is not a preprocessor command */
- X
- X warnf("undefined control");
- X tok = endline();
- X return(tok);
- X }
- X
- X /*
- X * invoke the appropriate handler
- X */
- X
- X tok = (*kp->ak_proc)(f);
- X return(tok);
- X}
- X
- X/*
- X * do_line - parse a #line command.
- X * #line syntax:
- X * #[<whitespace>]line[<whitespace>][<int>[<whitespace>]<string>
- X * where: <int> is the new integer line number for this line,
- X * <string> is the new double-quote enclosed filename.
- X */
- X
- Xint
- Xdo_line(f)
- Xchar *f;
- X{
- X int tok;
- X char *name; /* the new filename */
- X char *src;
- X char *dst;
- X
- X
- X if ((tok = nonwhite(gintok)) == 0 || tok == NL) {
- X return(tok);
- X }
- X
- X if (tok == INT) {
- X if (curfile >= &filestk[0]) {
- X curfile->af_line = inttok(curtext, nxtout);
- X }
- X
- X if ((tok = nonwhite(gintok)) == 0 || tok == NL) {
- X return(tok);
- X }
- X }
- X if (tok != STRING) {
- X tok = endline();
- X return(tok);
- X }
- X
- X name = savtok(curtext, nxtout);
- X for (dst = name, src = name + 1; (*dst = *src) != '\0';
- X ++dst, ++src)
- X ;
- X if (--dst <= name || *dst != '"') {
- X free(name);
- X tok = endline();
- X return(tok);
- X }
- X *dst = '\0';
- X
- X if (curfile >= &filestk[0]) {
- X free(curfile->af_name);
- X curfile->af_name = name;
- X }
- X
- X tok = endline();
- X return(tok);
- X}
- X
- Xint
- Xdo_include(f)
- Xchar *f; /* (unused because #include lines are never deleted) */
- X{
- X char *ifile; /* the (dynamically alloc'ed) filename */
- X int looktype; /* type of directory search to perform */
- X int tok; /* the current token's type */
- X char *src, *dst;
- X
- X
- X /*
- X * pickup the filename, scan the rest of the command line,
- X * then include the file.
- X */
- X
- X ifile = (char *) 0;
- X if ((tok = nonwhite(gintok)) == 0) {
- X goto badinc;
- X }
- X if (tok == STRING) {
- X /*
- X * the filename is enclosed in double-quotes.
- X * Set the search type to include the current file's directory;
- X * Save the filename, then remove the string delimiters from it.
- X */
- X
- X looktype = PF_DOT;
- X
- X ifile = savtok(curtext, nxtout);
- X
- X for (dst = ifile, src = ifile + 1; (*dst = *src) != '\0';
- X ++dst, ++src)
- X ;
- X if (--dst <= ifile || *dst != '"') {
- X goto badinc;
- X }
- X *dst = '\0';
- X } else if (tok == LT) {
- X /*
- X * The filename is enclosed in angle-brackets.
- X * Set the directory search to exclude the current file's
- X * directory; collect and save the filename.
- X */
- X
- X looktype = PF_NODOT;
- X
- X src = nxtout;
- X while ((tok = gtok()) != GT && tok != NL && tok != 0)
- X ;
- X if (tok != GT) {
- X goto badinc;
- X }
- X ifile = savtok(src, curtext);
- X } else {
- Xbadinc:
- X bombf("bad include syntax");
- X if (ifile) {
- X free(ifile);
- X }
- X tok = endline();
- X return(tok);
- X }
- X
- X tok = endline();
- X pushfile(ifile, looktype, PF_HIDE);
- X free(ifile);
- X return(tok);
- X}
- X
- Xint
- Xdo_define(f)
- Xchar *f;
- X{
- X int tok;
- X struct amacro *mac; /* the macro being defined */
- X struct amacro *arg; /*
- X * points to the slot for the current argument
- X * from the definition of a macro with
- X * parameters.
- X */
- X struct amacro maccopy; /*
- X * a copy of some of the info from the slot
- X * for the macro being defined. Copying the
- X * slot allows perverse macro definitions
- X * such as:
- X * # define boo(boo) boo()
- X */
- X struct aformal *formp; /* a temp pointer */
- X int defok = TRUE; /*
- X * 'ok to define the macro.' Used to prevent
- X * definition of a macro with parameters if
- X * there was a syntax error in the definition.
- X */
- X
- X
- X /*
- X * scan for the macro name with identifier expansion turned off.
- X * Find the slot corresponding to the macro name.
- X */
- X
- X if ((tok = nonwhite(gtok)) == 0) {
- X return(0);
- X }
- X if (tok != IDENT) {
- X warnf("illegal macro name");
- X tok = endline();
- X return(tok);
- X }
- X mac = findmac(curtext, nxtout);
- X
- X if ((tok = gtok()) != LP) {
- X /*
- X * a simple macro. If it hasn't been -M'ed, ignore it.
- X * Otherwise, save the replacement text (disposing of
- X * any quoted newlines, comments, and appropriate
- X * whitespace), define the macro, and dispose of this line.
- X */
- X
- X char *valstrt; /* points to the macro value within pend[] */
- X char *valstr; /* the dynamically alloc'ed value string */
- X
- X if (!mac->am_name) {
- X tok = endline();
- X return(tok);
- X }
- X
- X valstrt = curtext;
- X
- X /*
- X * if the delimiter is whitespace, skip the first character
- X * of the whitespace (and any preceeding ATTN bytes).
- X */
- X
- X if (tok == WHITE) {
- X while (valstrt < nxtout && *valstrt == ATTN) {
- X valstrt += 2;
- X }
- X if (valstrt < nxtout) {
- X valstrt++;
- X }
- X }
- X while (tok != NL && tok != 0) {
- X if (tok == QNL || (!savcom && tok == COMMENT)) {
- X (void) dispose(curtext);
- X }
- X tok = gtok();
- X }
- X if (tok == 0) {
- X warnf("unterminated preprocessor command");
- X } else {
- X valstr = savtok(valstrt, curtext);
- X if (!savcom) {
- X stripwhite(valstr);
- X }
- X defmac(mac->am_name,
- X mac->am_name + strlen(mac->am_name),
- X -1 /* npar */, valstr);
- X free(valstr);
- X }
- X (void) dispose(f);
- X return(tok);
- X }
- X
- X /* a macro with parameters. Copy relevant parts of it. */
- X
- X maccopy.am_name = mac->am_name;
- X
- X /*
- X * Collect the comma-separated formals of the macro.
- X * Temporarily define each formal of the macro, saving the old
- X * contents of that formal's slot in the symbol table,
- X * marking that symbol as -M'ed, but undefined (so that
- X * scanning an uninterpreted macro definition works in the
- X * following case:
- X * scpp -MMOO
- X * #define MOO lose
- X * #define goo(MOO) is a MOO.
- X * should generate
- X * #define goo(MOO) is a MOO.
- X * rather than
- X * #define goo(MOO) is a lose.
- X */
- X
- X formtop = &form[0];
- X while (formtop < &form[FORMSIZ]) {
- X if ((tok = nonwhite(gtok)) != IDENT) {
- X break;
- X }
- X
- X /* process the formal argument */
- X
- X formtop->fm_sym = findmac(curtext, nxtout);
- X for (formp = &form[0]; formp < formtop &&
- X formp->fm_sym != formtop->fm_sym; ++formp)
- X ;
- X if (formp < formtop) {
- X warnf("duplicate formal names in macro definition");
- X }
- X
- X formtop->fm_copy.am_name = formtop->fm_sym->am_name;
- X formtop->fm_copy.am_npar = formtop->fm_sym->am_npar;
- X formtop->fm_copy.am_val = formtop->fm_sym->am_val;
- X
- X formtop->fm_sym->am_name = savtok(curtext, nxtout);
- X formtop->fm_sym->am_npar = -1;
- X formtop->fm_sym->am_val = (char *) 0;
- X
- X ++formtop;
- X
- X if ((tok = nonwhite(gtok)) != CM) {
- X break;
- X }
- X }
- X if (tok != RP) {
- X if (formtop >= &form[FORMSIZ]) {
- X warnf("too many formal arguments");
- X } else {
- X warnf("syntax error in formal arguments");
- X }
- X tok = endline();
- X defok = FALSE;
- X goto rollback;
- X }
- X
- X if (!maccopy.am_name) {
- X
- X /*
- X * This macro is not -M'ed, so don't interpret this #define.
- X * scan to the end of the line.
- X */
- X
- X tok = endline();
- X defok = FALSE;
- X } else {
- X
- X /*
- X * This macro is -M'ed. Record the number of parameters,
- X * then save the value of this macro,
- X * marking occurrences of the formal arguments.
- X */
- X
- X maccopy.am_npar = formtop - &form[0];
- X
- X valend = &valbuf[0];
- X *valend = '\0';
- X
- X while ((tok = gtok()) != 0 && tok != NL) {
- X if (tok == QNL || (!savcom && tok == COMMENT)) {
- X /* ignore the token */
- X } else {
- X /*
- X * if this token is a formal parameter name,
- X * add its parameter number & an ATTN byte
- X * to the macro value. Otherwise add the
- X * token's value (less ATTN bytes) to the value.
- X */
- X
- X formp = formtop;
- X if (tok == IDENT) {
- X arg = findmac(curtext, nxtout);
- X for (formp = &form[0]; formp < formtop &&
- X formp->fm_sym != arg; ++formp)
- X ;
- X }
- X
- X if (formp < formtop) {
- X if (valend + 2 >= &valbuf[VALLEN]) {
- X bombf("macro value too long");
- X }
- X *valend++ = (char) ((formp - &form[0]) + 1);
- X *valend++ = ATTN;
- X *valend = '\0';
- X } else {
- X if (valend + (nxtout - curtext) >=
- X &valbuf[VALLEN]) {
- X bombf("macro value too long");
- X }
- X while (curtext < nxtout) {
- X if (*curtext == ATTN) {
- X curtext += 2;
- X } else {
- X *valend++ = *curtext++;
- X }
- X }
- X *valend = '\0';
- X }
- X }
- X }
- X (void) dispose(f);
- X }
- X
- Xrollback:
- X
- X /*
- X * restore the formal parameter's original values
- X * (in reverse order to take care of duplicate formal parameters).
- X */
- X
- X while (--formtop >= &form[0]) {
- X free(formtop->fm_sym->am_name);
- X formtop->fm_sym->am_name = formtop->fm_copy.am_name;
- X formtop->fm_sym->am_npar = formtop->fm_copy.am_npar;
- X formtop->fm_sym->am_val = formtop->fm_copy.am_val;
- X }
- X
- X /*
- X * (finally) define the macro (if there was no problem),
- X * stripping whitespace where appropriate.
- X */
- X
- X if (defok) {
- X if (!savcom) {
- X stripwhite(&valbuf[0]);
- X }
- X defmac(maccopy.am_name,
- X maccopy.am_name + strlen(maccopy.am_name),
- X maccopy.am_npar, &valbuf[0]);
- X }
- X return(tok);
- X}
- X
- Xint
- Xdo_undef(f)
- Xchar *f;
- X{
- X int tok; /* the current token's type */
- X struct amacro *mac; /* the macro to be undefined */
- X char *cp;
- X
- X
- X
- X /*
- X * find the macro to be undefined (it is legal to undef an undefined
- X * macro, a non "-M"ed macro, or a preprocessor keyword);
- X * Read the rest of the "#undef" line;
- X * If this macro is one of the magic preprocessor macros
- X * (e.g. "defined()"), it cannot be undef'ed.
- X * Otherwise, find the beginning of the value and free it,
- X * then zero the value, undefining the macro.
- X * Destroy the original text of the #undef.
- X */
- X
- X if ((tok = nonwhite(gtok)) != IDENT) {
- X warnf("illegal macro name");
- X tok = endline();
- X return(tok);
- X }
- X mac = findmac(curtext, nxtout);
- X if (!mac->am_name) {
- X tok = endline();
- X return(tok);
- X }
- X if (mac->am_val) {
- X if (mac->am_val == &magicval) {
- X warnf("cannot undef implicit macro");
- X tok = endline();
- X return(tok);
- X }
- X cp = mac->am_val;
- X while (*--cp != '\0')
- X ;
- X free(cp);
- X mac->am_val = (char *) 0;
- X }
- X tok = endline();
- X (void) dispose(f);
- X return(tok);
- X}
- X
- Xint
- Xdo_ifdef(f)
- Xchar *f;
- X{
- X return(ifdorn(f,TRUE));
- X}
- X
- Xint
- Xdo_ifndef(f)
- Xchar *f;
- X{
- X return(ifdorn(f, FALSE));
- X}
- X
- X/*
- X * ifdorn() - "if defined or not defined" -- this is the common code for
- X * ifdef and ifndef processing.
- X */
- X
- Xint
- Xifdorn(f, defed)
- Xchar *f; /* points to the beginning of the command in pend[] */
- Xint defed; /* "the if is true if the macro is defined" */
- X{
- X int tok; /* the current token's type */
- X struct amacro *mac; /* the macro in question */
- X
- X
- X if (++curif >= &ifstk[IFSIZ]) {
- X bombf("too many nested if's");
- X }
- X *curif = IF_INIF;
- X
- X tok = nonwhite(gtok);
- X if (tok != IDENT) {
- X warnf("illegal macro name");
- X tok = endline();
- X return(tok);
- X }
- X mac = findmac(curtext, nxtout);
- X tok = endline();
- X
- X if (!mac->am_name) {
- X return(tok);
- X }
- X
- X if ((mac->am_val && defed) || (!mac->am_val && !defed)) {
- X *curif |= IF_TRUE;
- X } else {
- X *curif |= IF_FALSE;
- X ift_f();
- X }
- X
- X (void) dispose(f);
- X return(tok);
- X}
- X
- Xint
- Xdo_if(f)
- Xchar *f;
- X{
- X int tok;
- X int oldnint; /* interp' count prior to parsing the exp */
- X int wasraw; /* the state of interpretation prior to parse */
- X
- X
- X if (++curif >= &ifstk[IFSIZ]) {
- X bombf("too many nested if's");
- X }
- X *curif = IF_INIF;
- X
- X wasraw = curfile->af_raw;
- X oldnint = ninterp;
- X
- X expparse = TRUE;
- X if (yyparse() != 0) {
- X /* syntax error - don't interpret this 'if' */
- X
- X *curif &= ~(IF_TRUE | IF_FALSE);
- X tok = endline();
- X expparse = FALSE;
- X return(tok);
- X }
- X tok = endline();
- X expparse = FALSE;
- X
- X if (!(*curif & (IF_TRUE | IF_FALSE)) ||
- X (wasraw && oldnint == ninterp)) {
- X /*
- X * either the truth is not known or
- X * no macro interpretation was performed;
- X * Don't interpret the #if.
- X */
- X
- X *curif &= ~(IF_TRUE | IF_FALSE);
- X return(tok);
- X }
- X if (*curif & IF_FALSE) {
- X ift_f();
- X }
- X
- X (void) dispose(f);
- X return(tok);
- X}
- X
- Xint
- Xdo_else(f)
- Xchar *f;
- X{
- X int tok;
- X
- X
- X if (curif < &ifstk[0] || !(*curif & IF_INIF)) {
- X warnf("if-less else");
- X tok = endline();
- X return(tok);
- X }
- X tok = endline();
- X
- X *curif &= ~IF_INIF;
- X
- X if (*curif & IF_TRUE) {
- X *curif &= ~IF_TRUE;
- X *curif |= IF_FALSE;
- X ift_f();
- X (void) dispose(f);
- X return(tok);
- X }
- X if (*curif & IF_FALSE) {
- X *curif &= ~IF_FALSE;
- X *curif |= IF_TRUE;
- X iff_t();
- X (void) dispose(f);
- X return(tok);
- X }
- X /* this is the 'else' of an uninterpreted if */
- X return(tok);
- X}
- X
- Xint
- Xdo_endif(f)
- Xchar *f;
- X{
- X int tok;
- X
- X
- X if (curif < &ifstk[0]) {
- X warnf("if-less endif");
- X tok = endline();
- X return(tok);
- X }
- X
- X tok = endline();
- X
- X if (!(*curif & (IF_TRUE | IF_FALSE))) {
- X /* this is the 'endif' of an uninterpreted if */
- X --curif;
- X return(tok);
- X }
- X if (*curif & IF_FALSE) {
- X iff_t();
- X }
- X
- X --curif;
- X (void) dispose(f);
- X return(tok);
- X}
- X
- X/*
- X * ift_f(), iff_t() - #if statement transitions which may affect output.
- X * Ift_f() is called whenever an #if statement makes a transition from
- X * from true (or non-existent) to false;
- X * Iff_t() is called whenever one goes from false to true (or non-existent).
- X */
- X
- Xift_f()
- X{
- X if (falsecnt++ == 0 && hidecnt == 0) {
- X quec(ATTN);
- X quec(AT_OUTOFF);
- X }
- X}
- X
- Xiff_t()
- X{
- X if (--falsecnt == 0 && hidecnt == 0) {
- X quec(ATTN);
- X quec(AT_OUTON);
- X }
- X}
- X
- X/*
- X * stripwhite() - given a pointer to a (possibly dynamically allocated)
- X * string which is to become the value of a macro, strip the leading
- X * and trailing whitespace from the value.
- X */
- X
- Xstripwhite(s)
- Xchar *s;
- X{
- X char *cp;
- X char *nb; /*
- X * points to the char beyond the last non-blank
- X * character in the string.
- X */
- X
- X /*
- X * skip the initial whitespace, but don't count as whitespace a
- X * parameter number which preceeds an ATTN byte.
- X */
- X
- X for (cp = s; *cp == ' ' || *cp == '\t'; ++cp)
- X ;
- X if (*cp == ATTN) {
- X if (cp == s) {
- X bombf("INTERNAL: ATTN at beginning of string");
- X } else {
- X --cp;
- X }
- X }
- X
- X /*
- X * slide the string into its new position, noting the position of
- X * the char beyond the final non-white character so that the final
- X * whitespace can be eliminated.
- X */
- X
- X for (nb = cp; (*s++ = *cp) != '\0'; ++cp) {
- X if (*cp != ' ' && *cp != '\t') {
- X nb = s;
- X }
- X }
- X *nb = '\0';
- X}
- X
- X/*
- X * nonwhite() - read until the next non-white (and non-comment) token,
- X * using the scanner provided.
- X * This routine is used only to skip whitespace within preprocessor command
- X * lines.
- X */
- X
- Xint /* the non-white, non-comment token */
- Xnonwhite(scan)
- Xint (*scan)(); /* token scanner - either gtok() or gintok() */
- X{
- X int tok;
- X
- X while ((tok = (*scan)()) == WHITE || tok == COMMENT)
- X ;
- X if (tok == 0) {
- X warnf("unterminated preprocessor command");
- X }
- X return(tok);
- X}
- X
- X/*
- X * endline() - if not already at the end of the line, read tokens to get there.
- X * return the final token (either NL or 0).
- X * Used only to read the ends of preprocessor command lines.
- X * For the benefit of uninterpreted command lines, macros are interpreted.
- X *
- X * Endline should be called as late as possible in processing a line
- X * so that error messages will be correlated to the offending line rather
- X * than the following line.
- X */
- X
- Xint
- Xendline()
- X{
- X int tok; /* the current token */
- X char *cp; /* the current character in a backward search */
- X
- X
- X /*
- X * if the last character read (less ATTN byte pairs)
- X * was an unescaped newline, return;
- X * Otherwise, skip tokens until the end of the line or
- X * the end of the file.
- X */
- X
- X for (cp = nxtout - 1; cp >= &pend[1]; cp -= 2) {
- X if (*(cp - 1) != ATTN) {
- X break;
- X }
- X }
- X if (cp >= &pend[0] && *cp == '\n' &&
- X (cp == &pend[0] || *(cp - 1) != '\\')) {
- X /* an unescaped newline has already been read */
- X
- X return(NL);
- X }
- X
- X while ((tok = gintok()) != NL) {
- X if (tok == 0) {
- X warnf("unterminated preprocessor command");
- X return(tok);
- X }
- X }
- X return(tok);
- X}
- SHAR_EOF
- if test 19059 -ne "`wc -c < 'ctrl.c'`"
- then
- echo shar: error transmitting "'ctrl.c'" '(should have been 19059 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'interp'" '(1986 characters)'
- if test -f 'interp'
- then
- echo shar: will not over-write existing file "'interp'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'interp'
- XInterpretation rules:
- XText is, by default, interpreted. The following chart shows what sections
- Xof preprocessor directives are not interpreted (i.e. no macro interpretation,
- Xno preprocessor line interpretation). Note, however that the lexical analyzer
- Xis still used -- this prevents the recognition of floating point numbers as
- Xan instance of a formal parameter named, for example, "e4".
- X
- X(\n is an unescaped newline -- escaped newlines are recognized)
- X
- X# line n ..............\n
- X
- X# line n filename .....\n
- X (the filename is treated as garbage)
- X# line n "filename"....\n
- X (the filename is not interp'ed 'cause it's tween "")
- X (#line lines are no-ops)
- X# include "file".......\n
- X (again, "file" is in quotes & is not interpreted)
- X# include <file>.......\n
- X -----
- X# define macro replacement-text\n
- X ------------------------- (if 'macro' is one to interpret)
- X ------ (if 'macro' is not one to interpret --
- X also, the line is a no-op in this case)
- X# define macro( f1 , f2 , f3 ...) replacement-text with formals\n
- X ---------------------------------------------------------
- X ------------------------- (if 'macro' is not one to be interpreted)
- X (the above case is strange in that the formal parameters in the replacement
- X text must be protected against interpretation)
- X [remember to allow comments in the formals]
- X# undef macro .........\n (a no-op if 'macro' is not to be interpreted)
- X ------
- X# ifdef macro .........\n (also a no-op if 'macro is not -M'ed, except that
- X ------ there must be a matching #endif or #else)
- X# ifndef macro ........\n (same note as above)
- X ------
- X# else.................\n
- X
- X# endif................\n
- X
- X# if expression\n (if the truth of the expression is known, this is
- X interpreted. Otherwise it is not)
- X#\n
- X
- X
- XSpecial case: text is not interpreted (but preprocessor lines are interpreted)
- X during the scan for the actual parameters of a macro with parameters.
- SHAR_EOF
- if test 1986 -ne "`wc -c < 'interp'`"
- then
- echo shar: error transmitting "'interp'" '(should have been 1986 characters)'
- fi
- fi # end of overwriting check
- echo shar: extracting "'io.c'" '(8707 characters)'
- if test -f 'io.c'
- then
- echo shar: will not over-write existing file "'io.c'"
- else
- sed 's/^ X//' << \SHAR_EOF > 'io.c'
- X/*
- X * io.c - input and output primitives for the selective C preprocessor, scpp.
- X *
- X * Copyright (c) 1985 by
- X * Tektronix, Incorporated Beaverton, Oregon 97077
- X * All rights reserved.
- X *
- X * Permission is hereby granted for personal, non-commercial
- X * reproduction and use of this program, provided that this
- X * notice and all copyright notices are included in any copy.
- X */
- X
- X# include <stdio.h>
- X# include "scpp.h"
- X
- X# define STDINPUT 0 /* file descriptor of stdin */
- X# define BSIZE 512 /*
- X * # of bytes per read -- controls how quickly
- X * istk[] is consumed.
- X */
- Xint dooutput = 1; /* "actually write data" rather than tossing it */
- X
- X/*
- X * nxtc() - return the next character from the input stream.
- X * Nxtc() is used only by lex.
- X */
- X
- Xchar
- Xnxtc()
- X{
- X char ch;
- X int readcnt;
- X
- X
- X while ((ch = *nxtin++) == ATTN) {
- X switch (ch = *nxtin++) {
- X case AT_EPUSH: /* end of pushback (interpreted text) */
- X curfile->af_raw = TRUE;
- X break;
- X case AT_EBLK: /* end of block */
- X
- X /*
- X * The current block is exhausted.
- X * Mark the end of the new block
- X * then read in the new block (if there's space)
- X * and adjust the top of stack.
- X */
- X
- X unc(AT_EBLK);
- X unc(ATTN);
- X if (nxtin < &istk[BSIZE]) {
- X over();
- X }
- X nxtin -= BSIZE;
- X readcnt = read(curfile->af_fd, nxtin, BSIZE);
- X if (readcnt < 0) {
- X bombf("read error");
- X }
- X if (readcnt > 0) {
- X if (readcnt < BSIZE) {
- X /* slide the new data into place */
- X
- X register char *src, *dst;
- X
- X for (dst = nxtin + BSIZE,
- X src = nxtin + readcnt;
- X src > nxtin; *--dst = *--src)
- X ;
- X nxtin = dst;
- X }
- X break;
- X }
- X
- X /*
- X * The current file is exhausted.
- X * Pop the nonexistent block and the ATTN bytes
- X * from the input stack;
- X * Turn on the output if necessary;
- X * Close and pop the file.
- X */
- X
- X nxtin += BSIZE + 2;
- X if (curfile->af_hide) {
- X if (--hidecnt == 0 && falsecnt == 0) {
- X quec(ATTN);
- X quec(AT_OUTON);
- X }
- X }
- X if (curfile->af_fd != STDINPUT) {
- X close(curfile->af_fd);
- X }
- X free(curfile->af_name);
- X if (--curfile >= &filestk[0]){
- X break;
- X }
- X
- X /*
- X * no more current files remain - open the next
- X * file to be processed (if there is one),
- X * or pushback the EOF character and an ATTN
- X * so that further nxtc() calls return EOF.
- X */
- X
- X if (*nxtfile == (char *) 0) {
- X unc(AT_EBLK);
- X unc(ATTN);
- X unc('\0');
- X break;
- X }
- X pushfile(*nxtfile++, PF_NOLOOK, PF_NOHIDE);
- X break;
- X
- X default:
- X bombf("illegal character in input: 0x%x", ATTN);
- X }
- X }
- X
- X return(ch);
- X}
- X
- X/*
- X * untok() - push back the most recent token (less ATTN bytes)
- X * from the output stream into the input stream.
- X */
- X
- Xuntok()
- X{
- X char *cp;
- X
- X for (cp = nxtout - 1; cp >= curtext; --cp) {
- X if (cp > curtext && *(cp - 1) == ATTN) {
- X --cp;
- X } else {
- X if (*cp == '\n' && curfile->af_raw) {
- X curfile->af_line--;
- X }
- X unc(*cp);
- X }
- X }
- X nxtout = dispose(curtext);
- X}
- X
- X/*
- X * pushmac() - push the given macro value back into the input stream.
- X * Used to expand a macro.
- X * pushmac() is passed a pointer to the END of a string to be pushed
- X * (some part of a macro's replacement text). Pushmac() pushes the string
- X * backwards onto the input stack until it comes to a null-terminator or
- X * an ATTN byte. It returns a pointer to the terminator.
- X */
- X
- Xchar *
- Xpushmac(v)
- Xchar *v; /* points to a null-terminator or other ignored byte */
- X{
- X if (curfile->af_raw) {
- X unc(AT_EPUSH);
- X unc(ATTN);
- X curfile->af_raw = FALSE;
- X }
- X while (*--v != '\0' && *v != ATTN) {
- X if (nxtin-- < &istk[0]) {
- X over();
- X }
- X *nxtin = *v;
- X }
- X return(v);
- X}
- X
- X/*
- X * pushfile() - effectively push the given file into the input stream.
- X * Used to include a file.
- X */
- X
- Xpushfile(name, itype, hide)
- Xchar *name;
- Xint itype;
- X{
- X#define PNLEN 257
- X char pname[PNLEN];
- X char *cp;
- X char **dp;
- X struct afile *ip;
- X char *rindex();
- X char *malloc();
- X
- X
- X if (++curfile >= &filestk[FILESIZ]) {
- X --curfile;
- X warnf("too many nested include files. skipping `%s'", name);
- X return;
- X }
- X
- X /*
- X * if the name is to be opened with no modification, do that.
- X * If the directory of the current file is to be searched, do that.
- X * Search each directory in the list for the file.
- X */
- X
- X if (name[0] == '/' || itype == PF_NOLOOK) {
- X (void) strcpy(pname, name);
- X if (strcmp(name, "-") == 0) {
- X curfile->af_fd = STDINPUT;
- X } else {
- X curfile->af_fd = open(pname, 0);
- X }
- X } else {
- X curfile->af_fd = -1;
- X if (itype == PF_DOT) {
- X (void) strcpy(pname, (curfile - 1)->af_name);
- X if ((cp = rindex(pname, '/'))) {
- X ++cp;
- X } else {
- X cp = &pname[0];
- X }
- X if (cp + strlen(name) >= &pname[PNLEN]) {
- X --curfile;
- X bombf("name too long `%s%s'", pname, name);
- X }
- X (void) strcpy(cp, name);
- X curfile->af_fd = open(pname, 0);
- X }
- X for (dp = &dirlist[0]; *dp && curfile->af_fd < 0; dp++) {
- X cp = &pname[0] + strlen(*dp);
- X if (cp >= &pname[PNLEN]) {
- X --curfile;
- X bombf("name too long `%s'", *dp);
- X }
- X (void) strcpy(pname, *dp);
- X if (cp > &pname[0] && *(cp - 1) != '/') {
- X *cp++ = '/';
- X *cp = '\0';
- X }
- X if (cp + strlen(name) >= &pname[PNLEN]) {
- X --curfile;
- X bombf("name too long `%s%s'", pname, name);
- X }
- X (void) strcpy(cp, name);
- X curfile->af_fd = open(pname, 0);
- X }
- X }
- X if (curfile->af_fd < 0) {
- X --curfile;
- X warnf("cannot find%s file `%s'",
- X curfile > &filestk[0] ? " include" : "", name);
- X return;
- X }
- X
- X /*
- X * the file is open.
- X * See if this is a recursive include.
- X */
- X
- X for (ip = &filestk[0]; ip < curfile; ip++) {
- X if (strcmp(ip->af_name, pname) == 0) {
- X close(curfile->af_fd);
- X --curfile;
- X warnf("skipping recursive inclusion of `%s'", pname);
- X return;
- X }
- X }
- X
- X /*
- X * fill in the rest of the afile structure.
- X */
- X
- X if (!(curfile->af_name = malloc((unsigned) strlen(pname) + 1))) {
- X --curfile;
- X bombf("out of memory");
- X }
- X (void) strcpy(curfile->af_name, pname);
- X curfile->af_line = 1;
- X curfile->af_raw = TRUE;
- X curfile->af_hide = hide;
- X if (hide) {
- X if (hidecnt++ == 0 && falsecnt == 0) {
- X quec(ATTN);
- X quec(AT_OUTOFF);
- X }
- X }
- X unc(AT_EBLK);
- X unc(ATTN);
- X
- X#undef PNLEN
- X}
- X
- X/*
- X * quec() - move a character to the output queue, pend[]
- X */
- X
- Xquec(c)
- Xchar c;
- X{
- X *nxtout = c;
- X if (++nxtout >= &pend[PENDSIZ]) {
- X bombf("too much forward search");
- X }
- X}
- X
- X/*
- X * questr() - move the null-terminated string to the output queue, pend[]
- X * Used only by xxlex().
- X */
- X
- Xquestr(s, len)
- Xregister char *s;
- Xint len; /* length (in bytes) of the string to be moved */
- X{
- X register char *d = nxtout;
- X
- X
- X if (d + len < &pend[PENDSIZ]) {
- X while (*d++ = *s++)
- X ;
- X nxtout += len;
- X } else {
- X bombf("too much forward search");
- X }
- X}
- X
- X/*
- X * writepend() - write pending data to the output file, scanning for
- X * output control characters. Called only by the macro outpend().
- X */
- X
- Xwritepend()
- X{
- X char *cp;
- X
- X for (cp = &pend[0]; cp < nxtout; cp++) {
- X if (*cp != ATTN) {
- X if (dooutput) {
- X putchar(*cp);
- X }
- X } else {
- X switch(*++cp) {
- X case AT_OUTON:
- X dooutput = TRUE;
- X break;
- X case AT_OUTOFF:
- X dooutput = FALSE;
- X break;
- X default:
- X bombf("INTERNAL illegal character in output: 0x%x", ATTN);
- X }
- X }
- X }
- X nxtout = &pend[0];
- X}
- X
- X/*
- X * dispose() - dispose of pending output.
- X * output from the given point to nxtout is discarded, output control ATTN's
- X * are not discarded.
- X */
- X
- Xchar * /* returns the new end of the buffer (nxttok) */
- Xdispose(f)
- Xchar *f;
- X{
- X char *cp;
- X
- X for (cp = f; cp < nxtout; cp++) {
- X if (*cp == ATTN) {
- X /* copy the ATTN byte and the following code */
- X
- X *f++ = *cp++;
- X *f++ = *cp;
- X }
- X }
- X nxtout = f;
- X return(f);
- X}
- X
- X/*
- X * warnf - print a file-specific error and continue;
- X */
- X
- X/*VARARGS1*/
- Xwarnf(s, x1, x2, x3, x4, x5, x6, x7, x8)
- Xchar *s;
- Xint x1, x2, x3, x4, x5, x6, x7, x8;
- X{
- X if (curfile >= &filestk[0]) {
- X fprintf(stderr, "\"%s\", line %d: ",
- X curfile->af_name, curfile->af_line);
- X }
- X fprintf(stderr, s, x1, x2, x3, x4, x5, x6, x7, x8);
- X fprintf(stderr, "\n");
- X sawerror = TRUE;
- X}
- X
- X/*
- X * bombf - print a file-specific error and exit.
- X */
- X
- X/*VARARGS1*/
- Xbombf(s, x1, x2, x3, x4, x5, x6, x7, x8)
- Xchar *s;
- Xint x1, x2, x3, x4, x5, x6, x7, x8;
- X{
- X warnf(s, x1, x2, x3, x4, x5, x6, x7, x8);
- X exit(1);
- X}
- X
- X/*
- X * warn - print a non-file-specific error and continue.
- X */
- X
- X/*VARARGS1*/
- Xwarn(s, x1, x2, x3, x4, x5, x6, x7, x8)
- Xchar *s;
- Xint x1, x2, x3, x4, x5, x6, x7, x8;
- X{
- X fprintf(stderr, s, x1, x2, x3, x4, x5, x6, x7, x8);
- X fprintf(stderr, "\n");
- X sawerror = TRUE;
- X}
- X
- X/*
- X * bomb - print a non-file-specific error and exit.
- X */
- X
- X/*VARARGS1*/
- Xbomb(s, x1, x2, x3, x4, x5, x6, x7, x8)
- Xchar *s;
- Xint x1, x2, x3, x4, x5, x6, x7, x8;
- X{
- X fprintf(stderr, s, x1, x2, x3, x4, x5, x6, x7, x8);
- X exit(1);
- X}
- X
- X/*
- X * over() - input pushback overflow
- X */
- X
- Xover()
- X{
- X bombf("too much pushback");
- X}
- SHAR_EOF
- if test 8707 -ne "`wc -c < 'io.c'`"
- then
- echo shar: error transmitting "'io.c'" '(should have been 8707 characters)'
- fi
- fi # end of overwriting check
- # End of shell archive
- exit 0
-
-