home *** CD-ROM | disk | FTP | other *** search
- Subject: v11i041: Inline code expander for C, Part03/04
- Newsgroups: comp.sources.unix
- Sender: sources
- Approved: rs@uunet.UU.NET
-
- Submitted-by: omepd!mcg
- Posting-number: Volume 11, Issue 41
- Archive-name: inline/Part03
-
- # 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:
- # ./expand.c
- # ./rewrite.c
- # ./yylex.c
- # ./tokens.c
- # ./utils.c
- # ./mem.c
- #
- if `test ! -s ./expand.c`
- then
- echo "writing ./expand.c"
- sed 's/^X//' > ./expand.c << '\Rogue\Monster\'
- X/*
- X * inline code expander
- X *
- X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
- X */
- X
- X/* $Header: expand.c,v 1.13 87/06/24 13:11:24 mcg Rel $ */
- X
- X/*
- X * find an expansion opportunity, get its parameters, and expand the node
- X */
- X
- X#include "inline.h"
- X#include "tokens.h"
- X
- Xextern struct expand_node *mkenode(); /* forward declaration */
- Xextern struct expand_node *doactuals();
- Xextern struct token *dostmt();
- Xextern struct token *doexpr();
- X
- Xdoinline(mem,prog)
- Xregister int mem;
- Xregister struct toklist *prog;
- X{
- X register struct token *tt, *tl, *tx;
- X register struct token *begin = NILTOK;
- X register struct token *end;
- X register struct expand_node *e;
- X register struct inline_node *node;
- X register int i;
- X register int emem;
- X int expanded = 0;
- X
- X /*
- X * look through list to find first expansion possibility,
- X * keeping track of statement breaks. a statement break occurs
- X * at the last semicolon, closing brace, or opening brace. expansions
- X * inside control statements complicate matters
- X */
- X
- X emem = openpool();
- X tt = NILTOK;
- X for (tl = prog->tl_head; tl != NILTOK; tt = tl, tl = tl->t_next) {
- X switch(tl->t_tok) {
- X case T_IDENT:
- X if (iscall(tl) && (node = isinline(tl->t_id))) {
- X node->i_nseen++;
- X
- X /* don't expand if this expression has ||, && */
- X /* or ?: --- should not expand if there's a */
- X /* comma operator, but can't identify those */
- X /* easily */
- X
- X for (tx = begin; tx && tx != tl; tx = tx->t_next) {
- X if (tx->t_tok == T_CAND ||
- X tx->t_tok == T_COR ||
- X tx->t_tok == T_QUEST) {
- X if (node->i_flags&I_EXPR) {
- X tl->t_flags |= TNEEDEXPR;
- X } else {
- X tl->t_flags |= TNOEXPAND;
- X warn(tl->t_line,"inline %s is not expandable in this context", tl->t_id);
- X }
- X }
- X }
- X if (tl->t_flags&TNOEXPAND) {
- X break;
- X }
- X
- X if ((e = doactuals(emem,tt,node)) == NILP(struct expand_node *)) {
- X /* don't expand again */
- X tl->t_flags |= TNOEXPAND;
- X warn(tl->t_line,"inline %s is not expandable in this context", tl->t_id);
- X } else {
- X
- X end = dostmt(begin->t_next,0);
- X if (doexpand(mem,begin,end,tt->t_next,tl->t_flags&TNEEDEXPR,e)) {
- X node->i_nexpand++;
- X tl = begin;
- X expanded++;
- X }
- X }
- X }
- X break;
- X
- X case T_IF:
- X case T_SWITCH:
- X begin = tt; /* point to node before */
- X break;
- X
- X case T_WHILE:
- X case T_FOR:
- X /* skip over control part */
- X end = dostmt(tl,1);
- X i = 0;
- X for (tx = tl->t_next; tx != end; tx = tx->t_next) {
- X if (iscall(tx) && (node = isinline(tx->t_id))) {
- X node->i_nseen++;
- X if (node->i_flags&I_EXPR) {
- X tx->t_flags |= TNEEDEXPR;
- X i = 1;
- X } else {
- X warn(tx->t_line,"inline %s is not expandable in this context", tx->t_id);
- X tx->t_flags |= TNOEXPAND;
- X }
- X }
- X }
- X /* no expansion possibility inside for, while */
- X if (i) {
- X begin = tt;
- X } else {
- X begin = tl = end;
- X }
- X break;
- X
- X case T_COLON:
- X /* distinguish between label and ? : op */
- X for (tx = begin; tx != tl; tx = tx->t_next) {
- X if (tx->t_tok == T_QUEST) {
- X break;
- X }
- X }
- X if (tx->t_tok == T_QUEST) {
- X break;
- X }
- X /*FALLTHROUGH*/
- X
- X case T_SEMIC:
- X case T_LBRACE:
- X case T_RBRACE:
- X begin = tl;
- X break;
- X
- X default:
- X if (istype(tl) || isstoreclass(tl)) {
- X end = dostmt(tl->t_next,0);
- X for (tx = tl->t_next; tx != end; tx = tx->t_next) {
- X if (iscall(tx) && (node = isinline(tx->t_id))) {
- X node->i_nseen++;
- X tx->t_flags |= TNOEXPAND;
- X warn(tx->t_line,"inline %s is not expandable in this context", tx->t_id);
- X }
- X }
- X /* no expansion in initializations */
- X begin = tl = end;
- X }
- X break;
- X }
- X }
- X (void) closepool(emem);
- X return(expanded);
- X}
- X
- Xstruct token *
- Xdostmt(begin,ctrl)
- Xregister struct token *begin;
- Xregister int ctrl;
- X{
- X register struct token *tx;
- X register int seenquest = 0;
- X
- X begin = skipws(begin);
- X while (begin) {
- X switch(begin->t_tok) {
- X case T_SWITCH:
- X case T_WHILE:
- X case T_FOR:
- X case T_IF:
- X /* find end of control part */
- X tx = doexpr(begin->t_next,1);
- X if (ctrl) {
- X return(tx);
- X }
- X /* find end of body */
- X tx = dostmt(tx->t_next,0);
- X
- X if (begin->t_tok == T_IF) {
- X /* look for 'else' */
- X begin = skipws(tx->t_next);
- X if (begin->t_tok == T_ELSE) {
- X return(dostmt(begin,0));
- X }
- X }
- X return(tx);
- X
- X case T_ELSE:
- X return(dostmt(begin->t_next,0));
- X
- X case T_LBRACE:
- X for (tx = begin; tx != NILTOK; tx = tx->t_next) {
- X if ((tx->t_tok == T_RBRACE) &&
- X (tx->t_level == begin->t_level)) {
- X return(tx);
- X }
- X }
- X error(begin->t_line,"unmatched {");
- X break;
- X
- X case T_SEMIC:
- X return(begin);
- X
- X case T_COLON:
- X if (seenquest--) {
- X begin = begin->t_next;
- X continue;
- X }
- X return(begin);
- X
- X case T_QUEST:
- X seenquest++;
- X default:
- X begin = begin->t_next;
- X continue;
- X }
- X /* if we get here, it's an error */
- X break;
- X }
- X error(begin->t_line, "statement termination error");
- X return(NILTOK);
- X}
- X
- Xstruct token *
- Xdoexpr(begin,ctrl)
- Xregister struct token *begin;
- Xregister int ctrl;
- X{
- X register int seenquest = 0;
- X register struct token *tx;
- X
- X begin = skipws(begin);
- X while (begin) {
- X switch(begin->t_tok) {
- X case T_LPAREN:
- X for(tx = begin; tx != NILTOK; tx = tx->t_next) {
- X if ((tx->t_tok == T_RPAREN) &&
- X (tx->t_paren == begin->t_paren)) {
- X if (ctrl) {
- X return(tx);
- X } else {
- X begin = begin->t_next;
- X continue;
- X }
- X }
- X }
- X error(begin->t_line, "unmatched parenthesis");
- X break;
- X
- X case T_WHILE:
- X case T_FOR:
- X case T_SWITCH:
- X case T_IF:
- X break;
- X
- X
- X case T_RBRACE:
- X case T_LBRACE:
- X case T_SEMIC:
- X return(begin);
- X
- X case T_QUEST:
- X seenquest++;
- X begin = begin->t_next;
- X continue;
- X
- X case T_COLON:
- X if (seenquest--) {
- X return(begin);
- X }
- X default:
- X begin = begin->t_next;
- X continue;
- X }
- X /* if we get here, it's an error */
- X break;
- X }
- X error(begin->t_line, "expression error");
- X return(NILTOK);
- X}
- X
- Xdoexpand(mem,begin,end,here,expr,enode)
- Xregister int mem;
- Xregister int expr;
- Xregister struct token *begin, *end, *here;
- Xregister struct expand_node *enode;
- X{
- X struct toklist insert;
- X register struct token *tl, *tx, *th, *tp;
- X register struct inline_node *node;
- X register int formal;
- X register int i;
- X static int ident = 0;
- X
- X if ((here->t_tok != T_ARGLIST) || !(node = isinline(here->t_id))) {
- X error(here->t_line, "bad call to doexpand '%s' not inline",
- X here->t_id);
- X return(0);
- X }
- X if (expr && !node->i_flags&I_EXPR) {
- X error(here->t_line, "bad call to doexpand '%s' not inline",
- X here->t_id);
- X return(0);
- X }
- X
- X insert.tl_head = insert.tl_tail = NILTOK;
- X
- X addtok(&insert, newtok(mem,T_WS, "\n"));
- X addtok(&insert, newtok(mem,T_LBRACE, NIL));
- X addtok(&insert, newtok(mem,T_WS, "\n"));
- X
- X /* output declaration sections for each inline */
- X /* declare formal parameters */
- X
- X cpytoklist(mem,&insert,&node->i_tl[SDECLBODY]);
- X if (expr) {
- X cpytoklist(mem,&insert,&node->i_tl[SEXPRDECL]);
- X }
- X
- X for(tx = insert.tl_head; tx != NILTOK; tx = tx->t_next) {
- X if (tx->t_tok == T_FORMAL) {
- X tx->t_flags |= TNOEXPAND;
- X }
- X }
- X
- X /* declare return value holders */
- X
- X if (node->i_flags&NEEDRETVAL) {
- X addtok(&insert, newtok(mem,T_AUTO,NIL));
- X addtok(&insert, newtok(mem,T_WS, " "));
- X
- X /* cpytoklist(mem, &insert, &node->i_tl[SDECL]); */
- X
- X /*
- X * this is a hack to rewrite function pointers found in
- X * declaration form, e.g:
- X * int (*(*fp())())() {} [1]
- X * int (*fp())() {} [2]
- X * into pointer declaration form:
- X * int (*(*fp)())(); [1]
- X * int (*fp)(); [2]
- X *
- X * we do this by putting an RPAREN immediately after the
- X * identifier, and then deleting the next RPAREN of the
- X * appropriate nesting level.
- X *
- X * thanks to the bizarre syntax of C for this one
- X */
- X
- X {
- X int plev = -1;
- X for(tp = node->i_tl[SDECL].tl_head;tp != NILTOK; tp = tp->t_next) {
- X if (tp->t_tok == T_RPAREN && tp->t_paren == plev) {
- X plev = -1;
- X continue;
- X }
- X if ((tp->t_tok == T_LPAREN) && (tp->t_paren > 0) &&
- X (tp->t_next->t_tok == T_RPAREN)) {
- X addtok(&insert,newtok(mem,T_RPAREN,NIL));
- X plev = tp->t_paren - 1;
- X }
- X addtok(&insert,duptok(mem,tp));
- X }
- X }
- X
- X /* end of hack */
- X
- X addtok(&insert, newtok(mem,T_SEMIC,NIL));
- X addtok(&insert, newtok(mem,T_WS, "\n"));
- X }
- X
- X /* determine which actuals can be substituted directly, and */
- X /* which need to be copied in -- if the formal is never used */
- X /* as an lvalue in the expanded routine, and if the actual */
- X /* doesn't have any side-effects of referencing it, then it is */
- X /* ok to replace instances of the formal with the actual string */
- X
- X /* output initialization */
- X /* ... but only for those not sub'd directly */
- X
- X /* cpytoklist(mem,&insert,&node->i_tl[SINITBODY]); */
- X
- X for (i = 0; i < node->i_nformals; i++) {
- X node->i_formalinfo[i] &= ~I_SUB_OK;
- X if ((node->i_formalinfo[i]&I_LVALUE) ||
- X (sideeffect(&enode->e_actuals[i]))) {
- X addtok(&insert,newtok(mem,T_FORMAL,node->i_formals[i]));
- X /* addtok(&insert,newtok(mem,T_EQ,NIL)); */
- X addtok(&insert,newtok(mem,T_ACTUAL,node->i_formals[i]));
- X addtok(&insert,newtok(mem,T_SEMIC,NIL));
- X addtok(&insert,newtok(mem,T_WS," "));
- X } else {
- X /* this actual can be sub'd directly */
- X node->i_formalinfo[i] |= I_SUB_OK;
- X }
- X }
- X
- X /* output body */
- X
- X
- X here->t_tok = T_WS;
- X here->t_id = "";
- X
- X if (expr) {
- X (void) instok(begin, insert.tl_head);
- X insert.tl_head = insert.tl_tail = NILTOK;
- X cpytoklist(mem,&insert,&node->i_tl[SEXPRBODY]);
- X (void) instok(here, insert.tl_head);
- X } else {
- X cpytoklist(mem,&insert,&node->i_tl[SBODY]);
- X if (node->i_flags&NEEDRETVAL) {
- X here->t_tok = T_IDENT;
- X here->t_id = mkstr(mem,"_",node->i_id,"_ret_",itoa(ident),"_",0);
- X }
- X (void) instok(begin, insert.tl_head);
- X }
- X
- X tl = instok(end, newtok(mem,T_RBRACE, NIL));
- X end = instok(tl, newtok(mem,T_WS, "\n"));
- X
- X /* go back and fix up all the special stuff */
- X
- X for(tp = NILTOK,tx = begin; tx && tx != end; tp = tx,tx = tx->t_next) {
- X switch(tx->t_tok) {
- X case T_RETLAB:
- X tx->t_tok = T_IDENT;
- X tx->t_id = mkstr(mem,"_",node->i_id,"_end_",itoa(ident),"_",0);
- X break;
- X
- X case T_RETVAL:
- X tx->t_tok = T_IDENT;
- X tx->t_id = mkstr(mem,"_",node->i_id,"_ret_",itoa(ident),"_",0);
- X break;
- X
- X case T_FORMAL:
- X if ((formal = isformal(node,tx)) < 0) {
- X error(tx->t_line,"bogus formal");
- X break;
- X }
- X if ((node->i_formalinfo[formal]&I_SUB_OK) && !(tx->t_flags&TNOEXPAND)) {
- X insert.tl_head = insert.tl_tail = NILTOK;
- X addtok(&insert,newtok(mem,T_LPAREN,NIL));
- X cpytoklist(mem,&insert,&enode->e_actuals[formal]);
- X addtok(&insert,newtok(mem,T_RPAREN,NIL));
- X tp->t_next = tx->t_next; /* drop formal node */
- X (void) instok(tp, insert.tl_head);
- X
- X } else {
- X tx->t_tok = T_IDENT;
- X tx->t_id = mkstr(mem,"_",node->i_id,"_",tx->t_id,"_",itoa(ident),0);
- X tx->t_flags &= ~TNOEXPAND;
- X }
- X break;
- X
- X case T_ACTUAL:
- X if ((formal = isformal(node,tx)) < 0) {
- X error(tx->t_line,"actual-formal mismatch");
- X break;
- X }
- X insert.tl_head = insert.tl_tail = NILTOK;
- X addtok(&insert, newtok(mem,T_WS, " "));
- X addtok(&insert, newtok(mem,T_EQ, NIL));
- X addtok(&insert, newtok(mem,T_WS, " "));
- X cpytoklist(mem,&insert,&enode->e_actuals[formal]);
- X tp->t_next = tx->t_next; /* drop formal node */
- X (void) instok(tp, insert.tl_head);
- X
- X break;
- X
- X case T_LABEL:
- X tx->t_id = mkstr(mem,"_",node->i_id,"_",tx->t_id,"_",itoa(ident),0);
- X break;
- X }
- X }
- X
- X /* update expansion identifier digit */
- X ident++;
- X
- X return(1);
- X}
- X
- X/*
- X * begin an inline expansion by gathering actual arguments
- X */
- X
- Xstruct expand_node *
- Xdoactuals(mem,prog,node)
- Xregister int mem;
- Xstruct token *prog;
- Xstruct inline_node *node;
- X{
- X register struct token *tl;
- X int paramnest = 0;
- X register struct toklist *subparam;
- X struct expand_node *e;
- X int sawtok = 0;
- X
- X for (tl = prog->t_next; tl != NILTOK; tl = tl->t_next) {
- X if (tl->t_tok == T_LPAREN)
- X break;
- X }
- X
- X if (!tl) { /* error */
- X error(prog->t_line, "gack!! lost '(' in doactuals()");
- X return(NILP(struct expand_node *));
- X }
- X
- X /* setup an expansion node for this expansion */
- X
- X e = mkenode(mem);
- X e->e_node = node;
- X subparam = e->e_actuals;
- X
- X /* store the actuals away in the expansion node */
- X
- X for ( ; tl != NILTOK; tl = tl->t_next) {
- X /* gather the actual parameter list */
- X switch(tl->t_tok) {
- X case T_LPAREN:
- X if (paramnest++ == 0) {
- X /* don't add the paren */
- X continue;
- X }
- X break;
- X
- X case T_RPAREN:
- X if (paramnest == 0) {
- X error(tl->t_line, "bad parameter list - too many ')'s");
- X return(NILP(struct expand_node *));
- X }
- X if (--paramnest == 0) { /* end of parameter list */
- X if (sawtok) {
- X e->e_nactuals++;
- X }
- X if (e->e_nactuals != node->i_nformals) {
- X error(tl->t_line, "wrong number of actuals to inline func %s", node->i_id);
- X return(NILP(struct expand_node *));
- X }
- X /* replace to argument list with the ARGLIST token */
- X prog->t_next = newtok(mem,T_ARGLIST,e->e_node->i_id);
- X prog->t_next->t_next = tl->t_next;
- X
- X return(e);
- X }
- X break;
- X
- X case T_COMMA:
- X if (paramnest == 1) {
- X subparam++;
- X e->e_nactuals++;
- X sawtok = 0;
- X /* don't include the comma */
- X continue;
- X }
- X break;
- X }
- X if (paramnest) {
- X sawtok = 1;
- X addtok(subparam,duptok(mem,tl));
- X }
- X }
- X /* hmm, got an EOF */
- X error(prog->t_line, "improper call - EOF during arg gathering");
- X return(NILP(struct expand_node *));
- X}
- X
- Xstruct expand_node *
- Xmkenode(mem) {
- X register struct expand_node *e;
- X register int i;
- X
- X e = (struct expand_node *) getmem(mem,1,sizeof(struct expand_node));
- X
- X e->e_node = NILP(struct inline_node *);
- X e->e_multiple = 0; /* more than one call to this inline */
- X for (i = 0; i < NFORMALS; i++) {
- X e->e_actuals[i].tl_head = NILTOK;
- X e->e_actuals[i].tl_tail = NILTOK;
- X }
- X e->e_nactuals = 0;
- X return(e);
- X}
- X
- Xsideeffect(tl)
- Xregister struct toklist *tl;
- X{
- X register struct token *t,*tp;
- X
- X tp = NILTOK;
- X for (t = tl->tl_head; t != NILTOK; t = t->t_next) {
- X switch(t->t_tok) {
- 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 return(1);
- X
- X case T_LPAREN:
- X /* function call */
- X /* catches "fp(x)", "(*fp)(x)", "fp[foo](x)" */
- X if (tp && (
- X (tp->t_tok == T_IDENT) ||
- X (tp->t_tok == T_RPAREN) ||
- X (tp->t_tok == T_RSQ)
- X )) {
- X return(1);
- X }
- X break;
- X
- X case T_LBRACE: case T_RBRACE:
- X error(tp->t_line, "brace in actual argument", 0);
- X return(1);
- X
- X case T_WS: case T_COMMENT:
- X break;
- X
- X default:
- X if (istype(t)) { /* must be a cast */
- X return(1); /* ???? */
- X }
- X tp = t; /* save previous non-ws token */
- X break;
- X }
- X if (t == tl->tl_tail) {
- X break;
- X }
- X }
- X return(0);
- X}
- X
- \Rogue\Monster\
- else
- echo "will not over write ./expand.c"
- fi
- chmod 444 ./expand.c
- if [ `wc -c ./expand.c | awk '{printf $1}'` -ne 14621 ]
- then
- echo `wc -c ./expand.c | awk '{print "Got " $1 ", Expected " 14621}'`
- fi
- if `test ! -s ./rewrite.c`
- then
- echo "writing ./rewrite.c"
- sed 's/^X//' > ./rewrite.c << '\Rogue\Monster\'
- X/*
- X * inline code expander - rewrite a procedure into an expression if possible
- X *
- X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
- X */
- X
- X/* $Header: rewrite.c,v 1.3 87/05/12 10:53:05 mcg Rel $ */
- X
- X#include "inline.h"
- X#include "tokens.h"
- X
- Xextern struct token *dostmt(); /* see expand.c */
- Xextern struct token *doexpr(); /* see expand.c */
- X
- X
- X/*
- X * This module takes arbitrary sequences of C statements (assumed to be
- X * the output of the inline declaration process), and rewrites them, if
- X * possible, in an expression form, depositing the result in the
- X * appropriate place (i_tl[SEXPRBODY]) in the inline node structure.
- X *
- X * This is done, fundamentally, by replacing semicolons with commas,
- X * and deleting if's, following if conditional expressions with '?', and
- X * replacing else's with ':'. Clearly, it is somewhat more complex than
- X * that, but most of the difficulty merely comes in keeping one's
- X * parentheses matched.
- X *
- X * One subtlety is that local declarations need to be factored out,
- X * except that if they contain initializations, the initializations need
- X * to be separated from the declarations and prepended to the expression
- X * list. This is handled by the routine coalesce(). Coalesce() also
- X * needs to handle name conflicts caused by local variables declared in
- X * inner scopes when it is moving these to outer scopes.
- X *
- X * If rewrite() finds a statement that it can't rewrite into an expression
- X * (this class consists entirely of loops (while(), for()), goto's, and
- X * switch statements, and the break's and continue's that go along with
- X * these), then it returns -1, and the calling routine (declare.c:dodecl())
- X * frees the memory pool associated with it.
- X */
- X
- X
- Xstatic int saw_innerret = 0;
- X
- X
- X/* turn a basic block into an expression */
- X
- Xrewrite(node,tl,toplevel)
- Xregister struct inline_node *node;
- Xregister struct toklist *tl;
- Xregister int toplevel;
- X{
- X register struct token *tx, *tt;
- X register struct token *estart; /* start of current expression */
- X register struct token *bstart; /* start of this block */
- X register struct token *last = NILTOK;
- X struct toklist *expr = &node->i_tl[SEXPRBODY];
- X register int mem = node->i_exprmem;
- X struct toklist block;
- X register int inblock = 0;
- X register int ntok = 0;
- X int saw_topret = 0;
- X int nonempty = 0;
- X
- X
- X /* skip over leading whitespace */
- X
- X tx = skipws(tl->tl_head);
- X if (tx->t_tok == T_LBRACE) {
- X inblock++;
- X }
- X if (toplevel) {
- X addtok(expr,last = bstart = estart = newtok(mem,T_WS,""));
- X saw_innerret = 0;
- X } else {
- X bstart = estart = expr->tl_tail;
- X }
- X
- X for( ; tx && tx != tl->tl_tail; last = tx, tx = tx->t_next) {
- X if (istype(tx) || isstoreclass(tx)) {
- X /* local definition block */
- X block.tl_head = tx;
- X tx = block.tl_tail = dostmt(tx,0);
- X
- X if (tx->t_tok != T_SEMIC) {
- X /* weird */
- X return(-1);
- X }
- X
- X if (ntok = coalesce(node,&block)) {
- X nonempty++;
- X }
- X }
- X
- X
- X switch(tx->t_tok) {
- X case T_CONTINUE:
- X case T_BREAK:
- X /*FALLTHROUGH*/
- X case T_WHILE:
- X case T_FOR:
- X case T_SWITCH:
- X return(-1);
- X
- X case T_RBRACE:
- X if (inblock && tx->t_level == tl->tl_head->t_level) {
- X goto end;
- X }
- X /*FALLTHROUGH*/
- X
- X case T_LBRACE:
- X break;
- X
- X case T_GOTO:
- X /* if it's not a rewritten return(), it's an error */
- X if (tx->t_next->t_next->t_tok == T_RETLAB) {
- X tx = dostmt(tx,0);
- X break;
- X }
- X return(-1);
- X
- X case T_IF:
- X block.tl_head = skipws(tx->t_next);
- X block.tl_tail = doexpr(block.tl_head,1);
- X
- X /* copy control part */
- X cpytoklist(mem,expr,&block);
- X
- X addtok(expr,newtok(mem,T_QUEST,NIL));
- X addtok(expr,newtok(mem,T_WS," "));
- X
- X block.tl_head = skipws(block.tl_tail->t_next);
- X block.tl_tail = dostmt(block.tl_head,0);
- X
- X if ((ntok = rewrite(node,&block,0)) < 0) {
- X return(-1);
- X }
- X /* if no tokens added - i.e. empty block */
- X if (ntok == 0) {
- X addtok(expr,newtok(mem,T_NUM,"0"));
- X }
- X
- X addtok(expr,newtok(mem,T_COLON,NIL));
- X addtok(expr,newtok(mem,T_WS," "));
- X
- X tx = skipws(block.tl_tail->t_next);
- X if (tx && tx != tl->tl_tail) {
- X if (tx->t_tok != T_ELSE) {
- X /* no else - treat rest of block like else */
- X block.tl_head = tx;
- X tx = block.tl_tail = tl->tl_tail;
- X if ((ntok = rewrite(node,&block,0)) < 0) {
- X return(-1);
- X }
- X } else {
- X block.tl_head = skipws(tx->t_next);
- X tx = block.tl_tail = dostmt(block.tl_head,0);
- X if ((ntok = rewrite(node,&block,0)) < 0) {
- X return(-1);
- X }
- X }
- X } else {
- X ntok = 0;
- X }
- X /* if no tokens added - i.e. empty block */
- X if (ntok == 0) {
- X addtok(expr,newtok(mem,T_NUM,"0"));
- X }
- X ntok = 1;
- X nonempty++;
- X /*FALLTHROUGH*/
- X
- X case T_SEMIC:
- X if (ntok == 0) {
- X break;
- X }
- X /* if there was a preceding expression, insert a comma */
- X if (estart && estart->t_tok == T_RPAREN) {
- X instok(estart,tt = newtok(mem,T_COMMA,NIL));
- X estart = tt;
- X }
- X
- X /* wrap some parens around the expression itself */
- X instok(estart,newtok(mem,T_LPAREN,NIL));
- X addtok(expr,newtok(mem,T_RPAREN,NIL));
- X
- X /* ... and around the whole expression so far */
- X if (bstart && bstart != expr->tl_head) {
- X instok(bstart,newtok(mem,T_LPAREN,NIL));
- X addtok(expr,newtok(mem,T_RPAREN,NIL));
- X }
- X estart = expr->tl_tail;
- X bstart = bstart->t_next;
- X ntok = 0;
- X nonempty++;
- X if (debug >= 9) {
- X fprintf(stderr,"> ");
- X prtoklist(expr,0,stderr);
- X fprintf(stderr,"\n");
- X }
- X break;
- X
- X case T_WS:
- X if (last && last->t_tok != T_WS &&
- X last->t_tok != T_RPAREN &&
- X last->t_tok != T_LPAREN) {
- X addtok(expr,newtok(mem,T_WS," "));
- X }
- X break;
- X
- X case T_RETVAL:
- X if (toplevel) {
- X saw_topret++;
- X for ( ; tx && tx != tl->tl_tail; tx = tx->t_next) {
- X if (tx->t_tok == T_EQ) {
- X break;
- X }
- X }
- X break;
- X } else {
- X saw_innerret++;
- X }
- X /*FALLTHROUGH*/
- X default:
- X addtok(expr,duptok(mem,tx));
- X ntok++;
- X nonempty++;
- X break;
- X }
- X }
- X end:
- X if (toplevel) {
- X if (saw_innerret == 0 && saw_topret == 0) {
- X /* no returns, must be void */
- X return(-1);
- X }
- X if (saw_innerret) {
- X if (expr->tl_head != expr->tl_tail) {
- X addtok(expr,newtok(mem,T_COMMA,NIL));
- X }
- X addtok(expr,newtok(mem,T_RETVAL,NIL));
- X }
- X instok(expr->tl_head,newtok(mem,T_LPAREN,NIL));
- X addtok(expr,newtok(mem,T_RPAREN,NIL));
- X fixparens(expr,0,0);
- X }
- X if (debug >= 9) {
- X fprintf(stderr,"% ");
- X prtoklist(expr,0,stderr);
- X fprintf(stderr,"\n");
- X }
- X return(nonempty);
- X}
- X
- X
- Xcoalesce(node,tl)
- Xregister struct inline_node *node;
- Xregister struct toklist *tl;
- X{
- X register struct token *tx, *ts, *estart, *bstart;
- X struct toklist *expr = &node->i_tl[SEXPRBODY];
- X struct toklist *exprdecl = &node->i_tl[SEXPRDECL];
- X register int mem = node->i_exprmem;
- X int initializer = 0;
- X int ntok = 0;
- X
- X bstart = expr->tl_tail;
- X
- X /* copy up to an '=' or ';' */
- X for(tx = tl->tl_head; tx && tx != tl->tl_tail->t_next; tx = tx->t_next) {
- X if (!initializer) {
- X if (tx->t_tok == T_IDENT) {
- X ts = tx; /* save for future reference */
- X }
- X if (tx->t_tok != T_EQ) {
- X addtok(exprdecl,duptok(mem,tx));
- X if (tx->t_tok == T_SEMIC) {
- X return(ntok);
- X }
- X continue;
- X }
- X estart = expr->tl_tail;
- X /* an '=' */
- X addtok(expr,duptok(mem,ts));
- X addtok(expr,newtok(mem,T_WS," "));
- X ntok++;
- X initializer = 1;
- X }
- X /* in initializer */
- X
- X /* look for ',' or ';' terminating initialization */
- X if ((tx->t_tok == T_COMMA && tx->t_paren <= ts->t_paren)
- X || tx->t_tok == T_SEMIC) {
- X
- X addtok(exprdecl,duptok(mem,tx));
- X
- X /* if there was a preceeding expr, prepend a comma */
- X if (estart && estart->t_tok == T_RPAREN) {
- X instok(estart,ts = newtok(mem,T_COMMA,NIL));
- X estart = ts;
- X }
- X
- X /* wrap some parens around this expr */
- X instok(estart,newtok(mem,T_LPAREN,NIL));
- X addtok(expr,newtok(mem,T_RPAREN,NIL));
- X
- X /* ... and around the whole expression so far */
- X if (bstart && bstart != estart) {
- X instok(bstart,newtok(mem,T_LPAREN,NIL));
- X addtok(expr,newtok(mem,T_RPAREN,NIL));
- X }
- X estart = expr->tl_tail;
- X bstart = bstart->t_next;
- X initializer = 0;
- X if (debug >= 9) {
- X fprintf(stderr,">> ");
- X prtoklist(expr,0,stderr);
- X fprintf(stderr,"\n");
- X }
- X } else {
- X addtok(expr,duptok(mem,tx));
- X }
- X }
- X if (debug >= 9) {
- X fprintf(stderr,">> ");
- X prtoklist(expr,0,stderr);
- X fprintf(stderr,"\n");
- X }
- X return(ntok);
- X}
- \Rogue\Monster\
- else
- echo "will not over write ./rewrite.c"
- fi
- chmod 444 ./rewrite.c
- if [ `wc -c ./rewrite.c | awk '{printf $1}'` -ne 8260 ]
- then
- echo `wc -c ./rewrite.c | awk '{print "Got " $1 ", Expected " 8260}'`
- fi
- if `test ! -s ./yylex.c`
- then
- echo "writing ./yylex.c"
- sed 's/^X//' > ./yylex.c << '\Rogue\Monster\'
- X/*
- X * inline code expander
- X *
- X * (c) 1986,1987 - copyright 1986,1987, s. mcgeady, all rights reserved
- X */
- X
- X/*
- X * fast lexer for C
- X */
- X
- X/* $Header: yylex.c,v 1.9 87/06/24 13:05:47 mcg Rel $ */
- X
- X#include "inline.h"
- X#include <ctype.h>
- X#include "tokens.h"
- X
- X#define MAXLEXBUF 1024
- X
- X/* you can use these macros on any machine with stdio guts like a VAX */
- X#if defined(vax) || defined(sun) || defined(gould) || defined(pyr)
- X
- X#ifndef lint
- X#define peekc(p) ((p)->_cnt > 0 ? (int)(*(unsigned char *)(p)->_ptr) \
- X :((_filbuf(p) == EOF) ? EOF : \
- X ((p)->_cnt++),(int)(*(unsigned char *)(--(p)->_ptr))))
- X
- X
- X#define ungetc(c, p) ((c) == EOF) ? EOF : ((p)->_cnt++ == 0 ? \
- X (((p)->_ptr == (p)->_base) ? \
- X *(p)->_ptr = (c) : (*--((p)->_ptr) = (c))) \
- X : (((p)->_ptr == (p)->_base) ? (p)->_cnt--,EOF : \
- X (*--((p)->_ptr) = (c))))
- X
- X#endif
- X#else
- Xstatic int _pc; /* 'peek'ed character holder */
- X
- X#define peekc(p) ((_pc = getc(p),ungetc(_pc,p)),_pc)
- X#endif
- X
- Xextern char *gather();
- X
- X#ifndef NIL
- X#define NIL (char *) 0
- X#endif
- X
- X/* 33 keywords */
- Xstruct keys {
- X char *k_str;
- X int k_val;
- X} kw[8][10] = {
- X{
- X { NIL, 0, /* */ },
- X},
- X{
- X { "do", T_DO, /* do */ },
- X { "if", T_IF, /* if */ },
- X { NIL, 0, /* */ },
- X},
- X{
- X { "for", T_FOR, /* for */ },
- X { "int", T_INT, /* int */ },
- X { NIL, 0, /* */ },
- X},
- X{
- X { "auto", T_AUTO, /* auto */ },
- X { "case", T_CASE, /* case */ },
- X { "char", T_CHAR, /* char */ },
- X { "else", T_ELSE, /* else */ },
- X { "enum", T_ENUM, /* enum */ },
- X { "goto", T_GOTO, /* goto */ },
- X { "long", T_LONG, /* long */ },
- X { "void", T_VOID, /* void */ },
- X { NIL, 0, /* */ },
- X},
- X{
- X { "break", T_BREAK, /* break */ },
- X { "const", T_CONST, /* const */ },
- X { "float", T_FLOAT, /* float */ },
- X { "short", T_SHORT, /* short */ },
- X { "union", T_UNION, /* union */ },
- X { "while", T_WHILE, /* while */ },
- X { NIL, 0, /* */ },
- X},
- X{
- X { "double", T_DOUBLE, /* double */ },
- X { "extern", T_EXTERN, /* extern */ },
- X { "inline", T_INLINE, /* inline */ },
- X { "return", T_RETURN, /* return */ },
- X { "signed", T_SIGNED, /* signed */ },
- X { "sizeof", T_SIZEOF, /* sizeof */ },
- X { "static", T_STATIC, /* static */ },
- X { "struct", T_STRUCT, /* struct */ },
- X { "switch", T_SWITCH, /* switch */ },
- X { NIL, 0, /* */ },
- X},
- X{
- X { "default", T_DEFAULT, /* default */ },
- X { "typedef", T_TYPEDEF, /* typedef */ },
- X { NIL, 0, /* */ },
- X},
- X{
- X { "continue", T_CONTINUE, /* continue */ },
- X { "register", T_REGISTER, /* register */ },
- X { "unsigned", T_UNSIGNED, /* unsigned */ },
- X { "volatile", T_VOLATILE, /* volatile */ },
- X { NIL, 0, /* */ },
- X}
- X};
- X
- Xiskeyword(s,n)
- Xregister char *s;
- Xregister int n;
- X{
- X register struct keys *kwp;
- X
- X kwp = &kw[n-1][0];
- X
- X if (n < 2 || n > 8) return(0);
- X do {
- X if (s[0] != kwp->k_str[0] || s[1] != kwp->k_str[1])
- X continue;
- X if (strncmp(s,kwp->k_str,n) == 0)
- X return(kwp->k_val);
- X } while ((++kwp)->k_str); /* fix thanks to ucbcad!thomas */
- X return(0);
- X}
- X
- Xstatic char yytext[MAXLEXBUF];
- Xstatic char *yylval;
- Xint line = 1;
- X
- Xyylex(mem)
- Xregister int mem;
- X{
- X register int c, cc, pc;
- X register int len;
- X register char *p;
- X int base, i;
- X
- X base = 10;
- X yylval = NIL;
- X
- X if ((c = getc(stdin)) == EOF) {
- X return(0);
- X }
- X pc = peekc(stdin);
- X if (pc == '=') {
- X cc = getc(stdin);
- X switch(c) {
- X case '+': { return(T_ADD_EQ); }
- X case '-': { return(T_SUB_EQ); }
- X case '*': { return(T_MUL_EQ); }
- X case '/': { return(T_DIV_EQ); }
- X case '%': { return(T_MOD_EQ); }
- X case '&': { return(T_AND_EQ); }
- X case '^': { return(T_XOR_EQ); }
- X case '|': { return(T_OR_EQ); }
- X case '=': { return(T_CEQ); }
- X case '!': { return(T_NE); }
- X default:
- X ungetc(cc,stdin);
- X /* pc is correct */
- X break;
- X }
- X } else if (pc == c) {
- X cc = getc(stdin);
- X pc = peekc(stdin);
- X switch(c) {
- X case '+': { return(T_INC); }
- X case '-': { return(T_DEC); }
- X case '&': { return(T_CAND); }
- X case '|': { return(T_COR); }
- X case '>': /* also >>, >>= */
- X if (pc == '=') {
- X getc(stdin);
- X return(T_RS_EQ);
- X }
- X return(T_RS);
- X
- X case '<': /* also <<, <<= */
- X if (pc == '=') {
- X getc(stdin);
- X return(T_LS_EQ);
- X }
- X return(T_LS);
- X
- X default:
- X ungetc(cc,stdin);
- X pc = cc;
- X break;
- X }
- X }
- X switch(c) {
- X case '#': /* CPP line */
- X yylval = gather(mem,T_CPP,"#");
- X return(T_CPP);
- X
- X
- X case '-': /* also --, -=, -> */
- X if (pc == '>') { getc(stdin); return(T_PTR); }
- X return(T_MINUS);
- X
- X
- X case '/': /* also /=, comment */
- X if (pc == '*') { /* comment */
- X getc(stdin);
- X yylval = gather(mem,T_COMMENT,"/*");
- X return(T_COMMENT);
- X }
- X return(T_DIV);
- X
- X case '<': return(T_LT); /* also <<, <<= */
- X case '>': return(T_GT); /* also >>, >>= */
- X case '+': return(T_PLUS); /* also ++, += */
- X case '*': return(T_STAR); /* also *= */
- X case '%': return(T_MOD); /* also %= */
- X case '&': return(T_AMPER); /* also &&, &= */
- X case '^': return(T_XOR); /* also ^= */
- X case '|': return(T_OR); /* also ||, |= */
- X case '=': return(T_EQ); /* also == */
- X case '!': return(T_NOT); /* also != */
- X case '.': /* also ... */
- X if (pc == '.') {
- X cc = getc(stdin);
- X if (peekc(stdin) == '.') {
- X getc(stdin);
- X return(T_ELLIPSES);
- X }
- X ungetc(cc,stdin);
- X }
- X return(T_DOT);
- X
- X case ';': return(T_SEMIC);
- X case '{': return(T_LBRACE);
- X case '}': return(T_RBRACE);
- X case ',': return(T_COMMA);
- X case ':': return(T_COLON);
- X case '(': return(T_LPAREN);
- X case ')': return(T_RPAREN);
- X case '[': return(T_LSQ);
- X case ']': return(T_RSQ);
- X case '~': return(T_TILDE);
- X case '?': return(T_QUEST);
- X
- X case '\'':
- X yylval = gather(mem,T_CHARCONST,"'");
- X return(T_CHARCONST);
- X
- X case '"':
- X yylval = gather(mem,T_STR,"\"");
- X return(T_STR);
- X
- X case ' ': case '\t': case '\v': case '\n': case '\f':
- X p = yytext;
- X do {
- X *p++ = c;
- X if (c == '\n') line++;
- X c = peekc(stdin);
- X } while ((c == ' ' || c == '\t' || c == '\v' || c == '\n' ||
- X c == '\f') && (p < &yytext[MAXLEXBUF]) &&
- X ((c = getc(stdin)) != EOF));
- X *p = '\0';
- X yylval = yytext;
- X return(T_WS);
- X
- X case '0':
- X p = yytext;
- X *p++ = c;
- X if (tolower(pc) == 'x') {
- X base = 16;
- X *p++ = getc(stdin);
- X c = getc(stdin);
- X } else if (tolower(pc) == 'f') {
- X#ifdef notdef
- X /* 0finf or 0fnan(xxx) */
- X *p++ = getc(stdin);
- X base = -1; /* FLOAT */
- X c = getc(stdin);
- X#endif
- X } else if (isdigit(pc)) {
- X base = 8;
- X c = getc(stdin);
- X } else {
- X p = yytext;
- X }
- X /*FALLTHROUGH*/
- X
- X case '1': case '2': case '3': case '4': case '5':
- X case '6': case '7': case '8': case '9':
- X
- X if (base == 10) {
- X p = yytext;
- X }
- X do {
- X if (!isdigit(c) &&
- X !((c == '.') || (tolower(c) == 'e') ||
- X (c == '+') || (c == '-'))) {
- X ungetc(c,stdin);
- X break;
- X }
- X *p++ = c;
- X } while((c = getc(stdin)) != EOF);
- X *p = '\0';
- X yylval = yytext;
- X return(T_NUM);
- X
- X case EOF:
- X return(0);
- X
- X default: /* an identifier or keyword */
- X if ((c < ' ') || (c > '~') || !isalpha(c)) {
- X error(line,"illegal character");
- X yytext[0] = c; yytext[1] = '\0';
- X yylval = yytext;
- X return(T_WS);
- X }
- X /*FALLTHROUGH*/
- X case '_':
- X yytext[0] = c;
- X p = &yytext[1];
- X len = 1;
- X while((c = getc(stdin)) != EOF) {
- X if (!isalpha(c) && !isdigit(c) && c != '$' && c != '_') {
- X ungetc(c,stdin);
- X break;
- X }
- X *p++ = c;
- X len++;
- X }
- X *p = '\0';
- X if (i = iskeyword(yytext,len)) {
- X return(i);
- X } else {
- X yylval = yytext;
- X return(T_IDENT);
- X }
- X }
- X /*NOTREACHED*/
- X}
- X
- X/*
- X */
- X
- Xchar *
- Xgather(mem,type,init)
- Xregister int mem;
- Xint type;
- Xchar *init;
- X{
- X char buf[MAXLEXBUF];
- X register int c;
- X register char *tbuf;
- X register int tbufsize = 0;
- X register char *bb = buf;
- X register char *p = bb;
- X register char *ebuf = &buf[MAXLEXBUF-1];
- X
- X
- X strcpy(buf,init);
- X p = buf + strlen(init);
- X while ((c = getc(stdin)) != EOF) {
- X *p = c;
- X if (*p == 0)
- X break;
- X
- X if (*p == '\n') line++;
- X
- X switch (type) {
- X case T_COMMENT:
- X if (*p == '*' && peekc(stdin) == '/') {
- X *++p = getc(stdin);
- X goto end;
- X }
- X break;
- X case T_CPP:
- X if (*p == '\\') {
- X *++p = getc(stdin);
- X } else if (*p == '\n') {
- X /* ungetc(*p,stdin); */
- X goto end;
- X }
- X break;
- X case T_STR:
- X if (*p == '\\') {
- X *++p = getc(stdin);
- X } else if (*p == '\n') {
- X /* error */
- X } else if (*p == '"') {
- X goto end;
- X }
- X break;
- X
- X case T_CHARCONST:
- X if (*p == '\\') {
- X *++p = getc(stdin);
- X } else if (*p == '\n') {
- X /* error */
- X } else if (*p == '\'') {
- X goto end;
- X }
- X break;
- X }
- X /* leave two slots open at end */
- X if (++p >= ebuf-1) {
- X *p = '\0';
- X if (tbufsize == 0) {
- X tbufsize = 1024;
- X }
- X if (mem < 0) {
- X tbuf = (char *) malloc((unsigned) (tbufsize *= 2));
- X } else {
- X tbuf = getmem(mem, 0, (unsigned) (tbufsize *= 2));
- X }
- X strcpy(tbuf, bb);
- X p = tbuf + (p - bb);
- X if (bb != buf) {
- X free(bb);
- X }
- X bb = tbuf;
- X ebuf = bb + tbufsize;
- X }
- X }
- X end:
- X *++p = '\0';
- X p++;
- X if (tbufsize == 0) {
- X if (mem < 0) {
- X tbuf = (char *) malloc((unsigned) (p-bb));
- X } else {
- X tbuf = getmem(mem, 0, (unsigned) (p-bb));
- X }
- X strcpy(tbuf, bb);
- X bb = tbuf;
- X }
- X return(bb);
- X}
- X
- X
- X#ifndef TEST
- X
- Xcheck_type(tok)
- Xregister struct token *tok;
- X{
- X register int i;
- X register char **p;
- X
- X for (i = 0; (i < NSCOPE) && (typeid[i] != NILP(struct typelist *));i++) {
- X for (p = typeid[i]->type_id; *p != NIL; p++) {
- X if (strcmp(tok->t_id,*p) == 0) {
- X tok->t_tok = T_TYPE_ID;
- X return;
- X }
- X }
- X }
- X}
- X
- Xstruct token *
- Xgettok(mem)
- Xregister int mem;
- X{
- X register int t;
- X struct token *tok;
- X static int bracelev = 0;
- X static int parenlev = 0;
- X
- X if ((t = yylex(mem)) == 0)
- X return((struct token *) 0);
- X tok = newtok(mem, t, yylval);
- X tok->t_line = line;
- X switch(t) {
- X case T_COMMENT:
- X case T_CPP:
- X tok->t_tok = T_WS;
- X /*FALLTHROUGH*/
- X case T_STR:
- X /* free(yylval); */
- X break;
- X
- X case T_LBRACE:
- X tok->t_level = bracelev++;
- X tok->t_paren = parenlev;
- X pushscope(bracelev);
- X break;
- X case T_LPAREN:
- X tok->t_paren = parenlev++;
- X tok->t_level = bracelev;
- X break;
- X case T_RPAREN:
- X tok->t_level = bracelev;
- X tok->t_paren = --parenlev;
- X break;
- X case T_RBRACE:
- X popscope(bracelev);
- X tok->t_level = --bracelev;
- X tok->t_paren = parenlev;
- X break;
- X
- X default:
- X tok->t_level = bracelev;
- X tok->t_paren = parenlev;
- X break;
- X }
- X if (t == T_IDENT) {
- X check_type(tok);
- X }
- X return(tok);
- X}
- X#endif
- X
- X#ifdef TEST
- Xmain() {
- X int tok;
- X extern char *tokens[];
- X
- X while(tok = yylex(-1)) {
- X switch (tok) {
- X case T_COMMENT:
- X case T_STR:
- X case T_CPP:
- X free(yylval);
- X
- X case T_IDENT:
- X case T_WS:
- X case T_NUM:
- X case T_CHARCONST:
- X case T_TYPE_ID:
- X fputs(yylval,stdout);
- X break;
- X case T_ACTUAL:
- X fputs("<ACTUAL>",stdout);
- X break;
- X case T_RETVAL:
- X fputs("<RETVAL>",stdout);
- X break;
- X case T_ARGLIST:
- X fprintf(stdout,"%s(ARGLIST)", yylval);
- X break;
- X case T_RETLAB:
- X fputs("<RETLAB>",stdout);
- X break;
- X case T_FORMAL:
- X fprintf(stdout,"<FORMAL '%s'>",yylval);
- X break;
- X default:
- X if (tok <= T_INLINE)
- X fputs(tokens[tok],stdout);
- X else
- X fputs("???",stdout);
- X
- X break;
- X }
- X }
- X}
- X#endif
- \Rogue\Monster\
- else
- echo "will not over write ./yylex.c"
- fi
- chmod 444 ./yylex.c
- if [ `wc -c ./yylex.c | awk '{printf $1}'` -ne 10795 ]
- then
- echo `wc -c ./yylex.c | awk '{print "Got " $1 ", Expected " 10795}'`
- fi
- if `test ! -s ./tokens.c`
- then
- echo "writing ./tokens.c"
- sed 's/^X//' > ./tokens.c << '\Rogue\Monster\'
- X/*
- X * inline code expander
- X *
- X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
- X */
- X
- X/* $Header: tokens.c,v 1.3 87/04/27 18:16:52 mcg Rel $ */
- X
- X
- Xchar *tokens[] = {
- X "",
- X "auto",
- X "break",
- X "case",
- X "char",
- X "const",
- X "continue",
- X "default",
- X "do",
- X "double",
- X "else",
- X "enum",
- X "extern",
- X "float",
- X "for",
- X "goto",
- X "if",
- X "int",
- X "long",
- X "register",
- X "return",
- X "short",
- X "signed",
- X "sizeof",
- X "static",
- X "struct",
- X "switch",
- X "typedef",
- X "union",
- X "unsigned",
- X "void",
- X "volatile",
- X "while",
- X "...",
- X "=",
- X ",",
- X "{",
- X "}",
- X ";",
- X ">>=",
- X "<<=",
- X "+=",
- X "-=",
- X "*=",
- X "/=",
- X "%=",
- X "&=",
- X "^=",
- X "|=",
- X ">>",
- X "<<",
- X "++",
- X "--",
- X "->",
- X "&&",
- X "||",
- X "<=",
- X ">=",
- X "==",
- X "!=",
- X ":",
- X "",
- X "(",
- X ")",
- X "[",
- X "]",
- X ".",
- X "&",
- X "!",
- X "~",
- X "-",
- X "+",
- X "*",
- X "/",
- X "%",
- X "<",
- X ">",
- X "^",
- X "|",
- X "?",
- X "inline",
- X};
- \Rogue\Monster\
- else
- echo "will not over write ./tokens.c"
- fi
- chmod 444 ./tokens.c
- if [ `wc -c ./tokens.c | awk '{printf $1}'` -ne 828 ]
- then
- echo `wc -c ./tokens.c | awk '{print "Got " $1 ", Expected " 828}'`
- fi
- if `test ! -s ./utils.c`
- then
- echo "writing ./utils.c"
- sed 's/^X//' > ./utils.c << '\Rogue\Monster\'
- X/*
- X * C inline code substituter - 11/24/86 - mcg
- X *
- X * utility routines
- X *
- X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
- X */
- X
- X/* $Header: utils.c,v 1.13 87/06/24 13:11:40 mcg Rel $ */
- X
- X
- X#include <stdio.h>
- X#include "tokens.h"
- X#include "inline.h"
- X
- Xstruct token *
- Xskipws(t)
- Xregister struct token *t;
- X{
- X while (t && t->t_next && (t->t_tok == T_WS)) {
- X t = t->t_next;
- X }
- X return(t);
- X}
- X
- X/*
- X * add a token to a list
- X */
- X
- Xaddtok(list, tok)
- Xregister struct toklist *list;
- Xregister struct token *tok;
- X{
- X if (list->tl_head == NILTOK) {
- X list->tl_head = tok;
- X }
- X if (list->tl_tail != NILTOK) {
- X list->tl_tail->t_next = tok;
- X }
- X list->tl_tail = tok;
- X}
- X
- Xstruct token *
- Xinstok(tok,ntok)
- Xregister struct token *tok;
- Xregister struct token *ntok;
- X{
- X register struct token *tl;
- X
- X if (ntok == NILTOK) {
- X return(tok);
- X }
- X /* find end of new token list */
- X for(tl = ntok; tl->t_next != NILTOK; tl = tl->t_next)
- X ;
- X
- X if (tok->t_next == NILTOK) {
- X tok->t_next = ntok;
- X } else {
- X tl->t_next = tok->t_next;
- X tok->t_next = ntok;
- X }
- X return(tl); /* return end of new list */
- X}
- X
- X/*
- X * get a new token
- X */
- X
- Xstruct token *
- Xnewtok(mem,val, id)
- Xint val;
- Xchar *id;
- X{
- X register struct token *t;
- X register unsigned int len,l;
- X
- X len = sizeof(struct token);
- X if (id) {
- X len += (l = strlen(id) + 1);
- X }
- X
- X t = (struct token *) getmem(mem,1,len);
- X
- X if (id) {
- X t->t_id = ((char *) t) + sizeof(struct token);
- X (void) strncpy(t->t_id,id,l);
- X } else {
- X t->t_id = NIL;
- X }
- X
- X t->t_tok = val;
- X t->t_flags = 0;
- X t->t_num = 0;
- X t->t_level = 0;
- X t->t_paren = 0;
- X t->t_line = 0;
- X t->t_next = NILTOK;
- X return(t);
- X}
- X
- Xstruct token *
- Xduptok(mem,tok)
- Xregister struct token *tok;
- X{
- X register struct token *t;
- X
- X t = newtok(mem,tok->t_tok, tok->t_id);
- X t->t_flags = tok->t_flags;
- X t->t_num = tok->t_num;
- X t->t_level = tok->t_level;
- X t->t_paren = tok->t_paren;
- X t->t_line = 0;
- X t->t_next = NILTOK; /* next token in this list */
- X return(t);
- X}
- X
- Xcpytoklist(mem, olist, ilist)
- Xint mem;
- Xregister struct toklist *olist;
- Xregister struct toklist *ilist;
- X{
- X register struct token *tl;
- X
- X for(tl = ilist->tl_head; tl != NILTOK; tl = tl->t_next) {
- X addtok(olist,duptok(mem,tl));
- X if (tl == ilist->tl_tail)
- X break;
- X }
- X}
- X
- Xfixparens(tl,plev,blev)
- Xregister struct toklist *tl;
- Xregister int plev, blev;
- X{
- X register struct token *tp;
- X register int paren = plev;
- X register int brace = blev;
- X
- X for (tp = tl->tl_head; tp && tp != tl->tl_tail->t_next; tp = tp->t_next) {
- X tp->t_paren = paren;
- X tp->t_level = brace;
- X switch(tp->t_tok) {
- X case T_LPAREN:
- X paren++;
- X break;
- X case T_LBRACE:
- X brace++;
- X break;
- X case T_RBRACE:
- X tp->t_level = --brace;
- X break;
- X case T_RPAREN:
- X tp->t_paren = --paren;
- X break;
- X default:
- X break;
- X }
- X }
- X}
- X
- X#include "varargs.h"
- X
- X/*VARARGS1*/
- Xchar *
- Xmkstr(mem,va_alist)
- Xint mem;
- Xva_dcl
- X{
- X va_list s;
- X register int i;
- X register char *rs,*ts;
- X
- X va_start(s);
- X i = 0;
- X while(1) {
- X rs = va_arg(s, char *);
- X if (rs == NIL) {
- X break;
- X }
- X i += strlen(rs);
- X }
- X va_end(s);
- X rs = (char *) getmem(mem,0,(unsigned) i+1);
- X *rs = '\0';
- X va_start(s);
- X while(1) {
- X ts = va_arg(s, char *);
- X if (ts == NIL) {
- X break;
- X }
- X (void) strcat(rs,ts);
- X }
- X va_end(s);
- X return(rs);
- X}
- X
- X
- X#ifdef vax
- X/*VARARGS*/
- Xerror(lin,fmt,args)
- Xint lin;
- Xchar *fmt;
- Xchar *args;
- X{
- X if (infile) {
- X fprintf(stderr,"\"%s\", line %d: ",infile,lin);
- X } else {
- X fprintf(stderr,"%s: line %d: ",myname,lin);
- X }
- X _doprnt(fmt,&args,stderr);
- X fputs("\n",stderr);
- X errs++;
- X}
- X
- X
- X/*VARARGS*/
- Xwarn(lin,fmt,args)
- Xint lin;
- Xchar *fmt;
- Xchar *args;
- X{
- X if (nowarn) return;
- X
- X if (infile) {
- X fprintf(stderr,"\"%s\", line %d: warning: ",infile,lin);
- X } else {
- X fprintf(stderr,"%s: line %d: warning: ",myname,lin);
- X }
- X _doprnt(fmt,&args,stderr);
- X fputs("\n",stderr);
- X}
- X#else
- X/*VARARGS*/
- Xerror(line,fmt,va_alist)
- Xint line;
- Xchar *fmt;
- Xva_dcl
- X{
- X va_list s;
- X va_list *p;
- X register int i;
- X register char *rs,*ts;
- X
- X va_start(s);
- X p = &s;
- X if (infile) {
- X fprintf(stderr,"\"%s\", line %d: ",infile,line);
- X } else {
- X fprintf(stderr,"%s: line %d: ",myname,line);
- X }
- X _doprnt(fmt,p,stderr);
- X fputs("\n",stderr);
- X va_end(s);
- X errs++;
- X}
- X
- X/*VARARGS*/
- Xwarn(line,fmt,va_alist)
- Xint line;
- Xchar *fmt;
- Xva_dcl
- X{
- X va_list s;
- X va_list *p;
- X register int i;
- X register char *rs,*ts;
- X
- X if (nowarn) return;
- X
- X va_start(s);
- X p = &s;
- X if (infile) {
- X fprintf(stderr,"%s: \"%s\", line %d: ",infile,line);
- X } else {
- X fprintf(stderr,"%s: line %d: ",myname,line);
- X }
- X _doprnt(fmt,p,stderr);
- X fputs("\n",stderr);
- X}
- X
- X#endif
- X
- X
- X/* extremely limited - positive numbers only */
- X/* useful only for appending positive digits to strings */
- X
- Xchar *
- Xitoa(n)
- X{
- X static char buf[20];
- X register char *p = &buf[18];
- X
- X buf[19] = '\0';
- X do {
- X *p-- = '0' + (n%10);
- X n /= 10;
- X } while(n && (p >= buf));
- X return(++p);
- X}
- X
- X/*
- X * create a (non-filled-in) inline expansion node
- X */
- X
- Xstruct inline_node *
- Xmknode(mem)
- Xint mem;
- X{
- X register struct inline_node *node;
- X register int i;
- X
- X node = (struct inline_node *) getmem(mem,1,sizeof (struct inline_node));
- X node->i_id = NIL;
- X for (i=0; i < NSTATES; i++) {
- X node->i_tl[i].tl_head = NILTOK;
- X node->i_tl[i].tl_tail = NILTOK;
- X }
- X
- X node->i_text.tl_head = NILTOK;
- X node->i_text.tl_tail = NILTOK;
- X
- X for(i=0; i < NFORMALS; i++) {
- X node->i_formals[i] = NIL;
- X node->i_formalinfo[i] = 0;
- X }
- X node->i_nformals = 0;
- X
- X node->i_mem = mem;
- X node->i_line = 0;
- X node->i_flags = 0;
- X node->i_storclass = 0;
- X node->i_nseen = 0;
- X node->i_nexpand = 0;
- X
- X node->i_exprmem = -1;
- X
- X return(node);
- X}
- X
- Xprtoklist(tl,doauto,s)
- Xregister struct toklist *tl;
- Xint doauto;
- XFILE *s;
- X{
- X register struct token *th = tl->tl_head;
- X
- X while (th != NILTOK) {
- X prtok(th,doauto,s);
- X th = th->t_next;
- X }
- X}
- X
- Xprtok(tok,doauto,s)
- Xstruct token *tok;
- Xint doauto;
- XFILE *s;
- X{
- X extern char *tokens[];
- X
- X switch (tok->t_tok) {
- X case T_IDENT:
- X if (doauto && tok->t_flags&TAUTO) {
- X if (tok->t_flags&TINLINE) {
- X if (tok->t_num > 1) {
- X fprintf(s,"_loc_%s_%d",tok->t_id,tok->t_num);
- X break;
- X }
- X } else {
- X fprintf(s,"_auto_%s",tok->t_id);
- X break;
- X }
- X }
- X /*FALLTHROUGH*/
- X case T_LABEL:
- X case T_WS:
- X case T_NUM:
- X case T_CHARCONST:
- X case T_CPP:
- X case T_STR:
- X case T_TYPE_ID:
- X case T_STRTAG:
- X fputs(tok->t_id,s);
- X break;
- X case T_ACTUAL:
- X fputs("<ACTUAL>",s);
- X break;
- X case T_RETVAL:
- X fputs("<RETVAL>",s);
- X break;
- X case T_ARGLIST:
- X fprintf(s,"%s(ARGLIST)", tok->t_id);
- X break;
- X case T_RETLAB:
- X fputs("<RETLAB>",s);
- X break;
- X case T_FORMAL:
- X fprintf(s,"<FORMAL '%s'>",tok->t_id);
- X break;
- X default:
- X if (tok->t_tok <= T_INLINE)
- X fputs(tokens[tok->t_tok],s);
- X else
- X fputs("???",s);
- X
- X break;
- X }
- X}
- X
- X
- Xdebugnode(node)
- Xregister struct inline_node *node;
- X{
- X register int i;
- X
- X fprintf(stderr,"> inline '%s' @ line %d\n",node->i_id,node->i_line);
- X fprintf(stderr,"> formals (%d):\n", node->i_nformals);
- X for (i = 0; i < node->i_nformals; i++) {
- X fprintf(stderr,"> '%s'\n", node->i_formals[i]);
- X }
- X fprintf(stderr,"> function type:\n");
- X prtoklist(&node->i_tl[SDECL],0,stderr);
- X fprintf(stderr,"\n");
- X fprintf(stderr,"> declarations:\n");
- X prtoklist(&node->i_tl[SDECLBODY],0,stderr);
- X fprintf(stderr,"> body:\n");
- X prtoklist(&node->i_tl[SBODY],1,stderr);
- X fprintf(stderr,"\n");
- X if (node->i_flags&I_EXPR) {
- X fprintf(stderr,"> as expression:\n");
- X fprintf(stderr,"> declarations:\n");
- X prtoklist(&node->i_tl[SEXPRDECL],1,stderr);
- X fprintf(stderr,"\n> body:\n");
- X prtoklist(&node->i_tl[SEXPRBODY],1,stderr);
- X fprintf(stderr,"\n");
- X } else {
- X fprintf(stderr, "(not an expression)\n");
- X }
- X}
- X
- X
- X
- Xistype(tok)
- Xstruct token *tok;
- X{
- X switch(tok->t_tok) {
- X case T_CHAR:
- X case T_INT:
- X case T_SHORT:
- X case T_LONG:
- X case T_FLOAT:
- X case T_DOUBLE:
- X case T_UNSIGNED:
- X case T_SIGNED:
- X case T_VOID:
- X case T_ENUM:
- X case T_STRUCT:
- X case T_UNION:
- X case T_TYPE_ID:
- X return(1);
- X
- X default:
- X return(0);
- X }
- X}
- X
- Xisstoreclass(tok)
- Xstruct token *tok;
- X{
- X switch(tok->t_tok) {
- X case T_REGISTER:
- X case T_EXTERN:
- X case T_STATIC:
- X case T_AUTO:
- X case T_CONST:
- X case T_VOLATILE:
- X return(1);
- X default:
- X return(0);
- X }
- X}
- X
- Xiscontrol(tok)
- Xstruct token *tok;
- X{
- X switch(tok->t_tok) {
- X case T_IF:
- X case T_WHILE:
- X case T_FOR:
- X case T_SWITCH:
- X return(1);
- X default:
- X return(0);
- X }
- X}
- X
- X/*
- X * returns true if the tokens following the argument conform to
- X * the pattern of a simple call:
- X * identifier, optional whitespace, leftparen
- X * e.g.:
- X * foo /* comment ();
- X *
- X * thus
- X * (foo)(); (*foo)(); etc
- X * are not calls
- X */
- X
- Xiscall(tok)
- Xregister struct token *tok;
- X{
- X if (tok == NILTOK) {
- X return(0);
- X }
- X if ((tok->t_tok != T_IDENT) || (tok->t_flags&TNOEXPAND)) {
- X return(0);
- X }
- X /* skip over any leading whitespace */
- X for(tok = tok->t_next; tok != NILTOK; tok = tok->t_next) {
- X if (tok->t_tok != T_WS) {
- X break;
- X }
- X }
- X if (tok && (tok->t_tok == T_LPAREN)) {
- X return(1);
- X }
- X return(0);
- X}
- X
- \Rogue\Monster\
- else
- echo "will not over write ./utils.c"
- fi
- chmod 444 ./utils.c
- if [ `wc -c ./utils.c | awk '{printf $1}'` -ne 8665 ]
- then
- echo `wc -c ./utils.c | awk '{print "Got " $1 ", Expected " 8665}'`
- fi
- if `test ! -s ./mem.c`
- then
- echo "writing ./mem.c"
- sed 's/^X//' > ./mem.c << '\Rogue\Monster\'
- X/*
- X * pool-based memory allocation scheme
- X *
- X * (c) 1986 - copyright 1986, s. mcgeady, all rights reserved
- X *
- X * this is good for low-overhead memory allocation of many small units,
- X * where all the memory is freed at once at the end
- X */
- X
- X/* $Header: mem.c,v 1.6 87/04/27 18:16:43 mcg Rel $ */
- X
- X
- X#define STATS 1
- X#define FREELIST 1 /* maintain freelist of hunks and bufs, cutting down */
- X /* on calls to malloc() and free() */
- X#define NFREEBUFS 10 /* number of free buffers to maintain */
- X
- X/* #define TEST 1 */
- X/* #define ZEROMEM(p,n,a) bzero(p,n) /* define to zero memory on allocation */
- X#define ZEROMEM(p,n,a)
- X
- Xextern char *malloc();
- Xextern char *sbrk();
- Xextern char *getmem();
- X
- X#define NIL 0
- X#define POOLSIZE 4096
- X
- Xstruct memhunk {
- X char *m_base; /* pointer to memory buffer */
- X char *m_free; /* pointer to free mem */
- X unsigned m_size; /* size of this buffer */
- X unsigned m_nleft; /* number of bytes left */
- X struct memhunk *m_next; /* next pool in this cache */
- X};
- X
- X/*
- X * each pool consists of a series of 'hunks' of memory, organized
- X * as a linked list. the pool 'handle' is really a pointer to the
- X * poolhead for the list
- X */
- X
- Xstruct poolhead {
- X struct memhunk *pl_pool;
- X struct poolhead *pl_next;
- X};
- X
- Xstatic struct poolhead head = {0};
- X
- X#ifdef STATS
- Xstatic int nrequest = 0;
- Xstatic int nloops = 0;
- Xstatic int maxloops = 0;
- Xstatic int minloops = 0;
- Xstatic int nfree = 0;
- Xstatic int nmalloc = 0;
- Xstatic int maxsize = 0;
- Xstatic int npools = 0;
- Xstatic int maxpools = 0;
- Xstatic int nhunks = 0;
- Xstatic int maxhunks = 0;
- Xstatic int firsttime = 0;
- Xstatic unsigned totsize = 0;
- Xstatic char *lowwater = 0;
- Xstatic char *hiwater = 0;
- Xstatic int nphdr = 0;
- X
- Xstatic
- Xchar *
- XMALLOC(n)
- Xunsigned int n;
- X{
- X register char *p;
- X
- X nmalloc++;
- X p = malloc(n);
- X if (p > hiwater) {
- X hiwater = p;
- X }
- X return(p);
- X}
- X
- X#define FREE(x) (nfree++,free((unsigned)x))
- X
- X#else
- X
- X#define MALLOC malloc
- X#define FREE free
- X
- X#endif
- X
- X#ifndef FREELIST
- X
- X#define getpool() ((struct poolhead *) MALLOC(sizeof(struct poolhead)))
- X#define gethunk() ((struct memhunk *) MALLOC(sizeof(struct memhunk)))
- X#define getbuf(s) ((char *) MALLOC(*(s)))
- X#define freebuf(p,s) (FREE(p))
- X#define freehunk(p) (FREE(p))
- X
- X#else
- X#define getpool() ((struct poolhead *) MALLOC(sizeof(struct poolhead)))
- X
- Xstruct freebufs {
- X int fb_size;
- X char *fb_buf;
- X};
- X
- Xstatic struct memhunk *hunks = {0};
- Xstatic struct freebufs bufs[NFREEBUFS] = {0};
- X
- X
- Xstruct memhunk *
- Xgethunk() {
- X register struct memhunk *p = hunks;
- X
- X if (p != NIL) {
- X hunks = p->m_next;
- X return(p);
- X }
- X return((struct memhunk *) MALLOC(sizeof(struct memhunk)));
- X}
- X
- X#define freehunk(p) ((p)->m_next = hunks, hunks = (p))
- X
- Xchar *
- Xgetbuf(size)
- Xunsigned int *size;
- X{
- X register int i;
- X register struct freebufs *p;
- X
- X if (*size == 0) return(NIL);
- X
- X for (i = 0, p = bufs; i < NFREEBUFS; i++, p++) {
- X if (p->fb_size >= *size) {
- X *size = p->fb_size;
- X p->fb_size = 0;
- X return(p->fb_buf);
- X }
- X }
- X return((char *) MALLOC(*size));
- X}
- X
- Xvoid
- Xfreebuf(p,size)
- Xchar *p;
- Xunsigned size;
- X{
- X register int i;
- X register struct freebufs *q;
- X
- X for (i = 0, q = bufs; i < NFREEBUFS; i++, q++) {
- X if (q->fb_size == 0) {
- X q->fb_size = size;
- X q->fb_buf = p;
- X return;
- X }
- X }
- X FREE(p);
- X}
- X
- X#endif
- X
- X
- X/*
- X * open a new memory pool, returning a handle to it
- X */
- X
- Xopenpool() {
- X register struct poolhead *pl, *lastpl;
- X register int pool = 0;
- X
- X#ifdef STATS
- X if (firsttime == 0) {
- X firsttime++;
- X lowwater = sbrk(0);
- X }
- X npools++;
- X if (npools > maxpools) {
- X maxpools = npools;
- X }
- X#endif
- X /* this finds the last pool header */
- X for (pl = &head;
- X ((pl != NIL) && (pl->pl_pool != NIL));
- X lastpl = pl, pl = pl->pl_next)
- X {
- X pool++;
- X }
- X if (pl == NIL) {
- X /* add a new pool header on the end */
- X pl = lastpl->pl_next = getpool();
- X pl->pl_pool = gethunk();
- X pl->pl_next = NIL;
- X pl->pl_pool->m_base = NIL;
- X pl->pl_pool->m_free = NIL;
- X pl->pl_pool->m_size = 0;
- X pl->pl_pool->m_nleft = 0;
- X pl->pl_pool->m_next = NIL;
- X#ifdef STATS
- X nhunks++;
- X nphdr++;
- X#endif
- X }
- X return(pool);
- X}
- X
- X
- X
- X/*
- X * close a memory pool, freeing all memory associated with it
- X */
- X
- Xclosepool(pool)
- Xregister int pool;
- X{
- X register struct poolhead *pl;
- X register struct memhunk *p, *q;
- X
- X if (pool < 0) {
- X return(NIL);
- X }
- X for(pl = &head; pl != NIL; pl = pl->pl_next) {
- X if (pool == 0) {
- X break;
- X }
- X pool--;
- X }
- X if (pool != 0) { /* invalid pool */
- X return(0);
- X }
- X
- X for(p = pl->pl_pool; p != NIL; p = q) {
- X q = p->m_next;
- X if (p->m_base) {
- X freebuf(p->m_base,p->m_size);
- X }
- X freehunk(p);
- X#ifdef STATS
- X nhunks--;
- X#endif
- X }
- X pl->pl_pool = NIL;
- X#ifdef STATS
- X npools--;
- X#endif
- X return(1);
- X}
- X
- X
- X/*
- X * get 'size' bytes, from 'pool'
- X * if 'align' is 1, align the result on a (sizeof long) boundary
- X */
- X
- Xchar *
- Xgetmem(pool,align,size)
- Xint pool;
- Xunsigned align;
- Xunsigned size;
- X{
- X register struct poolhead *pl;
- X register struct memhunk *p,*lastp;
- X register char *r;
- X register int psize;
- X register int lnloops;
- X
- X#ifdef STATS
- X nrequest++;
- X totsize += size;
- X if (size > maxsize) {
- X maxsize = size;
- X }
- X lnloops = 0;
- X#endif
- X
- X if (pool < 0) {
- X return(NIL);
- X }
- X for(pl = &head; pl != NIL; pl = pl->pl_next) {
- X if (pool == 0) {
- X break;
- X }
- X pool--;
- X }
- X if (pool != 0) { /* invalid pool */
- X return(NIL);
- X }
- X
- X for(p = pl->pl_pool,lastp = NIL; p != NIL; lastp = p, p = p->m_next) {
- X#ifdef STATS
- X nloops++;
- X lnloops++;
- X#endif
- X if (!p->m_nleft)
- X continue;
- X if (align && (psize = (((int) p->m_free) % sizeof(long)))) {
- X psize = sizeof(long) - psize;
- X if (p->m_nleft >= size+psize) {
- X p->m_nleft -= psize;
- X p->m_free += psize;
- X } else {
- X continue;
- X }
- X }
- X if (p->m_nleft && (p->m_nleft >= size)) {
- X r = p->m_free;
- X p->m_nleft -= size;
- X p->m_free += size;
- X ZEROMEM(r,size,align);
- X return(r);
- X }
- X }
- X if (size < POOLSIZE) {
- X psize = POOLSIZE;
- X } else {
- X psize = size;
- X }
- X
- X#ifdef STATS
- X nhunks++;
- X if (nhunks > maxhunks) {
- X maxhunks = nhunks;
- X }
- X if (lnloops > maxloops) {
- X maxloops = lnloops;
- X }
- X if ((minloops == 0) || (lnloops < minloops)) {
- X minloops = lnloops;
- X }
- X#endif
- X
- X /* don't need to worry about alignment here, malloc always aligned */
- X p = gethunk();
- X
- X /* if lastp == NIL, then this is first allocation for this pool */
- X if (lastp != NIL) {
- X lastp->m_next = p;
- X } else {
- X pl->pl_pool = p;
- X }
- X p->m_nleft = p->m_size = psize;
- X p->m_free = p->m_base = getbuf(&p->m_nleft);
- X p->m_next = NIL;
- X
- X r = p->m_free;
- X p->m_nleft -= size;
- X p->m_free += size;
- X ZEROMEM(r,size,align);
- X return(r);
- X}
- X
- X#ifdef notdef
- X/* should improve this */
- X
- Xbzero(p,s,a)
- Xregister char *p;
- Xregister int s;
- Xregister int a;
- X{
- X while(s--) {
- X *p++ = 0;
- X }
- X}
- X#endif
- X
- X#ifdef STATS
- X#include <stdio.h>
- X
- Xmemstats() {
- X fprintf(stderr,"%d hunks (max %d) in %d pools (max %d), (%d hdrs), largest is %d\n",
- X nhunks,maxhunks,npools,maxpools,nphdr,maxsize);
- X fprintf(stderr,"%d loops in getmem (avg), %d min, %d max\n",
- X nloops/nrequest, minloops, maxloops);
- X fprintf(stderr, "pools between 0x%x and 0x%x, heap max %d.%d Kb\n",
- X lowwater, hiwater, (hiwater-lowwater)/1024, (hiwater-lowwater)%1024);
- X fprintf(stderr, "%d requests, %d mallocs, %d frees\n", nrequest,nmalloc,nfree);
- X fprintf(stderr, "%d total bytes, average request %d.%d\n", totsize,
- X totsize/nrequest, totsize%nrequest);
- X}
- X#endif
- X
- X#ifdef TEST
- X/*
- X * testing code
- X */
- X
- X#include <stdio.h>
- X
- X#define skipws(p) while((*p == ' ') || (*p == '\t')) p++
- X#define skiptows(p) while((*p != ' ') && (*p != '\t') && (*p != '\0')) p++
- X
- Xmain() {
- X register int i,n,x;
- X char buf[20];
- X char c;
- X register char *p,*q;
- X
- X printf("memory allocator test routine\n");
- X while(printf("> "),gets(buf) != NIL) {
- X p = buf;
- X skipws(p);
- X c = *p++;
- X skipws(p);
- X switch(c) {
- X case 'd':
- X dump();
- X break;
- X case 's':
- X#ifdef STATS
- X memstats();
- X#else
- X printf("no statistics available\n");
- X#endif
- X break;
- X case 'g': /* get mem (nbytes) (align) (poolnum) */
- X n = atoi(p);
- X skiptows(p); skipws(p);
- X i = atoi(p);
- X skiptows(p); skipws(p);
- X x = atoi(p);
- X q = getmem(x, i, n);
- X printf("got %d bytes @ 0x%x %sfrom pool %d\n", n, q,
- X i ? "(aligned) ": "", x);
- X break;
- X case 'o': /* open a new pool */
- X n = openpool();
- X printf("pool %d opened\n", n);
- X break;
- X case 'c': /* close pool */
- X printf("closing pool %d\n", n = atoi(p));
- X x = closepool(n);
- X if (!x) {
- X printf("error closing pool %d\n", x);
- X }
- X break;
- X case 'q':
- X printf("exiting ...\n");
- X return;
- X default:
- X printf("unrecognized command '%c'\n", c);
- X break;
- X
- X }
- X }
- X}
- X
- Xdump() {
- X register struct poolhead *pl;
- X register struct memhunk *p;
- X register int i,j;
- X
- X for (i=0, pl = &head; pl != NIL; i++,pl = pl->pl_next) {
- X printf("\tpool %d (@ 0x%x):\n", i, pl);
- X for(j=0, p = pl->pl_pool; p != NIL; j++,p = p->m_next) {
- X printf("\t\tmemhunk %d (@ 0x%x)", j, p);
- X printf("buf %d bytes @ 0x%x (%d left @ 0x%x)\n",
- X p->m_size, p->m_base, p->m_nleft, p->m_free);
- X }
- X }
- X}
- X
- Xstatic
- Xatoi(p)
- Xregister char *p;
- X{
- X register int n = 0;
- X
- X while ((*p >= '0') && (*p <= '9')) {
- X n = (n*10) + (*p - '0');
- X p++;
- X }
- X return(n);
- X}
- X
- X#endif /* TEST */
- \Rogue\Monster\
- else
- echo "will not over write ./mem.c"
- fi
- chmod 444 ./mem.c
- if [ `wc -c ./mem.c | awk '{printf $1}'` -ne 8948 ]
- then
- echo `wc -c ./mem.c | awk '{print "Got " $1 ", Expected " 8948}'`
- fi
- echo "Finished archive 2 of 3"
- # if you want to concatenate archives, remove anything after this line
- exit
-