⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 preproc.c

📁 汇编编译器的最新版本的源码.买了自己动手写操作系统这本书的人一定要下
💻 C
📖 第 1 页 / 共 5 页
字号:
        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 + -