home *** CD-ROM | disk | FTP | other *** search
- Subject: v11i040: Inline code expander for C, Part02/04
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rs@uunet.UU.NET
-
- Submitted-by: seismo!omepd!mcg@uunet.UU.NET
- Posting-number: Volume 11, Issue 40
- Archive-name: inline/Part02
-
- # This is a shell archive. Remove anything before this line
- # then unpack it by saving it in a file and typing "sh file"
- # (Files unpacked will be owned by you and have original permissions).
- # This archive contains the following files:
- # ./inline.1
- # ./inline.h
- # ./tokens.h
- # ./inline.c
- # ./declare.c
- #
- if `test ! -s ./inline.1`
- then
- echo "writing ./inline.1"
- sed 's/^X//' > ./inline.1 << '\Rogue\Monster\'
- X.TH INLINE 1
- X.\" $Header: inline.1,v 1.8 87/06/24 13:21:28 mcg Rel $
- X.SH NAME
- Xinline \- C preprocessor for inline functions
- X.SH SYNOPSIS
- X.B inline
- X[
- X.B \-w
- X] [
- X.B \-e
- X] [
- X.B \-s
- X] [
- X.B \-n
- X] [
- X.B \-d
- X] [
- X.B \-2
- X] [
- X.B \-S [ em
- X]
- X]
- X[ infile ] [ outfile ]
- X.SH DESCRIPTION
- X.I Inline
- Xis a
- Xpreprocessor that accepts C language programs
- Xcontaining the additional storage-class keyword
- X\fBinline\fR applied to function declarations, and
- Xgenerates identical C programs that (usually) have the
- Xfunctions so marked expanded where they are called.
- XInput code lacking the
- X.B inline
- Xkeyword is output unchanged.
- XThus
- X.I inline
- Xallows C programmers a feature similar to that provided
- Xby the C++ language.
- XHowever, while the specifications are the same, the
- X.I inline
- Xprogram works substantially differently from currently
- Ximplemented C++ compilers.
- XCurrent C++ compilers rewrite
- Xinline functions into expressions, thus prohibiting loops in them, but
- Xallowing their use in contexts such as control statements of looping
- Xconstructs.
- X.I Inline
- Xnormally
- Xreformats
- Xinline functions into code concealed in local blocks, adds
- Xvariables for parameter and return values, and changes
- X.B return
- Xstatements into
- X.BR goto s.
- XThis allows use of all normal C constructs within inlines.
- XThis rewriting is appropriate in all contexts except when
- Xinline functions are called in the control parts of
- X.B for
- Xand
- X.B while
- Xloops, and in a few other cases.
- XIn these cases, the C++ style expansion is used, and the procedures are
- Xrewritten as expressions when
- Xpossible (that is, when they lack loops, switches, and goto's).
- X.PP
- X.I Inline
- Xemits
- X.B extern
- X(or, optionally,
- X.BR static )
- Xpredeclarations for
- Xinline functions, so that unexpanded instances are compiled correctly,
- Xand can be supplied externally.
- XAdditionally, options are provided to emit the bodies of any unexpanded
- Xfunctions as static procedures at the end of a module, or to emit
- Xthe bodies of all inline functions alone, allowing inline functions to
- Xbe collected into a library.
- X.PP
- XIn normal operation,
- X.I inline
- Xfunctions must be declared before they are used (like C++).
- XThe \-2 (two-pass) option relaxes this requirement, at a 30% penalty in
- Xprocessing time.
- X.PP
- XThe following options are provided:
- X.IP \-w
- Xsupress warning messages about unexpandable instances of inline functions.
- X.IP \-e
- Xemit predeclarations as
- X.BR extern s,
- Xand do not dump bodies of unexpanded functions (default).
- X.IP \-s
- Xemit predeclarations as
- X.BR static s,
- Xand dump bodies of unexpanded functions.
- X.IP \-n
- Xemit no predeclarations at all, and do not
- Xdump bodies of unexpanded functions.
- XThis allows the gathering of
- X.B inline
- Xfunctions into a library, to resolve unexpanded
- Xreferences and any instances where the address
- Xof an
- X.B inline
- Xwas taken.
- X.IP \-d
- Xdo not emit the main program, only dump the
- Xbodies of all inlines (incompatible with \-e, \-s, and \-n).
- X.IP \-2
- Xprocess the file in two passes. This allows inline functions to be
- Xdeclared after their use. For this option, standard input is not
- Xaccepted.
- X.IP \-S
- Xemit (on the standard error output) statistics
- Xabout the expansion process.
- X.IP \-Se
- Xemit extended statistics, giving expansion statistics
- Xfor each
- X.BR inline .
- X.IP \-Sm
- Xemit statistics about the memory usage of the program (if the program is
- Xcompiled to collect these statistics).
- X.PP
- XIf no input file is specified, the standard input is assumed,
- Xand likewise for the standard output.
- X.SH BUGS/CAVEATS
- X.I Inline
- Xdoes not perform predictably when given incorrect C programs.
- XIt is easy to test a program that contains inlines with the
- Xcommand:
- X.sp
- X.nf
- X.na
- X cc -c -Dinline=static file.c
- X.fi
- X.ad
- X.PP
- XWhen multiple inline functions are present in a single expression,
- Xthe order in which the functions are executed in the inline code
- Xis sometimes different from the order in which they would have been
- Xcalled had they not been expanded.
- XIn particular, all functions in the expression will be evaluated,
- Xleft-to-right, before the operations in the expression are performed.
- XThis is correct for most C operators,
- X.I except
- Xthe comma, boolean-or (||), and boolean-and (&&) operators.
- XInline handles all but the comma operator correctly, expressionizing
- Xcalls on the right side of the conditional operators.
- X.PP
- XWhile
- X.I inline
- Xattempts to pass preprocessor defines through without change,
- Xit is strongly suggested that
- X.I inline
- Xbe executed
- Xon code that has already been processed by
- Xthe C preprocessor /lib/cpp.
- X.PP
- X.I Inline
- Xdoes not recognize certain degenerate cases of function declarations
- Xand calls, in particular:
- X.sp
- X.nf
- X.na
- X (foo)(arg);
- X.fi
- X.ad
- X.I Inline
- Xalso does not correctly handle inline functions which take the address of
- Xlabels, or which use labels other than in \fBgoto\fR statements, both
- Xextremely distasteful (and probably illegal) practices.
- X.SH "SEE ALSO"
- Xcc(1), cpp(1)
- X.SH NOTE
- X.I Inline
- Xsource code
- Xis Copyright, 1986, 1987 by S. McGeady, all rights reserved.
- X.br
- XThe binaries for the VAX version of this program and this manual page are
- Xin the public domain.
- X.SH AUTHOR
- XS. McGeady
- X.br
- X3714 SE 26th Ave.
- X.br
- XPortland, OR 97202
- X.br
- X(503) 235-2462
- \Rogue\Monster\
- else
- echo "will not over write ./inline.1"
- fi
- chmod 444 ./inline.1
- if [ `wc -c ./inline.1 | awk '{printf $1}'` -ne 5093 ]
- then
- echo `wc -c ./inline.1 | awk '{print "Got " $1 ", Expected " 5093}'`
- fi
- if `test ! -s ./inline.h`
- then
- echo "writing ./inline.h"
- sed 's/^X//' > ./inline.h << '\Rogue\Monster\'
- X/*
- X * inline code expander
- X *
- X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
- X */
- X
- X/* $Header: inline.h,v 1.13 87/06/18 15:27:08 mcg Rel $ */
- X
- X
- X#include <stdio.h>
- X
- X#define NFORMALS 30 /* max number of formal params */
- X#define NINLINE 400 /* max number of inline decl's */
- X#define NEXPAND 20 /* max number of expansions per stmt */
- X#define NTYPEDEF 50 /* max number of typedefs per scope */
- X#define NSCOPE 20 /* max scoping depth */
- X#define NLOCALS 200 /* max # of local vars */
- X
- X#define NIL ((char *) 0)
- X#define NILP(t) ((t) 0)
- X#define NILTOK NILP(struct token *)
- X
- X/* token flags */
- X
- X#define TNOEXPAND 0x01
- X#define TNEEDEXPR 0x02
- X#define TAUTO 0x04 /* an auto identifier */
- X#define TINLINE 0x10
- X
- Xstruct token {
- X int t_tok; /* token type */
- X short t_flags; /* flag word */
- X short t_num; /* number for id expansion */
- X short t_level; /* brace level */
- X short t_paren; /* paren level */
- X int t_line; /* line this token occured on */
- X char *t_id; /* identifier of this token, if any */
- X struct token *t_next; /* next token in this list */
- X};
- X
- Xstruct toklist {
- X struct token *tl_head; /* pointer to head token */
- X struct token *tl_tail; /* pointer to last token in the list */
- X};
- X
- X#define SDECL 0 /* declaration */
- X#define SFORMAL 1 /* formal list */
- X#define SOPARAMDECL 2 /* old-style param declaration */
- X#define SBODY 3 /* body */
- X#define SDECLBODY 4 /* declaration of formals & return */
- X#define SEXPRDECL 5 /* expression form declarations */
- X#define SEXPRBODY 6 /* expression form body */
- X#define NSTATES 7
- X
- X/*
- X * flags
- X */
- X
- X#define NEEDRETVAL 1
- X
- X/*
- X * formal info
- X */
- X
- X#define I_LVALUE 1 /* formal is used as an lvalue */
- X#define I_SUB_OK 2 /* ok to substitute an actual here */
- X#define I_EXPR 4 /* successfully rewrote as an expression */
- X
- Xstruct inline_node {
- X char *i_id; /* ptr to identifier token */
- X struct toklist i_text; /* saved text of original */
- X struct toklist i_tl[NSTATES]; /* token lists for sections */
- X char *i_formals[NFORMALS]; /* list of formals */
- X int i_formalinfo[NFORMALS]; /* info about formals */
- X int i_flags; /* misc flags */
- X int i_nformals; /* number of formals */
- X int i_storclass; /* storage class of inline */
- X int i_line; /* line number */
- X int i_mem; /* memory pool for storage */
- X int i_exprmem; /* pool for expression store */
- X int i_nseen; /* # of calls seen */
- X int i_nexpand; /* # of calls expanded */
- X};
- X
- X
- Xstruct expand_node {
- X struct inline_node *e_node; /* ptr to inline node for this expansion */
- X int e_multiple; /* more than one call to this inline */
- X struct toklist e_actuals[NFORMALS]; /* actuals for this call */
- X int e_nactuals; /* number of actuals */
- X};
- X
- Xstruct typelist {
- X char type_mem;
- X char *type_id[NTYPEDEF];
- X};
- X
- Xstruct locallist {
- X char *l_id;
- X long l_scopes;
- X};
- X
- Xextern int line;
- Xextern int debug;
- Xextern int errs;
- Xextern int nowarn;
- Xextern int forward_decl;
- Xextern char *myname;
- Xextern char *infile;
- Xextern char *outfile;
- Xextern struct typelist *typeid[];
- X
- Xextern struct token *gettok();
- Xextern struct inline_node *isinline();
- Xextern struct inline_node *mknode();
- X
- X/* token manipulation routines */
- Xextern struct token *skipws();
- Xextern struct token *newtok();
- Xextern struct token *duptok();
- Xextern struct token *instok();
- X
- X/* miscellany */
- Xextern char *itoa();
- Xextern char *mkstr();
- Xextern char *MALLOC();
- Xextern char *getmem();
- X
- Xextern struct inline_node *nodelist[];
- \Rogue\Monster\
- else
- echo "will not over write ./inline.h"
- fi
- chmod 444 ./inline.h
- if [ `wc -c ./inline.h | awk '{printf $1}'` -ne 3395 ]
- then
- echo `wc -c ./inline.h | awk '{print "Got " $1 ", Expected " 3395}'`
- fi
- if `test ! -s ./tokens.h`
- then
- echo "writing ./tokens.h"
- sed 's/^X//' > ./tokens.h << '\Rogue\Monster\'
- X
- X/* $Header: tokens.h,v 1.5 87/06/24 13:11:37 mcg Rel $ */
- X
- X
- X#define T_EOT 0
- X
- X/*
- X * reserved words
- X */
- X
- X#define T_AUTO 1 /* auto */
- X#define T_BREAK 2 /* break */
- X#define T_CASE 3 /* case */
- X#define T_CHAR 4 /* char */
- X#define T_CONST 5 /* const */
- X#define T_CONTINUE 6 /* continue */
- X#define T_DEFAULT 7 /* default */
- X#define T_DO 8 /* do */
- X#define T_DOUBLE 9 /* double */
- X#define T_ELSE 10
- X#define T_ENUM 11
- X#define T_EXTERN 12
- X#define T_FLOAT 13
- X#define T_FOR 14
- X#define T_GOTO 15
- X#define T_IF 16
- X#define T_INT 17
- X#define T_LONG 18
- X#define T_REGISTER 19
- X#define T_RETURN 20
- X#define T_SHORT 21
- X#define T_SIGNED 22
- X#define T_SIZEOF 23
- X#define T_STATIC 24
- X#define T_STRUCT 25
- X#define T_SWITCH 26
- X#define T_TYPEDEF 27
- X#define T_UNION 28
- X#define T_UNSIGNED 29
- X#define T_VOID 30
- X#define T_VOLATILE 31
- X#define T_WHILE 32
- X
- X
- X#define T_ELLIPSES 33 /* ... */
- X#define T_EQ 34 /* = */
- X#define T_COMMA 35 /* , */
- X#define T_LBRACE 36 /* { */
- X#define T_RBRACE 37 /* } */
- X#define T_SEMIC 38 /* ; */
- X#define T_RS_EQ 39 /* <<= */
- X#define T_LS_EQ 40 /* >>= */
- X#define T_ADD_EQ 41 /* += */
- X#define T_SUB_EQ 42 /* -= */
- X#define T_MUL_EQ 43 /* *= */
- X#define T_DIV_EQ 44 /* /= */
- X#define T_MOD_EQ 45 /* %= */
- X#define T_AND_EQ 46 /* &= */
- X#define T_XOR_EQ 47 /* ^= */
- X#define T_OR_EQ 48 /* |= */
- X#define T_RS 49 /* >> */
- X#define T_LS 50 /* << */
- X#define T_INC 51 /* ++ */
- X#define T_DEC 52 /* -- */
- X#define T_PTR 53 /* -> */
- X#define T_CAND 54 /* && */
- X#define T_COR 55 /* || */
- X#define T_LE 56 /* <= */
- X#define T_GE 57 /* >= */
- X#define T_CEQ 58 /* == */
- X#define T_NE 59 /* != */
- X#define T_COLON 60 /* : */
- X /* 61 missing */
- X#define T_LPAREN 62 /* ( */
- X#define T_RPAREN 63 /* ) */
- X#define T_LSQ 64 /* [ */
- X#define T_RSQ 65 /* ] */
- X#define T_DOT 66 /* . */
- X#define T_AMPER 67 /* & */
- X#define T_NOT 68 /* ! */
- X#define T_TILDE 69 /* ~ */
- X#define T_MINUS 70 /* - */
- X#define T_PLUS 71 /* + */
- X#define T_STAR 72 /* * */
- X#define T_DIV 73 /* / */
- X#define T_MOD 74 /* % */
- X#define T_LT 75 /* < */
- X#define T_GT 76 /* > */
- X#define T_XOR 77 /* ^ */
- X#define T_OR 78 /* | */
- X#define T_QUEST 79 /* ? */
- X
- X#define T_INLINE 80 /* the 'inline' keyword */
- X#define T_IDENT 81 /* an identifier */
- X#define T_TYPE_ID 82 /* a type identifier */
- X#define T_WS 83 /* whitespace and comments */
- X#define T_NUM 84 /* a constant */
- X#define T_STR 85 /* string */
- X#define T_CPP 86 /* a preprocessor-style '#' line */
- X#define T_CHARCONST 87 /* a character constant */
- X#define T_COMMENT 88 /* a comment */
- X#define T_STRTAG 89 /* a structure or union tag */
- X#define T_LABEL 90 /* a label */
- X
- X#define T_ACTUAL 91 /* an actual parameter */
- X#define T_RETVAL 92
- X#define T_ARGLIST 93 /* a substitutable argument list */
- X#define T_RETLAB 94
- X#define T_FORMAL 95
- \Rogue\Monster\
- else
- echo "will not over write ./tokens.h"
- fi
- chmod 444 ./tokens.h
- if [ `wc -c ./tokens.h | awk '{printf $1}'` -ne 2763 ]
- then
- echo `wc -c ./tokens.h | awk '{print "Got " $1 ", Expected " 2763}'`
- fi
- if `test ! -s ./inline.c`
- then
- echo "writing ./inline.c"
- sed 's/^X//' > ./inline.c << '\Rogue\Monster\'
- X/*
- X * inline substituter for C
- X *
- X * s. mcgeady - 10/25/86
- X */
- X
- X/*
- X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
- X */
- X
- X/* $Header: inline.c,v 1.20 87/06/24 13:11:30 mcg Rel $ */
- X
- X#include <stdio.h>
- X#include "tokens.h"
- X#include "inline.h"
- X
- X#define strrchr rindex
- Xextern char *strrchr();
- X
- X#define LOGFILE "/c/mcg/.inline_use"
- X
- X/*
- X * global data declarations
- X */
- X
- Xstruct typelist *typeid[NSCOPE];
- X
- Xstatic struct locallist locals[NLOCALS];
- Xstatic int expanded = 0;
- X
- Xstruct inline_node *nodelist[NINLINE] = {0};
- X
- Xint forward_decl = T_EXTERN;
- Xchar *myname;
- Xchar *infile = NIL;
- Xchar *outfile = NIL;
- Xint debug = 0;
- Xint stats = 0;
- Xint mstats = 0;
- Xint dumpinline = 0;
- Xint noexpand = 0;
- Xint errs = 0;
- Xint nowarn = 0;
- Xint twopass = 0;
- Xint pass = 0;
- X
- Xmain(argc,argv)
- Xint argc;
- Xchar **argv;
- X{
- X register int mem;
- X struct toklist prog;
- X register int r;
- X
- X#ifdef LOGFILE
- X logusage(argc,argv);
- X#endif
- X if (!(myname = strrchr(argv[0],'/'))) {
- X myname = argv[0];
- X } else {
- X myname++;
- X }
- X
- X while (--argc) {
- X ++argv;
- X if ((*argv)[0] == '-') {
- X switch((*argv)[1]) {
- X case 'w': /* supress warnings */
- X nowarn++;
- X break;
- X case 'x': /* debug */
- X debug++;
- X if ((*argv)[2] != '\0') {
- X debug = (*argv)[2] - '0';
- X }
- X break;
- X case 'S': /* stats */
- X stats = 1;
- X for (r = 2; (*argv)[r] != '\0'; r++) {
- X switch((*argv)[r]) {
- X case 'e': /* expansion stats */
- X stats++;
- X break;
- X case 'm': /* memory stats */
- X mstats++;
- X break;
- X }
- X }
- X break;
- X case 'e': /* externals */
- X dumpinline = 0;
- X break;
- X case 's': /* static */
- X forward_decl = T_STATIC;
- X dumpinline = 1;
- X break;
- X case 'n': /* none */
- X dumpinline = 0;
- X forward_decl = 0;
- X break;
- X case 'd': /* dump inlines */
- X noexpand++;
- X forward_decl = 0;
- X dumpinline = 2;
- X break;
- X
- X case '2':
- X twopass++;
- X break;
- X
- X default:
- X error(0,"bad switch %s", *argv);
- X break;
- X }
- X } else { /* a filename */
- X if (!infile) {
- X infile = *argv;
- X if (!freopen(infile,"r",stdin)) {
- X error(0,"cannot open %s", *argv);
- X exit(1);
- X }
- X } else if (!outfile) {
- X outfile = *argv;
- X if (!freopen(outfile,"w",stdout)) {
- X error(0,"cannot create %s", *argv);
- X exit(1);
- X }
- X } else {
- X error(0,"usage: %s [flags] [infile] [outfile]", myname);
- X exit(1);
- X }
- X }
- X }
- X
- X if (twopass) {
- X if (dumpinline == 2) {
- X warn(0, "two pass operations nonsensical with -d - twopass disabled");
- X twopass = 0;
- X }
- X if (infile == NIL) {
- X error(0, "two pass operation requires a named input file");
- X exit(1);
- X }
- X }
- X pushscope(0);
- X while(1) {
- X mem = openpool();
- X expanded = 0;
- X prog.tl_head = prog.tl_tail = NILTOK;
- X r = doproc(mem,&prog);
- X if (!noexpand || r >= 0)
- X prtoklist(&prog,expanded,stdout);
- X (void) closepool(mem);
- X if (r == 0) { /* end of file */
- X if (twopass && (pass == 0)) {
- X fclose(stdin);
- X popscope(0);
- X pushscope(0);
- X if (!freopen(infile,"r",stdin)) {
- X error(0,"cannot reopen %s", infile);
- X exit(1);
- X }
- X pass = 1;
- X continue;
- X }
- X break;
- X }
- X }
- X if (dumpinline) {
- X dump(dumpinline);
- X }
- X /* print memory allocator stats */
- X if (mstats) {
- X memstats();
- X }
- X if (stats) {
- X prstats(stats);
- X }
- X return(errs);
- X}
- X
- X/*
- X * handle a procedure - return 0 on EOF
- X */
- X
- Xdoproc(mem,prog)
- Xregister int mem;
- Xstruct toklist *prog;
- X{
- X register struct token *tok = NILTOK;
- X register struct token *last = NILTOK;/* last **non-whitespace** token */
- X register struct token *savtok = NILTOK;
- X register struct token *decltok = NILTOK;
- X register int state = 0;
- X register int inlined = 0;
- X int seenquest = 0;
- X int seengoto = 0;
- X int scope = 0;
- X int i;
- X
- X#define STYPEDEF 1 /* a typedef declaration */
- X#define SSTRUCTDECL 2 /* a structure declaration */
- X#define SSTRUCTTAG 3 /* as above, but have seen struct tag */
- X#define SSTRUCTBODY 4 /* in the structure body */
- X#define SSTRUCTREF 5 /* saw a "." or "->" */
- X
- X clearlocals();
- X
- X while((tok && tok->t_tok != T_WS ? last = tok: 0), tok = gettok(mem)) {
- X
- X addtok(prog,tok);
- X
- X switch(tok->t_tok) {
- X case T_WS:
- X continue;
- X
- X case T_QUEST:
- X seenquest++;
- X continue;
- X
- X case T_COLON:
- X if (!seenquest && (last->t_tok == T_IDENT)) {
- X /* a label */
- X last->t_tok = T_LABEL;
- X }
- X if (seenquest) seenquest--;
- X continue;
- X
- X case T_GOTO:
- X seengoto++;
- X continue;
- X
- X case T_SEMIC:
- X seengoto = 0;
- X if (state == STYPEDEF) {
- X if (tok->t_level <= savtok->t_level) {
- X dotypedef(savtok);
- X state = 0;
- X decltok = savtok = NILTOK;
- X }
- X continue;
- X }
- X if (state == SSTRUCTBODY && (tok->t_level > savtok->t_level)) {
- X continue;
- X }
- X if (state) {
- X state = 0;
- X }
- X if (tok->t_level > 0 && decltok &&
- X decltok->t_tok != T_EXTERN) {
- X /* a declaration line */
- X if (!twopass || ((pass == 0) && inlined) || ((pass == 1) && !inlined)) {
- X dolocals(mem,decltok,tok,inlined);
- X }
- X }
- X decltok = NILTOK;
- X
- X continue;
- X
- X case T_LBRACE:
- X scope++;
- X if (state == SSTRUCTDECL || state == SSTRUCTTAG) {
- X state = SSTRUCTBODY;
- X continue;
- X }
- X if (state) { /* typedef or struct body */
- X continue;
- X }
- X if (scope-1 == 0) {
- X if (!inlined && !(twopass && (pass == 0)))
- X doargs(mem,prog->tl_head,tok);
- X decltok = NILTOK;
- X }
- X continue;
- X
- X case T_RBRACE:
- X scope--;
- X if (state == SSTRUCTBODY) {
- X if (tok->t_level <= savtok->t_level) {
- X state = 0;
- X decltok = savtok;
- X savtok = NILTOK;
- X }
- X continue;
- X }
- X if (scope != 0) {
- X clearscope(scope);
- X continue;
- X }
- X if (!state) {
- X if (isdecl(prog)) {
- X if (twopass && pass == 1) {
- X /* NIL it out */
- X prog->tl_head = prog->tl_tail = NILTOK;
- X } else {
- X dodecl(prog,dumpinline);
- X }
- X } else if (!noexpand) {
- X if (twopass && (pass == 0)) {
- X prog->tl_head = prog->tl_tail = NILTOK;
- X } else {
- X expanded += doinline(mem,prog);
- X }
- X }
- X }
- X clearlocals();
- X /* this is the only way out of doproc() except EOF */
- X break;
- X
- X case T_INLINE:
- X inlined++;
- X continue;
- X
- X case T_TYPEDEF:
- X savtok = tok;
- X state = STYPEDEF;
- X continue;
- X
- X case T_STRUCT:
- X case T_UNION:
- X savtok = tok;
- X if (tok->t_level > 0) {
- X decltok = savtok;
- X }
- X state = SSTRUCTDECL;
- X continue;
- X
- X case T_DOT:
- X case T_PTR:
- X state = SSTRUCTREF;
- X continue;
- X
- X case T_IDENT:
- X switch(state) {
- X case SSTRUCTBODY:
- X case STYPEDEF:
- X case SSTRUCTTAG:
- X continue;
- X
- X case SSTRUCTREF:
- X state = 0;
- X continue;
- X
- X case SSTRUCTDECL:
- X tok->t_tok = T_STRTAG;
- X state = SSTRUCTTAG;
- X continue;
- X }
- X if (seengoto) {
- X tok->t_tok = T_LABEL;
- X continue;
- X }
- X if (scope > 0 && !decltok && islocal(tok->t_id,scope)) {
- X tok->t_flags |= TAUTO;
- X if (inlined) {
- X tok->t_flags |= TINLINE;
- X tok->t_num = deflevel(tok->t_id,scope);
- X }
- X }
- X continue;
- X
- X default:
- X if (state == SSTRUCTBODY || state == STYPEDEF) {
- X continue;
- X }
- X if (tok->t_level > 0 && !decltok &&
- X (istype(tok) || isstoreclass(tok)) &&
- X (last->t_tok == T_SEMIC || last->t_tok == T_LBRACE)) {
- X
- X decltok = tok;
- X }
- X continue;
- X }
- X
- X break;
- X }
- X if (!tok) return(0);
- X return(1);
- X}
- X
- Xdoargs(mem,begin,end)
- Xint mem;
- Xregister struct token *begin, *end;
- X{
- X register struct token *tp = begin;
- X
- X /* first find an identifier */
- X while(tp && tp->t_tok != T_IDENT) {
- X tp = tp->t_next;
- X }
- X if (!tp) return;
- X
- X /* then find level 0 left paren */
- X while(tp && (tp->t_tok != T_LPAREN || tp->t_paren > 0)) {
- X tp = tp->t_next;
- X }
- X if (!tp) return;
- X
- X for ( ; tp && tp != end; tp = tp->t_next) {
- X if ((tp->t_tok == T_IDENT) && (tp->t_level >= begin->t_level)) {
- X if (addlocal(tp->t_id,1) < 0) {
- X error(tp->t_line, "too many local variables");
- X } else {
- X tp->t_flags |= TAUTO;
- X }
- X }
- X }
- X}
- X
- Xdolocals(mem,begin,end,inlined)
- Xint mem;
- Xregister struct token *begin, *end;
- Xint inlined;
- X{
- X register int skip = 0;
- X register struct token *tp;
- X register int i;
- X
- X for (tp = begin->t_next; tp && tp != end; tp = tp->t_next) {
- X if (skip) {
- X if (tp->t_tok == T_SEMIC ||
- X (tp->t_tok == T_COMMA &&
- X (tp->t_paren <= skip-1))) {
- X skip = 0;
- X } else if ((tp->t_tok == T_IDENT) &&
- X islocal(tp->t_id,tp->t_level)) {
- X tp->t_flags |= TAUTO;
- X if (inlined) {
- X tp->t_num = deflevel(tp->t_id,tp->t_level);
- X tp->t_flags |= TINLINE;
- X }
- X }
- X continue;
- X }
- X if (tp->t_tok == T_EQ) {
- X skip = tp->t_paren+1;
- X continue;
- X } else if ((tp->t_tok == T_IDENT) &&
- X (tp->t_level >= begin->t_level)) {
- X
- X if (addlocal(tp->t_id,tp->t_level) < 0) {
- X error(tp->t_line, "too many local variables");
- X continue;
- X }
- X tp->t_flags |= TAUTO;
- X if (inlined) {
- X tp->t_flags |= TINLINE;
- X tp->t_num = tp->t_level;
- X }
- X }
- X }
- X}
- X
- Xstatic int scopemask[] = {
- X 0x0001, /* scope 1 */
- X 0x0003, /* scope 2 */
- X 0x0007, /* scope 3 */
- X 0x000f, /* scope 4 */
- X 0x001f, /* scope 5 */
- X 0x003f, /* scope 6 */
- X 0x007f, /* scope 7 */
- X 0x00ff, /* scope 8 */
- X 0x01ff, /* scope 9 */
- X 0x03ff, /* scope 10 */
- X 0x07ff, /* scope 11 */
- X 0x0fff, /* scope 12 */
- X 0x1fff, /* scope 13 */
- X 0x3fff, /* scope 14 */
- X 0x7fff, /* scope 15 */
- X 0xffff, /* scope 16 */
- X 0x1ffff, /* scope 17 */
- X 0x3ffff, /* scope 18 */
- X 0x7ffff, /* scope 19 */
- X 0xfffff /* scope 20 */
- X};
- X
- X
- X
- Xaddlocal(s,scope)
- Xregister char *s;
- Xregister int scope;
- X{
- X register struct locallist *p;
- X register char *rs;
- X register int i = 0;
- X
- X if (scope > NSCOPE) return(-1);
- X
- X for (rs = s; *rs != '\0'; i += *rs++)
- X ;
- X
- X i %= NLOCALS;
- X
- X for (p = &locals[i]; p >= locals; p--) {
- X if (p->l_id == NIL) {
- X p->l_id = s;
- X p->l_scopes |= (1<<(scope-1));
- X return(0);
- X } else if (strcmp(s,p->l_id) == 0) {
- X p->l_scopes |= (1<<(scope-1));
- X return(1);
- X }
- X }
- X for (p = &locals[i+1]; p < &locals[NLOCALS]; p++) {
- X if (p->l_id == NIL) {
- X p->l_id = s;
- X p->l_scopes |= (1<<(scope-1));
- X return(0);
- X } else if (strcmp(s,p->l_id) == 0) {
- X p->l_scopes |= (1<<(scope-1));
- X return(1);
- X }
- X }
- X return(-1);
- X}
- X
- Xislocal(s,scope)
- Xregister char *s;
- Xregister int scope;
- X{
- X register struct locallist *p;
- X register char *rs;
- X register int i = 0;
- X
- X for (rs = s; *rs != '\0'; i += *rs++)
- X ;
- X
- X i %= NLOCALS;
- X
- X for (p = &locals[i]; p >= locals; p--) {
- X if (p->l_id == NIL) {
- X return(0);
- X } else if ((strcmp(s,p->l_id) == 0) &&
- X p->l_scopes&scopemask[scope-1]) {
- X return(1);
- X }
- X }
- X for (p = &locals[i+1]; p < &locals[NLOCALS]; p++) {
- X if (p->l_id == NIL) {
- X return(0);
- X } else if ((strcmp(s,p->l_id) == 0) &&
- X p->l_scopes&scopemask[scope-1]) {
- X return(1);
- X }
- X }
- X return(0);
- X}
- X
- X
- Xdeflevel(s,scope)
- Xregister char *s;
- Xregister int scope;
- X{
- X register struct locallist *p;
- X register char *rs;
- X register int i = 0;
- X
- X for (rs = s; *rs != '\0'; i += *rs++)
- X ;
- X
- X i %= NLOCALS;
- X
- X for (p = &locals[i]; p >= locals; p--) {
- X if (p->l_id == NIL) {
- X return(0);
- X } else if ((strcmp(s,p->l_id) == 0) &&
- X p->l_scopes&scopemask[scope-1]) {
- X goto end;
- X }
- X }
- X for (p = &locals[i+1]; p < &locals[NLOCALS]; p++) {
- X if (p->l_id == NIL) {
- X return(0);
- X } else if ((strcmp(s,p->l_id) == 0) &&
- X p->l_scopes&scopemask[scope-1]) {
- X goto end;
- X }
- X }
- X return(0);
- X
- X end:
- X if (scope < 1 || scope > NSCOPE) {
- X return(0);
- X }
- X for (i = scope-1; i >= 0; i--) {
- X if (p->l_scopes&(1<<i)) {
- X return(i+1);
- X }
- X }
- X return(0);
- X}
- X
- Xclearlocals() {
- X register int i;
- X
- X for (i = 0; i < NLOCALS; i++) {
- X locals[i].l_id = NIL;
- X locals[i].l_scopes = 0;
- X }
- X}
- X
- Xclearscope(scope)
- Xregister int scope;
- X{
- X register int i;
- X
- X for (i = 0; i < NLOCALS; i++) {
- X if (locals[i].l_id != NIL) {
- X locals[i].l_scopes &= scopemask[scope-1];
- X }
- X }
- X}
- X
- Xstruct inline_node *
- Xisinline(id)
- Xregister char *id;
- X{
- X register int i;
- X
- X for(i=0; (i < NINLINE) && (nodelist[i] != NILP(struct inline_node *)); i++) {
- X if (nodelist[i]->i_id && strcmp(nodelist[i]->i_id, id) == 0) {
- X return(nodelist[i]);
- X }
- X }
- X return((struct inline_node *) 0);
- X}
- X
- X
- Xpushscope(level)
- X{
- X register int mem;
- X register int i;
- X
- X if (level >= NSCOPE) {
- X error(line, "internal - push of invalid scope level");
- X return;
- X }
- X mem = openpool();
- X typeid[level] = (struct typelist *) getmem(mem,1,sizeof(struct typelist));
- X if (typeid[level] == NILP(struct typelist *)) {
- X error(line, "internal - out of memory");
- X return;
- X }
- X typeid[level]->type_mem = mem;
- X for (i = 0; i < NTYPEDEF; i++) {
- X typeid[level]->type_id[i] = NIL;
- X }
- X return;
- X}
- X
- Xpopscope(level)
- X{
- X#ifdef notdef
- X if (level == 0) {
- X error(line, "internal - pop of scope 0\n");
- X return;
- X }
- X#endif
- X if (level >= NSCOPE) {
- X error(line, "internal - invalid scope depth");
- X return;
- X }
- X
- X (void) closepool(typeid[level]->type_mem);
- X typeid[level] = NILP(struct typelist *);
- X return;
- X}
- X
- Xdump(n)
- Xint n;
- X{
- X register int i;
- X struct token tok;
- X
- X if (n < 1) return;
- X
- X for (i = 0; (i < NINLINE) && (nodelist[i] != NILP(struct inline_node *)); i++) {
- X if (n > 1 || (nodelist[i]->i_nseen > nodelist[i]->i_nexpand)) {
- X if (nodelist[i]->i_text.tl_head->t_tok == T_INLINE) {
- X nodelist[i]->i_text.tl_head =
- X nodelist[i]->i_text.tl_head->t_next;
- X }
- X
- X if (forward_decl) {
- X tok.t_tok = forward_decl;
- X prtok(&tok,0,stdout);
- X }
- X prtoklist(&nodelist[i]->i_text,0,stdout);
- X printf("\n\n");
- X }
- X }
- X}
- X
- X
- Xprstats(n)
- Xint n;
- X{
- X register int i;
- X int nseen = 0;
- X int nnode = 0;
- X int nexpand = 0;
- X
- X for(i=0; (i < NINLINE) && (nodelist[i] != NILP(struct inline_node *)); i++) {
- X nnode++;
- X nseen += nodelist[i]->i_nseen;
- X nexpand += nodelist[i]->i_nexpand;
- X if (n > 1) {
- X fprintf(stderr,
- X "inline %s(): %d expansions in %d occurences\n",
- X nodelist[i]->i_id,nodelist[i]->i_nexpand,
- X nodelist[i]->i_nseen);
- X }
- X }
- X fprintf(stderr, "%d nodes, %d expansions in %d occurences\n",
- X nnode, nexpand, nseen);
- X}
- X
- X#ifdef LOGFILE
- X
- X#include <pwd.h>
- Xextern char *ctime();
- X
- Xlogusage(argc,argv)
- Xint argc;
- Xchar **argv;
- X{
- X FILE *f;
- X struct passwd *pw;
- X char *name, *t;
- X long now;
- X
- X if (f = fopen(LOGFILE,"a")) {
- X setpwent();
- X pw = getpwuid(getuid());
- X endpwent();
- X if (pw) {
- X name = pw->pw_name;
- X /* don't log the author */
- X if (strcmp(name,"mcg") == 0) {
- X fclose(f);
- X return;
- X }
- X } else {
- X name = "???";
- X }
- X now = time(0);
- X t = ctime(&now);
- X t[strlen(t)-1] = '\0';
- X t += 4;
- X fprintf(f,"%s [%s]", pw->pw_name, t);
- X if (argc > 1) {
- X fprintf(f," (");
- X while(--argc) {
- X fprintf(f,"%s", *argv);
- X argv++;
- X if (argc) fprintf(f," ");
- X }
- X fprintf(f,")");
- X }
- X fprintf(f,"\n");
- X fclose(f);
- X }
- X return;
- X}
- X
- X#endif
- \Rogue\Monster\
- else
- echo "will not over write ./inline.c"
- fi
- chmod 444 ./inline.c
- if [ `wc -c ./inline.c | awk '{printf $1}'` -ne 14368 ]
- then
- echo `wc -c ./inline.c | awk '{print "Got " $1 ", Expected " 14368}'`
- fi
- if `test ! -s ./declare.c`
- then
- echo "writing ./declare.c"
- sed 's/^X//' > ./declare.c << '\Rogue\Monster\'
- X/*
- X * inline code expander
- X *
- X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
- X */
- X
- X/* $Header: declare.c,v 1.10 87/06/24 13:11:05 mcg Rel $ */
- X
- X
- X/*
- X * process the declaration of an inline subroutine
- X *
- X * this involves storing away the declaration, formal parameter list,
- X * formal parameter declarations, and body, and rewriting the body part
- X * of the inline by adding formal parameter declarations at the top
- X * with initialization templates, and replace return statements with
- X * assignments to the return value template and jumps to the end
- X * of the block
- X */
- X
- X
- X#include "inline.h"
- X#include "tokens.h"
- X
- Xdodecl(list,save)
- Xregister struct toklist *list;
- Xregister int save;
- X{
- X struct inline_node *node;
- X register int state = SDECL;
- X register int nextstate;
- X register struct token *t, *tok, *lasttok;
- X int retstmt = 0;
- X int sawretstmt = 0;
- X int structmember = 0;
- X int seenincdec = 0;
- X int i;
- X int mem;
- X
- X /* note that this memory pool is permanent */
- X mem = openpool(); /* a memory pool for this guy */
- X
- X node = mknode(mem); /* no need to ever free this */
- X
- X node->i_mem = mem;
- X
- X /* add the node to the list */
- X for(i = 0; i < NINLINE; i++) {
- X if (nodelist[i] == NILP(struct inline_node *)) {
- X nodelist[i] = node;
- X break;
- X }
- X }
- X if (nodelist[i] != node){
- X error(list->tl_head->t_line,"too many inline's");
- X return;
- X }
- X state = SDECL;
- X nextstate = -1;
- X node->i_line = line;
- X
- X lasttok = NILTOK;
- X for (tok = list->tl_head; tok != NILTOK; tok = tok->t_next) {
- X if (tok->t_tok == T_INLINE) {
- X break;
- X }
- X lasttok = tok;
- X }
- X if (tok == NILTOK) {
- X error(list->tl_head->t_line,"internal error in dodecl()");
- X return;
- X }
- X /* break the inline declaration off from the preceding stream */
- X if (lasttok) {
- X lasttok->t_next = NILTOK;
- X } else {
- X list->tl_head = NILTOK;
- X list->tl_tail = NILTOK;
- X }
- X for ( /* */ ; tok != NILTOK; tok = tok->t_next) {
- X /* put tokens on save list for possible dump later */
- X if (save) {
- X addtok(&node->i_text,duptok(mem,tok));
- X }
- X
- X if (nextstate >= 0) {
- X state = nextstate;
- X nextstate = -1;
- X }
- X if ((retstmt == 1) && (tok->t_tok != T_WS) &&
- X (tok->t_tok != T_SEMIC)) {
- X addtok(&node->i_tl[state], newtok(mem,T_RETVAL,NIL));
- X addtok(&node->i_tl[state], newtok(mem,T_WS," "));
- X addtok(&node->i_tl[state], newtok(mem,T_EQ,NIL));
- X addtok(&node->i_tl[state], newtok(mem,T_WS," "));
- X node->i_flags |= NEEDRETVAL;
- X retstmt++;
- X }
- X switch(tok->t_tok) {
- X
- X case T_INLINE:
- X continue;
- X
- X case T_LABEL:
- X if (state != SBODY) {
- X error(tok->t_line,"invalid label '%s:'",tok->t_id);
- X }
- X break;
- X
- X case T_IDENT:
- X /* an identifier, what state are we in? */
- X if (!structmember) {
- X doident(state, seenincdec, tok, node, mem);
- X }
- X structmember = 0;
- X seenincdec = 0;
- X break;
- X
- X case T_INC: case T_DEC:
- X seenincdec = 1;
- X break;
- X
- X case T_LPAREN:
- X if ((state == SDECL) && (tok->t_paren == 0) &&
- X (node->i_id != NIL)) {
- X state = SFORMAL;
- X }
- X break;
- X
- X case T_RPAREN:
- X if ((state == SFORMAL) && (tok->t_paren == 0)) {
- X nextstate = SOPARAMDECL;
- X }
- X break;
- X
- X case T_LBRACE:
- X if ((state == SFORMAL) || (state == SOPARAMDECL)) {
- X doformals(node);
- X state = SBODY;
- X nextstate = -1;
- X } else if (state != SBODY) {
- X error(tok->t_line,"no identifier found after 'inline'");
- X
- X /* rewrite node eliminating 'inline' */
- X }
- X seenincdec = 0;
- X break;
- X
- X case T_RBRACE:
- X if ((state == SBODY) && (tok->t_level == 0)) {
- X addtok(&node->i_tl[state], duptok(mem,tok));
- X if (sawretstmt) {
- X doretlab(&node->i_tl[state], node->i_id,mem);
- X }
- X /* add the extern or static decl for this */
- X if (forward_decl) {
- X struct toklist fdecl;
- X
- X putdecl(node,&fdecl);
- X if (lasttok) {
- X (void) instok(lasttok,fdecl.tl_head);
- X } else {
- X list->tl_head = fdecl.tl_head;
- X list->tl_tail = fdecl.tl_tail;
- X }
- X }
- X node->i_exprmem = openpool();
- X if (rewrite(node,&node->i_tl[SBODY],1) > 0) {
- X node->i_flags |= I_EXPR;
- X } else {
- X closepool(node->i_exprmem);
- X node->i_exprmem = -1;
- X }
- X if (debug) {
- X debugnode(node); /*DEBUG*/
- X }
- X return; /* this is the only way out */
- X }
- X seenincdec = 0;
- X break;
- X
- X case T_EXTERN:
- X case T_STATIC:
- X if (state == SDECL) {
- X node->i_storclass = tok->t_tok;
- X } else if (state != SBODY) {
- X error(tok->t_line,"illegal parameter declaration");
- X }
- X break;
- X
- X case T_ELLIPSES:
- X error(tok->t_line,"inline routines can't be varargs");
- X break;
- X
- X case T_RETURN:
- X addtok(&node->i_tl[state], t = newtok(mem,T_LBRACE,NIL));
- X t->t_level = tok->t_level;
- X retstmt = 1;
- X sawretstmt = 1;
- X seenincdec = 0;
- X continue;
- X
- X case T_SEMIC:
- X if ((state == SBODY) && retstmt) {
- X doreturn(&node->i_tl[state], node->i_id,mem);
- X retstmt = 0;
- X addtok(&node->i_tl[state], duptok(mem,tok));
- X addtok(&node->i_tl[state], t = newtok(mem,T_RBRACE,NIL));
- X t->t_level = tok->t_level;
- X continue;
- X }
- X seenincdec = 0;
- X break;
- X
- X case T_DOT:
- X case T_PTR:
- X structmember++;
- X break;
- X
- X default:
- X break;
- X }
- X
- X /* add the current token to the appropriate list */
- X addtok(&node->i_tl[state], duptok(mem,tok));
- X }
- X /*NOTREACHED*/
- X /* error(tok->t_line, "internal error in inline declaration"); */
- X}
- X
- Xdoident(state,seenincdec,tok,node, mem)
- Xint state, seenincdec;
- Xregister struct token *tok;
- Xregister struct inline_node *node;
- Xint mem;
- X{
- X register int i;
- X
- X switch(state) {
- X case SDECL: /* declaration */
- X if (node->i_id != NIL) {
- X error(tok->t_line, "too many identifiers on declaration line");
- X break;
- X }
- X if (isinline(tok->t_id)) {
- X error(tok->t_line, "redeclaration of inline '%s'", tok->t_id);
- X /* break; */
- X }
- X node->i_id = mkstr(mem,tok->t_id,0);
- X tok->t_tok = T_RETVAL;
- X break;
- X
- X case SFORMAL: /* formal parameter */
- X i = node->i_nformals++;
- X tok->t_tok = T_FORMAL;
- X node->i_formals[i] = mkstr(mem,tok->t_id,0);
- X break;
- X
- X case SOPARAMDECL: /* old-style param declaration */
- X if (isformal(node,tok) < 0) {
- X error(tok->t_line,"parameter '%s' not in formal list",tok->t_id);
- X } else {
- X tok->t_tok = T_FORMAL;
- X }
- X break;
- X case SBODY: /* found a formal in the body */
- X /*
- X * if an identifier in the body matches
- X * a formal, change it to be new formal name
- X *
- X * check to see if the formal is used as
- X * an lvalue, which prevents various
- X * optimizations we could otherwise perform
- X */
- X
- X if ((i = isformal(node,tok)) >= 0) {
- X tok->t_tok = T_FORMAL;
- X if (seenincdec || isassigned(tok)) {
- X node->i_formalinfo[i] |= I_LVALUE;
- X }
- X } else if ((strcmp(node->i_id,tok->t_id) == 0) && iscall(tok)) {
- X error(tok->t_line, "recursive inline expansion");
- X }
- X break;
- X default: /* somewhere else ?? */
- X break;
- X }
- X}
- X
- X
- Xdoreturn(list,id,mem)
- Xstruct toklist *list;
- Xchar *id;
- X{
- X addtok(list, newtok(mem,T_SEMIC, NIL));
- X addtok(list, newtok(mem,T_WS, " "));
- X addtok(list, newtok(mem,T_GOTO, NIL));
- X addtok(list, newtok(mem,T_WS, " "));
- X addtok(list, newtok(mem,T_RETLAB, NIL));
- X}
- X
- Xdoretlab(list,id,mem)
- Xstruct toklist *list;
- Xchar *id;
- Xint mem;
- X{
- X addtok(list, newtok(mem,T_WS,"\n"));
- X addtok(list, newtok(mem,T_RETLAB,NIL));
- X addtok(list, newtok(mem,T_COLON,NIL));
- X addtok(list, newtok(mem,T_SEMIC,NIL));
- X addtok(list, newtok(mem,T_WS,"\n"));
- X}
- X
- Xputdecl(node,decl)
- Xregister struct inline_node *node;
- Xregister struct toklist *decl;
- X{
- X register struct token *tl;
- X
- X decl->tl_head = decl->tl_tail = NILTOK;
- X
- X addtok(decl, newtok(node->i_mem,forward_decl,NIL));
- X
- X for(tl = node->i_tl[SDECL].tl_head; tl != NILTOK; tl = tl->t_next) {
- X addtok(decl,duptok(node->i_mem,tl));
- X if (tl->t_tok == T_RETVAL) {
- X decl->tl_tail->t_tok = T_IDENT;
- X }
- X }
- X addtok(decl, newtok(node->i_mem,T_LPAREN,NIL));
- X addtok(decl, newtok(node->i_mem,T_RPAREN,NIL));
- X addtok(decl, newtok(node->i_mem,T_SEMIC,NIL));
- X addtok(decl, newtok(node->i_mem,T_WS, " /* forward decl */\n"));
- X}
- X
- Xisassigned(tok)
- Xregister struct token *tok;
- X{
- X register struct token *t;
- X
- X for (t = tok; t != NILTOK; t = t->t_next) {
- X switch(t->t_tok) {
- X
- X case T_LPAREN: case T_RPAREN:
- X case T_WS: case T_COMMENT:
- X case T_FORMAL:
- X break;
- X
- X case T_EQ: case T_RS_EQ: case T_LS_EQ:
- X case T_ADD_EQ: case T_SUB_EQ: case T_MUL_EQ:
- X case T_DIV_EQ: case T_MOD_EQ: case T_AND_EQ:
- X case T_XOR_EQ: case T_OR_EQ:
- X case T_INC: case T_DEC:
- X case T_DOT: /* structure, no chances */
- X return(1);
- X
- X default:
- X return(0);
- X }
- X }
- X return(0);
- X}
- X
- X/*
- X * this is called when we see an opening brace indicating the beginning
- X * of the body of a function. we look through the stored function
- X * declaration, build up the formal parameter list, and rewrite the
- X * function declaration into a form that can be expanded inline:
- X *
- X * input: becomes:
- X *
- X * old-style:
- X * inline foo() { ... { ...
- X *
- X * inline foo(a,b,c) { ... { int a = T_ACTUAL,
- X * b = T_ACTUAL, c = T_ACTUAL;
- X * ...
- X *
- X * inline foo(a,b,c,d) { int a = T_ACTUAL;
- X * int a; float b; char c,d; float b = T_ACTUAL
- X * { ... char c = T_ACTUAL, d = T_ACTUAL;
- X * ...
- X * new-style:
- X * inline foo(int a, float b, char c) { {
- X * ... int a = T_ACTUAL;
- X * float b = T_ACTUAL;
- X * char c = T_ACTUAL;
- X * ...
- X *****
- X *
- X * NOTE:
- X *
- X * the above is how it would be done in the best of all possible worlds.
- X * in practice, it turns out to be easier to issue separate initializations
- X * for formals, like this:
- X *
- X * input: Becomes:
- X *
- X * inline foo(a,b) { ... { int a; int b;
- X * int foo_ret;
- X * a = T_ACTUAL; b = T_ACTUAL;
- X */
- X
- Xdoformals(node)
- Xregister struct inline_node *node;
- X{
- X register int new = 0;
- X register struct token *tl, *tok;
- X register struct toklist *paramdecl = &node->i_tl[SDECLBODY];
- X register int i;
- X int formal = -1;
- X int needsep = 0;
- X int gotformal[NFORMALS];
- X int parennest = 0;
- X int mem = node->i_mem;
- X
- X /* determine what style of function declaration it is */
- X /* an old style parameter declaration */
- X
- X tok = skipws(node->i_tl[SOPARAMDECL].tl_head);
- X
- X if (tok == NILTOK) {
- X /* nothing other than whitespace in here */
- X paramdecl->tl_head = node->i_tl[SOPARAMDECL].tl_head;
- X paramdecl->tl_tail = node->i_tl[SOPARAMDECL].tl_tail;
- X node->i_tl[SOPARAMDECL].tl_head = NILTOK;
- X node->i_tl[SOPARAMDECL].tl_tail = NILTOK;
- X }
- X
- X if (node->i_nformals == 0) {
- X /* no formal parameters */
- X return;
- X }
- X for (i = 0; i < NFORMALS; i++) {
- X gotformal[i] = 0;
- X }
- X
- X if (node->i_tl[SOPARAMDECL].tl_head == NILTOK) {
- X /* either new style prototype declaration or args are all int */
- X for (tl = node->i_tl[SFORMAL].tl_head; tl != NILTOK; tl = tl->t_next) {
- X /* we see something other than id's, commas */
- X /* and parens, it's new-style declaration */
- X switch(tl->t_tok) {
- X case T_FORMAL:
- X case T_LPAREN:
- X case T_COMMA:
- X case T_RPAREN:
- X /* it's a new-style prototype */
- X new++;
- X tl = node->i_tl[SFORMAL].tl_head;
- X break;
- X default:
- X continue;
- X }
- X break;
- X }
- X if (!new) { /* old style w/ args defaulted to int */
- X /* if it's old-style, then all args are 'int', so add that */
- X addtok(paramdecl,newtok(mem,T_INT,NIL));
- X addtok(paramdecl,newtok(mem,T_WS," "));
- X new = 1;
- X tl = node->i_tl[SFORMAL].tl_head;
- X }
- X } else {
- X /* loop through old-style param decl's, order them, and fill */
- X /* in those that have been defaulted */
- X for (tok = node->i_tl[SOPARAMDECL].tl_head; tok != NILTOK; tok = tok->t_next) {
- X if (tok->t_tok == T_FORMAL) {
- X if ((formal = isformal(node, tok)) >= 0) {
- X gotformal[formal] = 1;
- X } else {
- X error(tok->t_line, "parameter '%s' not in formal list",tok->t_id);
- X }
- X }
- X }
- X for (i = 0; i < node->i_nformals; i++) {
- X if (gotformal[i] == 0) {
- X addtok(&node->i_tl[SOPARAMDECL], newtok(mem,T_INT, NIL));
- X addtok(&node->i_tl[SOPARAMDECL], newtok(mem,T_WS, " "));
- X addtok(&node->i_tl[SOPARAMDECL], newtok(mem,T_FORMAL, node->i_formals[i]));
- X addtok(&node->i_tl[SOPARAMDECL], newtok(mem,T_SEMIC, NIL));
- X addtok(&node->i_tl[SOPARAMDECL], newtok(mem,T_WS, " "));
- X gotformal[i] = 1;
- X }
- X }
- X tl = node->i_tl[SOPARAMDECL].tl_head;
- X }
- X
- X
- X /*
- X * loop through the formal declaration token list (or old style
- X * parameter declaration list, if applicable)
- X */
- X for ( /* tl init above */ ; tl != NILTOK; tl = tl->t_next) {
- X switch(tl->t_tok) {
- X case T_LPAREN:
- X if ((++parennest == 1) && new) {
- X continue;
- X }
- X break;
- X
- X case T_SEMIC:
- X needsep = 0;
- X if (new) {
- X error(tl->t_line, "unexpected semicolon in new-style parameter list");
- X }
- X /*FALLTHROUGH*/
- X case T_RPAREN:
- X if (tl->t_tok == T_RPAREN) {
- X if (parennest >= 1) {
- X parennest--;
- X } else {
- X error(tl->t_line, "rparen error");
- X break;
- X }
- X if (new && (parennest > 0)) {
- X break;
- X }
- X }
- X /*FALLTHROUGH*/
- X case T_COMMA:
- X if (formal >= 0) { /* seen a comma or semi-colon */
- X
- X formal = -1;
- X /* haven't added the comma or semicolon */
- X if (tl->t_tok == T_SEMIC) {
- X addtok(paramdecl, newtok(mem,T_SEMIC, NIL));
- X } else {
- X needsep = 1;
- X }
- X continue;
- X }
- X break; /* go ahead and add the token */
- X
- X case T_FORMAL:
- X if (needsep) {
- X addtok(paramdecl,newtok(mem,T_COMMA,NIL));
- X needsep = 0;
- X }
- X addtok(paramdecl, tok = duptok(mem,tl));
- X if ((formal = isformal(node,tl)) < 0) {
- X error(tl->t_line,"parameter '%s' not in formals list", tl->t_id);
- X }
- X continue;
- X
- X default:
- X break;
- X }
- X if (needsep) {
- X if (istype(tl) || isstoreclass(tl)) {
- X addtok(paramdecl,newtok(mem,T_SEMIC,NIL));
- X needsep = 0;
- X } else if (tl->t_tok == T_STAR) {
- X addtok(paramdecl,newtok(mem,T_COMMA,NIL));
- X needsep = 0;
- X }
- X }
- X addtok(paramdecl, tok = duptok(mem,tl));
- X /* don't put other tokens in init list */
- X }
- X if (needsep) {
- X addtok(paramdecl,newtok(mem,T_SEMIC,NIL));
- X }
- X addtok(paramdecl,newtok(mem,T_WS,"\n"));
- X return;
- X}
- X/*
- X * return true if the argument tok is in the formal parameter list
- X */
- X
- Xisformal(node,tok)
- Xregister struct inline_node *node;
- Xregister struct token *tok;
- X{
- X register int i;
- X
- X for(i=0; i < node->i_nformals; i++) {
- X if (strcmp(tok->t_id, node->i_formals[i]) == 0) {
- X return(i);
- X }
- X }
- X return(-1);
- X}
- X
- Xisdecl(tl)
- Xregister struct toklist *tl;
- X{
- X register struct token *tok;
- X
- X for (tok = tl->tl_head; tok != NILTOK; tok = tok->t_next) {
- X if (tok->t_tok == T_INLINE) {
- X return(1);
- X }
- X }
- X return(0);
- X}
- X
- X
- X/*
- X * process a typedef line
- X *
- X * typedefs take the general form:
- X *
- X * typedef base_type new_type;
- X *
- X * however, one must watch for situations like:
- X *
- X * typedef int newtype[DEFINE];
- X * typedef struct { int a; int b } newtype;
- X *
- X * so the trick needs to be that the new type is the last identifier
- X * not embedded in braces or brackets;
- X */
- X
- Xdotypedef(begin)
- Xregister struct token *begin;
- X{
- X register struct token *lastid = NILTOK;
- X register struct token *tl;
- X register char **p;
- X int level = -1;
- X int needbrack = 0;
- X
- X for (tl = begin; tl != NILTOK; tl = tl->t_next) {
- X if (tl->t_tok == T_TYPEDEF) {
- X if (level >= 0) {
- X error(tl->t_line, "typedef within typedef");
- X return;
- X }
- X level = tl->t_level;
- X if ((level > NSCOPE) || (typeid[level] == NILP(struct typelist *))) {
- X error(tl->t_line, "bad level in dotypedef");
- X return;
- X }
- X continue;
- X }
- X if ((tl->t_tok == T_SEMIC) && (tl->t_level == level)) {
- X break;
- X }
- X if (tl->t_tok == T_LSQ) {
- X needbrack++;
- X continue;
- X }
- X if (needbrack) {
- X if (tl->t_tok == T_RSQ) {
- X needbrack--;
- X }
- X continue;
- X }
- X if ((tl->t_tok == T_IDENT) && (tl->t_level == level)) {
- X lastid = tl;
- X }
- X }
- X if (tl->t_tok != T_SEMIC) {
- X error(tl->t_line, "dotypedef terminated abnormally");
- X }
- X if (level < 0) {
- X error(tl->t_line, "internal error in dotypedef");
- X return;
- X }
- X if (lastid) {
- X lastid->t_tok = T_TYPE_ID;
- X for (p = typeid[level]->type_id; *p != NIL; p++) {
- X if (strcmp(lastid->t_id,*p) == 0) {
- X error(tl->t_line, "redeclaration of %s",*p);
- X }
- X }
- X if ((p-typeid[level]->type_id) < NTYPEDEF) {
- X *p = mkstr(typeid[level]->type_mem,lastid->t_id,0);
- X } else {
- X error(tl->t_line, "too many typedefs at scope level %d", level);
- X }
- X }
- X}
- X
- \Rogue\Monster\
- else
- echo "will not over write ./declare.c"
- fi
- chmod 444 ./declare.c
- if [ `wc -c ./declare.c | awk '{printf $1}'` -ne 15931 ]
- then
- echo `wc -c ./declare.c | awk '{print "Got " $1 ", Expected " 15931}'`
- fi
- echo "Finished archive 3 of 3"
- # if you want to concatenate archives, remove anything after this line
- exit
-