📄 preproc.c
字号:
/*
Copyright 2001-2003 Free Software Foundation, Inc.
Written by David Lindauer, LADSoft
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; either version 2 of the License, or
(at your option) any later 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; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
You may contact the author at:
mailto::camille@bluegrass.net
or by snail mail at:
David Lindauer
850 Washburn Ave Apt 99
Louisville, KY 40222
*/
#include <stdio.h>
#include <ctype.h>
#include <string.h>
#include "utype.h"
#include "cmdline.h"
#include "umem.h"
#include "preproc.h"
#include <time.h>
#include "interp.h"
#define MAX_STRLEN 257
extern int prm_packing;
extern int prm_nasm;
extern short inputline[];
extern FILE *inputFile;
extern TABLE *gsyms, defsyms;
extern long ival;
extern char laststr[];
extern HASHREC **defhash;
extern char *infile;
extern int incconst;
extern char *prm_searchpath;
extern int prm_cplusplus, prm_ansi;
extern short *lptr;
extern int cantnewline;
extern char *infile;
extern int backupchar;
extern int prm_cmangle;
extern enum e_sym lastst;
extern char lastid[];
extern char laststr[];
extern int lastch;
extern int lineno;
typedef struct _startups_
{
struct _startups_ *link;
char *name;
int prio;
} STARTUPS;
char *errfile;
int errlineno = 0;
IFSTRUCT *ifshold[10];
char *inclfname[10];
FILE *inclfile[10];
int incldepth = 0;
int inclline[10];
int inclhfile[10];
int inhfile;
short *lptr;
LIST *incfiles = 0, *lastinc;
LIST *libincludes = 0;
IFSTRUCT *ifs = 0;
int ifskip = 0;
int elsetaken = 0;
void filemac(short *string);
void datemac(short *string);
void timemac(short *string);
void linemac(short *string);
static char *unmangid; /* In this module we have to ignore leading underscores
*/
static STARTUPS *startuplist, *rundownlist;
static short defkw[] =
{
'd', 'e', 'f', 'i', 'n', 'e', 'd', 0
};
static int definelistcount;
static SYM *definelist[100]; /* Way deep but hey! */
static int skiplevel;
/* List of standard macros */
#define INGROWNMACROS 4
struct inmac
{
char *s;
void(*func)();
} ingrownmacros[INGROWNMACROS] =
{
{
"__FILE__", filemac
}
,
{
"__DATE__", datemac,
}
,
{
"__TIME__", timemac
}
,
{
"__LINE__", linemac
}
};
static void repdefines(short *lptr);
void pushif(void);
/* Moudle init */
void preprocini()
{
skiplevel = 0;
libincludes = 0;
incldepth = 0;
incfiles = 0;
ifs = 0;
ifskip = elsetaken = 0;
unmangid = lastid;
if (prm_cmangle)
unmangid++;
startuplist = rundownlist = 0;
}
/* Preprocessor dispatch */
int preprocess(void)
{
++lptr;
lastch = ' ';
getsym(); /* get first word on line */
if (lastst != ident)
{
generror(ERR_IDEXPECT, 0, 0);
return incldepth == 0;
}
if (strcmp(unmangid, "include") == 0)
return doinclude(FALSE);
else if (strcmp(unmangid, "define") == 0)
return dodefine();
else if (strcmp(unmangid, "endif") == 0)
return doendif();
else if (strcmp(unmangid, "else") == 0)
return doelse();
else if (strcmp(unmangid, "ifdef") == 0)
return doifdef(TRUE);
else if (strcmp(unmangid, "ifndef") == 0)
return doifdef(FALSE);
else if (strcmp(unmangid, "if") == 0)
{
repdefines(lptr);
defcheck(lptr);
return doif(0);
}
else if (strcmp(unmangid, "elif") == 0)
{
repdefines(lptr);
defcheck(lptr);
return doelif();
}
else if (strcmp(unmangid, "undef") == 0)
return (doundef());
else if (strcmp(unmangid, "error") == 0)
return (doerror());
else if (strcmp(unmangid, "pragma") == 0)
return (dopragma());
else if (strcmp(unmangid, "line") == 0)
return (doline());
else
{
gensymerror(ERR_PREPROCID, unmangid);
return incldepth == 0;
}
}
//-------------------------------------------------------------------------
int doerror(void)
{
char *temp;
int i = 0;
if (ifskip)
return incldepth == 0;
temp = AllocateMemory(pstrlen(lptr) *3+2);
pstrcpy(temp, lptr);
while (*lptr)
i += installphichar(*lptr++, temp, i);
temp[i - 1] = 0;
basicerror(ERR_ERROR, temp);
return incldepth == 0;
}
//-------------------------------------------------------------------------
static int pragerror(int errno)
{
char buf[100], *p = buf, i = 99;
short *s = lptr;
while (i-- && *s && *s != '\n')
*p++ = *s++;
*p = 0;
basicerror(errno, buf);
return (incldepth == 0);
}
//-------------------------------------------------------------------------
int dopragma(void)
{
char buf[40], *p = buf;
STARTUPS *a;
int val = 0, sflag;
if (ifskip)
return incldepth == 0;
// cantnewline = TRUE;
lineToCpp();
getsym();
// cantnewline = FALSE;
if (lastst != ident)
return incldepth == 0;
if (!strcmp(unmangid, "error"))
return pragerror(ERR_USERERR);
else if (!strcmp(unmangid, "warning"))
return pragerror(ERR_USERWARN);
else
return incldepth == 0;
}
//-------------------------------------------------------------------------
int doline(void)
/*
* Handle #line directive
*/
{
int n;
if (ifskip)
return incldepth == 0;
getsym();
if (lastst != iconst)
gensymerror(ERR_PREPROCID, "#line");
else
{
n = ival;
getsym();
if (lastst != sconst)
gensymerror(ERR_PREPROCID, "#line");
else
{
errfile = litlate(laststr);
errlineno = n - 1;
}
}
return incldepth == 0;
}
//-------------------------------------------------------------------------
int doinclude(int unquoted)
/*
* HAndle include files
*/
{
int rv;
FILE *oldfile = inputFile;
incconst = TRUE;
getsym(); /* get file to include */
incconst = FALSE;
if (ifskip)
return incldepth == 0;
if (!unquoted)
{
if (lastst != sconst)
{
gensymerror(ERR_INCLFILE, "include");
return incldepth == 0;
}
}
else if (lastst == ident)
getfilename();
if (incldepth > 9)
{
generror(ERR_PREPROCID, 0, 0);
return incldepth == 0;
}
inputFile = SearchPath(laststr, prm_searchpath, "r");
if (inputFile == 0)
{
gensymerror(ERR_CANTOPEN, laststr);
inputFile = oldfile;
rv = incldepth == 0;
}
else
{
LIST *list;
pushif();
ifshold[incldepth] = ifs;
elsetaken = 0;
ifskip = 0;
ifs = 0;
inclhfile[incldepth] = inhfile;
inclline[incldepth] = lineno;
inclfile[incldepth] = oldfile; /* push current input file */
inclfname[incldepth++] = infile;
infile = litlate(laststr);
list = AllocateMemory(sizeof(LIST));
list->data = infile;
list->link = 0;
if (incfiles)
lastinc = lastinc->link = list;
else
incfiles = lastinc = list;
errfile = infile;
errlineno = 0;
rv = incldepth == 1;
lineno = 0;
inhfile = !stricmp(infile + strlen(infile) - 2, ".h");
}
return rv;
}
//-------------------------------------------------------------------------
short *plitlate(short *string)
{
short *temp = AllocateMemory(pstrlen(string) *sizeof(short) + sizeof(short))
;
pstrcpy(temp, string);
return temp;
}
//-------------------------------------------------------------------------
void glbdefine(char *name, char *value)
{
{
SYM *sp;
short *p;
DEFSTRUCT *def;
if ((sp = search(name, &defsyms)) != 0)
return ;
sp = AllocateMemory(sizeof(SYM));
sp->name = litlate(name);
def = AllocateMemory(sizeof(DEFSTRUCT));
def->args = 0;
def->argcount = 0;
def->string = p = AllocateMemory(strlen(value) *sizeof(short) + 2);
while (*value)
*p++ = *value++;
*p++ = 0;
sp->value.s = (char*)def;
insert(sp, &defsyms);
return ;
}
}
/* Handle #defines
* Doesn't check for redefine with different value
* Does handle ANSI macros
*/
int dodefine(void)
{
SYM *sp;
DEFSTRUCT *def;
short *args[40], count = 0;
short *olptr;
int p;
getsym(); /* get past #define */
if (ifskip)
return incldepth == 0;
olptr = lptr;
if (lastst != ident)
{
generror(ERR_IDEXPECT, 0, 0);
return incldepth == 0;
}
if ((sp = search(unmangid, &defsyms)) != 0)
undef2();
sp = AllocateMemory(sizeof(SYM));
sp->name = litlate(unmangid);
def = AllocateMemory(sizeof(DEFSTRUCT));
def->args = 0;
def->argcount = 0;
if (lastch == '(')
{
getdefsym();
getdefsym();
while (lastst == ident)
{
args[count++] = plitlate(unmangid);
getdefsym();
if (lastst != comma)
break;
getdefsym();
}
if (lastst != closepa)
generror(ERR_PUNCT, closepa, 0);
olptr = lptr - 1;
def->args = AllocateMemory(count *sizeof(short*));
memcpy(def->args, args, count *sizeof(short*));
def->argcount = count + 1;
}
while (iswhitespacechar(*olptr))
olptr++;
p = pstrlen(olptr);
if (olptr[p - 1] == 0x0a)
olptr[p - 1] = 0;
def->string = plitlate(olptr);
sp->value.s = (char*)def;
insert(sp, &defsyms);
return incldepth == 0;
}
/*
* Undefine
*/
int doundef(void)
{
getsym();
if (!ifskip)
undef2();
return (incldepth == 0);
}
//-------------------------------------------------------------------------
int undef2(void)
{
if (lastst != ident)
generror(ERR_IDEXPECT, 0, 0);
else
{
SYM **p = (SYM **)LookupHash(unmangid, defhash, HASHTABLESIZE);
if (p)
{
*p = (*p)->next;
}
}
}
//-------------------------------------------------------------------------
void getdefsym(void)
{
if (backupchar != - 1)
{
lastst = backupchar;
backupchar = - 1;
return ;
}
restart: /* we come back here after comments */
while (iswhitespacechar(lastch))
getch();
if (lastch == - 1)
lastst = eof;
else if (isdigit(lastch))
getnum();
else if (isstartchar(lastch))
{
lptr--;
defid(unmangid, &lptr, 0);
lastch = *lptr++;
lastst = ident;
}
else if (getsym2())
goto restart;
}
//-------------------------------------------------------------------------
int defid(short *name, short **p, char *q)
/*
* Get an identifier during macro replacement
*/
{
int count = 0, i = 0;
while (issymchar(**p))
{
if (count < 100)
{
name[count++] = *(*p);
if (q)
i += installphichar(*(*p), q, i);
}
(*p)++;
}
if (q)
{
if ((q[i - 1] &0xf0) == 0x90)
q[i - 1] = 0x90;
q[i] = '\0';
}
name[count] = 0;
return (count);
}
/*
* Insert a replacement string
*/
int definsert(short *end, short *begin, short *text, int len, int replen)
{
short *q;
int i, p, r;
int val;
if (begin != inputline)
if (*(begin - 1) == '#')
{
if (*(begin - 2) != '#')
{
begin--;
replen++;
r = pstrlen(text);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -