File: [local] / OpenXM_contrib2 / windows / cpp / cpp_main.c (download)
Revision 1.1.1.1 (vendor branch), Wed Nov 22 06:21:07 2000 UTC (23 years, 10 months ago) by noro
Branch: NORO, MAIN
CVS Tags: R_1_3_1-2, RELEASE_1_3_1_13b, RELEASE_1_2_3_12, RELEASE_1_2_3, RELEASE_1_2_2_KNOPPIX_b, RELEASE_1_2_2_KNOPPIX, RELEASE_1_2_2, RELEASE_1_2_1, KNOPPIX_2006, HEAD, DEB_REL_1_2_3-9, CPP Changes since 1.1: +0 -0
lines
I'll import cpp, a private C preprocessor.
|
#define VISUAL
/*
* Copyright (c) 1994-2000 FUJITSU LABORATORIES LIMITED
* All rights reserved.
*
* FUJITSU LABORATORIES LIMITED ("FLL") hereby grants you a limited,
* non-exclusive and royalty-free license to use, copy, modify and
* redistribute, solely for non-commercial and non-profit purposes, the
* computer program, "Risa/Asir" ("SOFTWARE"), subject to the terms and
* conditions of this Agreement. For the avoidance of doubt, you acquire
* only a limited right to use the SOFTWARE hereunder, and FLL or any
* third party developer retains all rights, including but not limited to
* copyrights, in and to the SOFTWARE.
*
* (1) FLL does not grant you a license in any way for commercial
* purposes. You may use the SOFTWARE only for non-commercial and
* non-profit purposes only, such as academic, research and internal
* business use.
* (2) The SOFTWARE is protected by the Copyright Law of Japan and
* international copyright treaties. If you make copies of the SOFTWARE,
* with or without modification, as permitted hereunder, you shall affix
* to all such copies of the SOFTWARE the above copyright notice.
* (3) An explicit reference to this SOFTWARE and its copyright owner
* shall be made on your publication or presentation in any form of the
* results obtained by use of the SOFTWARE.
* (4) In the event that you modify the SOFTWARE, you shall notify FLL by
* e-mail at risa-admin@sec.flab.fujitsu.co.jp of the detailed specification
* for such modification or the source code of the modified part of the
* SOFTWARE.
*
* THE SOFTWARE IS PROVIDED AS IS WITHOUT ANY WARRANTY OF ANY KIND. FLL
* MAKES ABSOLUTELY NO WARRANTIES, EXPRESSED, IMPLIED OR STATUTORY, AND
* EXPRESSLY DISCLAIMS ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT OF THIRD PARTIES'
* RIGHTS. NO FLL DEALER, AGENT, EMPLOYEES IS AUTHORIZED TO MAKE ANY
* MODIFICATIONS, EXTENSIONS, OR ADDITIONS TO THIS WARRANTY.
* UNDER NO CIRCUMSTANCES AND UNDER NO LEGAL THEORY, TORT, CONTRACT,
* OR OTHERWISE, SHALL FLL BE LIABLE TO YOU OR ANY OTHER PERSON FOR ANY
* DIRECT, INDIRECT, SPECIAL, INCIDENTAL, PUNITIVE OR CONSEQUENTIAL
* DAMAGES OF ANY CHARACTER, INCLUDING, WITHOUT LIMITATION, DAMAGES
* ARISING OUT OF OR RELATING TO THE SOFTWARE OR THIS AGREEMENT, DAMAGES
* FOR LOSS OF GOODWILL, WORK STOPPAGE, OR LOSS OF DATA, OR FOR ANY
* DAMAGES, EVEN IF FLL SHALL HAVE BEEN INFORMED OF THE POSSIBILITY OF
* SUCH DAMAGES, OR FOR ANY CLAIM BY ANY OTHER PARTY. EVEN IF A PART
* OF THE SOFTWARE HAS BEEN DEVELOPED BY A THIRD PARTY, THE THIRD PARTY
* DEVELOPER SHALL HAVE NO LIABILITY IN CONNECTION WITH THE USE,
* PERFORMANCE OR NON-PERFORMANCE OF THE SOFTWARE.
*
* $OpenXM: OpenXM_contrib2/windows/cpp/cpp_main.c,v 1.1.1.1 2000/11/22 06:21:07 noro Exp $
*/
#if defined(__MWERKS__)
#define THINK_C
#endif
#include <stdio.h>
#include <ctype.h>
#include <setjmp.h>
jmp_buf cpp_env;
#if 0
#include "accum.h"
#include "expr.h"
#include "if.h"
#include "io.h"
#include "is.h"
#include "malloc.h"
#include "stats.h"
#include "symtbl.h"
#include "unctrl.h"
#endif
#if defined(THINK_C)
#include <string.h>
int define(char *,int,unsigned char *,int);
void Bcopy(char *,char *,int);
#endif
#include "cpp.h"
char *init_accum(void)
{
ACCUM *a;
a = NEW(ACCUM);
check_malloc(a);
a->used = 0;
a->have = 8;
a->buf = malloc(8);
check_malloc(a->buf);
return((char *)a);
}
void accum_char(char *A, char c)
#define a ((ACCUM *)A)
{
while (a->used >= a->have)
{ a->buf = realloc(a->buf,a->have+=8);
check_malloc(a->buf);
}
a->buf[a->used++] = c;
}
#undef a
char accum_regret(char *A)
#define a ((ACCUM *)A)
{
if (a->used > 0)
{ return(a->buf[--a->used]);
}
else
{ return(0);
}
}
#undef a
char *accum_result(char *A)
#define a ((ACCUM *)A)
{
char *cp;
cp = realloc(a->buf,a->used+1);
check_malloc(cp);
cp[a->used] = '\0';
OLD(a);
return(cp);
}
#undef a
char *accum_sofar(char *A)
#define a ((ACCUM *)A)
{
char *cp;
cp = malloc(a->used+1);
check_malloc(cp);
Bcopy(a->buf,cp,a->used);
cp[a->used] = '\0';
return(cp);
}
#undef a
char *accum_buf(char *A)
#define a ((ACCUM *)A)
{
return(a->buf);
}
#undef a
int accum_howfar(char *A)
#define a ((ACCUM *)A)
{
return(a->used);
}
#undef a
void do_at(void)
{
char *w;
w = read_ctrl();
if (strcmp(w,"include") == 0)
{ do_include(0);
}
else if (strcmp(w,"define") == 0)
{ do_define(0,0);
}
else if (strcmp(w,"undef") == 0)
{ do_undef(0);
}
else if (strcmp(w,"redefine") == 0)
{ do_define(0,1);
}
else if (strcmp(w,"ifdef") == 0)
{ do_ifdef(0);
}
else if (strcmp(w,"ifndef") == 0)
{ do_ifndef(0);
}
else if (strcmp(w,"if") == 0)
{ do_if(0);
}
else if (strcmp(w,"else") == 0)
{ do_else(0);
}
else if (strcmp(w,"elif") == 0)
{ do_elif(0);
}
else if (strcmp(w,"endif") == 0)
{ do_endif(0);
}
else if (strcmp(w,"set") == 0)
{ do_set();
}
else if (strcmp(w,"while") == 0)
{ do_while();
}
else if (strcmp(w,"endwhile") == 0)
{ do_endwhile();
}
else if (strcmp(w,"dump") == 0)
{ do_dump();
}
else if (strcmp(w,"debug") == 0)
{ do_debug();
}
else if (strcmp(w,"eval") == 0)
{ do_eval();
}
else
{ if (! in_false_if())
{ err_head();
fprintf(stderr,"unknown control `%s'\n",w);
}
}
free(w);
}
static char *temp;
void autodef_file(char *f)
{
int i;
i = strlen(f);
temp = malloc(i+2+1);
check_malloc(temp);
sprintf(temp,"\"%s\"",f);
undef("__FILE__");
define("__FILE__",-1,(unsigned char *)temp,0);
}
void autodef_line(int l)
{
defd("__LINE__",l);
}
char *copyofstr(char *str)
{
char *cp;
if (str == 0)
{ return(0);
}
cp = malloc(strlen(str)+1);
if (cp == 0)
{ return(0);
}
strcpy(cp,str);
return(cp);
}
char *copyofblk(char *blk, int len)
{
char *cp;
if (blk == 0)
{ return(0);
}
cp = malloc(len);
if (cp == 0)
{ return(0);
}
Bcopy(blk,cp,len);
return(cp);
}
/* these really don't beint here; they should be in their own file */
#if 0
char *malloc(nb)
#undef malloc
int nb;
{
extern char *malloc();
return(malloc(nb?nb:1));
}
char *realloc(old,nb)
#undef realloc
char *old;
int nb;
{
extern char *realloc();
return(realloc(old,(nb?nb:1)));
}
#endif
static char buf[BUFSIZ];
int debugging = 0;
void do_debug(void)
{
char c;
fflush(outfile);
c = getnonspace();
switch (c)
{ case '1':
case 'y':
case 'Y':
debugging = 1;
break;
default:
debugging = 0;
break;
}
setbuf(outfile,debugging?NULL:buf);
}
static int nargs;
static int nfound;
static char **argnames;
void read_formals(void)
{
char *arg;
char c;
nargs = 0;
argnames = (char **) malloc(1);
check_malloc(argnames);
while (1)
{ arg = read_ident();
if (arg)
{ argnames = (char **) realloc((char *)argnames,(nargs+1)*sizeof(char *));
check_malloc(argnames);
argnames[nargs] = arg;
nargs ++;
c = getnonspace();
if (c == ')')
{ return;
}
else if (c != ',')
{ err_head();
fprintf(stderr,"invalid macro parameter delimiter\n");
}
}
else
{ c = Get();
if ((c == ')') && (nargs == 0))
{ return;
}
else
{ Push(c);
}
err_head();
fprintf(stderr,"missing/illegal macro parameter\n");
while (1)
{ c = Get();
if (c == ')')
{ return;
}
if (isbsymchar(c))
{ Push(c);
break;
}
}
}
}
}
void do_define(int sharp, int redef)
{
char *mac;
char c;
char *acc;
unsigned char *repl;
int quoted;
int incomment;
unsigned char *f;
unsigned char *t;
unsigned char *g;
int i;
if (in_false_if())
{ char e = '\0';
if (sharp)
{ while (1)
{ c = e;
e = Get();
if (e == '\n')
{ if (c == '\\')
{ maybe_print('\n');
}
else
{ break;
}
}
}
}
else
{ do
{ c = e;
e = Get();
} while ((c != '@') || (e == '@'));
Push(e);
}
return;
}
mac = read_ident();
if (! mac)
{ err_head();
fprintf(stderr,"missing/illegal macro name\n");
flush_sharp_line();
return;
}
c = Get();
if (c == '(')
{ read_formals();
nfound = nargs;
if (nargs > 128)
{ err_head();
fprintf(stderr,"too many macro formals, more than 128 ignored\n");
nargs = 128;
}
}
else
{ argnames = 0;
nargs = -1;
nfound = -1;
if ((c != ' ') && (c != '\t'))
{ Push(c);
}
}
quoted = 0;
incomment = 0;
acc = init_accum();
if (sharp)
{ while (1)
{ c = Get();
if (quoted && (c == '\n'))
{ quoted = 0;
maybe_print('\n');
}
else if (quoted)
{ accum_char(acc,'\\');
accum_char(acc,c);
quoted = 0;
}
else if (c == '/')
{ char d = Get();
accum_char(acc,'/');
if (d == '*')
{ accum_char(acc,'*');
incomment = 1;
}
else
{ Push(d);
}
}
else if (incomment)
{ accum_char(acc,c);
if (c == '*')
{ char d = Get();
if (d == '/')
{ accum_char(acc,'/');
incomment = 0;
}
else
{ Push(d);
}
}
else if (c == '\n')
{ maybe_print('\n');
}
}
else if (c == '\\')
{ quoted = 1;
}
else if (c == '\n')
{ break;
}
else
{ accum_char(acc,c);
}
}
}
else
{ while (1)
{ c = Get();
if (quoted && (c == '@'))
{ accum_char(acc,'@');
quoted = 0;
}
else if (quoted)
{ Push(c);
break;
}
else if (c == '/')
{ char d = Get();
accum_char(acc,'/');
if (d == '*')
{ accum_char(acc,'*');
incomment = 1;
}
else
{ Push(d);
}
}
else if (incomment)
{ accum_char(acc,c);
if (c == '*')
{ char d = Get();
if (d == '/')
{ accum_char(acc,'/');
incomment = 0;
}
else
{ Push(d);
}
}
else if (c == '\n')
{ maybe_print('\n');
}
}
else if (c == '@')
{ quoted = 1;
}
else
{ if (c == '\n')
{ maybe_print('\n');
}
accum_char(acc,c);
}
}
}
repl = (unsigned char *) accum_result(acc);
f = repl;
t = repl;
while (*f)
{ if (isbsymchar(*f) && !incomment)
{ for (g=f;issymchar(*g);g++) ;
c = *g;
*g = '\0';
for (i=0;i<nargs;i++)
{ if (strcmp((char *)f,argnames[i]) == 0)
{ break;
}
}
if (i < nargs)
{ *t++ = 0x80 | i;
f = g;
}
else
{ while (*t++ = *f++) ;
f --;
t --;
}
*g = c;
}
else if ((f[0] == '/') && (f[1] == '*'))
{ f += 2;
*t++ = '/';
*t++ = '*';
incomment = 1;
}
else if (incomment && (f[0] == '*') && (f[1] == '/'))
{ f += 2;
*t++ = '*';
*t++ = '/';
incomment = 0;
}
else
{ *t++ = *f++;
}
}
*t++ = '\0';
repl = (unsigned char *) realloc((char *)repl,t-repl);
check_malloc(repl);
if (redef)
{ undef(mac);
}
n_defines ++;
define(mac,nargs,repl,DEF_DEFINE);
if (argnames)
{ for (i=0;i<nfound;i++)
{ free(argnames[i]);
}
free((char *)argnames);
}
free(mac);
}
void do_dump(void)
{
int i;
DEF *d;
extern char *cur_incldir;
extern char *incldir[];
extern int fstackdepth;
fprintf(stderr,
"\n\n\tDump of definition table (%d entries in %d buckets):\n\n",
n_in_table,symtbl_size);
for (i=0;i<symtbl_size;i++)
{ fprintf(stderr,"Bucket %d:\n",i);
for (d=symtbl[i];d;d=d->link)
{ dump_single(d);
putc('\n',stderr);
}
}
fprintf(stderr,"\n\tInclude directory stack:\n\n");
for (i=0;i<fstackdepth;i++)
{ fprintf(stderr,"\t\t%s\n",incldir[i]);
}
fprintf(stderr,"\t\t%s\n",cur_incldir);
}
void dump_single(DEF *d)
{
unsigned char *cp;
fprintf(stderr,"\t%s",d->name);
if (d->nargs == 0)
{ fprintf(stderr,"()");
}
else if (d->nargs > 0)
{ int i;
for (i=0;i<d->nargs;i++)
{ fprintf(stderr,"%c#%d",i?',':'(',i);
}
putc(')',stderr);
}
putc(' ',stderr);
for (cp=d->repl;*cp;cp++)
{ if (*cp & 0x80)
{ fprintf(stderr,"#%d",(*cp)&~0x80);
}
else
{ putc(*cp,stderr);
}
}
}
void err_head(void)
{
fprintf(stderr,"\"%s\", line %d: ",curfile(),curline());
}
void Check_malloc(char *ptr)
{
if (ptr == 0)
{ fprintf(stderr,"out of memory!\n");
abort();
}
}
void do_eval(void)
{
char c;
char temp[64];
int i;
if (! in_false_if())
{ c = getnonspace();
if (c != '(')
{ err_head();
fprintf(stderr,"@eval must have ()s\n");
Push(c);
return;
}
sprintf(temp,"%d",eval_expr(0,1));
for (i=strlen(temp)-1;i>=0;i--)
{ Push(temp[i]);
}
}
}
#define DEBUG_EXPAND/**/
#ifdef DEBUG_EXPAND
extern int debugging;
#endif
extern int keep_comments;
static char **actuals;
static int *actlens;
void read_actuals(DEF *d)
{
int n;
int i;
int pc;
char c;
char last;
char quote;
int backslash;
int comment;
char *acc;
n = d->nargs;
actuals = (char **) malloc(n*sizeof(char *));
check_malloc(actuals);
actlens = (int *) malloc(n*sizeof(int));
check_malloc(actlens);
c = getnonspace();
if (c != '(')
{ err_head();
if (n == 0)
{ fprintf(stderr,"missing () on %s\n",d->name);
}
else
{ fprintf(stderr,"missing argument%s to %s\n",(n==1)?"":"s",d->name);
}
for (i=0;i<n;i++)
{ actuals[i] = copyofstr("");
check_malloc(actuals[i]);
actlens[i] = 0;
}
Push(c);
return;
}
if (n == 0)
{ c = getnonspace();
if (c != ')')
{ err_head();
fprintf(stderr,"unwanted argument to %s\n",d->name);
Push(c);
}
return;
}
i = 0;
while (1)
{ pc = 0;
quote = 0;
backslash = 0;
comment = 0;
c = 0;
acc = init_accum();
while (1)
{ last = c;
c = Get();
accum_char(acc,c);
if (comment)
{ if ((last == '*') && (c == '/'))
{ comment = 0;
}
}
else
{ if (backslash)
{ backslash = 0;
}
else if (quote && (c == quote))
{ quote = 0;
}
else if (c == '\\')
{ backslash = 1;
}
else if (quote)
{
}
else if ((last == '/') && (c == '*'))
{ comment = 1;
}
else if ((c == '\'') || (c == '"'))
{ quote = c;
}
else if (c == '(')
{ pc ++;
}
else if (c == ')')
{ if (pc > 0)
{ pc --;
}
else
{ accum_regret(acc);
break;
}
}
else if ((c == ',') && (pc == 0))
{ accum_regret(acc);
break;
}
}
}
if (i < n)
{ actuals[i] = accum_result(acc);
actlens[i] = strlen(actuals[i]);
i ++;
}
else if (i == n)
{ err_head();
fprintf(stderr,"too many arguments to %s\n",d->name);
i ++;
}
if (c == ')')
{ break;
}
}
if (i < n)
{ err_head();
fprintf(stderr,"too few arguments to %s\n",d->name);
for (;i<n;i++)
{ actuals[i] = copyofstr("");
check_malloc(actuals[i]);
actlens[i] = 0;
}
}
}
void expand_def(DEF *d)
{
unsigned char *cp;
char *dp;
char *ep;
char *result;
int ok;
int incomm;
char last;
if (d->nargs >= 0)
{ read_actuals(d);
}
#ifdef DEBUG_EXPAND
if (debugging)
{ char *cp;
outputs("~EXPAND:");
outputs(d->name);
if (d->nargs == 0)
{ outputs("()");
}
else if (d->nargs > 0)
{ int i;
for (i=0;i<d->nargs;i++)
{ outputc((char)(i?',':'('));
outputs(actuals[i]);
}
outputc(')');
}
outputs("-->");
for (cp=(char *)d->repl;*cp;cp++)
{ outputs(unctrl(*cp));
}
outputc('~');
}
#endif
result = init_accum();
for (cp=d->repl;*cp;cp++)
{ if (*cp & 0x80)
{ char *dp;
int i;
i = *cp & ~0x80;
for (dp=actuals[i];*dp;dp++)
{ accum_char(result,*dp);
}
}
else
{ accum_char(result,*cp);
}
}
dp = accum_result(result);
#ifdef DEBUG_EXPAND
if (debugging)
{ outputs("first:");
for (ep=dp;*ep;ep++)
{ outputs(unctrl(*ep));
}
outputc('~');
}
#endif
result = init_accum();
last = '\0';
ok = 1;
incomm = 0;
for (ep=dp;*ep;ep++)
{ if (!incomm && (last == '/') && (*ep == '*'))
{ incomm = 1;
if (!keep_comments || (strncmp(ep,"**/",3) == 0))
{ accum_regret(result);
ok = 0;
}
}
if (ok)
{ accum_char(result,*ep);
}
if ((last == '*') && (*ep == '/'))
{ incomm = 0;
ok = 1;
}
last = *ep;
}
free(dp);
result = accum_result(result);
#ifdef DEBUG_EXPAND
if (debugging)
{ outputs("/**/strip:");
outputs(result);
outputc('~');
}
#endif
for (dp=result+strlen(result)-1;dp>=result;dp--)
{ Push(*dp);
}
free(result);
if (d->nargs >= 0)
{ int i;
for (i=0;i<d->nargs;i++)
{ free(actuals[i]);
}
free((char *)actuals);
}
}
#define DEBUG_EXPR/**/
#define TWOCHAR(c1,c2) (((c1)<<8)|(c2))
#define LSH TWOCHAR('<','<')
#define RSH TWOCHAR('>','>')
#define LEQ TWOCHAR('<','=')
#define GEQ TWOCHAR('>','=')
#define EQL TWOCHAR('=','=')
#define NEQ TWOCHAR('!','=')
#define AND TWOCHAR('&','&')
#define OR TWOCHAR('|','|')
#define ALLBINS \
BIN('*',*) \
BIN('/',/) \
BIN('%',%) \
BIN('+',+) \
BIN(LSH,<<) \
BIN(RSH,>>) \
BIN('<',<) \
BIN('>',>) \
BIN(LEQ,<=) \
BIN(GEQ,>=) \
BIN(EQL,==) \
BIN(NEQ,!=) \
BIN('&',&) \
BIN('^',^) \
BIN('|',|) \
BIN(AND,&&) \
BIN(OR ,||)
char *Index(char *s, int c);
static NODE *expr;
int expr_sharp;
#define sharp expr_sharp
static int complain;
#ifdef DEBUG_EXPR
extern int debugging;
#endif
void free_expr(NODE *n)
{
switch (n->op)
{ case 0:
break;
case '-':
if (n->left)
{ free_expr(n->left);
}
free_expr(n->right);
break;
case '!':
case '~':
free_expr(n->right);
break;
case 'd':
free(n->name);
break;
default:
free_expr(n->left);
free_expr(n->right);
break;
}
OLD(n);
}
int exec_free(NODE *n)
{
int rv;
int l;
int r;
switch (n->op)
{ case 0:
rv = n->leaf;
break;
case '-':
if (n->left)
{ rv = exec_free(n->left);
}
else
{ rv = 0;
}
rv -= exec_free(n->right);
break;
case '!':
rv = ! exec_free(n->right);
break;
case '~':
rv = ~ exec_free(n->right);
break;
case 'd':
rv = !! find_def(n->name);
free(n->name);
break;
#define BIN(key,op) case key:l=exec_free(n->left);r=exec_free(n->right);rv=l op r;break;
ALLBINS
#undef BIN
}
OLD(n);
return(rv);
}
int exec_nofree(NODE *n)
{
int rv;
switch (n->op)
{ case 0:
rv = n->leaf;
break;
case '-':
if (n->left)
{ rv = exec_nofree(n->left);
}
else
{ rv = 0;
}
rv -= exec_nofree(n->right);
break;
case '!':
rv = ! exec_nofree(n->right);
break;
case '~':
rv = ~ exec_nofree(n->right);
break;
case 'd':
rv = !! find_def(n->name);
free(n->name);
break;
#define BIN(key,op) case key:rv=(exec_nofree(n->left)op exec_nofree(n->right));break;
ALLBINS
#undef BIN
}
return(rv);
}
NODE *newnode(NODE *l, int c, NODE *r)
{
NODE *n;
n = NEW(NODE);
check_malloc(n);
n->left = l;
n->right = r;
n->op = c;
return(n);
}
NODE *newleaf(int v)
{
NODE *n;
n = NEW(NODE);
check_malloc(n);
n->op = 0;
n->left = 0;
n->right = 0;
n->leaf = v;
return(n);
}
NODE *newname(char *name)
{
NODE *n;
n = NEW(NODE);
check_malloc(n);
n->op = 'd';
n->name = copyofstr(name);
check_malloc(n->name);
return(n);
}
int get_quote_char(void)
{
char c;
char d;
c = Get();
if (c == '\'')
{ return(-1);
}
if (c == '\n')
{ err_head();
fprintf(stderr,"newline in character constant\n");
return(-1);
}
if (c != '\\')
{ return(0xff&(int)c);
}
c = Get();
if ((c >= '0') && (c <= '7'))
{ d = c - '0';
c = Get();
if ((c >= '0') && (c <= '7'))
{ d = (d << 3) + c - '0';
c = Get();
if ((c >= '0') && (c <= '7'))
{ d = (d << 3) + c - '0';
}
else
{ Push(c);
}
}
else
{ Push(c);
}
return(0xff&(int)d);
}
switch (c)
{ case 'n':
return('\n');
break;
case 'r':
return('\r');
break;
case 'e':
return('\033');
break;
case 'f':
return('\f');
break;
case 't':
return('\t');
break;
case 'b':
return('\b');
break;
case 'v':
return('\v');
break;
default:
return(0xff&(int)c);
break;
}
}
NODE *read_expr_11(void)
{
char c;
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~E11:");
}
#endif
while (1)
{ c = getnhsexpand();
if (c == '(')
{ NODE *n;
NODE *read_expr_(void);
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("()");
}
#endif
n = read_expr_();
c = getnhsexpand();
if (c != ')')
{ err_head();
fprintf(stderr,"expression syntax error -- missing ) supplied\n");
Push(c);
}
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~");
}
#endif
return(n);
}
else if (isdigit(c))
{ int base;
static char digits[] = "0123456789abcdefABCDEF";
static char values[] =
"\0\1\2\3\4\5\6\7\10\11\12\13\14\15\16\17\12\13\14\15\16\17";
char *d;
int v;
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("N");
}
#endif
base = 10;
if (c == '0')
{ base = 8;
c = Get();
if ((c == 'x') || (c == 'X'))
{ base = 16;
c = Get();
}
}
v = 0;
while (1)
{ d = Index(digits,c);
if (d == 0)
{ Push(c);
#ifdef DEBUG_EXPR
if (debugging)
{ outputd(v);
outputs("~");
}
#endif
return(newleaf(v));
}
else if (values[d-digits] >= base)
{ err_head();
fprintf(stderr,"warning: illegal %sdigit `%c'\n",
(base==16)?"hex ":(base==8)?"octal ":"",c);
}
v = (v * base) + values[d-digits];
c = Get();
}
}
else if (c == '\'')
{ int i;
int j;
int n;
i = 0;
n = 0;
while (1)
{ j = get_quote_char();
if (j < 0)
{ break;
}
i = (i << 8) | j;
n ++;
}
if (n > 4)
{ err_head();
fprintf(stderr,"warning: too many characters in character constant\n");
}
return(newleaf(i));
}
else if ((c == '\n') && !sharp)
{
}
else
{ char *id;
if (complain)
{ err_head();
fprintf(stderr,"expression syntax error -- number expected\n");
}
if (isbsymchar(c))
{ Push(c);
id = read_ident();
}
else
{ id = 0;
}
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("0(");
outputc(c);
outputs(":");
outputs(id?id:"(none)");
outputs(")~");
}
#endif
if (id)
{ free(id);
}
return(newleaf(0));
}
}
}
NODE *read_expr_10(void)
{
char c;
char *w;
NODE *n;
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~E10:");
}
#endif
while (1)
{ c = getnhsexpand();
switch (c)
{ case '-':
case '~':
case '!':
#ifdef DEBUG_EXPR
if (debugging)
{ outputc(c);
}
#endif
n = read_expr_10();
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~");
}
#endif
return(newnode(0,c,n));
break;
case 'd':
Push(c);
input_mark();
w = read_ident();
if (strcmp(w,"defined") == 0)
{ c = getnonspace();
if (c == '(')
{ char *id;
id = read_ident();
if (id)
{ c = getnonspace();
if (c == ')')
{ input_unmark();
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("ifdef");
}
#endif
return(newname(id));
}
}
}
else if (isbsymchar(c))
{ char *id;
Push(c);
id = read_ident();
if (id)
{ input_unmark();
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("ifdef");
}
#endif
return(newname(id));
}
}
}
input_recover();
n = read_expr_11();
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~");
}
#endif
return(n);
break;
default:
Push(c);
n = read_expr_11();
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~");
}
#endif
return(n);
break;
}
}
}
NODE *read_expr_9(void)
{
NODE *l;
NODE *r;
char c;
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~E9:");
}
#endif
l = read_expr_10();
while (1)
{ c = getnhsexpand();
switch (c)
{ case '*':
case '/':
case '%':
#ifdef DEBUG_EXPR
if (debugging)
{ outputc(c);
}
#endif
r = read_expr_10();
l = newnode(l,c,r);
break;
default:
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~");
}
#endif
Push(c);
return(l);
break;
}
}
}
NODE *read_expr_8(void)
{
NODE *l;
NODE *r;
char c;
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~E8:");
}
#endif
l = read_expr_9();
while (1)
{ c = getnhsexpand();
switch (c)
{ case '+':
case '-':
#ifdef DEBUG_EXPR
if (debugging)
{ outputc(c);
}
#endif
r = read_expr_9();
l = newnode(l,c,r);
break;
default:
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~");
}
#endif
Push(c);
return(l);
break;
}
}
}
NODE *read_expr_7(void)
{
NODE *l;
NODE *r;
char c;
char d;
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~E7:");
}
#endif
l = read_expr_8();
while (1)
{ c = getnhsexpand();
switch (c)
{ case '<':
case '>':
d = Get();
if (d == c)
{
#ifdef DEBUG_EXPR
if (debugging)
{ outputc(c);
outputc(d);
}
#endif
r = read_expr_8();
l = newnode(l,(c=='<')?LSH:RSH,r);
break;
}
Push(d);
/* fall through ... */
default:
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~");
}
#endif
Push(c);
return(l);
break;
}
}
}
NODE *read_expr_6(void)
{
NODE *l;
NODE *r;
char c;
char d;
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~E6:");
}
#endif
l = read_expr_7();
while (1)
{ c = getnhsexpand();
switch (c)
{ case '<':
case '>':
d = Get();
if (d == '=')
{
#ifdef DEBUG_EXPR
if (debugging)
{ outputc(c);
outputc(d);
}
#endif
r = read_expr_7();
l = newnode(l,(c=='<')?LEQ:GEQ,r);
}
else
{
#ifdef DEBUG_EXPR
if (debugging)
{ outputc(c);
}
#endif
Push(d);
r = read_expr_7();
l = newnode(l,c,r);
}
break;
default:
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~");
}
#endif
Push(c);
return(l);
break;
}
}
}
NODE *read_expr_5(void)
{
NODE *l;
NODE *r;
char c;
char d;
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~E5:");
}
#endif
l = read_expr_6();
while (1)
{ c = getnhsexpand();
switch (c)
{ case '=':
case '!':
d = Get();
if (d == '=')
{
#ifdef DEBUG_EXPR
if (debugging)
{ outputc(c);
outputc(d);
}
#endif
r = read_expr_6();
l = newnode(l,(c=='=')?EQL:NEQ,r);
break;
}
Push(d);
/* fall through ... */
default:
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~");
}
#endif
Push(c);
return(l);
break;
}
}
}
NODE *read_expr_4(void)
{
NODE *l;
NODE *r;
char c;
char d;
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~E4:");
}
#endif
l = read_expr_5();
while (1)
{ c = getnhsexpand();
switch (c)
{ case '&':
d = Get();
if (d != '&')
{
#ifdef DEBUG_EXPR
if (debugging)
{ outputc(c);
outputc(d);
}
#endif
r = read_expr_5();
l = newnode(l,c,r);
break;
}
Push(d);
/* fall through ... */
default:
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~");
}
#endif
Push(c);
return(l);
break;
}
}
}
NODE *read_expr_3(void)
{
NODE *l;
NODE *r;
char c;
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~E3:");
}
#endif
l = read_expr_4();
while (1)
{ c = getnhsexpand();
switch (c)
{ case '^':
#ifdef DEBUG_EXPR
if (debugging)
{ outputc(c);
}
#endif
r = read_expr_4();
l = newnode(l,c,r);
break;
default:
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~");
}
#endif
Push(c);
return(l);
break;
}
}
}
NODE *read_expr_2(void)
{
NODE *l;
NODE *r;
char c;
char d;
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~E2:");
}
#endif
l = read_expr_3();
while (1)
{ c = getnhsexpand();
switch (c)
{ case '|':
d = Get();
if (d != '|')
{ Push(d);
#ifdef DEBUG_EXPR
if (debugging)
{ outputc(c);
}
#endif
r = read_expr_3();
l = newnode(l,c,r);
break;
}
Push(d);
/* fall through ... */
default:
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~");
}
#endif
Push(c);
return(l);
break;
}
}
}
NODE *read_expr_1(void)
{
NODE *l;
NODE *r;
char c;
char d;
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~E1:");
}
#endif
l = read_expr_2();
while (1)
{ c = getnhsexpand();
switch (c)
{ case '&':
d = Get();
if (d == c)
{
#ifdef DEBUG_EXPR
if (debugging)
{ outputc(c);
outputc(d);
}
#endif
r = read_expr_2();
l = newnode(l,AND,r);
break;
}
Push(d);
/* fall through ... */
default:
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~");
}
#endif
Push(c);
return(l);
break;
}
}
}
NODE *read_expr_0(void)
{
NODE *l;
NODE *r;
char c;
char d;
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~E0:");
}
#endif
l = read_expr_1();
while (1)
{ c = getnhsexpand();
switch (c)
{ case '|':
d = Get();
if (d == c)
{
#ifdef DEBUG_EXPR
if (debugging)
{ outputc(c);
outputc(d);
}
#endif
r = read_expr_1();
l = newnode(l,OR,r);
break;
}
Push(d);
/* fall through ... */
default:
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~");
}
#endif
Push(c);
return(l);
break;
}
}
}
NODE *read_expr_(void)
{
NODE *l;
NODE *r;
char c;
#ifdef DEBUG_EXPR
if (debugging)
{ outputs("~E");
}
#endif
l = read_expr_0();
while (1)
{ c = getnhsexpand();
switch (c)
{ case '\n':
case ')':
Push(c);
return(l);
break;
case ',':
r = read_expr_0();
l = newnode(l,c,r);
break;
default:
err_head();
fprintf(stderr,"expression syntax error -- bad operator `%c'\n",c);
return(l);
break;
}
}
}
NODE *read_expr_p(void)
{
char c;
NODE *rv;
sharp = 0;
complain = 1;
c = getnonspace();
if (c != '(')
{ Push(c);
return(0);
}
rv = read_expr_();
c = getnonspace();
if (c != ')')
{ err_head();
fprintf(stderr,"junk after expression\n");
}
return(rv);
}
int eval_expr(int Sharp, int Complain)
{
char c;
char d;
int rv;
sharp = Sharp;
complain = Complain;
expr = read_expr_();
if (sharp)
{ c = getnonhspace();
d = '\n';
}
else
{ c = getnonspace();
d = ')';
}
if (c != d)
{ if (complain)
{ err_head();
fprintf(stderr,"expression syntax error -- junk after expression\n");
}
while (Get() != d) ;
}
#ifdef DEBUG_EXPR
if (debugging)
{ outputc('<');
dump_expr(expr);
outputc('=');
rv = exec_free(expr);
outputd(rv);
outputc('>');
}
else
{ rv = exec_free(expr);
}
return(rv);
#else
return(exec_free(expr));
#endif
}
#ifdef DEBUG_EXPR
void dump_expr(NODE *n)
{
switch (n->op)
{ case 0:
outputd(n->leaf);
break;
case '-':
if (n->left)
{ dump_expr(n->left);
}
outputc('-');
dump_expr(n->right);
break;
case '!':
outputc('!');
dump_expr(n->right);
break;
case '~':
outputc('~');
dump_expr(n->right);
break;
case 'd':
outputs("defined(");
outputs(n->name);
outputc(')');
break;
#define BIN(key,op) case key:dump_expr(n->left);\
putx(key);\
dump_expr(n->right);\
break;
ALLBINS
#undef BIN
}
}
void putx(int i)
{
if (i > 0xff) outputc((char)(i>>8));
outputc((char)(i&0xff));
}
#endif
/*#define DEBUG_IF/**/
#ifdef DEBUG_IF
extern int debugging;
#endif
void do_if(int expr_sharp)
{
char c;
char d;
#ifdef DEBUG_IF
if (debugging)
{ outputc('<');
outputc(sharp?'#':'@');
outputs("if: ");
fflush(outfile);
}
#endif
if (in_false_if())
{ n_skipped_ifs ++;
#ifdef DEBUG_IF
if (debugging)
{ outputs("in-false, skipped>");
fflush(outfile);
}
#endif
if (sharp)
{ d = '\0';
do
{ c = d;
d = Get();
} while ((c == '\\') || (d != '\n'));
}
return;
}
if (! sharp)
{ c = getnonspace();
if (c != '(')
{ err_head();
fprintf(stderr,"@if must have ()s\n");
Push(c);
iffalse();
#ifdef DEBUG_IF
if (debugging)
{ outputc('>');
fflush(outfile);
}
#endif
return;
}
}
if (eval_expr(sharp,0))
{ iftrue();
}
else
{ iffalse();
}
#ifdef DEBUG_IF
if (debugging)
{ outputc('>');
fflush(outfile);
}
#endif
}
void do_ifdef(int expr_sharp)
{
char *w;
#ifdef DEBUG_IF
if (debugging)
{ outputc('<');
outputc(sharp?'#':'@');
outputs("ifdef: ");
fflush(outfile);
}
#endif
if (in_false_if())
{ n_skipped_ifs ++;
#ifdef DEBUG_IF
if (debugging)
{ outputs("in-false, skipped>");
fflush(outfile);
}
#endif
}
else
{ w = read_ident();
if (! w)
{
#ifdef DEBUG_IF
if (debugging)
{ outputs("no ident ");
fflush(outfile);
}
#endif
iffalse();
}
else
{
#ifdef DEBUG_IF
if (debugging)
{ outputs(w);
outputc(' ');
fflush(outfile);
}
#endif
if (find_def(w))
{ iftrue();
}
else
{ iffalse();
}
free(w);
}
#ifdef DEBUG_IF
if (debugging)
{ outputc('>');
fflush(outfile);
}
#endif
}
if (sharp)
{ flush_sharp_line();
}
}
void do_ifndef(int expr_sharp)
{
char *w;
#ifdef DEBUG_IF
if (debugging)
{ outputc('<');
outputc(sharp?'#':'@');
outputs("ifndef: ");
fflush(outfile);
}
#endif
if (in_false_if())
{ n_skipped_ifs ++;
#ifdef DEBUG_IF
if (debugging)
{ outputs("in-false, skipped>");
fflush(outfile);
}
#endif
}
else
{ w = read_ident();
if (! w)
{
#ifdef DEBUG_IF
if (debugging)
{ outputs("no ident ");
fflush(outfile);
}
#endif
iftrue();
}
else
{
#ifdef DEBUG_IF
if (debugging)
{ outputs(w);
outputc(' ');
fflush(outfile);
}
#endif
if (find_def(w))
{ iffalse();
}
else
{ iftrue();
}
free(w);
}
#ifdef DEBUG_IF
if (debugging)
{ outputc('>');
fflush(outfile);
}
#endif
}
if (sharp)
{ flush_sharp_line();
}
}
void do_else(int expr_sharp)
{
#ifdef DEBUG_IF
if (debugging)
{ outputc('<');
outputc(sharp?'#':'@');
outputs("else: ");
fflush(outfile);
}
#endif
if (n_skipped_ifs == 0)
{ if (ifstack)
{
#ifdef DEBUG_IF
if (debugging)
{ outputs("top ");
output_ifstate(ifstack->condstate);
fflush(outfile);
}
#endif
switch (ifstack->condstate)
{ case IFSTATE_TRUE:
ifstack->condstate = IFSTATE_STAYFALSE;
break;
case IFSTATE_FALSE:
ifstack->condstate = IFSTATE_TRUE;
break;
}
#ifdef DEBUG_IF
if (debugging)
{ outputs(" now ");
output_ifstate(ifstack->condstate);
outputc('>');
fflush(outfile);
}
#endif
}
else
{
#ifdef DEBUG_IF
if (debugging)
{ outputs(" no if>");
fflush(outfile);
}
#endif
err_head();
fprintf(stderr,"if-less else\n");
}
}
else
{
#ifdef DEBUG_IF
if (debugging)
{ outputs("in-false, forgetting>");
fflush(outfile);
}
#endif
}
if (sharp)
{ flush_sharp_line();
}
}
#ifdef DEBUG_IF
void output_ifstate(state)
int state;
{
switch (state)
{ case IFSTATE_TRUE:
outputs("TRUE");
break;
case IFSTATE_FALSE:
outputs("FALSE");
break;
case IFSTATE_STAYFALSE:
outputs("STAYFALSE");
break;
default:
outputs("BAD");
outputd(state);
break;
}
}
#endif
void do_elif(int expr_sharp)
{
char c;
char d;
int e;
#ifdef DEBUG_IF
if (debugging)
{ outputc('<');
outputc(sharp?'#':'@');
outputs("elif: ");
fflush(outfile);
}
#endif
if (ifstack == 0)
{ err_head();
fprintf(stderr,"if-less elif converted to normal if\n");
iffalse();
}
if (n_skipped_ifs > 0)
{
#ifdef DEBUG_IF
if (debugging)
{ outputs("being skipped, ignoring>");
fflush(outfile);
}
#endif
if (sharp)
{ d = '\0';
do
{ c = d;
d = Get();
} while ((c == '\\') || (d != '\n'));
}
return;
}
if (! sharp)
{ c = getnonspace();
if (c != '(')
{ err_head();
fprintf(stderr,"@elif must have ()s\n");
Push(c);
ifstack->condstate = IFSTATE_STAYFALSE;
#ifdef DEBUG_IF
if (debugging)
{ outputs("forcing STAYFALSE>");
fflush(outfile);
}
#endif
return;
}
}
e = eval_expr(sharp,0);
#ifdef DEBUG_IF
if (debugging)
{ outputs("expr ");
outputd(e);
outputc(' ');
fflush(outfile);
}
#endif
#ifdef DEBUG_IF
if (debugging)
{ outputs(" top ");
output_ifstate(ifstack->condstate);
fflush(outfile);
}
#endif
switch (ifstack->condstate)
{ case IFSTATE_TRUE:
ifstack->condstate = IFSTATE_STAYFALSE;
break;
case IFSTATE_FALSE:
if (e)
{ ifstack->condstate = IFSTATE_TRUE;
}
break;
}
#ifdef DEBUG_IF
if (debugging)
{ outputs(" now ");
output_ifstate(ifstack->condstate);
outputc('>');
fflush(outfile);
}
#endif
}
void do_endif(int expr_sharp)
{
IF *i;
#ifdef DEBUG_IF
if (debugging)
{ outputc('<');
outputc(sharp?'#':'@');
outputs("endif: ");
fflush(outfile);
}
#endif
if (n_skipped_ifs > 0)
{ n_skipped_ifs --;
#ifdef DEBUG_IF
if (debugging)
{ outputs("n_skipped -->");
fflush(outfile);
}
#endif
}
else if (ifstack)
{ i = ifstack->next;
OLD(ifstack);
ifstack = i;
#ifdef DEBUG_IF
if (debugging)
{ outputs("popping stack>");
fflush(outfile);
}
#endif
}
else
{ err_head();
fprintf(stderr,"if-less endif\n");
#ifdef DEBUG_IF
if (debugging)
{ outputc('>');
fflush(outfile);
}
#endif
}
if (sharp)
{ flush_sharp_line();
}
}
void iftrue(void)
{
IF *i;
i = NEW(IF);
check_malloc(i);
i->next = ifstack;
ifstack = i;
i->condstate = IFSTATE_TRUE;
#ifdef DEBUG_IF
if (debugging)
{ outputs("IFTRUE");
fflush(outfile);
}
#endif
}
void iffalse(void)
{
IF *i;
i = NEW(IF);
check_malloc(i);
i->next = ifstack;
ifstack = i;
i->condstate = IFSTATE_FALSE;
#ifdef DEBUG_IF
if (debugging)
{ outputs("IFFALSE");
fflush(outfile);
}
#endif
}
int in_false_if(void)
{
return(ifstack && (ifstack->condstate != IFSTATE_TRUE));
}
void maybe_print(char c)
{
extern int incldep;
if (incldep)
{ return;
}
if ((c == '\n') || !in_false_if())
{ outputc(c);
}
}
char *Rindex(char *s, int c);
int nIfiles;
char **Ifiles;
void init_include(void)
{
nIfiles = 0;
Ifiles = (char **) malloc(1);
check_malloc(Ifiles);
}
void Ifile(char *f)
{
Ifiles = (char **) realloc((char *)Ifiles,(nIfiles+1)*sizeof(char *));
check_malloc(Ifiles);
Ifiles[nIfiles] = copyofstr(f);
check_malloc(Ifiles[nIfiles]);
nIfiles ++;
}
void do_include(int expr_sharp)
{
char c;
char *acc;
if (in_false_if())
{ if (sharp)
{ flush_sharp_line();
}
return;
}
while (1)
{ c = getnonspace();
if (isbsymchar(c))
{ char *cp;
DEF *d;
cp = init_accum();
while (issymchar(c))
{ accum_char(cp,c);
c = Get();
}
Push(c);
cp = accum_result(cp);
d = find_def(cp);
if (d)
{ expand_def(d);
n_hits ++;
}
else
{ char *dp;
for (dp=cp+strlen(cp);dp>cp;dp--) Push(*dp);
n_misses ++;
}
}
else
{ break;
}
}
acc = init_accum();
if (c == '"')
{ while (1)
{ c = Get();
if (c == '\n')
{ Push('\n');
c = '"';
err_head();
fprintf(stderr,"warning: unterminated %cinclude filename\n",
sharp?'#':'@');
}
if (c == '"')
{ break;
}
accum_char(acc,c);
}
if (sharp)
{ flush_sharp_line();
}
read_include_file(accum_result(acc),1,sharp);
}
else if (c == '<')
{ while (1)
{ c = Get();
if (c == '\n')
{ Push('\n');
c = '>';
err_head();
fprintf(stderr,"warning: unterminated %cinclude filename\n",
sharp?'#':'@');
}
if (c == '>')
{ break;
}
accum_char(acc,c);
}
if (sharp)
{ flush_sharp_line();
}
read_include_file(accum_result(acc),0,sharp);
}
else
{ free(accum_result(acc));
err_head();
fprintf(stderr,"illegal %cinclude filename delimiter\n",sharp?'#':'@');
}
}
#if defined(THINK_C)
#if defined(DELIM)
#undef DELIM
#endif
#define DELIM ':'
#endif
#if defined(SYSV)
#else
#if defined(DELIM)
#undef DELIM
#endif
#define DELIM '/'
#endif
#if defined(VISUAL)
#if defined(DELIM)
#undef DELIM
#endif
#define DELIM '\\'
#endif
void read_include_file(char *name, int dohere, int expr_sharp)
{
FILE *f;
char *n;
char temp[1024];
char *cp;
extern int incldep;
extern char *incldep_o;
f = NULL;
if (dohere)
{ if ((strcmp(curdir(),".") != 0) && (name[0] != DELIM))
{ sprintf(temp,"%s%c%s",curdir(),DELIM,name);
n = temp;
}
else
{ n = name;
}
f = fopen(n,"r");
}
if (f == NULL)
{ if (name[0] == DELIM)
{ f = fopen(name,"r");
n = name;
}
else
{ int i;
n = temp;
for (i=0;i<nIfiles;i++)
{ sprintf(temp,"%s%c%s",Ifiles[i],DELIM,name);
f = fopen(temp,"r");
if (f != NULL)
{ break;
}
}
}
}
if (f == NULL)
{ err_head();
fprintf(stderr,"can't find include file %s\n",name);
free(name);
return;
}
if (incldep)
{ printf("%s: %s\n",incldep_o,n);
}
out_at(!sharp,n);
autodef_file(n);
autodef_line(1);
Push('\n');
Get();
push_new_file(n,f);
cp = Rindex(n,DELIM);
if (cp)
{ *cp = '\0';
cp = copyofstr(n);
}
else
{ cp = copyofstr(".");
}
check_malloc(cp);
*Curdir() = cp;
free(name);
return;
}
/*#define DEBUG_IO/**/
/*#define DEBUG_INCL/**/
#if defined(DEBUG_IO) || defined(DEBUG_INCL)
extern int debugging;
#endif
extern int no_line_lines;
int linefirst;
int willbefirst;
int lineno[MAXFILES];
FILE *fstack[MAXFILES];
int fstackdepth;
char *fn[MAXFILES];
int npushed[MAXFILES];
char pushback[MAXFILES][MAX_PUSHBACK];
char *incldir[MAXFILES];
FILE *outfile;
char *cur_pushback;
int cur_npushed;
FILE *cur_fstack;
char *cur_fn;
char *cur_incldir;
int cur_lineno;
typedef struct _mark {
struct _mark *link;
char *acc;
int startdepth;
int incs[MAXFILES];
int nincs;
int nignore; } MARK;
static MARK *marks;
static int atline;
static char *atfile;
static int done_line;
static int nnls;
/* XXX these definitions assume no input chars are 81, 82, 83 */
#define NOEXPAND ((char)0x81)
#define MARKLINE ((char)0x82)
#define MARKLEND ((char)0x83)
void init_io(FILE *f, char *fnname)
{
register int i;
fstackdepth = 0;
cur_pushback = pushback[0];
cur_npushed = 0;
cur_fstack = f;
cur_fn = copyofstr(fnname);
check_malloc(cur_fn);
cur_lineno = 1;
nnls = 0;
atfile = copyofstr("");
check_malloc(atfile);
for (i=0;i<MAXFILES;i++)
{ npushed[i] = 0;
}
marks = 0;
}
void init_incldir(char *d)
{
cur_incldir = copyofstr(d);
check_malloc(cur_incldir);
}
void change_fstackdepth(int delta)
{
npushed[fstackdepth] = cur_npushed;
fstack[fstackdepth] = cur_fstack;
fn[fstackdepth] = cur_fn;
incldir[fstackdepth] = cur_incldir;
lineno[fstackdepth] = cur_lineno;
fstackdepth += delta;
cur_pushback = pushback[fstackdepth];
cur_npushed = npushed[fstackdepth];
cur_fstack = fstack[fstackdepth];
cur_fn = fn[fstackdepth];
cur_incldir = incldir[fstackdepth];
cur_lineno = lineno[fstackdepth];
}
#define GET() (cur_pushback[--cur_npushed])
#define PUSH() (cur_pushback[cur_npushed++])
char Get(void)
{
char c;
linefirst = willbefirst;
willbefirst = 0;
while (1)
{ if (cur_npushed > 0)
{ do
{ c = GET();
} while (c == NOEXPAND);
if (c == MARKLINE)
{ mark_get_line();
continue;
}
mark_got_from_pushback(c);
#ifdef DEBUG_IO
if (debugging)
{ outputc('(');
outputs(unctrl(c));
outputc(')');
fflush(outfile);
}
#endif
break;
}
else
{ c = getc(cur_fstack);
if (feof(cur_fstack))
{ if (fstackdepth > 0)
{
#ifdef DEBUG_INCL
if (debugging)
{ outputs("--eof:");
outputs(cur_fn);
outputs("--");
}
#endif
fclose(cur_fstack);
free(cur_fn);
free(cur_incldir);
change_fstackdepth(-1);
mark_file_ending();
out_at(cur_lineno,cur_fn);
autodef_file(curfile());
autodef_line(curline());
continue;
}
else
{ flush_final_nl();
save_stats();
#if 0
exit(0);
#endif
longjmp(cpp_env,1);
}
}
mark_got_from_file(c);
#ifdef DEBUG_IO
if (debugging)
{ outputc('<');
outputs(unctrl(c));
outputc('>');
fflush(outfile);
}
#endif
break;
}
}
if (c == '\n')
{ cur_lineno ++;
autodef_line(curline());
willbefirst = 1;
}
return(c);
}
void push_new_file(char *name, FILE *f)
{
change_fstackdepth(1);
cur_fn = copyofstr(name);
check_malloc(cur_fn);
cur_lineno = 1;
cur_fstack = f;
cur_npushed = 0;
#ifdef DEBUG_INCL
if (debugging)
{ outputs("--newfile:");
outputs(name);
outputs("--");
}
#endif
mark_file_beginning();
}
void Push(char c)
{
if (cur_npushed > MAX_PUSHBACK)
{ fprintf(stderr,"too much pushback\n");
cur_npushed = 0;
}
PUSH() = c;
mark_charpushed();
willbefirst = 0;
if (c == '\n')
{ cur_lineno --;
autodef_line(curline());
}
#ifdef DEBUG_IO
if (debugging)
{ outputc('[');
outputs(unctrl(c));
outputc(']');
fflush(outfile);
}
#endif
}
char *curfile(void)
{
return(cur_fn);
}
char **Curfile(void)
{
return(&cur_fn);
}
int curline(void)
{
return(cur_lineno);
}
int *Curline(void)
{
return(&cur_lineno);
}
char *curdir(void)
{
return(cur_incldir);
}
char **Curdir(void)
{
return(&cur_incldir);
}
char getnonspace(void)
{
char c;
while (isspace(c=Get())) ;
return(c);
}
char getnonhspace(void)
{
char c;
while (ishspace(c=Get())) ;
return(c);
}
char getnhsexpand(void)
{
char c;
while (1)
{ c = getexpand();
if (ishspace(c))
{ continue;
}
if (expr_sharp && (c == '\\'))
{ c = Get();
if (c == '\n')
{ continue;
}
else
{ Push(c);
c = '\\';
}
}
break;
}
return(c);
}
char getexpand(void)
{
char c;
char *str;
DEF *d;
while (1)
{ c = Get();
if (c == '/')
{ char d;
d = Get();
if (d == '*')
{ d = '\0';
do
{ c = d;
d = Get();
} while ((c != '*') || (d != '/'));
continue;
}
else
{ Push(d);
return('/');
}
}
else if (c == NOEXPAND)
{ c = Get();
if (issymchar(c))
{ Push(NOEXPAND);
}
return(c);
}
else if (! isbsymchar(c))
{
return(c);
}
str = init_accum();
do
{ accum_char(str,c);
} while (issymchar(c=Get()));
Push(c);
str = accum_result(str);
if (d = find_def(str))
{ expand_def(d);
free(str);
}
else
{ int i;
for (i=strlen(str)-1;i>0;i--)
{ Push(str[i]);
}
Push(NOEXPAND);
c = str[0];
free(str);
return(c);
}
}
}
char *read_ctrl(void)
{
char c;
char *acc;
acc = init_accum();
while (ishspace(c=Get())) ;
Push(c);
while (1)
{ c = Get();
if (islower(c))
{ accum_char(acc,c);
}
else
{ Push(c);
return(accum_result(acc));
}
}
}
char *read_ident(void)
{
char *acc;
char c;
c = getnonspace();
if (! isbsymchar(c))
{ Push(c);
return(0);
}
acc = init_accum();
do
{ accum_char(acc,c);
} while (issymchar(c=Get()));
Push(c);
return(accum_result(acc));
}
void out_at(int line, char *file)
{
if ((line-nnls != atline) || strcmp(file,atfile))
{ free(atfile);
atline = line - nnls;
atfile = copyofstr(file);
check_malloc(atfile);
done_line = 0;
}
}
void outputc(char c)
{
extern int incldep;
static char *white = 0;
if (incldep)
{ return;
}
if (c == '\n')
{ nnls ++;
if (white)
{ free(accum_result(white));
white = 0;
}
}
else if ((nnls > 0) && ((c == ' ') || (c == '\t')))
{ if (! white)
{ white = init_accum();
}
accum_char(white,c);
}
else
{ if ((nnls > 2) || !done_line)
{ atline += nnls;
nnls = 0;
if (no_line_lines)
{ fprintf(outfile,"\n");
}
else
{ fprintf(outfile,"\n# %d \"%s\"\n",atline,atfile);
}
done_line = 1;
}
for (;nnls;nnls--)
{ atline ++;
putc('\n',outfile);
}
if (white)
{ white = accum_result(white);
fputs(white,outfile);
free(white);
white = 0;
}
putc(c,outfile);
}
}
void flush_final_nl(void)
{
if (nnls > 0)
{ putc('\n',outfile);
}
}
void outputs(char *s)
{
for (;*s;s++)
{ outputc(*s);
}
}
void outputd(int n)
{
char temp[64];
sprintf(temp,"%d",n);
outputs(temp);
}
void mark_push_here(MARK *,int,char *);
void input_mark(void)
{
MARK *m;
m = NEW(MARK);
check_malloc(m);
m->link = marks;
marks = m;
m->startdepth = fstackdepth;
m->acc = init_accum();
m->nignore = 0;
m->nincs = 0;
mark_push_here(m,curline(),curfile());
#ifdef DEBUG_IO
if (debugging)
{ outputs("~MARK~");
}
#endif
}
void input_unmark(void)
{
MARK *m;
if (marks)
{ m = marks;
marks = m->link;
free(accum_result(m->acc));
OLD(m);
#ifdef DEBUG_IO
if (debugging)
{ outputs("~UNMARK~");
}
#endif
}
}
void input_recover(void)
{
register MARK *m;
register char *txt;
register int i;
register int l;
char c;
if (marks)
{ m = marks;
marks = m->link;
#ifdef DEBUG_IO
if (debugging)
{ outputs("~RECOVER~");
}
#endif
for (;m->nignore>0;m->nignore--)
{ accum_regret(m->acc);
}
txt = accum_result(m->acc);
i = strlen(txt) - 1;
while (m->nincs > 0)
{ l = m->incs[--m->nincs];
for (;i>=l;i--)
{ Push(txt[i]);
}
Push(MARKLEND);
c = txt[i];
for (i--;txt[i]!=c;i--)
{ Push(txt[i]);
}
Push('A');
Push('@');
Push('@');
Push('@');
Push('@');
Push('@');
Push('@');
Push('@');
for (;(txt[i]!='#')&&(txt[i]!='@');i--) ;
Push(MARKLINE);
i --;
}
for (;i>=0;i--)
{ Push(txt[i]);
}
free(txt);
OLD(m);
}
}
void mark_file_beginning(void)
{
register MARK *m;
for (m=marks;m;m=m->link)
{ m->incs[m->nincs++] = accum_howfar(m->acc);
}
}
void mark_file_ending(void)
{
register MARK *m;
register int i;
register int to;
register char *acc;
for (m=marks;m;m=m->link)
{ if (m->startdepth > fstackdepth)
{ m->startdepth = fstackdepth;
mark_push_here(m,curline(),curfile());
}
else if (m->nincs <= 0)
{ fprintf(stderr,"INTERNAL BUG: nincs<0 in mark_file_ending\n");
abort();
}
else
{ to = m->incs[--m->nincs];
acc = m->acc;
for (i=accum_howfar(acc);i>to;i--)
{ accum_regret(acc);
}
}
}
}
void mark_charpushed(void)
{
register MARK *m;
for (m=marks;m;m=m->link)
{ m->nignore ++;
}
}
void mark_got_from_pushback(char c)
{
mark_got(c);
}
void mark_got_from_file(char c)
{
mark_got(c);
}
void mark_got(char c)
{
register MARK *m;
for (m=marks;m;m=m->link)
{ if (m->nignore > 0)
{ m->nignore --;
}
else
{ accum_char(m->acc,c);
}
}
}
void mark_push_here(MARK *m, int l, char *f)
{
int i;
char c;
switch (c=accum_regret(m->acc))
{ case 0:
break;
case MARKLEND:
while (accum_regret(m->acc) != MARKLINE) ;
break;
default:
accum_char(m->acc,c);
break;
}
accum_char(m->acc,MARKLINE);
for (i=28;i>=0;i-=4)
{ accum_char(m->acc,(char)('@'+((l>>i)&0xf)));
}
for (;*f;f++)
{ accum_char(m->acc,*f);
}
accum_char(m->acc,MARKLEND);
}
void mark_get_line(void)
{
int l;
char *f;
int i;
char c;
MARK *m;
l = 0;
for (i=0;i<8;i++)
{ l = (l << 4) + (GET() & 0xf);
}
f = init_accum();
while ((c=GET()) != MARKLEND)
{ accum_char(f,c);
}
f = accum_result(f);
out_at(l,f);
for (m=marks;m;m=m->link)
{ mark_push_here(m,l,f);
}
free(f);
}
int ishspace(char c)
{
return((c == ' ') || (c == '\t'));
}
int isbsymchar(char c)
{
return(isalpha(c) || (c == '_'));
}
int issymchar(char c)
{
return(isalnum(c) || (c == '_') || (c == '$'));
}
void do_line(void)
{
char c;
outputc('#');
while ((c=Get()) != '\n')
{ outputc(c);
}
}
#define DEBUG_MAIN/**/
extern char **argvec;
char *Index(char *s, int c);
char *Rindex(char *s, int c);
#ifdef DEBUG_MAIN
extern int debugging;
#endif
static char quote;
IF *ifstack;
int n_skipped_ifs;
int keep_comments;
int no_line_lines;
int incldep;
char *incldep_o;
int do_at_ctrls;
extern char *predefs[];
#if defined(SYSV)
void main(ac,av)
#else
void cpp_main(int ac, char **av)
#endif
{
int argno;
int rest;
char *cp;
static FILE *inf;
static FILE *outf;
char *inname;
int backslash;
int i;
if ( setjmp(cpp_env) ) {
if ( inf != stdin )
fclose(inf);
if ( outf == stdout )
fflush(outf);
else
fclose(outf);
return;
}
init_symtbl();
#define predef(str) ( (cp=copyofstr("1")), \
check_malloc(cp), \
define((str),-1,(unsigned char *)cp,DEF_PREDEF) )
for (i=0;predefs[i];i++)
{ predef(predefs[i]);
}
init_include();
inf = stdin;
outf = stdout;
inname = "";
keep_comments = 0;
no_line_lines = 0;
do_at_ctrls = 0;
incldep = 0;
argno = 0;
for (ac--,av++;ac;ac--,av++)
{ if (**av == '-')
{ rest = 0;
if (!strcmp(*av,"-undef"))
{ undef_predefs();
}
else
{ for (++*av;(**av)&&!rest;++*av)
{ switch (**av)
{ case 'C':
keep_comments = 1;
break;
case 'D':
rest = 1;
++*av;
if (strcmp(*av,"@") == 0)
{ do_at_ctrls = 1;
}
else
{ cp = Index(*av,'=');
if (cp)
{ if (cp != *av)
{ char *dp;
*cp++ = '\0';
dp = copyofstr(cp);
check_malloc(dp);
define(*av,-1,(unsigned char *)dp,DEF_CMDLINE);
}
else
{ fprintf(stderr,"Must give a name for -D\n");
}
}
else
{ char *dp;
dp = copyofstr("1");
check_malloc(dp);
define(*av,-1,(unsigned char *)dp,DEF_CMDLINE);
}
}
break;
case 'E':
break;
case 'I':
rest = 1;
++*av;
if (**av)
{ Ifile(*av);
}
else
{ fprintf(stderr,"Must give a directory name for -I\n");
}
break;
case 'M':
incldep = 1;
break;
case 'P':
no_line_lines = 1;
break;
case 'R':
break;
case 'U':
rest = 1;
++*av;
if (**av)
{ undef(*av);
}
else
{ fprintf(stderr,"Must give a name for -U\n");
}
break;
default:
fprintf(stderr,"Unknown flag -%c\n",**av);
break;
}
}
}
}
else
{ switch (argno++)
{ case 0:
if (strcmp(*av,"-") != 0)
{ FILE *f;
f = fopen(*av,"r");
if (f == NULL)
{ fprintf(stderr,"Cannot open source file %s\n",*av);
}
else
{ inf = f;
inname = *av;
}
}
break;
case 1:
if (strcmp(*av,"-") != 0)
{ FILE *f;
f = fopen(*av,"w");
if (f == NULL)
{ fprintf(stderr,"Can't create %s\n",*av);
}
else
{ outf = f;
}
}
break;
default:
fprintf(stderr,"Extra name %s ignored\n",*av);
break;
}
}
}
if (incldep && !inname[0])
{ fprintf(stderr,"No input file for -M flag\n");
#if 0
exit(1);
#endif
longjmp(cpp_env,1);
}
if (do_at_ctrls)
{ predef("at_sign_ctrls");
}
Ifile("/local/include");
Ifile("/usr/include");
willbefirst = 1;
quote = 0;
backslash = 0;
init_io(inf,inname);
outfile = outf;
ifstack = 0;
n_skipped_ifs = 0;
cp = Rindex(inname,'/');
if (cp)
{ *cp = '\0';
init_incldir(inname);
*cp = '/';
}
else
{ init_incldir(".");
}
autodef_file(inname);
autodef_line(1);
out_at(1,inname);
if (incldep)
{ char *dp;
cp = Rindex(inname,'/');
if (cp)
{ cp ++;
}
else
{ cp = inname;
}
dp = cp + strlen(cp) - 2;
if ((dp < cp) || strcmp(dp,".c"))
{ fprintf(stderr,"Missing .c in %s\n",inname);
#if 0
exit(1);
#endif
longjmp(cpp_env,1);
}
incldep_o = copyofstr(cp);
incldep_o[dp+1-cp] = 'o';
fprintf(outfile,"%s: ",incldep_o);
fprintf(outfile,"%s\n",inname);
}
init_stats();
while (1)
{ char c;
int haddigit;
c = Get();
if (backslash)
{ maybe_print(c);
backslash = 0;
continue;
}
if (!incldep && (isdigit(c) || (c == '.')))
{ haddigit = 0;
while (isdigit(c) || (c == '.'))
{ haddigit |= isdigit(c);
maybe_print(c);
c = Get();
}
if (haddigit && ((c == 'e') || (c == 'E')))
{ maybe_print(c);
c = Get();
while (isdigit(c))
{ maybe_print(c);
c = Get();
}
}
Push(c);
continue;
}
if (quote)
{ if (c == '\\')
{ maybe_print(c);
backslash = 1;
continue;
}
else if ((c == quote) || (c == '\n'))
{ maybe_print(c);
quote = 0;
continue;
}
else
{ maybe_print(c);
continue;
}
}
if (c == '\\') /* this weirdness is Reiser semantics.... */
{ backslash = 1;
maybe_print(c);
continue;
}
if ((c == '\'') || (c == '"'))
{ quote = c;
maybe_print(c);
}
else if (linefirst && (c == '#'))
{ do_sharp();
}
else if (do_at_ctrls && (c == '@'))
{ do_at();
}
else if (! incldep)
{ if (isbsymchar(c) && !in_false_if())
{ char *cp;
DEF *d;
cp = init_accum();
while (issymchar(c))
{ accum_char(cp,c);
c = Get();
}
Push(c);
cp = accum_result(cp);
#ifdef DEBUG_MAIN
if (debugging)
{ outputs("<word:");
outputs(cp);
outputs(">");
}
#endif
d = find_def(cp);
if (d)
{ expand_def(d);
n_hits ++;
}
else
{ for (;*cp;cp++)
{ maybe_print(*cp);
}
n_misses ++;
}
}
else if (c == '/')
{ char d;
d = Get();
if (d == '*')
{ d = '\0';
if (keep_comments)
{ maybe_print('/');
maybe_print('*');
}
do
{ c = d;
d = Get();
if ((d == '\n') || keep_comments)
{ maybe_print(d);
}
} while ((c != '*') || (d != '/'));
}
else
{ Push(d);
maybe_print(c);
}
}
else
{ maybe_print(c);
}
}
}
}
void do_pragma(void)
{
char c;
if (in_false_if())
{ while ((c=Get()) != '\n') ;
}
else
{ outputc('#');
outputc('p');
outputc('r');
outputc('a');
outputc('g');
outputc('m');
outputc('a');
outputc(' ');
while ((c=Get()) != '\n')
{ outputc(c);
}
}
}
char *predefs[] = {
"mc68000",
"unix",
"NeXT",
"__MACH__",
0
};
void do_set(void)
{
char *mac;
char c;
char temp[64];
mac = read_ident();
if (! mac)
{ err_head();
fprintf(stderr,"@set: missing/illegal macro name\n");
return;
}
if (! in_false_if())
{ char *cp;
c = getnonspace();
if (c != '(')
{ err_head();
fprintf(stderr,"@set must have ()s\n");
Push(c);
return;
}
sprintf(temp,"%d",eval_expr(0,1));
undef(mac);
cp = copyofstr(temp);
check_malloc(cp);
define(mac,-1,(unsigned char *)cp,DEF_DEFINE);
}
free(mac);
}
void do_sharp(void)
{
char *w;
char c;
w = read_ctrl();
if (strcmp(w,"ifdef") == 0)
{ do_ifdef(1);
}
else if (strcmp(w,"ifndef") == 0)
{ do_ifndef(1);
}
else if (strcmp(w,"if") == 0)
{ do_if(1);
}
else if (strcmp(w,"else") == 0)
{ do_else(1);
}
else if (strcmp(w,"elif") == 0)
{ do_elif(1);
}
else if (strcmp(w,"endif") == 0)
{ do_endif(1);
}
else if (strcmp(w,"include") == 0)
{ do_include(1);
}
else if (strcmp(w,"define") == 0)
{ do_define(1,0);
}
else if (strcmp(w,"undef") == 0)
{ do_undef(1);
}
else if (strcmp(w,"line") == 0)
{ do_line();
}
else if (strcmp(w,"pragma") == 0)
{ do_pragma();
}
else if (strcmp(w,"") == 0)
{
}
else
{ int isnull;
isnull = 0;
if (strcmp(w,"") == 0)
{ c = Get();
if (c != '\n')
{ Push(c);
}
else
{ isnull = 1;
}
}
if (!isnull && !in_false_if())
{ err_head();
fprintf(stderr,"unknown control `%s'\n",w);
flush_sharp_line();
}
}
maybe_print('\n');
free(w);
}
void flush_sharp_line(void)
{
int quote;
int backslash;
int comment;
int lastc;
int c;
quote = 0;
backslash = 0;
comment = 0;
c = 'x';
while (1)
{ lastc = c;
c = Get();
if (backslash)
{ backslash = 0;
continue;
}
if (comment)
{ if (c == '\\')
{ backslash = 1;
}
else if ((c == '/') && (lastc == '*'))
{ comment = 0;
}
continue;
}
if (quote)
{ if (c == '\\')
{ backslash = 1;
}
else if (c == quote)
{ quote = 0;
}
}
switch (c)
{ case '\\':
backslash = 1;
continue;
break;
case '"': case '\'':
quote = c;
continue;
break;
case '*':
comment = (lastc == '/');
continue;
break;
default:
continue;
break;
case '\n':
break;
}
break;
}
}
int n_defines;
int n_undefines;
int n_hits;
int n_misses;
void init_stats(void)
{
n_defines = 0;
n_undefines = 0;
n_hits = 0;
n_misses = 0;
}
void save_stats(void)
{
FILE *f;
f = fopen("/@larry/u1/mouse/Mouse-C/cpp.stats","a");
if (f)
{ fprintf(f,"%d def, %d undef, %d hits, %d misses\n",
n_defines,n_undefines,n_hits,n_misses);
fclose(f);
}
}
DEF **symtbl;
int symtbl_size;
int n_in_table;
static int size_index;
static int sizes[] = { 7, 37, 179, 719, 2003, 8009, 30011, 120011, 0 };
static int hash(unsigned char *s)
{
register unsigned int i;
for (i=0;*s;s++)
{ i = (i >> 8) + (i << 3) + *s;
}
i &= ~0x80000000;
return(i%symtbl_size);
}
void init_symtbl(void)
{
int i;
symtbl_size = sizes[size_index=0];
symtbl = (DEF **) malloc(symtbl_size*sizeof(DEF *));
check_malloc(symtbl);
for (i=0;i<symtbl_size;i++)
{ symtbl[i] = 0;
}
n_in_table = 0;
}
static void rehash_up(void)
{
int osize;
DEF **otbl;
int i;
DEF *d;
DEF *n;
int h;
if ((sizes[size_index] == 0) || (sizes[++size_index] == 0))
{ return;
}
osize = symtbl_size;
otbl = symtbl;
symtbl_size = sizes[size_index];
symtbl = (DEF **) malloc(symtbl_size*sizeof(DEF *));
check_malloc(symtbl);
for (i=0;i<symtbl_size;i++)
{ symtbl[i] = 0;
}
for (i=0;i<osize;i++)
{ for (d=otbl[i];d;d=n)
{ n = d->link;
h = hash((unsigned char *)d->name);
d->link = symtbl[h];
symtbl[h] = d;
}
}
free((char *)otbl);
}
void define(char *name, int nargs, unsigned char *repl, int how)
{
int h;
DEF *d;
char *n;
n = copyofstr(name);
h = hash((unsigned char *)n);
for (d=symtbl[h];d;d=d->link)
{ if (strcmp(d->name,n) == 0)
{ break;
}
}
if (d)
{ if ( (nargs != d->nargs) || strcmp((char *)repl,(char *)d->repl) )
{ err_head();
fprintf(stderr,"%s redefined\n",n);
}
free((char *)d->repl);
free(d->name);
d->name = n;
d->nargs = nargs;
d->repl = repl;
d->how = how;
}
else
{ d = NEW(DEF);
check_malloc(d);
d->name = n;
d->nargs = nargs;
d->repl = repl;
d->how = how;
d->link = symtbl[h];
symtbl[h] = d;
n_in_table ++;
if (n_in_table > 2*symtbl_size)
{ rehash_up();
}
}
if (strcmp(n,"at_sign_ctrls") == 0)
{ extern int do_at_ctrls;
do_at_ctrls = 1;
}
}
int undef(char *name)
{
int h;
DEF **D;
DEF *d;
int rv;
h = hash((unsigned char *)name);
for (D=symtbl+h;*D;D= &(*D)->link)
{ if (strcmp((*D)->name,name) == 0)
{ break;
}
}
rv = 0;
if (d = *D)
{ *D = d->link;
free(d->name);
free((char *)d->repl);
OLD(d);
n_in_table --;
rv = 1;
}
if (strcmp(name,"at_sign_ctrls") == 0)
{ extern int do_at_ctrls;
do_at_ctrls = 0;
}
return rv;
}
DEF *find_def(char *name)
{
int h;
DEF *d;
h = hash((unsigned char *)name);
for (d=symtbl[h];d;d=d->link)
{ if (strcmp(d->name,name) == 0)
{ break;
}
}
return(d);
}
void defd(char *name, int value)
{
char temp[64];
char *cp;
sprintf(temp,"%d",value);
undef(name);
cp = copyofstr(temp);
check_malloc(cp);
define(name,-1,(unsigned char *)cp,DEF_DEFINE);
}
void undef_predefs(void)
{
int h;
DEF **D;
DEF *d;
for (h=symtbl_size-1;h>=0;h--)
{ D = symtbl + h;
while (*D)
{ d = *D;
if (d->how == DEF_PREDEF)
{ free(d->name);
free((char *)d->repl);
*D = d->link;
OLD(d);
n_in_table --;
}
else
{ D = &d->link;
}
}
}
}
char *_unctrl[0400] = { "^@",
"^A",
"^B",
"^C",
"^D",
"^E",
"^F",
"^G",
"^H",
"^I",
"^J",
"^K",
"^L",
"^M",
"^N",
"^O",
"^P",
"^Q",
"^R",
"^S",
"^T",
"^U",
"^V",
"^W",
"^X",
"^Y",
"^Z",
"^[",
"^\\",
"^]",
"^^",
"^_",
" ",
"!",
"\"",
"#",
"$",
"%",
"&",
"'",
"(",
")",
"*",
"+",
",",
"-",
".",
"/",
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
":",
";",
"<",
"=",
">",
"?",
"@",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"[",
"\\",
"]",
"^",
"_",
"`",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"{"/*}*/,
"|",
/*{*/"}",
"~",
"^?",
"|^@",
"|^A",
"|^B",
"|^C",
"|^D",
"|^E",
"|^F",
"|^G",
"|^H",
"|^I",
"|^J",
"|^K",
"|^L",
"|^M",
"|^N",
"|^O",
"|^P",
"|^Q",
"|^R",
"|^S",
"|^T",
"|^U",
"|^V",
"|^W",
"|^X",
"|^Y",
"|^Z",
"|^[",
"|^\\",
"|^]",
"|^^",
"|^_",
"| ",
"|!",
"|\"",
"|#",
"|$",
"|%",
"|&",
"|'",
"|(",
"|)",
"|*",
"|+",
"|,",
"|-",
"|.",
"|/",
"|0",
"|1",
"|2",
"|3",
"|4",
"|5",
"|6",
"|7",
"|8",
"|9",
"|:",
"|;",
"|<",
"|=",
"|>",
"|?",
"|@",
"|A",
"|B",
"|C",
"|D",
"|E",
"|F",
"|G",
"|H",
"|I",
"|J",
"|K",
"|L",
"|M",
"|N",
"|O",
"|P",
"|Q",
"|R",
"|S",
"|T",
"|U",
"|V",
"|W",
"|X",
"|Y",
"|Z",
"|[",
"|\\",
"|]",
"|^",
"|_",
"|`",
"|a",
"|b",
"|c",
"|d",
"|e",
"|f",
"|g",
"|h",
"|i",
"|j",
"|k",
"|l",
"|m",
"|n",
"|o",
"|p",
"|q",
"|r",
"|s",
"|t",
"|u",
"|v",
"|w",
"|x",
"|y",
"|z",
"|{"/*}*/,
"||",
/*{*/"|}",
"|~",
"|^?" };
char *_Unctrl[0400] = { "^@",
"^A",
"^B",
"^C",
"^D",
"^E",
"^F",
"^G",
"^H",
"^I",
"^J",
"^K",
"^L",
"^M",
"^N",
"^O",
"^P",
"^Q",
"^R",
"^S",
"^T",
"^U",
"^V",
"^W",
"^X",
"^Y",
"^Z",
"^[",
"^\\",
"^]",
"^^",
"^_",
"sp",
"!",
"\"",
"#",
"$",
"%",
"&",
"'",
"(",
")",
"*",
"+",
",",
"-",
".",
"/",
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
":",
";",
"<",
"=",
">",
"?",
"@",
"A",
"B",
"C",
"D",
"E",
"F",
"G",
"H",
"I",
"J",
"K",
"L",
"M",
"N",
"O",
"P",
"Q",
"R",
"S",
"T",
"U",
"V",
"W",
"X",
"Y",
"Z",
"[",
"\\",
"]",
"^",
"_",
"`",
"a",
"b",
"c",
"d",
"e",
"f",
"g",
"h",
"i",
"j",
"k",
"l",
"m",
"n",
"o",
"p",
"q",
"r",
"s",
"t",
"u",
"v",
"w",
"x",
"y",
"z",
"{"/*}*/,
"|",
/*{*/"}",
"~",
"^?",
"|^@",
"|^A",
"|^B",
"|^C",
"|^D",
"|^E",
"|^F",
"|^G",
"|^H",
"|^I",
"|^J",
"|^K",
"|^L",
"|^M",
"|^N",
"|^O",
"|^P",
"|^Q",
"|^R",
"|^S",
"|^T",
"|^U",
"|^V",
"|^W",
"|^X",
"|^Y",
"|^Z",
"|^[",
"|^\\",
"|^]",
"|^^",
"|^_",
"|sp",
"|!",
"|\"",
"|#",
"|$",
"|%",
"|&",
"|'",
"|(",
"|)",
"|*",
"|+",
"|,",
"|-",
"|.",
"|/",
"|0",
"|1",
"|2",
"|3",
"|4",
"|5",
"|6",
"|7",
"|8",
"|9",
"|:",
"|;",
"|<",
"|=",
"|>",
"|?",
"|@",
"|A",
"|B",
"|C",
"|D",
"|E",
"|F",
"|G",
"|H",
"|I",
"|J",
"|K",
"|L",
"|M",
"|N",
"|O",
"|P",
"|Q",
"|R",
"|S",
"|T",
"|U",
"|V",
"|W",
"|X",
"|Y",
"|Z",
"|[",
"|\\",
"|]",
"|^",
"|_",
"|`",
"|a",
"|b",
"|c",
"|d",
"|e",
"|f",
"|g",
"|h",
"|i",
"|j",
"|k",
"|l",
"|m",
"|n",
"|o",
"|p",
"|q",
"|r",
"|s",
"|t",
"|u",
"|v",
"|w",
"|x",
"|y",
"|z",
"|{"/*}*/,
"||",
/*{*/"|}",
"|~",
"|^?" };
void do_undef(int expr_sharp)
{
char *mac;
if (! in_false_if())
{ mac = read_ident();
if (! mac)
{ err_head();
fprintf(stderr,"missing/illegal macro name\n");
}
else
{ if (undef(mac))
{ n_undefines ++;
}
}
}
if (sharp)
{ flush_sharp_line();
}
}
/*#define DEBUG_WHILE/**/
#ifdef DEBUG_WHILE
extern int debugging;
#endif
void do_while(void)
{
input_mark();
do_if(0);
}
void do_endwhile(void)
{
if (in_false_if())
{ do_endif(0);
input_unmark();
#ifdef DEBUG_WHILE
if (debugging)
{ outputs("//endwhile:");
outputd(curline());
outputs(",");
outputs(curfile());
outputs("\\\\");
}
#endif
out_at(curline(),curfile());
}
else
{ do_endif(0);
input_recover();
input_mark();
do_if(0);
}
}
char *Index(char *s, int c)
{
return strchr(s,c);
}
char *Rindex(char *s, int c)
{
return strrchr(s,c);
}
void Bcopy(char *from, char *to, int len)
{
#if defined(GO32)
bcopy(from,to,len);
#else
memmove((void *)from,(void *)to,(int)len);
#endif
}