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

📄 labels.c

📁 nasm的全套源代码,有些我做了些修改,以方便您更方便更容易调试成功,方便学习做编译器
💻 C
📖 第 1 页 / 共 2 页
字号:

void define_label(char *label, long segment, long offset, char *special,
                  int is_norm, int isextrn, struct ofmt *ofmt, efunc error)
{
    union label *lptr;
    int exi;

#ifdef DEBUG
#if DEBUG<3
    if (!strncmp(label, "debugdump", 9))
#endif
        error(ERR_DEBUG, "define_label (%s, %ld, %08lx, %s, %d, %d)",
              label, segment, offset, special, is_norm, isextrn);
#endif
    lptr = find_label(label, 1);
    if (lptr->defn.is_global & DEFINED_BIT) {
        error(ERR_NONFATAL, "symbol `%s' redefined", label);
        return;
    }
    lptr->defn.is_global |= DEFINED_BIT;
    if (isextrn)
        lptr->defn.is_global |= EXTERN_BIT;

    if (!islocalchar(label[0]) && is_norm)      /* not local, but not special either */
        prevlabel = lptr->defn.label;
    else if (islocal(label) && !*prevlabel) {
        error(ERR_NONFATAL, "attempt to define a local label before any"
              " non-local labels");
    }

    lptr->defn.segment = segment;
    lptr->defn.offset = offset;
    lptr->defn.is_norm = (!islocalchar(label[0]) && is_norm);

    if (pass0 == 1 || (!is_norm && !isextrn && (segment & 1))) {
        exi = !!(lptr->defn.is_global & GLOBAL_BIT);
        if (exi) {
            char *xsymbol;
            int slen;
            slen = strlen(lprefix);
            slen += strlen(lptr->defn.label);
            slen += strlen(lpostfix);
            slen++;             /* room for that null char */
            xsymbol = nasm_malloc(slen);
            snprintf(xsymbol, slen, "%s%s%s", lprefix, lptr->defn.label,
                     lpostfix);

            ofmt->symdef(xsymbol, segment, offset, exi,
                         special ? special : lptr->defn.special);
            ofmt->current_dfmt->debug_deflabel(xsymbol, segment, offset,
                                               exi,
                                               special ? special : lptr->
                                               defn.special);
/**	nasm_free(xsymbol);  ! outobj.c stores the pointer; ouch!!! **/
        } else {
            if ((lptr->defn.is_global & (GLOBAL_BIT | EXTERN_BIT)) !=
                EXTERN_BIT) {
                ofmt->symdef(lptr->defn.label, segment, offset, exi,
                             special ? special : lptr->defn.special);
                ofmt->current_dfmt->debug_deflabel(label, segment, offset,
                                                   exi,
                                                   special ? special :
                                                   lptr->defn.special);
            }
        }
    }                           /* if (pass0 == 1) */
}

void define_common(char *label, long segment, long size, char *special,
                   struct ofmt *ofmt, efunc error)
{
    union label *lptr;

    lptr = find_label(label, 1);
    if (lptr->defn.is_global & DEFINED_BIT) {
        error(ERR_NONFATAL, "symbol `%s' redefined", label);
        return;
    }
    lptr->defn.is_global |= DEFINED_BIT;

    if (!islocalchar(label[0])) /* not local, but not special either */
        prevlabel = lptr->defn.label;
    else
        error(ERR_NONFATAL, "attempt to define a local label as a "
              "common variable");

    lptr->defn.segment = segment;
    lptr->defn.offset = 0;

    ofmt->symdef(lptr->defn.label, segment, size, 2,
                 special ? special : lptr->defn.special);
    ofmt->current_dfmt->debug_deflabel(lptr->defn.label, segment, size, 2,
                                       special ? special : lptr->defn.
                                       special);
}

void declare_as_global(char *label, char *special, efunc error)
{
    union label *lptr;

    if (islocal(label)) {
        error(ERR_NONFATAL, "attempt to declare local symbol `%s' as"
              " global", label);
        return;
    }
    lptr = find_label(label, 1);
    switch (lptr->defn.is_global & TYPE_MASK) {
    case NOT_DEFINED_YET:
        lptr->defn.is_global = GLOBAL_PLACEHOLDER;
        lptr->defn.special = special ? perm_copy(special, "") : NULL;
        break;
    case GLOBAL_PLACEHOLDER:   /* already done: silently ignore */
    case GLOBAL_SYMBOL:
        break;
    case LOCAL_SYMBOL:
        if (!lptr->defn.is_global & EXTERN_BIT)
            error(ERR_NONFATAL, "symbol `%s': GLOBAL directive must"
                  " appear before symbol definition", label);
        break;
    }
}

int init_labels(void)
{
    int i;

    for (i = 0; i < LABEL_HASHES; i++) {
        ltab[i] = (union label *)nasm_malloc(LBLK_SIZE);
        if (!ltab[i])
            return -1;          /* can't initialise, panic */
        init_block(ltab[i]);
        lfree[i] = ltab[i];
    }

    perm_head =
        perm_tail = (struct permts *)nasm_malloc(sizeof(struct permts));

    if (!perm_head)
        return -1;

    perm_head->next = NULL;
    perm_head->size = PERMTS_SIZE;
    perm_head->usage = 0;

    prevlabel = "";

    initialised = TRUE;

    return 0;
}

void cleanup_labels(void)
{
    int i;

    initialised = FALSE;

    for (i = 0; i < LABEL_HASHES; i++) {
        union label *lptr, *lhold;

        lptr = lhold = ltab[i];

        while (lptr) {
            while (lptr->admin.movingon != END_BLOCK)
                lptr++;
            lptr = lptr->admin.next;
            nasm_free(lhold);
            lhold = lptr;
        }
    }

    while (perm_head) {
        perm_tail = perm_head;
        perm_head = perm_head->next;
        nasm_free(perm_tail);
    }
}

static void init_block(union label *blk)
{
    int j;

    for (j = 0; j < LABEL_BLOCK - 1; j++)
        blk[j].admin.movingon = END_LIST;
    blk[LABEL_BLOCK - 1].admin.movingon = END_BLOCK;
    blk[LABEL_BLOCK - 1].admin.next = NULL;
}

static char *perm_copy(char *string1, char *string2)
{
    char *p, *q;
    int len = strlen(string1) + strlen(string2) + 1;

    if (perm_tail->size - perm_tail->usage < len) {
        perm_tail->next =
            (struct permts *)nasm_malloc(sizeof(struct permts));
        perm_tail = perm_tail->next;
        perm_tail->next = NULL;
        perm_tail->size = PERMTS_SIZE;
        perm_tail->usage = 0;
    }
    p = q = perm_tail->data + perm_tail->usage;
    while ((*q = *string1++))
        q++;
    while ((*q++ = *string2++)) ;
    perm_tail->usage = q - perm_tail->data;

    return p;
}

/*
 * Notes regarding bug involving redefinition of external segments.
 *
 * Up to and including v0.97, the following code didn't work. From 0.97
 * developers release 2 onwards, it will generate an error.
 *
 * EXTERN extlabel
 * newlabel EQU extlabel + 1
 *
 * The results of allowing this code through are that two import records
 * are generated, one for 'extlabel' and one for 'newlabel'.
 *
 * The reason for this is an inadequacy in the defined interface between
 * the label manager and the output formats. The problem lies in how the
 * output format driver tells that a label is an external label for which
 * a label import record must be produced. Most (all except bin?) produce
 * the record if the segment number of the label is not one of the internal
 * segments that the output driver is producing.
 *
 * A simple fix to this would be to make the output formats keep track of
 * which symbols they've produced import records for, and make them not
 * produce import records for segments that are already defined.
 *
 * The best way, which is slightly harder but reduces duplication of code
 * and should therefore make the entire system smaller and more stable is
 * to change the interface between assembler, define_label(), and
 * the output module. The changes that are needed are:
 *
 * The semantics of the 'isextern' flag passed to define_label() need
 * examining. This information may or may not tell us what we need to
 * know (ie should we be generating an import record at this point for this
 * label). If these aren't the semantics, the semantics should be changed
 * to this.
 *
 * The output module interface needs changing, so that the `isextern' flag
 * is passed to the module, so that it can be easily tested for.
 */

⌨️ 快捷键说明

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