📄 preproc.c
字号:
len++;
if (len) {
oldchar = p[len];
p[len] = 0;
while (j - i > 1) {
k = (j + i) / 2;
m = nasm_stricmp(p, tasm_directives[k]);
if (m == 0) {
/* We have found a directive, so jam a % in front of it
* so that NASM will then recognise it as one if it's own.
*/
p[len] = oldchar;
len = strlen(p);
oldline = line;
line = nasm_malloc(len + 2);
line[0] = '%';
if (k == TM_IFDIFI) {
/* NASM does not recognise IFDIFI, so we convert it to
* %ifdef BOGUS. This is not used in NASM comaptible
* code, but does need to parse for the TASM macro
* package.
*/
strcpy(line + 1, "ifdef BOGUS");
} else {
memcpy(line + 1, p, len + 1);
}
nasm_free(oldline);
return line;
} else if (m < 0) {
j = k;
} else
i = k;
}
p[len] = oldchar;
}
return line;
}
/*
* The pre-preprocessing stage... This function translates line
* number indications as they emerge from GNU cpp (`# lineno "file"
* flags') into NASM preprocessor line number indications (`%line
* lineno file').
*/
static char *prepreproc(char *line)
{
int lineno, fnlen;
char *fname, *oldline;
if (line[0] == '#' && line[1] == ' ') {
oldline = line;
fname = oldline + 2;
lineno = atoi(fname);
fname += strspn(fname, "0123456789 ");
if (*fname == '"')
fname++;
fnlen = strcspn(fname, "\"");
line = nasm_malloc(20 + fnlen);
snprintf(line, 20 + fnlen, "%%line %d %.*s", lineno, fnlen, fname);
nasm_free(oldline);
}
if (tasm_compatible_mode)
return check_tasm_directive(line);
return line;
}
/*
* Free a linked list of tokens.
*/
static void free_tlist(Token * list)
{
while (list) {
list = delete_Token(list);
}
}
/*
* Free a linked list of lines.
*/
static void free_llist(Line * list)
{
Line *l;
while (list) {
l = list;
list = list->next;
free_tlist(l->first);
nasm_free(l);
}
}
/*
* Free an MMacro
*/
static void free_mmacro(MMacro * m)
{
nasm_free(m->name);
free_tlist(m->dlist);
nasm_free(m->defaults);
free_llist(m->expansion);
nasm_free(m);
}
/*
* Free all currently defined macros, and free the hash tables
*/
static void free_smacro_table(struct hash_table *smt)
{
SMacro *s;
const char *key;
struct hash_tbl_node *it = NULL;
while ((s = hash_iterate(smt, &it, &key)) != NULL) {
nasm_free((void *)key);
while (s) {
SMacro *ns = s->next;
nasm_free(s->name);
free_tlist(s->expansion);
nasm_free(s);
s = ns;
}
}
hash_free(smt);
}
static void free_mmacro_table(struct hash_table *mmt)
{
MMacro *m;
const char *key;
struct hash_tbl_node *it = NULL;
it = NULL;
while ((m = hash_iterate(mmt, &it, &key)) != NULL) {
nasm_free((void *)key);
while (m) {
MMacro *nm = m->next;
free_mmacro(m);
m = nm;
}
}
hash_free(mmt);
}
static void free_macros(void)
{
free_smacro_table(&smacros);
free_mmacro_table(&mmacros);
}
/*
* Initialize the hash tables
*/
static void init_macros(void)
{
hash_init(&smacros, HASH_LARGE);
hash_init(&mmacros, HASH_LARGE);
}
/*
* Pop the context stack.
*/
static void ctx_pop(void)
{
Context *c = cstk;
cstk = cstk->next;
free_smacro_table(&c->localmac);
nasm_free(c->name);
nasm_free(c);
}
/*
* Search for a key in the hash index; adding it if necessary
* (in which case we initialize the data pointer to NULL.)
*/
static void **
hash_findi_add(struct hash_table *hash, const char *str)
{
struct hash_insert hi;
void **r;
char *strx;
r = hash_findi(hash, str, &hi);
if (r)
return r;
strx = nasm_strdup(str); /* Use a more efficient allocator here? */
return hash_add(&hi, strx, NULL);
}
/*
* Like hash_findi, but returns the data element rather than a pointer
* to it. Used only when not adding a new element, hence no third
* argument.
*/
static void *
hash_findix(struct hash_table *hash, const char *str)
{
void **p;
p = hash_findi(hash, str, NULL);
return p ? *p : NULL;
}
#define BUF_DELTA 512
/*
* Read a line from the top file in istk, handling multiple CR/LFs
* at the end of the line read, and handling spurious ^Zs. Will
* return lines from the standard macro set if this has not already
* been done.
*/
static char *read_line(void)
{
char *buffer, *p, *q;
int bufsize, continued_count;
if (stdmacpos) {
unsigned char c;
const unsigned char *p = stdmacpos;
char *ret, *q;
size_t len = 0;
while ((c = *p++)) {
if (c >= 0x80)
len += pp_directives_len[c-0x80]+1;
else
len++;
}
ret = nasm_malloc(len+1);
q = ret;
while ((c = *stdmacpos++)) {
if (c >= 0x80) {
memcpy(q, pp_directives[c-0x80], pp_directives_len[c-0x80]);
q += pp_directives_len[c-0x80];
*q++ = ' ';
} else {
*q++ = c;
}
}
stdmacpos = p;
*q = '\0';
if (!*stdmacpos) {
/* This was the last of the standard macro chain... */
stdmacpos = NULL;
if (any_extrastdmac) {
stdmacpos = extrastdmac;
any_extrastdmac = false;
} else if (do_predef) {
Line *pd, *l;
Token *head, **tail, *t;
/*
* Nasty hack: here we push the contents of
* `predef' on to the top-level expansion stack,
* since this is the most convenient way to
* implement the pre-include and pre-define
* features.
*/
for (pd = predef; pd; pd = pd->next) {
head = NULL;
tail = &head;
for (t = pd->first; t; t = t->next) {
*tail = new_Token(NULL, t->type, t->text, 0);
tail = &(*tail)->next;
}
l = nasm_malloc(sizeof(Line));
l->next = istk->expansion;
l->first = head;
l->finishes = NULL;
istk->expansion = l;
}
do_predef = false;
}
}
return ret;
}
bufsize = BUF_DELTA;
buffer = nasm_malloc(BUF_DELTA);
p = buffer;
continued_count = 0;
while (1) {
q = fgets(p, bufsize - (p - buffer), istk->fp);
if (!q)
break;
p += strlen(p);
if (p > buffer && p[-1] == '\n') {
/* Convert backslash-CRLF line continuation sequences into
nothing at all (for DOS and Windows) */
if (((p - 2) > buffer) && (p[-3] == '\\') && (p[-2] == '\r')) {
p -= 3;
*p = 0;
continued_count++;
}
/* Also convert backslash-LF line continuation sequences into
nothing at all (for Unix) */
else if (((p - 1) > buffer) && (p[-2] == '\\')) {
p -= 2;
*p = 0;
continued_count++;
} else {
break;
}
}
if (p - buffer > bufsize - 10) {
int32_t offset = p - buffer;
bufsize += BUF_DELTA;
buffer = nasm_realloc(buffer, bufsize);
p = buffer + offset; /* prevent stale-pointer problems */
}
}
if (!q && p == buffer) {
nasm_free(buffer);
return NULL;
}
src_set_linnum(src_get_linnum() + istk->lineinc +
(continued_count * istk->lineinc));
/*
* Play safe: remove CRs as well as LFs, if any of either are
* present at the end of the line.
*/
while (--p >= buffer && (*p == '\n' || *p == '\r'))
*p = '\0';
/*
* Handle spurious ^Z, which may be inserted into source files
* by some file transfer utilities.
*/
buffer[strcspn(buffer, "\032")] = '\0';
list->line(LIST_READ, buffer);
return buffer;
}
/*
* Tokenize a line of text. This is a very simple process since we
* don't need to parse the value out of e.g. numeric tokens: we
* simply split one string into many.
*/
static Token *tokenize(char *line)
{
char *p = line;
enum pp_token_type type;
Token *list = NULL;
Token *t, **tail = &list;
while (*line) {
p = line;
if (*p == '%') {
p++;
if (nasm_isdigit(*p) ||
((*p == '-' || *p == '+') && nasm_isdigit(p[1])) ||
((*p == '+') && (nasm_isspace(p[1]) || !p[1]))) {
do {
p++;
}
while (nasm_isdigit(*p));
type = TOK_PREPROC_ID;
} else if (*p == '{') {
p++;
while (*p && *p != '}') {
p[-1] = *p;
p++;
}
p[-1] = '\0';
if (*p)
p++;
type = TOK_PREPROC_ID;
} else if (*p == '?') {
type = TOK_PREPROC_Q; /* %? */
p++;
if (*p == '?') {
type = TOK_PREPROC_QQ; /* %?? */
p++;
}
} else if (isidchar(*p) ||
((*p == '!' || *p == '%' || *p == '$') &&
isidchar(p[1]))) {
do {
p++;
}
while (isidchar(*p));
type = TOK_PREPROC_ID;
} else {
type = TOK_OTHER;
if (*p == '%')
p++;
}
} else if (isidstart(*p) || (*p == '$' && isidstart(p[1]))) {
type = TOK_ID;
p++;
while (*p && isidchar(*p))
p++;
} else if (*p == '\'' || *p == '"' || *p == '`') {
/*
* A string token.
*/
type = TOK_STRING;
p = nasm_skip_string(p);
if (*p) {
p++;
} else {
error(ERR_WARNING|ERR_PASS1, "unterminated string");
/* Handling unterminated strings by UNV */
/* type = -1; */
}
} else if (isnumstart(*p)) {
bool is_hex = false;
bool is_float = false;
bool has_e = false;
char c, *r;
/*
* A numeric token.
*/
if (*p == '$') {
p++;
is_hex = true;
}
for (;;) {
c = *p++;
if (!is_hex && (c == 'e' || c == 'E')) {
has_e = true;
if (*p == '+' || *p == '-') {
/* e can only be followed by +/- if it is either a
prefixed hex number or a floating-point number */
p++;
is_float = true;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -