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

📄 preproc.c

📁 nasm的全套源代码,有些我做了些修改,以方便您更方便更容易调试成功,方便学习做编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
             * Anything else is an operator of some kind. We check
             * for all the double-character operators (>>, <<, //,
             * %%, <=, >=, ==, !=, <>, &&, ||, ^^), but anything
             * else is a single-character operator.
             */
            type = TOK_OTHER;
            if ((p[0] == '>' && p[1] == '>') ||
                (p[0] == '<' && p[1] == '<') ||
                (p[0] == '/' && p[1] == '/') ||
                (p[0] == '<' && p[1] == '=') ||
                (p[0] == '>' && p[1] == '=') ||
                (p[0] == '=' && p[1] == '=') ||
                (p[0] == '!' && p[1] == '=') ||
                (p[0] == '<' && p[1] == '>') ||
                (p[0] == '&' && p[1] == '&') ||
                (p[0] == '|' && p[1] == '|') ||
                (p[0] == '^' && p[1] == '^')) {
                p++;
            }
            p++;
        }

        /* Handling unterminated string by UNV */
        /*if (type == -1)
           {
           *tail = t = new_Token(NULL, TOK_STRING, line, p-line+1);
           t->text[p-line] = *line;
           tail = &t->next;
           }
           else */
        if (type != TOK_COMMENT) {
            *tail = t = new_Token(NULL, type, line, p - line);
            tail = &t->next;
        }
        line = p;
    }
    return list;
}

/*
 * this function allocates a new managed block of memory and
 * returns a pointer to the block.  The managed blocks are 
 * deleted only all at once by the delete_Blocks function.
 */
static void *new_Block(size_t size)
{
    Blocks *b = &blocks;

    /* first, get to the end of the linked list */
    while (b->next)
        b = b->next;
    /* now allocate the requested chunk */
    b->chunk = nasm_malloc(size);

    /* now allocate a new block for the next request */
    b->next = nasm_malloc(sizeof(Blocks));
    /* and initialize the contents of the new block */
    b->next->next = NULL;
    b->next->chunk = NULL;
    return b->chunk;
}

/*
 * this function deletes all managed blocks of memory
 */
static void delete_Blocks(void)
{
    Blocks *a, *b = &blocks;

    /* 
     * keep in mind that the first block, pointed to by blocks
     * is a static and not dynamically allocated, so we don't 
     * free it.
     */
    while (b) {
        if (b->chunk)
            nasm_free(b->chunk);
        a = b;
        b = b->next;
        if (a != &blocks)
            nasm_free(a);
    }
}

/*
 *  this function creates a new Token and passes a pointer to it 
 *  back to the caller.  It sets the type and text elements, and
 *  also the mac and next elements to NULL.
 */
static Token *new_Token(Token * next, int type, char *text, int txtlen)
{
    Token *t;
    int i;

    if (freeTokens == NULL) {
        freeTokens = (Token *) new_Block(TOKEN_BLOCKSIZE * sizeof(Token));
        for (i = 0; i < TOKEN_BLOCKSIZE - 1; i++)
            freeTokens[i].next = &freeTokens[i + 1];
        freeTokens[i].next = NULL;
    }
    t = freeTokens;
    freeTokens = t->next;
    t->next = next;
    t->mac = NULL;
    t->type = type;
    if (type == TOK_WHITESPACE || text == NULL) {
        t->text = NULL;
    } else {
        if (txtlen == 0)
            txtlen = strlen(text);
        t->text = nasm_malloc(1 + txtlen);
        strncpy(t->text, text, txtlen);
        t->text[txtlen] = '\0';
    }
    return t;
}

static Token *delete_Token(Token * t)
{
    Token *next = t->next;
    nasm_free(t->text);
    t->next = freeTokens;
    freeTokens = t;
    return next;
}

/*
 * Convert a line of tokens back into text.
 * If expand_locals is not zero, identifiers of the form "%$*xxx"
 * will be transformed into ..@ctxnum.xxx
 */
static char *detoken(Token * tlist, int expand_locals)
{
    Token *t;
    int len;
    char *line, *p;

    len = 0;
    for (t = tlist; t; t = t->next) {
        if (t->type == TOK_PREPROC_ID && t->text[1] == '!') {
            char *p = getenv(t->text + 2);
            nasm_free(t->text);
            if (p)
                t->text = nasm_strdup(p);
            else
                t->text = NULL;
        }
        /* Expand local macros here and not during preprocessing */
        if (expand_locals &&
            t->type == TOK_PREPROC_ID && t->text &&
            t->text[0] == '%' && t->text[1] == '$') {
            Context *ctx = get_ctx(t->text, FALSE);
            if (ctx) {
                char buffer[40];
                char *p, *q = t->text + 2;

                q += strspn(q, "$");
                snprintf(buffer, sizeof(buffer), "..@%lu.", ctx->number);
                p = nasm_strcat(buffer, q);
                nasm_free(t->text);
                t->text = p;
            }
        }
        if (t->type == TOK_WHITESPACE) {
            len++;
        } else if (t->text) {
            len += strlen(t->text);
        }
    }
    p = line = nasm_malloc(len + 1);
    for (t = tlist; t; t = t->next) {
        if (t->type == TOK_WHITESPACE) {
            *p = ' ';
            p++;
            *p = '\0';
        } else if (t->text) {
            strcpy(p, t->text);
            p += strlen(p);
        }
    }
    *p = '\0';
    return line;
}

/*
 * A scanner, suitable for use by the expression evaluator, which
 * operates on a line of Tokens. Expects a pointer to a pointer to
 * the first token in the line to be passed in as its private_data
 * field.
 */
static int ppscan(void *private_data, struct tokenval *tokval)
{
    Token **tlineptr = private_data;
    Token *tline;

    do {
        tline = *tlineptr;
        *tlineptr = tline ? tline->next : NULL;
    }
    while (tline && (tline->type == TOK_WHITESPACE ||
                     tline->type == TOK_COMMENT));

    if (!tline)
        return tokval->t_type = TOKEN_EOS;

    if (tline->text[0] == '$' && !tline->text[1])
        return tokval->t_type = TOKEN_HERE;
    if (tline->text[0] == '$' && tline->text[1] == '$' && !tline->text[2])
        return tokval->t_type = TOKEN_BASE;

    if (tline->type == TOK_ID) {
        tokval->t_charptr = tline->text;
        if (tline->text[0] == '$') {
            tokval->t_charptr++;
            return tokval->t_type = TOKEN_ID;
        }

        /*
         * This is the only special case we actually need to worry
         * about in this restricted context.
         */
        if (!nasm_stricmp(tline->text, "seg"))
            return tokval->t_type = TOKEN_SEG;

        return tokval->t_type = TOKEN_ID;
    }

    if (tline->type == TOK_NUMBER) {
        int rn_error;

        tokval->t_integer = readnum(tline->text, &rn_error);
        if (rn_error)
            return tokval->t_type = TOKEN_ERRNUM;
        tokval->t_charptr = NULL;
        return tokval->t_type = TOKEN_NUM;
    }

    if (tline->type == TOK_STRING) {
        int rn_warn;
        char q, *r;
        int l;

        r = tline->text;
        q = *r++;
        l = strlen(r);

        if (l == 0 || r[l - 1] != q)
            return tokval->t_type = TOKEN_ERRNUM;
        tokval->t_integer = readstrnum(r, l - 1, &rn_warn);
        if (rn_warn)
            error(ERR_WARNING | ERR_PASS1, "character constant too long");
        tokval->t_charptr = NULL;
        return tokval->t_type = TOKEN_NUM;
    }

    if (tline->type == TOK_OTHER) {
        if (!strcmp(tline->text, "<<"))
            return tokval->t_type = TOKEN_SHL;
        if (!strcmp(tline->text, ">>"))
            return tokval->t_type = TOKEN_SHR;
        if (!strcmp(tline->text, "//"))
            return tokval->t_type = TOKEN_SDIV;
        if (!strcmp(tline->text, "%%"))
            return tokval->t_type = TOKEN_SMOD;
        if (!strcmp(tline->text, "=="))
            return tokval->t_type = TOKEN_EQ;
        if (!strcmp(tline->text, "<>"))
            return tokval->t_type = TOKEN_NE;
        if (!strcmp(tline->text, "!="))
            return tokval->t_type = TOKEN_NE;
        if (!strcmp(tline->text, "<="))
            return tokval->t_type = TOKEN_LE;
        if (!strcmp(tline->text, ">="))
            return tokval->t_type = TOKEN_GE;
        if (!strcmp(tline->text, "&&"))
            return tokval->t_type = TOKEN_DBL_AND;
        if (!strcmp(tline->text, "^^"))
            return tokval->t_type = TOKEN_DBL_XOR;
        if (!strcmp(tline->text, "||"))
            return tokval->t_type = TOKEN_DBL_OR;
    }

    /*
     * We have no other options: just return the first character of
     * the token text.
     */
    return tokval->t_type = tline->text[0];
}

/*
 * Compare a string to the name of an existing macro; this is a
 * simple wrapper which calls either strcmp or nasm_stricmp
 * depending on the value of the `casesense' parameter.
 */
static int mstrcmp(char *p, char *q, int casesense)
{
    return casesense ? strcmp(p, q) : nasm_stricmp(p, q);
}

/*
 * Return the Context structure associated with a %$ token. Return
 * NULL, having _already_ reported an error condition, if the
 * context stack isn't deep enough for the supplied number of $
 * signs.
 * If all_contexts == TRUE, contexts that enclose current are
 * also scanned for such smacro, until it is found; if not -
 * only the context that directly results from the number of $'s
 * in variable's name.
 */
static Context *get_ctx(char *name, int all_contexts)
{
    Context *ctx;
    SMacro *m;
    int i;

    if (!name || name[0] != '%' || name[1] != '$')
        return NULL;

    if (!cstk) {
        error(ERR_NONFATAL, "`%s': context stack is empty", name);
        return NULL;
    }

    for (i = strspn(name + 2, "$"), ctx = cstk; (i > 0) && ctx; i--) {
        ctx = ctx->next;
/*        i--;  Lino - 02/25/02 */
    }
    if (!ctx) {
        error(ERR_NONFATAL, "`%s': context stack is only"
              " %d level%s deep", name, i - 1, (i == 2 ? "" : "s"));
        return NULL;
    }
    if (!all_contexts)
        return ctx;

    do {
        /* Search for this smacro in found context */
        m = ctx->localmac;
        while (m) {
            if (!mstrcmp(m->name, name, m->casesense))
                return ctx;
            m = m->next;
        }
        ctx = ctx->next;
    }
    while (ctx);
    return NULL;
}

/*
 * Open an include file. This routine must always return a valid
 * file pointer if it returns - it's responsible for throwing an
 * ERR_FATAL and bombing out completely if not. It should also try
 * the include path one by one until it finds the file or reaches
 * the end of the path.
 */
static FILE *inc_fopen(char *file)
{
    FILE *fp;
    char *prefix = "", *combine;
    IncPath *ip = ipath;
    static int namelen = 0;
    int len = strlen(file);

    while (1) {
        combine = nasm_malloc(strlen(prefix) + len + 1);
        strcpy(combine, prefix);
        strcat(combine, file);
        fp = fopen(combine, "r");
        if (pass == 0 && fp) {
            namelen += strlen(combine) + 1;
            if (namelen > 62) {
                printf(" \\\n  ");
                namelen = 2;
            }
            printf(" %s", combine);
        }
        nasm_free(combine);
        if (fp)
            return fp;
        if (!ip)
            break;
        prefix = ip->path;
        ip = ip->next;
    }

    error(ERR_FATAL, "unable to open include file `%s'", file);
    return NULL;                /* never reached - placate compilers */
}

/*
 * Determine if we should warn on defining a single-line macro of
 * name `name', with `nparam' parameters. If nparam is 0 or -1, will
 * return TRUE if _any_ single-line macro of that name is defined.
 * Otherwise, will return TRUE if a single-line macro with either
 * `nparam' or no parameters is defined.
 *
 * If a macro with precisely the right number of parameters is
 * defined, or nparam is -1, the address of the definition structure
 * will be returned in `defn'; otherwise NULL will be returned. If `defn'
 * is NULL, no action will be taken regarding its contents, and no
 * error will occur.
 *
 * Note that this is also called with nparam zero to resolve
 * `ifdef'.
 *

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -