blob: a31ed1ab2ca0db205b8ce7ec8c1b5bff2dd46e8f [file] [log] [blame]
/* "p2c", a Pascal to C translator.
Copyright (C) 1989, 1990, 1991 Free Software Foundation.
Author's address: daveg@csvax.caltech.edu; 256-80 Caltech/Pasadena CA 91125.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation (any version).
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; see the file COPYING. If not, write to
the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
#define PROTO_LEX_C
#include "trans.h"
/* Define LEXDEBUG for a token trace */
#define LEXDEBUG
#define EOFMARK 1
Static char dollar_flag, lex_initialized;
Static int if_flag, if_skip;
Static int commenting_flag;
Static char *commenting_ptr;
Static int skipflag;
Static char modulenotation;
Static short inputkind;
Static Strlist *instrlist;
Static char inbuf[300];
Static char *oldinfname, *oldctxname;
Static Strlist *endnotelist;
#define INP_FILE 0
#define INP_INCFILE 1
#define INP_STRLIST 2
Static struct inprec {
struct inprec *next;
short kind;
char *fname, *inbufptr;
int lnum;
FILE *filep;
Strlist *strlistp, *tempopts;
Token curtok, saveblockkind;
Symbol *curtoksym;
Meaning *curtokmeaning;
char *curtokbuf, *curtokcase;
} *topinput;
char *fixpascalname(name)
char *name;
{
char *cp, *cp2;
if (pascalsignif > 0) {
name = format_ds("%.*s", pascalsignif, name);
if (!pascalcasesens)
upc(name);
else if (pascalcasesens == 3)
lwc(name);
} else if (!pascalcasesens)
name = strupper(name);
else if (pascalcasesens == 3)
name = strlower(name);
if (ignorenonalpha) {
for (cp = cp2 = name; *cp; cp++)
if (isalnum(*cp))
*cp2++ = *cp;
}
return name;
}
Static void makekeyword(name)
char *name;
{
Symbol *sym;
if (*name) {
sym = findsymbol(name);
sym->flags |= AVOIDNAME;
}
}
Static void makeglobword(name)
char *name;
{
Symbol *sym;
if (*name) {
sym = findsymbol(name);
sym->flags |= AVOIDGLOB;
}
}
Static void makekeywords()
{
makekeyword("auto");
makekeyword("break");
makekeyword("char");
makekeyword("continue");
makekeyword("default");
makekeyword("defined"); /* is this one really necessary? */
makekeyword("double");
makekeyword("enum");
makekeyword("extern");
makekeyword("float");
makekeyword("int");
makekeyword("long");
makekeyword("noalias");
makekeyword("register");
makekeyword("return");
makekeyword("short");
makekeyword("signed");
makekeyword("sizeof");
makekeyword("static");
makekeyword("struct");
makekeyword("switch");
makekeyword("typedef");
makekeyword("union");
makekeyword("unsigned");
makekeyword("void");
makekeyword("volatile");
makekeyword("asm");
makekeyword("fortran");
makekeyword("entry");
makekeyword("pascal");
if (cplus != 0) {
makekeyword("class");
makekeyword("delete");
makekeyword("friend");
makekeyword("inline");
makekeyword("new");
makekeyword("operator");
makekeyword("overload");
makekeyword("public");
makekeyword("this");
makekeyword("virtual");
}
makekeyword(name_UCHAR);
makekeyword(name_SCHAR); /* any others? */
makekeyword(name_BOOLEAN);
makekeyword(name_PROCEDURE);
makekeyword(name_ESCAPE);
makekeyword(name_ESCIO);
makekeyword(name_CHKIO);
makekeyword(name_SETIO);
makeglobword("main");
makeglobword("vextern"); /* used in generated .h files */
makeglobword("argc");
makeglobword("argv");
makekeyword("TRY");
makekeyword("RECOVER");
makekeyword("RECOVER2");
makekeyword("ENDTRY");
}
Static Symbol *Pkeyword(name, tok)
char *name;
Token tok;
{
Symbol *sp = NULL;
if (pascalcasesens != 2) {
sp = findsymbol(strlower(name));
sp->kwtok = tok;
}
if (pascalcasesens != 3) {
sp = findsymbol(strupper(name));
sp->kwtok = tok;
}
return sp;
}
Static Symbol *Pkeywordposs(name, tok)
char *name;
Token tok;
{
Symbol *sp = NULL;
if (pascalcasesens != 2) {
sp = findsymbol(strlower(name));
sp->kwtok = tok;
sp->flags |= KWPOSS;
}
if (pascalcasesens != 3) {
sp = findsymbol(strupper(name));
sp->kwtok = tok;
sp->flags |= KWPOSS;
}
return sp;
}
Static void makePascalwords()
{
Pkeyword("AND", TOK_AND);
Pkeyword("ARRAY", TOK_ARRAY);
Pkeywordposs("ANYVAR", TOK_ANYVAR);
Pkeywordposs("ABSOLUTE", TOK_ABSOLUTE);
Pkeyword("BEGIN", TOK_BEGIN);
Pkeywordposs("BY", TOK_BY);
Pkeyword("CASE", TOK_CASE);
Pkeyword("CONST", TOK_CONST);
Pkeyword("DIV", TOK_DIV);
Pkeywordposs("DEFINITION", TOK_DEFINITION);
Pkeyword("DO", TOK_DO);
Pkeyword("DOWNTO", TOK_DOWNTO);
Pkeyword("ELSE", TOK_ELSE);
Pkeywordposs("ELSIF", TOK_ELSIF);
Pkeyword("END", TOK_END);
Pkeywordposs("EXPORT", TOK_EXPORT);
Pkeyword("FILE", TOK_FILE);
Pkeyword("FOR", TOK_FOR);
Pkeywordposs("FROM", TOK_FROM);
Pkeyword("FUNCTION", TOK_FUNCTION);
Pkeyword("GOTO", TOK_GOTO);
Pkeyword("IF", TOK_IF);
Pkeywordposs("IMPLEMENT", TOK_IMPLEMENT);
Pkeywordposs("IMPLEMENTATION", TOK_IMPLEMENT);
Pkeywordposs("IMPORT", TOK_IMPORT);
Pkeyword("IN", TOK_IN);
Pkeywordposs("INLINE", TOK_INLINE);
Pkeywordposs("INTERFACE", TOK_EXPORT);
Pkeywordposs("INTERRUPT", TOK_INTERRUPT);
Pkeyword("LABEL", TOK_LABEL);
Pkeywordposs("LOOP", TOK_LOOP);
Pkeyword("MOD", TOK_MOD);
Pkeywordposs("MODULE", TOK_MODULE);
Pkeyword("NIL", TOK_NIL);
Pkeyword("NOT", TOK_NOT);
Pkeyword("OF", TOK_OF);
Pkeyword("OR", TOK_OR);
Pkeywordposs("ORIGIN", TOK_ORIGIN);
Pkeywordposs("OTHERWISE", TOK_OTHERWISE);
Pkeywordposs("OVERLAY", TOK_SEGMENT);
Pkeyword("PACKED", TOK_PACKED);
Pkeywordposs("POINTER", TOK_POINTER);
Pkeyword("PROCEDURE", TOK_PROCEDURE);
Pkeyword("PROGRAM", TOK_PROGRAM);
Pkeywordposs("QUALIFIED", TOK_QUALIFIED);
Pkeyword("RECORD", TOK_RECORD);
Pkeywordposs("RECOVER", TOK_RECOVER);
Pkeywordposs("REM", TOK_REM);
Pkeyword("REPEAT", TOK_REPEAT);
Pkeywordposs("RETURN", TOK_RETURN);
if (which_lang == LANG_UCSD)
Pkeyword("SEGMENT", TOK_SEGMENT);
else
Pkeywordposs("SEGMENT", TOK_SEGMENT);
Pkeyword("SET", TOK_SET);
Pkeywordposs("SHL", TOK_SHL);
Pkeywordposs("SHR", TOK_SHR);
Pkeyword("THEN", TOK_THEN);
Pkeyword("TO", TOK_TO);
Pkeywordposs("TRY", TOK_TRY);
Pkeyword("TYPE", TOK_TYPE);
Pkeyword("UNTIL", TOK_UNTIL);
Pkeywordposs("USES", TOK_IMPORT);
Pkeywordposs("UNIT", TOK_MODULE);
if (which_lang == LANG_VAX)
Pkeyword("VALUE", TOK_VALUE);
else
Pkeywordposs("VALUE", TOK_VALUE);
Pkeyword("VAR", TOK_VAR);
Pkeywordposs("VARYING", TOK_VARYING);
Pkeyword("WHILE", TOK_WHILE);
Pkeyword("WITH", TOK_WITH);
Pkeywordposs("XOR", TOK_XOR);
Pkeyword("__MODULE", TOK_MODULE);
Pkeyword("__IMPORT", TOK_IMPORT);
Pkeyword("__EXPORT", TOK_EXPORT);
Pkeyword("__IMPLEMENT", TOK_IMPLEMENT);
}
Static void deterministic(name)
char *name;
{
Symbol *sym;
if (*name) {
sym = findsymbol(name);
sym->flags |= DETERMF;
}
}
Static void nosideeff(name)
char *name;
{
Symbol *sym;
if (*name) {
sym = findsymbol(name);
sym->flags |= NOSIDEEFF;
}
}
Static void recordsideeffects()
{
deterministic("abs");
deterministic("acos");
deterministic("asin");
deterministic("atan");
deterministic("atan2");
deterministic("atof");
deterministic("atoi");
deterministic("atol");
deterministic("ceil");
deterministic("cos");
deterministic("cosh");
deterministic("exp");
deterministic("fabs");
deterministic("feof");
deterministic("feoln");
deterministic("ferror");
deterministic("floor");
deterministic("fmod");
deterministic("ftell");
deterministic("isalnum");
deterministic("isalpha");
deterministic("isdigit");
deterministic("islower");
deterministic("isspace");
deterministic("isupper");
deterministic("labs");
deterministic("ldexp");
deterministic("log");
deterministic("log10");
deterministic("memcmp");
deterministic("memchr");
deterministic("pow");
deterministic("sin");
deterministic("sinh");
deterministic("sqrt");
deterministic("strchr");
deterministic("strcmp");
deterministic("strcspn");
deterministic("strlen");
deterministic("strncmp");
deterministic("strpbrk");
deterministic("strrchr");
deterministic("strspn");
deterministic("strstr");
deterministic("tan");
deterministic("tanh");
deterministic("tolower");
deterministic("toupper");
deterministic(setequalname);
deterministic(subsetname);
deterministic(signextname);
}
void init_lex()
{
int i;
inputkind = INP_FILE;
inf_lnum = 0;
inf_ltotal = 0;
*inbuf = 0;
inbufptr = inbuf;
keepingstrlist = NULL;
tempoptionlist = NULL;
switch_strpos = 0;
dollar_flag = 0;
if_flag = 0;
if_skip = 0;
commenting_flag = 0;
skipflag = 0;
inbufindent = 0;
modulenotation = 1;
notephase = 0;
endnotelist = NULL;
for (i = 0; i < SYMHASHSIZE; i++)
symtab[i] = 0;
C_lex = 0;
lex_initialized = 0;
}
void setup_lex()
{
lex_initialized = 1;
if (!strcmp(language, "MODCAL"))
sysprog_flag = 2;
else
sysprog_flag = 0;
if (shortcircuit < 0)
partial_eval_flag = (which_lang == LANG_TURBO ||
which_lang == LANG_VAX ||
which_lang == LANG_OREGON ||
modula2 ||
hpux_lang);
else
partial_eval_flag = shortcircuit;
iocheck_flag = 1;
range_flag = 1;
ovflcheck_flag = 1;
stackcheck_flag = 1;
fixedflag = 0;
withlevel = 0;
makekeywords();
makePascalwords();
recordsideeffects();
topinput = 0;
ignore_directives = 0;
skipping_module = 0;
blockkind = TOK_END;
gettok();
}
int checkeatnote(msg)
char *msg;
{
Strlist *lp;
char *cp;
int len;
for (lp = eatnotes; lp; lp = lp->next) {
if (!strcmp(lp->s, "1")) {
echoword("[*]", 0);
return 1;
}
if (!strcmp(lp->s, "0"))
return 0;
len = strlen(lp->s);
cp = msg;
while (*cp && (*cp != lp->s[0] || strncmp(cp, lp->s, len)))
cp++;
if (*cp) {
cp = lp->s;
if (*cp != '[')
cp = format_s("[%s", cp);
if (cp[strlen(cp)-1] != ']')
cp = format_s("%s]", cp);
echoword(cp, 0);
return 1;
}
}
return 0;
}
void beginerror()
{
end_source();
if (showprogress) {
fprintf(stderr, "\r%60s\r", "");
clearprogress();
} else
echobreak();
}
void counterror()
{
if (maxerrors > 0) {
if (--maxerrors == 0) {
fprintf(outf, "\n/* Translation aborted: Too many errors. */\n");
fprintf(outf, "-------------------------------------------\n");
if (outf != stdout)
printf("Translation aborted: Too many errors.\n");
if (verbose)
fprintf(logf, "Translation aborted: Too many errors.\n");
closelogfile();
exit(EXIT_FAILURE);
}
}
}
void error(msg) /* does not return */
char *msg;
{
flushcomments(NULL, -1, -1);
beginerror();
fprintf(outf, "/* %s, line %d: %s */\n", infname, inf_lnum, msg);
fprintf(outf, "/* Translation aborted. */\n");
fprintf(outf, "--------------------------\n");
if (outf != stdout) {
printf("%s, line %d/%d: %s\n", infname, inf_lnum, outf_lnum, msg);
printf("Translation aborted.\n");
}
if (verbose) {
fprintf(logf, "%s, line %d/%d: %s\n",
infname, inf_lnum, outf_lnum, msg);
fprintf(logf, "Translation aborted.\n");
}
closelogfile();
exit(EXIT_FAILURE);
}
void interror(proc, msg) /* does not return */
char *proc, *msg;
{
error(format_ss("Internal error in %s: %s", proc, msg));
}
void warning(msg)
char *msg;
{
if (checkeatnote(msg)) {
if (verbose)
fprintf(logf, "%s, %d/%d: Omitted warning: %s\n",
infname, inf_lnum, outf_lnum, msg);
return;
}
beginerror();
addnote(format_s("Warning: %s", msg), curserial);
counterror();
}
void intwarning(proc, msg)
char *proc, *msg;
{
if (checkeatnote(msg)) {
if (verbose)
fprintf(logf, "%s, %d/%d: Omitted internal error in %s: %s\n",
infname, inf_lnum, outf_lnum, proc, msg);
return;
}
beginerror();
addnote(format_ss("Internal error in %s: %s", proc, msg), curserial);
if (error_crash)
exit(EXIT_FAILURE);
counterror();
}
void note(msg)
char *msg;
{
if (blockkind == TOK_IMPORT || checkeatnote(msg)) {
if (verbose)
fprintf(logf, "%s, %d/%d: Omitted note: %s\n",
infname, inf_lnum, outf_lnum, msg);
return;
}
beginerror();
addnote(format_s("Note: %s", msg), curserial);
counterror();
}
void endnote(msg)
char *msg;
{
if (blockkind == TOK_IMPORT || checkeatnote(msg)) {
if (verbose)
fprintf(logf, "%s, %d/%d: Omitted end-note: %s\n",
infname, inf_lnum, outf_lnum, msg);
return;
}
if (verbose)
fprintf(logf, "%s, %d/%d: Recorded end-note: %s\n",
infname, inf_lnum, outf_lnum, msg);
(void) strlist_add(&endnotelist, msg);
}
void showendnotes()
{
while (initialcalls) {
if (initialcalls->value)
endnote(format_s("Remember to call %s in main program [215]",
initialcalls->s));
strlist_eat(&initialcalls);
}
if (endnotelist) {
end_source();
while (endnotelist) {
if (outf != stdout) {
beginerror();
printf("Note: %s\n", endnotelist->s);
}
fprintf(outf, "/* p2c: Note: %s */\n", endnotelist->s);
outf_lnum++;
strlist_eat(&endnotelist);
}
}
}
char *tok_name(tok)
Token tok;
{
if (tok == TOK_END && inputkind == INP_STRLIST)
return "end of macro";
if (tok == curtok && tok == TOK_IDENT)
return format_s("'%s'", curtokcase);
if (!modulenotation) {
switch (tok) {
case TOK_MODULE: return "UNIT";
case TOK_IMPORT: return "USES";
case TOK_EXPORT: return "INTERFACE";
case TOK_IMPLEMENT: return "IMPLEMENTATION";
default: break;
}
}
return toknames[(int) tok];
}
void expected(msg)
char *msg;
{
error(format_ss("Expected %s, found %s", msg, tok_name(curtok)));
}
void expecttok(tok)
Token tok;
{
if (curtok != tok)
expected(tok_name(tok));
}
void needtok(tok)
Token tok;
{
if (curtok != tok)
expected(tok_name(tok));
gettok();
}
int wexpected(msg)
char *msg;
{
warning(format_ss("Expected %s, found %s [227]", msg, tok_name(curtok)));
return 0;
}
int wexpecttok(tok)
Token tok;
{
if (curtok != tok)
return wexpected(tok_name(tok));
else
return 1;
}
int wneedtok(tok)
Token tok;
{
if (wexpecttok(tok)) {
gettok();
return 1;
} else
return 0;
}
void alreadydef(sym)
Symbol *sym;
{
warning(format_s("Symbol '%s' was already defined [220]", sym->name));
}
void undefsym(sym)
Symbol *sym;
{
warning(format_s("Symbol '%s' is not defined [221]", sym->name));
}
void symclass(sym)
Symbol *sym;
{
warning(format_s("Symbol '%s' is not of the appropriate class [222]", sym->name));
}
void badtypes()
{
warning("Type mismatch [223]");
}
void valrange()
{
warning("Value range error [224]");
}
void skipparens()
{
Token begintok;
if (curtok == TOK_LPAR) {
gettok();
while (curtok != TOK_RPAR)
skipparens();
} else if (curtok == TOK_LBR) {
gettok();
while (curtok != TOK_RBR)
skipparens();
} else if (curtok == TOK_BEGIN || curtok == TOK_RECORD ||
curtok == TOK_CASE) {
begintok = curtok;
gettok();
while (curtok != TOK_END)
if (curtok == TOK_CASE && begintok == TOK_RECORD)
gettok();
else
skipparens();
}
gettok();
}
void skiptotoken2(tok1, tok2)
Token tok1, tok2;
{
while (curtok != tok1 && curtok != tok2 &&
curtok != TOK_END && curtok != TOK_RPAR &&
curtok != TOK_RBR && curtok != TOK_EOF)
skipparens();
}
void skippasttoken2(tok1, tok2)
Token tok1, tok2;
{
skiptotoken2(tok1, tok2);
if (curtok == tok1 || curtok == tok2)
gettok();
}
void skippasttotoken(tok1, tok2)
Token tok1, tok2;
{
skiptotoken2(tok1, tok2);
if (curtok == tok1)
gettok();
}
void skiptotoken(tok)
Token tok;
{
skiptotoken2(tok, tok);
}
void skippasttoken(tok)
Token tok;
{
skippasttoken2(tok, tok);
}
int skipopenparen()
{
if (wneedtok(TOK_LPAR))
return 1;
skiptotoken(TOK_SEMI);
return 0;
}
int skipcloseparen()
{
if (curtok == TOK_COMMA)
warning("Too many arguments for built-in routine [225]");
else
if (wneedtok(TOK_RPAR))
return 1;
skippasttotoken(TOK_RPAR, TOK_SEMI);
return 0;
}
int skipcomma()
{
if (curtok == TOK_RPAR)
warning("Too few arguments for built-in routine [226]");
else
if (wneedtok(TOK_COMMA))
return 1;
skippasttotoken(TOK_RPAR, TOK_SEMI);
return 0;
}
char *findaltname(name, num)
char *name;
int num;
{
char *cp;
if (num <= 0)
return name;
if (num == 1 && *alternatename1)
return format_s(alternatename1, name);
if (num == 2 && *alternatename2)
return format_s(alternatename2, name);
if (*alternatename)
return format_sd(alternatename, name, num);
cp = name;
if (*alternatename1) {
while (--num >= 0)
cp = format_s(alternatename1, cp);
} else {
while (--num >= 0)
cp = format_s("%s_", cp);
}
return cp;
}
Symbol *findsymbol_opt(name)
char *name;
{
register int i;
register unsigned int hash;
register char *cp;
register Symbol *sp;
hash = 0;
for (cp = name; *cp; cp++)
hash = hash*3 + *cp;
sp = symtab[hash % SYMHASHSIZE];
while (sp && (i = strcmp(sp->name, name)) != 0) {
if (i < 0)
sp = sp->left;
else
sp = sp->right;
}
return sp;
}
Symbol *findsymbol(name)
char *name;
{
register int i;
register unsigned int hash;
register char *cp;
register Symbol **prev, *sp;
hash = 0;
for (cp = name; *cp; cp++)
hash = hash*3 + *cp;
prev = symtab + (hash % SYMHASHSIZE);
while ((sp = *prev) != 0 &&
(i = strcmp(sp->name, name)) != 0) {
if (i < 0)
prev = &(sp->left);
else
prev = &(sp->right);
}
if (!sp) {
sp = ALLOCV(sizeof(Symbol) + strlen(name), Symbol, symbols);
sp->mbase = sp->fbase = NULL;
sp->left = sp->right = NULL;
strcpy(sp->name, name);
sp->flags = 0;
sp->kwtok = TOK_NONE;
sp->symbolnames = NULL;
*prev = sp;
}
return sp;
}
void clearprogress()
{
oldinfname = NULL;
}
void progress()
{
char *ctxname;
int needrefr;
static int prevlen;
if (showprogress) {
if (!curctx || curctx == nullctx || curctx->kind == MK_MODULE ||
!strncmp(curctx->name, "__PROCPTR", 9) || blockkind == TOK_IMPORT)
ctxname = "";
else
ctxname = curctx->name;
needrefr = (inf_lnum & 15) == 0;
if (oldinfname != infname || oldctxname != ctxname) {
if (oldinfname != infname)
prevlen = 60;
fprintf(stderr, "\r%*s", prevlen + 2, "");
oldinfname = infname;
oldctxname = ctxname;
needrefr = 1;
}
if (needrefr) {
fprintf(stderr, "\r%5d %s %s", inf_lnum, infname, ctxname);
prevlen = 8 + strlen(infname) + strlen(ctxname);
} else {
fprintf(stderr, "\r%5d", inf_lnum);
prevlen = 5;
}
}
}
void p2c_getline()
{
char *cp, *cp2;
switch (inputkind) {
case INP_FILE:
case INP_INCFILE:
inf_lnum++;
inf_ltotal++;
if (fgets(inbuf, 300, inf)) {
cp = inbuf + strlen(inbuf);
if (*inbuf && cp[-1] == '\n')
cp[-1] = 0;
if (inbuf[0] == '#' && inbuf[1] == ' ' && isdigit(inbuf[2])) {
cp = inbuf + 2; /* in case input text came */
inf_lnum = 0; /* from the C preprocessor */
while (isdigit(*cp))
inf_lnum = inf_lnum*10 + (*cp++) - '0';
inf_lnum--;
while (isspace(*cp)) cp++;
if (*cp == '"' && (cp2 = my_strchr(cp+1, '"')) != NULL) {
cp++;
infname = stralloc(cp);
infname[cp2 - cp] = 0;
}
p2c_getline();
return;
}
if (copysource && *inbuf) {
start_source();
fprintf(outf, "%s\n", inbuf);
}
if (keepingstrlist) {
strlist_append(keepingstrlist, inbuf)->value = inf_lnum;
}
if (showprogress && inf_lnum % showprogress == 0)
progress();
} else {
if (showprogress)
fprintf(stderr, "\n");
if (inputkind == INP_INCFILE) {
pop_input();
p2c_getline();
} else
strcpy(inbuf, "\001");
}
break;
case INP_STRLIST:
if (instrlist) {
strcpy(inbuf, instrlist->s);
if (instrlist->value)
inf_lnum = instrlist->value;
else
inf_lnum++;
instrlist = instrlist->next;
} else
strcpy(inbuf, "\001");
break;
}
inbufptr = inbuf;
inbufindent = 0;
}
Static void push_input()
{
struct inprec *inp;
inp = ALLOC(1, struct inprec, inprecs);
inp->kind = inputkind;
inp->fname = infname;
inp->lnum = inf_lnum;
inp->filep = inf;
inp->strlistp = instrlist;
inp->inbufptr = stralloc(inbufptr);
inp->curtok = curtok;
inp->curtoksym = curtoksym;
inp->curtokmeaning = curtokmeaning;
inp->curtokbuf = stralloc(curtokbuf);
inp->curtokcase = stralloc(curtokcase);
inp->saveblockkind = TOK_NIL;
inp->next = topinput;
topinput = inp;
inbufptr = inbuf + strlen(inbuf);
}
void push_input_file(fp, fname, isinclude)
FILE *fp;
char *fname;
int isinclude;
{
push_input();
inputkind = (isinclude == 1) ? INP_INCFILE : INP_FILE;
inf = fp;
inf_lnum = 0;
infname = fname;
*inbuf = 0;
inbufptr = inbuf;
topinput->tempopts = tempoptionlist;
tempoptionlist = NULL;
if (isinclude != 2)
gettok();
}
void include_as_import()
{
if (inputkind == INP_INCFILE) {
if (topinput->saveblockkind == TOK_NIL)
topinput->saveblockkind = blockkind;
blockkind = TOK_IMPORT;
} else
warning(format_s("%s ignored except in include files [228]",
interfacecomment));
}
void push_input_strlist(sp, fname)
Strlist *sp;
char *fname;
{
push_input();
inputkind = INP_STRLIST;
instrlist = sp;
if (fname) {
infname = fname;
inf_lnum = 0;
} else
inf_lnum--; /* adjust for extra p2c_getline() */
*inbuf = 0;
inbufptr = inbuf;
gettok();
}
void pop_input()
{
struct inprec *inp;
if (inputkind == INP_FILE || inputkind == INP_INCFILE) {
while (tempoptionlist) {
undooption(tempoptionlist->value, tempoptionlist->s);
strlist_eat(&tempoptionlist);
}
tempoptionlist = topinput->tempopts;
if (inf)
fclose(inf);
}
inp = topinput;
topinput = inp->next;
if (inp->saveblockkind != TOK_NIL)
blockkind = inp->saveblockkind;
inputkind = inp->kind;
infname = inp->fname;
inf_lnum = inp->lnum;
inf = inp->filep;
curtok = inp->curtok;
curtoksym = inp->curtoksym;
curtokmeaning = inp->curtokmeaning;
strcpy(curtokbuf, inp->curtokbuf);
FREE(inp->curtokbuf);
strcpy(curtokcase, inp->curtokcase);
FREE(inp->curtokcase);
strcpy(inbuf, inp->inbufptr);
FREE(inp->inbufptr);
inbufptr = inbuf;
instrlist = inp->strlistp;
FREE(inp);
}
int undooption(i, name)
int i;
char *name;
{
char kind = rctable[i].kind;
switch (kind) {
case 'S':
case 'B':
if (rcprevvalues[i]) {
*((short *)rctable[i].ptr) = rcprevvalues[i]->value;
strlist_eat(&rcprevvalues[i]);
return 1;
}
break;
case 'I':
case 'D':
if (rcprevvalues[i]) {
*((int *)rctable[i].ptr) = rcprevvalues[i]->value;
strlist_eat(&rcprevvalues[i]);
return 1;
}
break;
case 'L':
if (rcprevvalues[i]) {
*((long *)rctable[i].ptr) = rcprevvalues[i]->value;
strlist_eat(&rcprevvalues[i]);
return 1;
}
break;
case 'R':
if (rcprevvalues[i]) {
*((double *)rctable[i].ptr) = atof(rcprevvalues[i]->s);
strlist_eat(&rcprevvalues[i]);
return 1;
}
break;
case 'C':
case 'U':
if (rcprevvalues[i]) {
strcpy((char *)rctable[i].ptr, rcprevvalues[i]->s);
strlist_eat(&rcprevvalues[i]);
return 1;
}
break;
case 'A':
strlist_remove((Strlist **)rctable[i].ptr, name);
return 1;
case 'X':
if (rctable[i].def == 1) {
strlist_remove((Strlist **)rctable[i].ptr, name);
return 1;
}
break;
}
return 0;
}
void badinclude()
{
warning("Can't handle an \"include\" directive here [229]");
inputkind = INP_INCFILE; /* expand it in-line */
gettok();
}
int handle_include(fn)
char *fn;
{
FILE *fp = NULL;
Strlist *sl;
for (sl = includedirs; sl; sl = sl->next) {
fp = fopen(format_s(sl->s, fn), "r");
if (fp) {
fn = stralloc(format_s(sl->s, fn));
break;
}
}
if (!fp) {
perror(fn);
warning(format_s("Could not open include file %s [230]", fn));
return 0;
} else {
if (!quietmode && !showprogress)
if (outf == stdout)
fprintf(stderr, "Reading include file \"%s\"\n", fn);
else
printf("Reading include file \"%s\"\n", fn);
if (verbose)
fprintf(logf, "Reading include file \"%s\"\n", fn);
if (expandincludes == 0) {
push_input_file(fp, fn, 2);
curtok = TOK_INCLUDE;
strcpy(curtokbuf, fn);
} else {
push_input_file(fp, fn, 1);
}
return 1;
}
}
int turbo_directive(closing, after)
char *closing, *after;
{
char *cp, *cp2;
int i, result;
if (!strcincmp(inbufptr, "$double", 7)) {
cp = inbufptr + 7;
while (isspace(*cp)) cp++;
if (cp == closing) {
inbufptr = after;
doublereals = 1;
return 1;
}
} else if (!strcincmp(inbufptr, "$nodouble", 9)) {
cp = inbufptr + 9;
while (isspace(*cp)) cp++;
if (cp == closing) {
inbufptr = after;
doublereals = 0;
return 1;
}
}
switch (inbufptr[2]) {
case '+':
case '-':
result = 1;
cp = inbufptr + 1;
for (;;) {
if (!isalpha(*cp++))
return 0;
if (*cp != '+' && *cp != '-')
return 0;
if (++cp == closing)
break;
if (*cp++ != ',')
return 0;
}
cp = inbufptr + 1;
do {
switch (*cp++) {
case 'b':
case 'B':
if (shortcircuit < 0 && which_lang != LANG_MPW)
partial_eval_flag = (*cp == '-');
break;
case 'i':
case 'I':
iocheck_flag = (*cp == '+');
break;
case 'r':
case 'R':
if (*cp == '+') {
if (!range_flag)
note("Range checking is ON [216]");
range_flag = 1;
} else {
if (range_flag)
note("Range checking is OFF [216]");
range_flag = 0;
}
break;
case 's':
case 'S':
if (*cp == '+') {
if (!stackcheck_flag)
note("Stack checking is ON [217]");
stackcheck_flag = 1;
} else {
if (stackcheck_flag)
note("Stack checking is OFF [217]");
stackcheck_flag = 0;
}
break;
default:
result = 0;
break;
}
cp++;
} while (*cp++ == ',');
if (result)
inbufptr = after;
return result;
case 'c':
case 'C':
if (toupper(inbufptr[1]) == 'S' &&
(inbufptr[3] == '+' || inbufptr[3] == '-') &&
inbufptr + 4 == closing) {
if (shortcircuit < 0)
partial_eval_flag = (inbufptr[3] == '+');
inbufptr = after;
return 1;
}
return 0;
case ' ':
switch (inbufptr[1]) {
case 'i':
case 'I':
if (skipping_module)
break;
cp = inbufptr + 3;
while (isspace(*cp)) cp++;
cp2 = cp;
i = 0;
while (*cp2 && cp2 != closing)
i++, cp2++;
if (cp2 != closing)
return 0;
while (isspace(cp[i-1]))
if (--i <= 0)
return 0;
inbufptr = after;
cp2 = ALLOC(i + 1, char, strings);
strncpy(cp2, cp, i);
cp2[i] = 0;
if (handle_include(cp2))
return 2;
break;
case 's':
case 'S':
cp = inbufptr + 3;
outsection(minorspace);
if (cp == closing) {
output("#undef __SEG__\n");
} else {
output("#define __SEG__ ");
while (*cp && cp != closing)
cp++;
if (*cp) {
i = *cp;
*cp = 0;
output(inbufptr + 3);
*cp = i;
}
output("\n");
}
outsection(minorspace);
inbufptr = after;
return 1;
}
return 0;
case '}':
case '*':
if (inbufptr + 2 == closing) {
switch (inbufptr[1]) {
case 's':
case 'S':
outsection(minorspace);
output("#undef __SEG__\n");
outsection(minorspace);
inbufptr = after;
return 1;
}
}
return 0;
case 'f': /* $ifdef etc. */
case 'F':
if (toupper(inbufptr[1]) == 'I' &&
((toupper(inbufptr[3]) == 'O' &&
toupper(inbufptr[4]) == 'P' &&
toupper(inbufptr[5]) == 'T') ||
(toupper(inbufptr[3]) == 'D' &&
toupper(inbufptr[4]) == 'E' &&
toupper(inbufptr[5]) == 'F') ||
(toupper(inbufptr[3]) == 'N' &&
toupper(inbufptr[4]) == 'D' &&
toupper(inbufptr[5]) == 'E' &&
toupper(inbufptr[6]) == 'F'))) {
note("Turbo Pascal conditional compilation directive was ignored [218]");
}
return 0;
}
return 0;
}
extern Strlist *addmacros;
void defmacro(name, kind, fname, lnum)
char *name, *fname;
long kind;
int lnum;
{
Strlist *defsl, *sl, *sl2;
Symbol *sym, *sym2;
Meaning *mp;
Expr *ex;
defsl = NULL;
sl = strlist_append(&defsl, name);
C_lex++;
if (fname && !strcmp(fname, "<macro>") && curtok == TOK_IDENT)
fname = curtoksym->name;
push_input_strlist(defsl, fname);
if (fname)
inf_lnum = lnum;
switch (kind) {
case MAC_VAR:
if (!wexpecttok(TOK_IDENT))
break;
for (mp = curtoksym->mbase; mp; mp = mp->snext) {
if (mp->kind == MK_VAR)
warning(format_s("VarMacro must be defined before declaration of variable %s [231]", curtokcase));
}
sl = strlist_append(&varmacros, curtoksym->name);
gettok();
if (!wneedtok(TOK_EQ))
break;
sl->value = (long)pc_expr();
break;
case MAC_CONST:
if (!wexpecttok(TOK_IDENT))
break;
for (mp = curtoksym->mbase; mp; mp = mp->snext) {
if (mp->kind == MK_CONST)
warning(format_s("ConstMacro must be defined before declaration of variable %s [232]", curtokcase));
}
sl = strlist_append(&constmacros, curtoksym->name);
gettok();
if (!wneedtok(TOK_EQ))
break;
sl->value = (long)pc_expr();
break;
case MAC_FIELD:
if (!wexpecttok(TOK_IDENT))
break;
sym = curtoksym;
gettok();
if (!wneedtok(TOK_DOT))
break;
if (!wexpecttok(TOK_IDENT))
break;
sym2 = curtoksym;
gettok();
if (!wneedtok(TOK_EQ))
break;
funcmacroargs = NULL;
sym->flags |= FMACREC;
ex = pc_expr();
sym->flags &= ~FMACREC;
for (mp = sym2->fbase; mp; mp = mp->snext) {
if (mp->rectype && mp->rectype->meaning &&
mp->rectype->meaning->sym == sym)
break;
}
if (mp) {
mp->constdefn = ex;
} else {
sl = strlist_append(&fieldmacros,
format_ss("%s.%s", sym->name, sym2->name));
sl->value = (long)ex;
}
break;
case MAC_FUNC:
if (!wexpecttok(TOK_IDENT))
break;
sym = curtoksym;
if (sym->mbase &&
(sym->mbase->kind == MK_FUNCTION ||
sym->mbase->kind == MK_SPECIAL))
sl = NULL;
else
sl = strlist_append(&funcmacros, sym->name);
gettok();
funcmacroargs = NULL;
if (curtok == TOK_LPAR) {
do {
gettok();
if (curtok == TOK_RPAR && !funcmacroargs)
break;
if (!wexpecttok(TOK_IDENT)) {
skiptotoken2(TOK_COMMA, TOK_RPAR);
continue;
}
sl2 = strlist_append(&funcmacroargs, curtoksym->name);
sl2->value = (long)curtoksym;
curtoksym->flags |= FMACREC;
gettok();
} while (curtok == TOK_COMMA);
if (!wneedtok(TOK_RPAR))
skippasttotoken(TOK_RPAR, TOK_EQ);
}
if (!wneedtok(TOK_EQ))
break;
if (sl)
sl->value = (long)pc_expr();
else
sym->mbase->constdefn = pc_expr();
for (sl2 = funcmacroargs; sl2; sl2 = sl2->next) {
sym2 = (Symbol *)sl2->value;
sym2->flags &= ~FMACREC;
}
strlist_empty(&funcmacroargs);
break;
}
if (curtok != TOK_EOF)
warning(format_s("Junk (%s) at end of macro definition [233]", tok_name(curtok)));
pop_input();
C_lex--;
strlist_empty(&defsl);
}
void check_unused_macros()
{
Strlist *sl;
if (warnmacros) {
for (sl = varmacros; sl; sl = sl->next)
warning(format_s("VarMacro %s was never used [234]", sl->s));
for (sl = constmacros; sl; sl = sl->next)
warning(format_s("ConstMacro %s was never used [234]", sl->s));
for (sl = fieldmacros; sl; sl = sl->next)
warning(format_s("FieldMacro %s was never used [234]", sl->s));
for (sl = funcmacros; sl; sl = sl->next)
warning(format_s("FuncMacro %s was never used [234]", sl->s));
}
}
#define skipspc(cp) while (isspace(*cp)) cp++
Static int parsecomment(p2c_only, starparen)
int p2c_only, starparen;
{
char namebuf[302];
char *cp, *cp2 = namebuf, *closing, *after;
char kind, chgmode, upcflag;
long val, oldval, sign;
double dval;
int i, tempopt, hassign;
Strlist *sp;
Symbol *sym;
if (if_flag)
return 0;
if (!p2c_only) {
if (!strncmp(inbufptr, noskipcomment, strlen(noskipcomment)) &&
*noskipcomment) {
inbufptr += strlen(noskipcomment);
if (skipflag < 0) {
if (skipflag < -1) {
skipflag++;
} else {
curtok = TOK_ENDIF;
skipflag = 1;
return 2;
}
} else {
skipflag = 1;
return 1;
}
}
}
closing = inbufptr;
while (*closing && (starparen
? (closing[0] != '*' || closing[1] != ')')
: (closing[0] != '}')))
closing++;
if (!*closing)
return 0;
after = closing + (starparen ? 2 : 1);
cp = inbufptr;
while (cp < closing && (*cp != '#' || cp[1] != '#'))
cp++; /* Ignore comments */
if (cp < closing) {
while (isspace(cp[-1]))
cp--;
*cp = '#'; /* avoid skipping spaces past closing! */
closing = cp;
}
if (!p2c_only) {
if (!strncmp(inbufptr, "DUMP-SYMBOLS", 12) &&
closing == inbufptr + 12) {
wrapup();
inbufptr = after;
return 1;
}
if (!strncmp(inbufptr, fixedcomment, strlen(fixedcomment)) &&
*fixedcomment &&
inbufptr + strlen(fixedcomment) == closing) {
fixedflag++;
inbufptr = after;
return 1;
}
if (!strncmp(inbufptr, permanentcomment, strlen(permanentcomment)) &&
*permanentcomment &&
inbufptr + strlen(permanentcomment) == closing) {
permflag = 1;
inbufptr = after;
return 1;
}
if (!strncmp(inbufptr, interfacecomment, strlen(interfacecomment)) &&
*interfacecomment &&
inbufptr + strlen(interfacecomment) == closing) {
inbufptr = after;
curtok = TOK_INTFONLY;
return 2;
}
if (!strncmp(inbufptr, skipcomment, strlen(skipcomment)) &&
*skipcomment &&
inbufptr + strlen(skipcomment) == closing) {
inbufptr = after;
skipflag--;
if (skipflag == -1) {
skipping_module++; /* eat comments in skipped portion */
do {
gettok();
} while (curtok != TOK_ENDIF);
skipping_module--;
}
return 1;
}
if (!strncmp(inbufptr, signedcomment, strlen(signedcomment)) &&
*signedcomment && !p2c_only &&
inbufptr + strlen(signedcomment) == closing) {
inbufptr = after;
gettok();
if (curtok == TOK_IDENT && curtokmeaning &&
curtokmeaning->kind == MK_TYPE &&
curtokmeaning->type == tp_char) {
curtokmeaning = mp_schar;
} else
warning("{SIGNED} applied to type other than CHAR [314]");
return 2;
}
if (!strncmp(inbufptr, unsignedcomment, strlen(unsignedcomment)) &&
*unsignedcomment && !p2c_only &&
inbufptr + strlen(unsignedcomment) == closing) {
inbufptr = after;
gettok();
if (curtok == TOK_IDENT && curtokmeaning &&
curtokmeaning->kind == MK_TYPE &&
curtokmeaning->type == tp_char) {
curtokmeaning = mp_uchar;
} else if (curtok == TOK_IDENT && curtokmeaning &&
curtokmeaning->kind == MK_TYPE &&
curtokmeaning->type == tp_integer) {
curtokmeaning = mp_unsigned;
} else if (curtok == TOK_IDENT && curtokmeaning &&
curtokmeaning->kind == MK_TYPE &&
curtokmeaning->type == tp_int) {
curtokmeaning = mp_uint;
} else
warning("{UNSIGNED} applied to type other than CHAR or INTEGER [313]");
return 2;
}
if (*inbufptr == '$') {
i = turbo_directive(closing, after);
if (i)
return i;
}
}
tempopt = 0;
cp = inbufptr;
if (*cp == '*') {
cp++;
tempopt = 1;
}
if (!isalpha(*cp))
return 0;
while ((isalnum(*cp) || *cp == '_') && cp2 < namebuf+300)
*cp2++ = toupper(*cp++);
*cp2 = 0;
i = numparams;
while (--i >= 0 && strcmp(rctable[i].name, namebuf)) ;
if (i < 0)
return 0;
kind = rctable[i].kind;
chgmode = rctable[i].chgmode;
if (chgmode == ' ') /* allowed in p2crc only */
return 0;
if (chgmode == 'T' && lex_initialized) {
if (cp == closing || *cp == '=' || *cp == '+' || *cp == '-')
warning(format_s("%s works only at top of program [235]",
rctable[i].name));
}
if (cp == closing) {
if (kind == 'S' || kind == 'I' || kind == 'D' || kind == 'L' ||
kind == 'R' || kind == 'B' || kind == 'C' || kind == 'U') {
undooption(i, "");
inbufptr = after;
return 1;
}
}
switch (kind) {
case 'S':
case 'I':
case 'L':
val = oldval = (kind == 'L') ? *(( long *)rctable[i].ptr) :
(kind == 'S') ? *((short *)rctable[i].ptr) :
*(( int *)rctable[i].ptr);
switch (*cp) {
case '=':
skipspc(cp);
hassign = (*++cp == '-' || *cp == '+');
sign = (*cp == '-') ? -1 : 1;
cp += hassign;
if (isdigit(*cp)) {
val = 0;
while (isdigit(*cp))
val = val * 10 + (*cp++) - '0';
val *= sign;
if (kind == 'D' && !hassign)
val += 10000;
} else if (toupper(cp[0]) == 'D' &&
toupper(cp[1]) == 'E' &&
toupper(cp[2]) == 'F') {
val = rctable[i].def;
cp += 3;
}
break;
case '+':
case '-':
if (chgmode != 'R')
return 0;
for (;;) {
if (*cp == '+')
val++;
else if (*cp == '-')
val--;
else
break;
cp++;
}
break;
}
skipspc(cp);
if (cp != closing)
return 0;
strlist_insert(&rcprevvalues[i], "")->value = oldval;
if (tempopt)
strlist_insert(&tempoptionlist, "")->value = i;
if (kind == 'L')
*((long *)rctable[i].ptr) = val;
else if (kind == 'S')
*((short *)rctable[i].ptr) = val;
else
*((int *)rctable[i].ptr) = val;
inbufptr = after;
return 1;
case 'D':
val = oldval = *((int *)rctable[i].ptr);
if (*cp++ != '=')
return 0;
skipspc(cp);
if (toupper(cp[0]) == 'D' &&
toupper(cp[1]) == 'E' &&
toupper(cp[2]) == 'F') {
val = rctable[i].def;
cp += 3;
} else {
cp2 = namebuf;
while (*cp && cp != closing && !isspace(*cp))
*cp2++ = *cp++;
*cp2 = 0;
val = parsedelta(namebuf, -1);
if (!val)
return 0;
}
skipspc(cp);
if (cp != closing)
return 0;
strlist_insert(&rcprevvalues[i], "")->value = oldval;
if (tempopt)
strlist_insert(&tempoptionlist, "")->value = i;
*((int *)rctable[i].ptr) = val;
inbufptr = after;
return 1;
case 'R':
if (*cp++ != '=')
return 0;
skipspc(cp);
if (toupper(cp[0]) == 'D' &&
toupper(cp[1]) == 'E' &&
toupper(cp[2]) == 'F') {
dval = rctable[i].def / 100.0;
cp += 3;
} else {
cp2 = cp;
while (isdigit(*cp) || *cp == '-' || *cp == '+' ||
*cp == '.' || toupper(*cp) == 'E')
cp++;
if (cp == cp2)
return 0;
dval = atof(cp2);
}
skipspc(cp);
if (cp != closing)
return 0;
sprintf(namebuf, "%g", *((double *)rctable[i].ptr));
strlist_insert(&rcprevvalues[i], namebuf);
if (tempopt)
strlist_insert(&tempoptionlist, namebuf)->value = i;
*((double *)rctable[i].ptr) = dval;
inbufptr = after;
return 1;
case 'B':
if (*cp++ != '=')
return 0;
skipspc(cp);
if (toupper(cp[0]) == 'D' &&
toupper(cp[1]) == 'E' &&
toupper(cp[2]) == 'F') {
val = rctable[i].def;
cp += 3;
} else {
val = parse_breakstr(cp);
while (*cp && cp != closing && !isspace(*cp))
cp++;
}
skipspc(cp);
if (cp != closing || val == -1)
return 0;
strlist_insert(&rcprevvalues[i], "")->value =
*((short *)rctable[i].ptr);
if (tempopt)
strlist_insert(&tempoptionlist, "")->value = i;
*((short *)rctable[i].ptr) = val;
inbufptr = after;
return 1;
case 'C':
case 'U':
if (*cp == '=') {
cp++;
skipspc(cp);
for (cp2 = cp; cp2 != closing && !isspace(*cp2); cp2++)
if (!*cp2 || cp2-cp >= rctable[i].def)
return 0;
cp2 = (char *)rctable[i].ptr;
sp = strlist_insert(&rcprevvalues[i], cp2);
if (tempopt)
strlist_insert(&tempoptionlist, "")->value = i;
while (cp != closing && !isspace(*cp2))
*cp2++ = *cp++;
*cp2 = 0;
if (kind == 'U')
upc((char *)rctable[i].ptr);
skipspc(cp);
if (cp != closing)
return 0;
inbufptr = after;
if (!strcmp(rctable[i].name, "LANGUAGE") &&
!strcmp((char *)rctable[i].ptr, "MODCAL"))
sysprog_flag |= 2;
return 1;
}
return 0;
case 'F':
case 'G':
if (*cp == '=' || *cp == '+' || *cp == '-') {
upcflag = (kind == 'F' && !pascalcasesens);
chgmode = *cp++;
skipspc(cp);
cp2 = namebuf;
while (isalnum(*cp) || *cp == '_' || *cp == '$' || *cp == '%')
*cp2++ = *cp++;
*cp2++ = 0;
if (!*namebuf)
return 0;
skipspc(cp);
if (cp != closing)
return 0;
if (upcflag)
upc(namebuf);
sym = findsymbol(namebuf);
if (rctable[i].def & FUNCBREAK)
sym->flags &= ~FUNCBREAK;
if (chgmode == '-')
sym->flags &= ~rctable[i].def;
else
sym->flags |= rctable[i].def;
inbufptr = after;
return 1;
}
return 0;
case 'A':
if (*cp == '=' || *cp == '+' || *cp == '-') {
chgmode = *cp++;
skipspc(cp);
cp2 = namebuf;
while (cp != closing && !isspace(*cp) && *cp)
*cp2++ = *cp++;
*cp2++ = 0;
skipspc(cp);
if (cp != closing)
return 0;
if (chgmode != '+')
strlist_remove((Strlist **)rctable[i].ptr, namebuf);
if (chgmode != '-')
sp = strlist_insert((Strlist **)rctable[i].ptr, namebuf);
if (tempopt)
strlist_insert(&tempoptionlist, namebuf)->value = i;
inbufptr = after;
return 1;
}
return 0;
case 'M':
if (!isspace(*cp))
return 0;
skipspc(cp);
if (!isalpha(*cp))
return 0;
for (cp2 = cp; *cp2 && cp2 != closing; cp2++) ;
if (cp2 > cp && cp2 == closing) {
inbufptr = after;
cp2 = format_ds("%.*s", (int)(cp2-cp), cp);
if (tp_integer != NULL) {
defmacro(cp2, rctable[i].def, NULL, 0);
} else {
sp = strlist_append(&addmacros, cp2);
sp->value = rctable[i].def;
}
return 1;
}
return 0;
case 'X':
switch (rctable[i].def) {
case 1: /* strlist with string values */
if (!isspace(*cp) && *cp != '=' &&
*cp != '+' && *cp != '-')
return 0;
chgmode = *cp++;
skipspc(cp);
cp2 = namebuf;
while (isalnum(*cp) || *cp == '_' ||
*cp == '$' || *cp == '%' ||
*cp == '.' || *cp == '-' ||
(*cp == '\'' && cp[1] && cp[2] == '\'' &&
cp+1 != closing && cp[1] != '=')) {
if (*cp == '\'') {
*cp2++ = *cp++;
*cp2++ = *cp++;
}
*cp2++ = *cp++;
}
*cp2++ = 0;
if (chgmode == '-') {
skipspc(cp);
if (cp != closing)
return 0;
strlist_remove((Strlist **)rctable[i].ptr, namebuf);
} else {
if (!isspace(*cp) && *cp != '=')
return 0;
skipspc(cp);
if (*cp == '=') {
cp++;
skipspc(cp);
}
if (chgmode == '=' || isspace(chgmode))
strlist_remove((Strlist **)rctable[i].ptr, namebuf);
sp = strlist_append((Strlist **)rctable[i].ptr, namebuf);
if (tempopt)
strlist_insert(&tempoptionlist, namebuf)->value = i;
cp2 = namebuf;
while (*cp && cp != closing && !isspace(*cp))
*cp2++ = *cp++;
*cp2++ = 0;
skipspc(cp);
if (cp != closing)
return 0;
sp->value = (long)stralloc(namebuf);
}
inbufptr = after;
if (lex_initialized)
handle_nameof(); /* as good a place to do this as any! */
return 1;
case 3: /* Synonym parameter */
if (isspace(*cp) || *cp == '=' ||
*cp == '+' || *cp == '-') {
chgmode = *cp++;
skipspc(cp);
cp2 = namebuf;
while (isalnum(*cp) || *cp == '_' ||
*cp == '$' || *cp == '%')
*cp2++ = *cp++;
*cp2++ = 0;
if (!*namebuf)
return 0;
skipspc(cp);
if (!pascalcasesens)
upc(namebuf);
sym = findsymbol(namebuf);
if (chgmode == '-') {
if (cp != closing)
return 0;
sym->flags &= ~SSYNONYM;
inbufptr = after;
return 1;
}
if (*cp == '=') {
cp++;
skipspc(cp);
}
cp2 = namebuf;
while (isalnum(*cp) || *cp == '_' ||
*cp == '$' || *cp == '%')
*cp2++ = *cp++;
*cp2++ = 0;
skipspc(cp);
if (cp != closing)
return 0;
sym->flags |= SSYNONYM;
if (!pascalcasesens)
upc(namebuf);
if (*namebuf)
strlist_append(&sym->symbolnames, "===")->value =
(long)findsymbol(namebuf);
else
strlist_append(&sym->symbolnames, "===")->value=0;
inbufptr = after;
return 1;
}
return 0;
}
return 0;
}
return 0;
}
Static void comment(starparen)
int starparen; /* 0={ }, 1=(* *), 2=C comments*/
{
register char ch;
int nestcount = 1, startlnum = inf_lnum, wasrel = 0, trailing;
int i, cmtindent, cmtindent2, saveeat = eatcomments;
char *cp;
if (!strncmp(inbufptr, embedcomment, strlen(embedcomment)) &&
*embedcomment)
eatcomments = 0;
cp = inbuf;
while (isspace(*cp))
cp++;
trailing = (*cp != '{' && ((*cp != '(' && *cp != '/') || cp[1] != '*'));
cmtindent = inbufindent;
cmtindent2 = cmtindent + 1 + (starparen != 0);
cp = inbufptr;
while (isspace(*cp))
cmtindent2++, cp++;
cp = curtokbuf;
for (;;) {
ch = *inbufptr++;
switch (ch) {
case '}':
if ((!starparen || nestedcomments == 0) &&
starparen != 2 &&
--nestcount <= 0) {
*cp = 0;
if (wasrel && !strcmp(curtokbuf, "\003"))
*curtokbuf = '\002';
if (!commenting_flag)
commentline(trailing ? CMT_TRAIL : CMT_POST);
eatcomments = saveeat;
return;
}
break;
case '{':
if (nestedcomments == 1 && starparen != 2)
nestcount++;
break;
case '*':
if ((*inbufptr == ((starparen == 2) ? '/' : ')') &&
(starparen || nestedcomments == 0)) &&
--nestcount <= 0) {
inbufptr++;
*cp = 0;
if (wasrel && !strcmp(curtokbuf, "\003"))
*curtokbuf = '\002';
if (!commenting_flag)
commentline(trailing ? CMT_TRAIL : CMT_POST);
eatcomments = saveeat;
return;
}
break;
case '(':
if (*inbufptr == '*' && nestedcomments == 1 &&
starparen != 2) {
*cp++ = ch;
ch = *inbufptr++;
nestcount++;
}
break;
case 0:
*cp = 0;
if (commenting_flag)
saveinputcomment(inbufptr-1);
else
commentline(CMT_POST);
trailing = 0;
p2c_getline();
i = 0;
for (;;) {
if (*inbufptr == ' ') {
inbufptr++;
i++;
} else if (*inbufptr == '\t') {
inbufptr++;
i++;
if (intabsize)
i = (i / intabsize + 1) * intabsize;
} else
break;
}
cp = curtokbuf;
if (*inbufptr) {
if (i == cmtindent2 && !starparen)
cmtindent--;
cmtindent2 = -1;
if (i >= cmtindent && i > 0) {
*cp++ = '\002';
i -= cmtindent;
wasrel = 1;
} else {
*cp++ = '\003';
}
while (--i >= 0)
*cp++ = ' ';
} else
*cp++ = '\003';
continue;
case EOFMARK:
error(format_d("Runaway comment from line %d", startlnum));
eatcomments = saveeat;
return; /* unnecessary */
}
*cp++ = ch;
}
}
char *getinlinepart()
{
char *cp, *buf;
for (;;) {
if (isspace(*inbufptr)) {
inbufptr++;
} else if (!*inbufptr) {
p2c_getline();
} else if (*inbufptr == '{') {
inbufptr++;
comment(0);
} else if (*inbufptr == '(' && inbufptr[1] == '*') {
inbufptr += 2;
comment(1);
} else
break;
}
cp = inbufptr;
while (isspace(*cp) || isalnum(*cp) ||
*cp == '_' || *cp == '$' ||
*cp == '+' || *cp == '-' ||
*cp == '<' || *cp == '>')
cp++;
if (cp == inbufptr)
return "";
while (isspace(cp[-1]))
cp--;
buf = format_s("%s", inbufptr);
buf[cp-inbufptr] = 0; /* truncate the string */
inbufptr = cp;
return buf;
}
Static int getflag()
{
int res = 1;
gettok();
if (curtok == TOK_IDENT) {
res = (strcmp(curtokbuf, "OFF") != 0);
gettok();
}
return res;
}
char getchartok()
{
if (!*inbufptr) {
warning("Unexpected end of line [236]");
return ' ';
}
if (isspace(*inbufptr)) {
warning("Whitespace not allowed here [237]");
return ' ';
}
return *inbufptr++;
}
char *getparenstr(buf)
char *buf;
{
int count = 0;
char *cp;
if (inbufptr < buf) /* this will get most bad cases */
error("Can't handle a line break here");
while (isspace(*buf))
buf++;
cp = buf;
for (;;) {
if (!*cp)
error("Can't handle a line break here");
if (*cp == '(')
count++;
if (*cp == ')')
if (--count < 0)
break;
cp++;
}
inbufptr = cp + 1;
while (cp > buf && isspace(cp[-1]))
cp--;
return format_ds("%.*s", (int)(cp - buf), buf);
}
void leadingcomments()
{
for (;;) {
switch (*inbufptr++) {
case 0:
p2c_getline();
break;
case ' ':
case '\t':
case 26:
/* ignore whitespace */
break;
case '{':
if (!parsecomment(1, 0)) {
inbufptr--;
return;
}
break;
case '(':
if (*inbufptr == '*') {
inbufptr++;
if (!parsecomment(1, 1)) {
inbufptr -= 2;
return;
}
break;
}
/* fall through */
default:
inbufptr--;
return;
}
}
}
void get_C_string(term)
int term;
{
char *cp = curtokbuf;
char ch;
int i;
while ((ch = *inbufptr++)) {
if (ch == term) {
*cp = 0;
curtokint = cp - curtokbuf;
return;
} else if (ch == '\\') {
if (isdigit(*inbufptr)) {
i = (*inbufptr++) - '0';
if (isdigit(*inbufptr))
i = i*8 + (*inbufptr++) - '0';
if (isdigit(*inbufptr))
i = i*8 + (*inbufptr++) - '0';
*cp++ = i;
} else {
ch = *inbufptr++;
switch (tolower(ch)) {
case 'n':
*cp++ = '\n';
break;
case 't':
*cp++ = '\t';
break;
case 'v':
*cp++ = '\v';
break;
case 'b':
*cp++ = '\b';
break;
case 'r':
*cp++ = '\r';
break;
case 'f':
*cp++ = '\f';
break;
case '\\':
*cp++ = '\\';
break;
case '\'':
*cp++ = '\'';
break;
case '"':
*cp++ = '"';
break;
case 'x':
if (isxdigit(*inbufptr)) {
if (isdigit(*inbufptr))
i = (*inbufptr++) - '0';
else
i = (toupper(*inbufptr++)) - 'A' + 10;
if (isdigit(*inbufptr))
i = i*16 + (*inbufptr++) - '0';
else if (isxdigit(*inbufptr))
i = i*16 + (toupper(*inbufptr++)) - 'A' + 10;
*cp++ = i;
break;
}
/* fall through */
default:
warning("Strange character in C string [238]");
}
}
} else
*cp++ = ch;
}
*cp = 0;
curtokint = cp - curtokbuf;
warning("Unterminated C string [239]");
}
void begincommenting(cp)
char *cp;
{
if (!commenting_flag) {
commenting_ptr = cp;
}
commenting_flag++;
}
void saveinputcomment(cp)
char *cp;
{
if (commenting_ptr)
sprintf(curtokbuf, "%.*s", (int)(cp - commenting_ptr), commenting_ptr);
else
sprintf(curtokbuf, "\003%.*s", (int)(cp - inbuf), inbuf);
commentline(CMT_POST);
commenting_ptr = NULL;
}
void endcommenting(cp)
char *cp;
{
commenting_flag--;
if (!commenting_flag) {
saveinputcomment(cp);
}
}
int peeknextchar()
{
char *cp;
cp = inbufptr;
while (isspace(*cp))
cp++;
return *cp;
}
#ifdef LEXDEBUG
Static void zgettok();
void gettok()
{
zgettok();
if (tokentrace) {
printf("gettok() found %s", tok_name(curtok));
switch (curtok) {
case TOK_HEXLIT:
case TOK_OCTLIT:
case TOK_INTLIT:
case TOK_MININT:
printf(", curtokint = %d", curtokint);
break;
case TOK_REALLIT:
case TOK_STRLIT:
printf(", curtokbuf = %s", makeCstring(curtokbuf, curtokint));
break;
default:
break;
}
putchar('\n');
}
}
Static void zgettok()
#else
void gettok()
#endif
{
register char ch;
register char *cp;
char ch2;
char *startcp;
int i;
debughook();
for (;;) {
switch ((ch = *inbufptr++)) {
case 0:
if (commenting_flag)
saveinputcomment(inbufptr-1);
p2c_getline();
cp = curtokbuf;
for (;;) {
inbufindent = 0;
for (;;) {
if (*inbufptr == '\t') {
inbufindent++;
if (intabsize)
inbufindent = (inbufindent / intabsize + 1) * intabsize;
} else if (*inbufptr == ' ')
inbufindent++;
else if (*inbufptr != 26)
break;
inbufptr++;
}
if (!*inbufptr && !commenting_flag) { /* blank line */
*cp++ = '\001';
p2c_getline();
} else
break;
}
if (cp > curtokbuf) {
*cp = 0;
commentline(CMT_POST);
}
break;
case '\t':
case ' ':
case 26: /* ignore ^Z's in Turbo files */
while (*inbufptr++ == ch) ;
inbufptr--;
break;
case '$':
if (dollar_idents)
goto ident;
if (dollar_flag) {
dollar_flag = 0;
curtok = TOK_DOLLAR;
return;
}
startcp = inbufptr-1;
while (isspace(*inbufptr))
inbufptr++;
cp = inbufptr;
while (isxdigit(*cp))
cp++;
if (cp > inbufptr && cp <= inbufptr+8 && !isalnum(*cp)) {
while (isspace(*cp))
cp++;
if (!isdigit(*cp) && *cp != '\'') {
cp = curtokbuf; /* Turbo hex constant */
while (isxdigit(*inbufptr))
*cp++ = *inbufptr++;
*cp = 0;
curtok = TOK_HEXLIT;
curtokint = my_strtol(curtokbuf, NULL, 16);
return;
}
}
dollar_flag++; /* HP Pascal compiler directive */
do {
gettok();
if (curtok == TOK_IF) { /* $IF expr$ */
Expr *ex;
Value val;
if (!skipping_module) {
if (!setup_complete)
error("$IF$ not allowed at top of program");
/* Even though HP Pascal doesn't let these nest,
there's no harm in supporting it. */
if (if_flag) {
skiptotoken(TOK_DOLLAR);
if_flag++;
break;
}
gettok();
ex = p_expr(tp_boolean);
val = eval_expr_consts(ex);
freeexpr(ex);
i = (val.type == tp_boolean && val.i);
free_value(&val);
if (!i) {
if (curtok != TOK_DOLLAR) {
warning("Syntax error in $IF$ expression [240]");
skiptotoken(TOK_DOLLAR);
}
begincommenting(startcp);
if_flag++;
while (if_flag > 0)
gettok();
endcommenting(inbufptr);
}
} else {
skiptotoken(TOK_DOLLAR);
}
} else if (curtok == TOK_END) { /* $END$ */
if (if_flag) {
gettok();
if (!wexpecttok(TOK_DOLLAR))
skiptotoken(TOK_DOLLAR);
curtok = TOK_ENDIF;
if_flag--;
return;
} else {
gettok();
if (!wexpecttok(TOK_DOLLAR))
skiptotoken(TOK_DOLLAR);
}
} else if (curtok == TOK_IDENT) {
if (!strcmp(curtokbuf, "INCLUDE") &&
!if_flag && !skipping_module) {
char *fn;
gettok();
if (curtok == TOK_IDENT) {
fn = stralloc(curtokcase);
gettok();
} else if (wexpecttok(TOK_STRLIT)) {
fn = stralloc(curtokbuf);
gettok();
} else
fn = "";
if (!wexpecttok(TOK_DOLLAR)) {
skiptotoken(TOK_DOLLAR);
} else {
if (handle_include(fn))
return;
}
} else if (ignore_directives ||
if_flag ||
!strcmp(curtokbuf, "SEARCH") ||
!strcmp(curtokbuf, "REF") ||
!strcmp(curtokbuf, "DEF")) {
skiptotoken(TOK_DOLLAR);
} else if (!strcmp(curtokbuf, "SWITCH_STRPOS")) {
switch_strpos = getflag();
} else if (!strcmp(curtokbuf, "SYSPROG")) {
if (getflag())
sysprog_flag |= 1;
else
sysprog_flag &= ~1;
} else if (!strcmp(curtokbuf, "MODCAL")) {
if (getflag())
sysprog_flag |= 2;
else
sysprog_flag &= ~2;
} else if (!strcmp(curtokbuf, "PARTIAL_EVAL")) {
if (shortcircuit < 0)
partial_eval_flag = getflag();
} else if (!strcmp(curtokbuf, "IOCHECK")) {
iocheck_flag = getflag();
} else if (!strcmp(curtokbuf, "RANGE")) {
if (getflag()) {
if (!range_flag)
note("Range checking is ON [216]");
range_flag = 1;
} else {
if (range_flag)
note("Range checking is OFF [216]");
range_flag = 0;
}
} else if (!strcmp(curtokbuf, "OVFLCHECK")) {
if (getflag()) {
if (!ovflcheck_flag)
note("Overflow checking is ON [219]");
ovflcheck_flag = 1;
} else {
if (ovflcheck_flag)
note("Overflow checking is OFF [219]");
ovflcheck_flag = 0;
}
} else if (!strcmp(curtokbuf, "STACKCHECK")) {
if (getflag()) {
if (!stackcheck_flag)
note("Stack checking is ON [217]");
stackcheck_flag = 1;
} else {
if (stackcheck_flag)
note("Stack checking is OFF [217]");
stackcheck_flag = 0;
}
}
skiptotoken2(TOK_DOLLAR, TOK_COMMA);
} else {
warning("Mismatched '$' signs [241]");
dollar_flag = 0; /* got out of sync */
return;
}
} while (curtok == TOK_COMMA);
break;
case '"':
if (C_lex) {
get_C_string(ch);
curtok = TOK_STRLIT;
return;
}
goto stringLiteral;
case '#':
if (modula2) {
curtok = TOK_NE;
return;
}
cp = inbufptr;
while (isspace(*cp)) cp++;
if (!strcincmp(cp, "INCLUDE", 7)) {
char *cp2, *cp3;
cp += 7;
while (isspace(*cp)) cp++;
cp2 = cp + strlen(cp) - 1;
while (isspace(*cp2)) cp2--;
if ((*cp == '"' && *cp2 == '"' && cp2 > cp) ||
(*cp == '<' && *cp2 == '>')) {
inbufptr = cp2 + 1;
cp3 = stralloc(cp + 1);
cp3[cp2 - cp - 1] = 0;
if (handle_include(cp3))
return;
else
break;
}
}
/* fall through */
case '\'':
if (C_lex && ch == '\'') {
get_C_string(ch);
if (curtokint != 1)
warning("Character constant has length != 1 [242]");
curtokint = *curtokbuf;
curtok = TOK_CHARLIT;
return;
}
stringLiteral:
cp = curtokbuf;
ch2 = (ch == '"') ? '"' : '\'';
do {
if (ch == ch2) {
while ((ch = *inbufptr++) != '\n' &&
ch != EOF) {
if (ch == ch2) {
if (*inbufptr != ch2 || modula2)
break;
else
inbufptr++;
}
*cp++ = ch;
}
if (ch != ch2)
warning("Error in string literal [243]");
} else {
ch = *inbufptr++;
if (isdigit(ch)) {
i = 0;
while (isdigit(ch)) {
i = i*10 + ch - '0';
ch = *inbufptr++;
}
inbufptr--;
*cp++ = i;
} else {
*cp++ = ch & 0x1f;
}
}
while (*inbufptr == ' ' || *inbufptr == '\t')
inbufptr++;
} while ((ch = *inbufptr++) == ch2 || ch == '#');
inbufptr--;
*cp = 0;
curtokint = cp - curtokbuf;
curtok = TOK_STRLIT;
return;
case '(':
if (*inbufptr == '*' && !C_lex) {
inbufptr++;
switch (commenting_flag ? 0 : parsecomment(0, 1)) {
case 0:
comment(1);
break;
case 2:
return;
}
break;
} else if (*inbufptr == '.') {
curtok = TOK_LBR;
inbufptr++;
} else {
curtok = TOK_LPAR;
}
return;
case '{':
if (C_lex || modula2) {
curtok = TOK_LBRACE;
return;
}
switch (commenting_flag ? 0 : parsecomment(0, 0)) {
case 0:
comment(0);
break;
case 2:
return;
}
break;
case '}':
if (C_lex || modula2) {
curtok = TOK_RBRACE;
return;
}
if (skipflag > 0) {
skipflag = 0;
} else
warning("Unmatched '}' in input file [244]");
break;
case ')':
curtok = TOK_RPAR;
return;
case '*':
if (*inbufptr == (C_lex ? '/' : ')')) {
inbufptr++;
if (skipflag > 0) {
skipflag = 0;
} else
warning("Unmatched '*)' in input file [245]");
break;
} else if (*inbufptr == '*' && !C_lex) {
curtok = TOK_STARSTAR;
inbufptr++;
} else
curtok = TOK_STAR;
return;
case '+':
if (C_lex && *inbufptr == '+') {
curtok = TOK_PLPL;
inbufptr++;
} else
curtok = TOK_PLUS;
return;
case ',':
curtok = TOK_COMMA;
return;
case '-':
if (C_lex && *inbufptr == '-') {
curtok = TOK_MIMI;
inbufptr++;
} else if (*inbufptr == '>') {
curtok = TOK_ARROW;
inbufptr++;
} else
curtok = TOK_MINUS;
return;
case '.':
if (*inbufptr == '.') {
curtok = TOK_DOTS;
inbufptr++;
} else if (*inbufptr == ')') {
curtok = TOK_RBR;
inbufptr++;
} else
curtok = TOK_DOT;
return;
case '/':
if (C_lex && *inbufptr == '*') {
inbufptr++;
comment(2);
break;
}
curtok = TOK_SLASH;
return;
case ':':
if (*inbufptr == '=') {
curtok = TOK_ASSIGN;
inbufptr++;
} else if (*inbufptr == ':') {
curtok = TOK_COLONCOLON;
inbufptr++;
} else
curtok = TOK_COLON;
return;
case ';':
curtok = TOK_SEMI;
return;
case '<':
if (*inbufptr == '=') {
curtok = TOK_LE;
inbufptr++;
} else if (*inbufptr == '>') {
curtok = TOK_NE;
inbufptr++;
} else if (*inbufptr == '<') {
curtok = TOK_LTLT;
inbufptr++;
} else
curtok = TOK_LT;
return;
case '>':
if (*inbufptr == '=') {
curtok = TOK_GE;
inbufptr++;
} else if (*inbufptr == '>') {
curtok = TOK_GTGT;
inbufptr++;
} else
curtok = TOK_GT;
return;
case '=':
if (*inbufptr == '=') {
curtok = TOK_EQEQ;
inbufptr++;
} else
curtok = TOK_EQ;
return;
case '[':
curtok = TOK_LBR;
return;
case ']':
curtok = TOK_RBR;
return;
case '^':
curtok = TOK_HAT;
return;
case '&':
if (*inbufptr == '&') {
curtok = TOK_ANDAND;
inbufptr++;
} else
curtok = TOK_AMP;
return;
case '|':
if (*inbufptr == '|') {
curtok = TOK_OROR;
inbufptr++;
} else
curtok = TOK_VBAR;
return;
case '~':
curtok = TOK_TWIDDLE;
return;
case '!':
if (*inbufptr == '=') {
curtok = TOK_BANGEQ;
inbufptr++;
} else
curtok = TOK_BANG;
return;
case '%':
if (C_lex) {
curtok = TOK_PERC;
return;
}
goto ident;
case '?':
curtok = TOK_QM;
return;
case '@':
curtok = TOK_ADDR;
return;
case EOFMARK:
if (curtok == TOK_EOF) {
if (inputkind == INP_STRLIST)
error("Unexpected end of macro");
else
error("Unexpected end of file");
}
curtok = TOK_EOF;
return;
default:
if (isdigit(ch)) {
cp = inbufptr;
while (isxdigit(*cp))
cp++;
if (*cp == '#' && isxdigit(cp[1])) {
i = atoi(inbufptr-1);
inbufptr = cp+1;
} else if (toupper(cp[-1]) == 'B' ||
toupper(cp[-1]) == 'C') {
inbufptr--;
i = 8;
} else if (toupper(*cp) == 'H') {
inbufptr--;
i = 16;
} else if ((ch == '0' && toupper(*inbufptr) == 'X' &&
isxdigit(inbufptr[1]))) {
inbufptr++;
i = 16;
} else {
i = 10;
}
if (i != 10) {
curtokint = 0;
while (isdigit(*inbufptr) ||
(i > 10 && isxdigit(*inbufptr))) {
ch = toupper(*inbufptr++);
curtokint *= i;
if (ch <= '9')
curtokint += ch - '0';
else
curtokint += ch - 'A' + 10;
}
sprintf(curtokbuf, "%ld", curtokint);
if ((toupper(*inbufptr) == 'B' && i == 8) ||
(toupper(*inbufptr) == 'H' && i == 16))
inbufptr++;
if (toupper(*inbufptr) == 'C' && i == 8) {
inbufptr++;
curtok = TOK_STRLIT;
curtokbuf[0] = curtokint;
curtokbuf[1] = 0;
curtokint = 1;
return;
}
if (toupper(*inbufptr) == 'L') {
strcat(curtokbuf, "L");
inbufptr++;
}
curtok = (i == 8) ? TOK_OCTLIT : TOK_HEXLIT;
return;
}
cp = curtokbuf;
i = 0;
while (ch == '0')
ch = *inbufptr++;
if (isdigit(ch)) {
while (isdigit(ch)) {
*cp++ = ch;
ch = *inbufptr++;
}
} else
*cp++ = '0';
if (ch == '.') {
if (isdigit(*inbufptr)) {
*cp++ = ch;
ch = *inbufptr++;
i = 1;
while (isdigit(ch)) {
*cp++ = ch;
ch = *inbufptr++;
}
}
}
if (ch == 'e' || ch == 'E' ||
ch == 'd' || ch == 'D' ||
ch == 'q' || ch == 'Q') {
ch = *inbufptr;
if (isdigit(ch) || ch == '+' || ch == '-') {
*cp++ = 'e';
inbufptr++;
i = 1;
do {
*cp++ = ch;
ch = *inbufptr++;
} while (isdigit(ch));
}
}
inbufptr--;
*cp = 0;
if (i) {
curtok = TOK_REALLIT;
curtokint = cp - curtokbuf;
} else {
if (cp >= curtokbuf+10) {
i = strcmp(curtokbuf, "2147483648");
if (cp > curtokbuf+10 || i > 0) {
curtok = TOK_REALLIT;
curtokint = cp - curtokbuf + 2;
strcat(curtokbuf, ".0");
return;
}
if (i == 0) {
curtok = TOK_MININT;
curtokint = -2147483648;
return;
}
}
curtok = TOK_INTLIT;
curtokint = atol(curtokbuf);
if (toupper(*inbufptr) == 'L') {
strcat(curtokbuf, "L");
inbufptr++;
}
}
return;
} else if (isalpha(ch) || ch == '_') {
ident:
{
register char *cp2;
curtoksym = NULL;
cp = curtokbuf;
cp2 = curtokcase;
*cp2++ = symcase ? ch : tolower(ch);
*cp++ = pascalcasesens ? ch : toupper(ch);
while (isalnum((ch = *inbufptr++)) ||
ch == '_' ||
(ch == '%' && !C_lex) ||
(ch == '$' && dollar_idents)) {
*cp2++ = symcase ? ch : tolower(ch);
if (!ignorenonalpha || isalnum(ch))
*cp++ = pascalcasesens ? ch : toupper(ch);
}
inbufptr--;
*cp2 = 0;
*cp = 0;
if (pascalsignif > 0)
curtokbuf[pascalsignif] = 0;
}
if (*curtokbuf == '%') {
if (!strcicmp(curtokbuf, "%INCLUDE")) {
char *cp2 = inbufptr;
while (isspace(*cp2)) cp2++;
if (*cp2 == '\'')
cp2++;
cp = curtokbuf;
while (*cp2 && *cp2 != '\'' &&
*cp2 != ';' && !isspace(*cp2)) {
*cp++ = *cp2++;
}
*cp = 0;
cp = my_strrchr(curtokbuf, '/');
if (cp && (!strcicmp(cp, "/LIST") ||
!strcicmp(cp, "/NOLIST")))
*cp = 0;
if (*cp2 == '\'')
cp2++;
while (isspace(*cp2)) cp2++;
if (*cp2 == ';')
cp2++;
while (isspace(*cp2)) cp2++;
if (!*cp2) {
inbufptr = cp2;
(void) handle_include(stralloc(curtokbuf));
return;
}
} else if (!strcicmp(curtokbuf, "%TITLE") ||
!strcicmp(curtokbuf, "%SUBTITLE")) {
gettok(); /* string literal */
break;
} else if (!strcicmp(curtokbuf, "%PAGE")) {
/* should store a special page-break comment? */
break; /* ignore token */
} else if ((i = 2, !strcicmp(curtokbuf, "%B")) ||
(i = 8, !strcicmp(curtokbuf, "%O")) ||
(i = 16, !strcicmp(curtokbuf, "%X"))) {
while (isspace(*inbufptr)) inbufptr++;
if (*inbufptr == '\'') {
inbufptr++;
curtokint = 0;
while (*inbufptr && *inbufptr != '\'') {
ch = toupper(*inbufptr++);
if (isxdigit(ch)) {
curtokint *= i;
if (ch <= '9')
curtokint += ch - '0';
else
curtokint += ch - 'A' + 10;
} else if (!isspace(ch))
warning("Bad digit in literal [246]");
}
if (*inbufptr)
inbufptr++;
sprintf(curtokbuf, "%ld", curtokint);
curtok = (i == 8) ? TOK_OCTLIT : TOK_HEXLIT;
return;
}
}
}
{
register unsigned int hash;
register Symbol *sp;
hash = 0;
for (cp = curtokbuf; *cp; cp++)
hash = hash*3 + *cp;
sp = symtab[hash % SYMHASHSIZE];
while (sp && (i = strcmp(sp->name, curtokbuf)) != 0) {
if (i < 0)
sp = sp->left;
else
sp = sp->right;
}
if (!sp)
sp = findsymbol(curtokbuf);
if (sp->flags & SSYNONYM) {
i = 100;
while (--i > 0 && sp && (sp->flags & SSYNONYM)) {
Strlist *sl;
sl = strlist_find(sp->symbolnames, "===");
if (sl)
sp = (Symbol *)sl->value;
else
sp = NULL;
}
if (!sp)
break; /* ignore token */
}
if (sp->kwtok && !(sp->flags & KWPOSS) &&
(pascalcasesens != 2 || !islower(*curtokbuf)) &&
(pascalcasesens != 3 || !isupper(*curtokbuf))) {
curtok = sp->kwtok;
return;
}
curtok = TOK_IDENT;
curtoksym = sp;
if ((i = withlevel) != 0 && sp->fbase) {
while (--i >= 0) {
curtokmeaning = sp->fbase;
while (curtokmeaning) {
if (curtokmeaning->rectype == withlist[i]) {
curtokint = i;
return;
}
curtokmeaning = curtokmeaning->snext;
}
}
}
curtokmeaning = sp->mbase;
while (curtokmeaning && !curtokmeaning->isactive)
curtokmeaning = curtokmeaning->snext;
if (!curtokmeaning)
return;
while (curtokmeaning->kind == MK_SYNONYM)
curtokmeaning = curtokmeaning->xnext;
/* look for unit.ident notation */
if (curtokmeaning->kind == MK_MODULE ||
curtokmeaning->kind == MK_FUNCTION) {
for (cp = inbufptr; isspace(*cp); cp++) ;
if (*cp == '.') {
for (cp++; isspace(*cp); cp++) ;
if (isalpha(*cp)) {
Meaning *mp = curtokmeaning;
Symbol *sym = curtoksym;
char *saveinbufptr = inbufptr;
gettok();
if (curtok == TOK_DOT)
gettok();
else
curtok = TOK_END;
if (curtok == TOK_IDENT) {
curtokmeaning = curtoksym->mbase;
while (curtokmeaning &&
curtokmeaning->ctx != mp)
curtokmeaning = curtokmeaning->snext;
if (!curtokmeaning &&
!strcmp(sym->name, "SYSTEM")) {
curtokmeaning = curtoksym->mbase;
while (curtokmeaning &&
curtokmeaning->ctx != nullctx)
curtokmeaning = curtokmeaning->snext;
}
} else
curtokmeaning = NULL;
if (!curtokmeaning) {
/* oops, was probably funcname.field */
inbufptr = saveinbufptr;
curtokmeaning = mp;
curtoksym = sym;
}
}
}
}
return;
}
} else {
warning(format_d("Unrecognized character 0%o in file [247]",
ch));
}
}
}
}
void checkkeyword(tok)
Token tok;
{
if (curtok == TOK_IDENT &&
curtoksym->kwtok == tok) {
curtoksym->flags &= ~KWPOSS;
curtok = tok;
}
}
void checkmodulewords()
{
if (modula2) {
checkkeyword(TOK_FROM);
checkkeyword(TOK_DEFINITION);
checkkeyword(TOK_IMPLEMENT);
checkkeyword(TOK_MODULE);
checkkeyword(TOK_IMPORT);
checkkeyword(TOK_EXPORT);
} else if (curtok == TOK_IDENT &&
(curtoksym->kwtok == TOK_MODULE ||
curtoksym->kwtok == TOK_IMPORT ||
curtoksym->kwtok == TOK_EXPORT ||
curtoksym->kwtok == TOK_IMPLEMENT)) {
if (!strcmp(curtokbuf, "UNIT") ||
!strcmp(curtokbuf, "USES") ||
!strcmp(curtokbuf, "INTERFACE") ||
!strcmp(curtokbuf, "IMPLEMENTATION")) {
modulenotation = 0;
findsymbol("UNIT")->flags &= ~KWPOSS;
findsymbol("USES")->flags &= ~KWPOSS;
findsymbol("INTERFACE")->flags &= ~KWPOSS;
findsymbol("IMPLEMENTATION")->flags &= ~KWPOSS;
} else {
modulenotation = 1;
findsymbol("MODULE")->flags &= ~KWPOSS;
findsymbol("EXPORT")->flags &= ~KWPOSS;
findsymbol("IMPORT")->flags &= ~KWPOSS;
findsymbol("IMPLEMENT")->flags &= ~KWPOSS;
}
curtok = curtoksym->kwtok;
}
}
/* End. */