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

📄 outobj.c

📁 nasm的全套源代码,有些我做了些修改,以方便您更方便更容易调试成功,方便学习做编译器
💻 C
📖 第 1 页 / 共 5 页
字号:
                }
                if (eb)
                    method |= 0x20, fidx = eb->exts[i]->index;
                else
                    error(ERR_PANIC,
                          "unrecognised WRT value in obj_write_fixup");
            }
        }
    }

    forp = obj_byte(forp, method);
    if (fidx != -1)
        forp = obj_index(forp, fidx);
    forp = obj_index(forp, tidx);
    obj_commit(forp);
}

static long obj_segment(char *name, int pass, int *bits)
{
    /*
     * We call the label manager here to define a name for the new
     * segment, and when our _own_ label-definition stub gets
     * called in return, it should register the new segment name
     * using the pointer it gets passed. That way we save memory,
     * by sponging off the label manager.
     */
#if defined(DEBUG) && DEBUG>=3
    fprintf(stderr, " obj_segment: < %s >, pass=%d, *bits=%d\n",
            name, pass, *bits);
#endif
    if (!name) {
        *bits = 16;
        current_seg = NULL;
        return first_seg;
    } else {
        struct Segment *seg;
        struct Group *grp;
        struct External **extp;
        int obj_idx, i, attrs, rn_error;
        char *p;

        /*
         * Look for segment attributes.
         */
        attrs = 0;
        while (*name == '.')
            name++;             /* hack, but a documented one */
        p = name;
        while (*p && !isspace(*p))
            p++;
        if (*p) {
            *p++ = '\0';
            while (*p && isspace(*p))
                *p++ = '\0';
        }
        while (*p) {
            while (*p && !isspace(*p))
                p++;
            if (*p) {
                *p++ = '\0';
                while (*p && isspace(*p))
                    *p++ = '\0';
            }

            attrs++;
        }

        obj_idx = 1;
        for (seg = seghead; seg; seg = seg->next) {
            obj_idx++;
            if (!strcmp(seg->name, name)) {
                if (attrs > 0 && pass == 1)
                    error(ERR_WARNING, "segment attributes specified on"
                          " redeclaration of segment: ignoring");
                if (seg->use32)
                    *bits = 32;
                else
                    *bits = 16;
                current_seg = seg;
                return seg->index;
            }
        }

        *segtail = seg = nasm_malloc(sizeof(*seg));
        seg->next = NULL;
        segtail = &seg->next;
        seg->index = (any_segs ? seg_alloc() : first_seg);
        seg->obj_index = obj_idx;
        seg->grp = NULL;
        any_segs = TRUE;
        seg->name = NULL;
        seg->currentpos = 0;
        seg->align = 1;         /* default */
        seg->use32 = FALSE;     /* default */
        seg->combine = CMB_PUBLIC;      /* default */
        seg->segclass = seg->overlay = NULL;
        seg->pubhead = NULL;
        seg->pubtail = &seg->pubhead;
        seg->lochead = NULL;
        seg->loctail = &seg->lochead;
        seg->orp = obj_new();
        seg->orp->up = &(seg->orp);
        seg->orp->ori = ori_ledata;
        seg->orp->type = LEDATA;
        seg->orp->parm[1] = obj_idx;

        /*
         * Process the segment attributes.
         */
        p = name;
        while (attrs--) {
            p += strlen(p);
            while (!*p)
                p++;

            /*
             * `p' contains a segment attribute.
             */
            if (!nasm_stricmp(p, "private"))
                seg->combine = CMB_PRIVATE;
            else if (!nasm_stricmp(p, "public"))
                seg->combine = CMB_PUBLIC;
            else if (!nasm_stricmp(p, "common"))
                seg->combine = CMB_COMMON;
            else if (!nasm_stricmp(p, "stack"))
                seg->combine = CMB_STACK;
            else if (!nasm_stricmp(p, "use16"))
                seg->use32 = FALSE;
            else if (!nasm_stricmp(p, "use32"))
                seg->use32 = TRUE;
            else if (!nasm_stricmp(p, "flat")) {
                /*
                 * This segment is an OS/2 FLAT segment. That means
                 * that its default group is group FLAT, even if
                 * the group FLAT does not explicitly _contain_ the
                 * segment.
                 * 
                 * When we see this, we must create the group
                 * `FLAT', containing no segments, if it does not
                 * already exist; then we must set the default
                 * group of this segment to be the FLAT group.
                 */
                struct Group *grp;
                for (grp = grphead; grp; grp = grp->next)
                    if (!strcmp(grp->name, "FLAT"))
                        break;
                if (!grp) {
                    obj_directive("group", "FLAT", 1);
                    for (grp = grphead; grp; grp = grp->next)
                        if (!strcmp(grp->name, "FLAT"))
                            break;
                    if (!grp)
                        error(ERR_PANIC, "failure to define FLAT?!");
                }
                seg->grp = grp;
            } else if (!nasm_strnicmp(p, "class=", 6))
                seg->segclass = nasm_strdup(p + 6);
            else if (!nasm_strnicmp(p, "overlay=", 8))
                seg->overlay = nasm_strdup(p + 8);
            else if (!nasm_strnicmp(p, "align=", 6)) {
                seg->align = readnum(p + 6, &rn_error);
                if (rn_error) {
                    seg->align = 1;
                    error(ERR_NONFATAL, "segment alignment should be"
                          " numeric");
                }
                switch ((int)seg->align) {
                case 1:        /* BYTE */
                case 2:        /* WORD */
                case 4:        /* DWORD */
                case 16:       /* PARA */
                case 256:      /* PAGE */
                case 4096:     /* PharLap extension */
                    break;
                case 8:
                    error(ERR_WARNING,
                          "OBJ format does not support alignment"
                          " of 8: rounding up to 16");
                    seg->align = 16;
                    break;
                case 32:
                case 64:
                case 128:
                    error(ERR_WARNING,
                          "OBJ format does not support alignment"
                          " of %d: rounding up to 256", seg->align);
                    seg->align = 256;
                    break;
                case 512:
                case 1024:
                case 2048:
                    error(ERR_WARNING,
                          "OBJ format does not support alignment"
                          " of %d: rounding up to 4096", seg->align);
                    seg->align = 4096;
                    break;
                default:
                    error(ERR_NONFATAL, "invalid alignment value %d",
                          seg->align);
                    seg->align = 1;
                    break;
                }
            } else if (!nasm_strnicmp(p, "absolute=", 9)) {
                seg->align = SEG_ABS + readnum(p + 9, &rn_error);
                if (rn_error)
                    error(ERR_NONFATAL, "argument to `absolute' segment"
                          " attribute should be numeric");
            }
        }

        /* We need to know whenever we have at least one 32-bit segment */
        obj_use32 |= seg->use32;

        obj_seg_needs_update = seg;
        if (seg->align >= SEG_ABS)
            deflabel(name, NO_SEG, seg->align - SEG_ABS,
                     NULL, FALSE, FALSE, &of_obj, error);
        else
            deflabel(name, seg->index + 1, 0L,
                     NULL, FALSE, FALSE, &of_obj, error);
        obj_seg_needs_update = NULL;

        /*
         * See if this segment is defined in any groups.
         */
        for (grp = grphead; grp; grp = grp->next) {
            for (i = grp->nindices; i < grp->nentries; i++) {
                if (!strcmp(grp->segs[i].name, seg->name)) {
                    nasm_free(grp->segs[i].name);
                    grp->segs[i] = grp->segs[grp->nindices];
                    grp->segs[grp->nindices++].index = seg->obj_index;
                    if (seg->grp)
                        error(ERR_WARNING,
                              "segment `%s' is already part of"
                              " a group: first one takes precedence",
                              seg->name);
                    else
                        seg->grp = grp;
                }
            }
        }

        /*
         * Walk through the list of externals with unresolved
         * default-WRT clauses, and resolve any that point at this
         * segment.
         */
        extp = &dws;
        while (*extp) {
            if ((*extp)->defwrt_type == DEFWRT_STRING &&
                !strcmp((*extp)->defwrt_ptr.string, seg->name)) {
                nasm_free((*extp)->defwrt_ptr.string);
                (*extp)->defwrt_type = DEFWRT_SEGMENT;
                (*extp)->defwrt_ptr.seg = seg;
                *extp = (*extp)->next_dws;
            } else
                extp = &(*extp)->next_dws;
        }

        if (seg->use32)
            *bits = 32;
        else
            *bits = 16;
        current_seg = seg;
        return seg->index;
    }
}

static int obj_directive(char *directive, char *value, int pass)
{
    if (!strcmp(directive, "group")) {
        char *p, *q, *v;
        if (pass == 1) {
            struct Group *grp;
            struct Segment *seg;
            struct External **extp;
            int obj_idx;

            q = value;
            while (*q == '.')
                q++;            /* hack, but a documented one */
            v = q;
            while (*q && !isspace(*q))
                q++;
            if (isspace(*q)) {
                *q++ = '\0';
                while (*q && isspace(*q))
                    q++;
            }
            /*
             * Here we used to sanity-check the group directive to
             * ensure nobody tried to declare a group containing no
             * segments. However, OS/2 does this as standard
             * practice, so the sanity check has been removed.
             *
             * if (!*q) {
             *     error(ERR_NONFATAL,"GROUP directive contains no segments");
             *     return 1;
             * }
             */

            obj_idx = 1;
            for (grp = grphead; grp; grp = grp->next) {
                obj_idx++;
                if (!strcmp(grp->name, v)) {
                    error(ERR_NONFATAL, "group `%s' defined twice", v);
                    return 1;
                }
            }

            *grptail = grp = nasm_malloc(sizeof(*grp));
            grp->next = NULL;
            grptail = &grp->next;
            grp->index = seg_alloc();
            grp->obj_index = obj_idx;
            grp->nindices = grp->nentries = 0;
            grp->name = NULL;

            obj_grp_needs_update = grp;
            deflabel(v, grp->index + 1, 0L,
                     NULL, FALSE, FALSE, &of_obj, error);
            obj_grp_needs_update = NULL;

            while (*q) {
                p = q;
                while (*q && !isspace(*q))
                    q++;
                if (isspace(*q)) {
                    *q++ = '\0';
                    while (*q && isspace(*q))
                        q++;
                }
                /*
                 * Now p contains a segment name. Find it.
                 */
                for (seg = seghead; seg; seg = seg->next)
                    if (!strcmp(seg->name, p))
                        break;
                if (seg) {
                    /*
                     * We have a segment index. Shift a name entry
                     * to the end of the array to make room.
                     */
                    grp->segs[grp->nentries++] = grp->segs[grp->nindices];
                    grp->segs[grp->nindices++].index = seg->obj_index;
                    if (seg->grp)
                        error(ERR_WARNING,
                              "segment `%s' is already part of"
                              " a group: first one takes precedence",
                              seg->name);
                    else
                        seg->grp = grp;
                } else {
                    /*
                     * We have an as-yet undefined segment.
                     * Remember its name, for later.
                     */
                    grp->segs[grp->nentries++].name = nasm_strdup(p);
                }
            }

            /*
             * Walk through the list of externals with unresolved
             * default-WRT clauses, and resolve any that point at
             * this group.
             */
            extp = &dws;
            while (*extp) {
                if ((*extp)->defwrt_type == DEFWRT_STRING &&
                    !strcmp((*extp)->defwrt_ptr.string, grp->name)) {
                    nasm_free((*extp)->defwrt_ptr.string);
                    (*extp)->defwrt_type = DEFWRT_GROUP;
                    (*extp)->defwrt_ptr.grp = grp;
                    *extp = (*extp)->next_dws;
                } else
                    extp = &(*extp)->next_dws;
            }
        }
        return 1;
    }
    if (!strcmp(directive, "uppercase")) {
        obj_uppercase = TRUE;
        return 1;
    }
    if (!strcmp(directive, "import")) {
        char *q, *extname, *libname, *impname;

        if (pass == 2)
            return 1;           /* ignore in pass two */
        extname = q = value;
        while (*q && !isspace(*q))
            q++;
        if (isspace(*q)) {
            *q++ = '\0';
            while (*q && isspace(*q))
                q++;
        }

        libname = q;
        while (*q && !isspace(*q))
            q++;
        if (isspace(*q)) {
            *q++ = '\0';
            while (*q && isspace(*q))
                q++;
        }

        impname = q;

        if (!*extname || !*libname)
            error(ERR_NONFATAL, "`import' directive requires symbol name"
                  " and library name");
        else {

⌨️ 快捷键说明

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