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

📄 obj386.c

📁 CC386 is a general-purpose 32-bit C compiler. It is not an optimizing compiler but given that the co
💻 C
📖 第 1 页 / 共 2 页
字号:
/* 
Copyright 1994-2003 Free Software Foundation, Inc.

This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.  

This program is derived from the cc68k complier by 
Matthew Brandt (mattb@walkingdog.net) 

You may contact the author of this derivative at:

mailto::camille@bluegrass.net

or by snail mail at:

David Lindauer
850 Washburn Ave Apt 99
Louisville, KY 40222
 */
#include <stdio.h>
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
#include "lists.h"
#include "expr.h"
#include "c.h"
#include "gen386.h"
#include "diag.h"
#include "lists.h"

#define DEBUG_VERSION 3.1

enum omf_type
{
    THEADR = 0x80,  /* module header */
    COMENT = 0x88,  /* comment record */

    LINNUM = 0x95,  /* line number record */
    LNAMES = 0x96,  /* list of names */

    SEGDEF = 0x99,  /* segment definition */
    GRPDEF = 0x9A,  /* group definition */
    EXTDEF = 0x8C,  /* external definition */
    PUBDEF = 0x91,  /* public definition */
    COMDEF = 0xB0,  /* common definition */

    LEDATA = 0xA1,  /* logical enumerated data */
    LIDATA = 0xA3, FIXUPP = 0x9D,  /* fixups (relocations) */

    MODEND = 0x8A /* module end */
};

extern HASHREC **templateFuncs;
extern FILELIST *incfiles;
extern VIRTUAL_LIST *virtualFirst;
extern int prm_debug;
extern FILE *outputFile;
extern char version[];
extern char *infile;
extern EMIT_TAB segs[MAX_SEGS];
extern LIST *libincludes;
extern LINEBUF *linelist;
extern HASHREC **gsyms;
extern LIST *localfuncs,  *localdata;
extern int prm_bss;
extern int outcode_base_address;

static int segxlattab[MAX_SEGS];
static int dgroupVal;
static int extSize, extIndex;
static char extbuf[1024];

static char *segnames[] = 
{
    0, "_TEXT", "_DATA", "_BSS", "_CONST", "_STRING", "cstartup", "crundown", 
        "cppinit", "cppexit", "$$TYPES", "$$SYMBOLS", "$$BROWSE"
};
static char *segclasses[] = 
{
    0, "CODE", "DATA", "BSS", "CONST", "STRING", "INITDATA", "EXITDATA", 
        "CPPINIT", "CPPEXIT", "DEBTYP", "DEBSYM", "BROWSE"
};
static char DgroupText[] = "DGROUP";
int put_ident(char *buf, int ident)
{
    char *p = buf;
    if (ident &0xc0000000)
        *p++ = 0xc0;
    ident &= 0x7fff;
    *p++ = ident > 127 ? (ident >> 8) | 0x80: ident;
    if (ident > 127)
        *p++ = ident;
    return p - buf;
}

//-------------------------------------------------------------------------

void emit_record(enum omf_type type, char *data, int len)
{
    int i, cs = 0;
    char buf[1100];
    buf[0] = type;
    *(short*)(buf + 1) = len + 1;
    memcpy(buf + 3, data, len);
    for (i = 0; i < len + 3; i++)
        cs += buf[i];
    buf[len + 3] =  - cs;
    owrite(buf, len + 4, 1, outputFile);
} 

void omfFileName(void)
{
    char buf[256];
    strcpy(buf + 1, fullqualify(infile));
    buf[0] = strlen(buf + 1);
    emit_record(THEADR, buf, buf[0] + 1);
}

//-------------------------------------------------------------------------

void omfTranslatorName(void)
{
    char buf[100];
    *(short*)buf = 0;
    sprintf(buf + 3, "CC386 Version %s (LADSoft)", version);
    buf[2] = strlen(buf + 3);
    emit_record(COMENT, buf, 3+buf[2]);
}

//-------------------------------------------------------------------------

void omfFileTime(char *file)
{
    unsigned short time, date;
    char buf[256];
    int fd;
    *(short*)buf = 0xe900;
    if (file)
    {
        if (_dos_open(file, 0, &fd))
        {
            time = 0;
            date = 0;
        }
        else
        {
            _dos_getftime(fd, &date, &time);
            _dos_close(fd);
        }
        *(short*)(buf + 2) = time;
        *(short*)(buf + 4) = date;
        memcpy(buf + 7, file, strlen(file));
        buf[6] = strlen(file);
        emit_record(COMENT, buf, 7+buf[6]);
    }
    else
        emit_record(COMENT, buf, 2);
}

//-------------------------------------------------------------------------

void omfDebugMarker(void)
{
    if (prm_debug)
    {
        char buf[3];
        buf[0] = 0x40;
        buf[1] = 0xe9;
        emit_record(COMENT, buf, 2);
    }
}

//-------------------------------------------------------------------------

void omfLNames(void)
{
    char buf[1024],  *p = buf;
    int pos = 1, i;
    *p++ = 0;
    for (i = 1; i < MAX_SEGS; i++)
    {
        if (segs[i].curlast || i < 4)
        {
            segxlattab[i] = pos++;
            *p = strlen(segnames[i]);
            strcpy(p + 1, segnames[i]);
            p +=  *p + 1;
            *p = strlen(segclasses[i]);
            strcpy(p + 1, segclasses[i]);
            p +=  *p + 1;

        }
        else
            segxlattab[i] = 0;
    }
    dgroupVal = pos;
    *p = strlen(DgroupText);
    strcpy(p + 1, DgroupText);
    p +=  *p + 1;
    emit_record(LNAMES, buf, p - buf);
}

//-------------------------------------------------------------------------

void omfLibMod(void)
{
    if (libincludes)
    {
        while (libincludes)
        {
            char buf[256],  *p;
            p = strrchr(libincludes->data, '\\');
            if (p)
                p++;
            else
                p = libincludes->data;
            buf[0] = 0xa3;
            buf[1] = strlen(p);
            strcpy(buf + 2, p);
            emit_record(COMENT, buf, buf[1] + 2);
            libincludes = libincludes->link;
        }
    }
}

//-------------------------------------------------------------------------

void omfSegs(void)
{
    char buf[100];
    int i;
    for (i = 1; i < MAX_SEGS; i++)
    {
        if (segxlattab[i])
        {
            if (i == codeseg)
                buf[0] = 0x29;
            else
                buf[0] = 0xA9;
            *(int*)(buf + 1) = segs[i].curlast;
            buf[5] = segxlattab[i] *2;
            buf[6] = segxlattab[i] *2+1;
            buf[7] = 1;
            emit_record(SEGDEF, buf, 8);
        }
    }
}

//-------------------------------------------------------------------------

void omfComDefs(void)
{
    VIRTUAL_LIST *v = virtualFirst;
    char buf[512], name[512],  *p;
    while (v)
    {
        putsym(name, v->sp, v->sp->name);
        p = buf;
        *p = strlen(name) + 1;
        strcpy(p + 2, name);
        p[1] = '@';
        p += (*p) + 1;
        *p++ = 0;
        if (v->data)
            *p++ = segxlattab[dataseg];
        else
            *p++ = segxlattab[codeseg];
        if (v->seg->curlast > 128)
        {
            *p++ = 0x88;
            *((int*)p)++ = v->seg->curlast;
        }
        else
            *p++ = v->seg->curlast;
        emit_record(COMDEF, buf, p - buf);
        v = v->next;
    }
}

//-------------------------------------------------------------------------

void omfGroups(void)
{
    char buf[100],  *p = buf + 1;
    buf[0] = dgroupVal * 2;
    if (segxlattab[2])
    {
        *p++ = 0xff;
        *p++ = segxlattab[2];
    }
    if (segxlattab[3])
    {
        *p++ = 0xff;
        *p++ = segxlattab[3];
    }
    if (segxlattab[4])
    {
        *p++ = 0xff;
        *p++ = segxlattab[4];
    }
    if (segxlattab[5])
    {
        *p++ = 0xff;
        *p++ = segxlattab[5];
    }
    emit_record(GRPDEF, buf, p - buf);
}

//-------------------------------------------------------------------------

void FlushExtBuf(void)
{
    if (extSize)
    {
        emit_record(EXTDEF, extbuf, extSize);
        extSize = 0;
    }
}

//-------------------------------------------------------------------------

void omfputext(SYM *sp)
{
    char buf[512];
    putsym(buf, sp, sp->name);
    sp->mainsym->value.i = extIndex++;
    if (strlen(buf) + extSize > 1024-2)
        FlushExtBuf();
    extbuf[extSize] = strlen(buf);
    strcpy(extbuf + extSize + 1, buf);
    extSize += extbuf[extSize] + 1;
    extbuf[extSize++] = 0;
}

//-------------------------------------------------------------------------

static void omfextdumphash(HASHREC **syms)
{
    int i;
    SYM *sp;
    for (i = 0; i < HASHTABLESIZE; i++)
    {
        if ((sp = (SYM*)syms[i]) != 0)
        {
            while (sp)
            {
                if (sp->storage_class == sc_externalfunc && sp->mainsym
                    ->extflag && !(sp->tp->cflags &DF_INTRINS))
                {
                    omfputext(sp);
                }
                if (sp->storage_class == sc_external && sp->mainsym->extflag)
                {
                    omfputext(sp);
                }
                if (sp->storage_class == sc_defunc)
                {
                    SYM *sp1 = sp->tp->lst.head;
                    while (sp1)
                    {
                        if (sp1->storage_class == sc_externalfunc && sp1
                            ->mainsym->extflag && !(sp1->tp->cflags &DF_INTRINS)
                            )
                        {
                            omfputext(sp1);
                        }
                        sp1 = sp1->next;
                    }
                }
                if (sp->storage_class == sc_namespace && !sp
                    ->value.classdata.parentns->anonymous)
                    omfextdumphash(sp->value.classdata.parentns->table);
                sp = sp->next;
            }
        }
    }
}

//-------------------------------------------------------------------------

void omfExtDefs(void)
{
    int i;
    SYM *sp;
    VIRTUAL_LIST *v = virtualFirst;
    LIST *lf = localfuncs;
    extIndex = 1;
    extSize = 0;
    while (v)
    {
        v->sp->value.i = extIndex++ + 0xc0000000;
        v = v->next;
    }
    omfextdumphash(gsyms);

    while (lf)
    {
        sp = lf->data;
        if (sp->storage_class == sc_externalfunc && sp->mainsym->extflag && !
            (sp->tp->cflags &DF_INTRINS))
        {
            omfputext(sp);
        }
        lf = lf->link;
    }
    lf = localdata;
    while (lf)
    {
        sp = lf->data;
        if (sp->mainsym->extflag)
            omfputext(sp);
        lf = lf->link;
    }
    for (i = 0; i < HASHTABLESIZE; i++)
    {
        struct _templatelist *tl;
        if ((tl = (struct templatelist*)templateFuncs[i]) != 0)
        {
            while (tl)
            {
                if (!tl->sp->value.classdata.templatedata->hasbody && tl
                    ->finalsp)
                {
                    omfputext(tl->finalsp);
                } tl = tl->next;
            }
        }
    }
    FlushExtBuf();
}

//-------------------------------------------------------------------------

void omfputimport(SYM *sp)
{
    char buf[512], obuf[512];
    int l, l1;
    putsym(buf, sp, sp->name);
    l = strlen(buf);
    *(short*)obuf = 0xa000;
    obuf[2] = 1; // import
    obuf[3] = 0; // import by name
    obuf[4] = l;
    strcpy(obuf + 5, buf);
    obuf[5+l] = l1 = strlen(sp->importfile);
    strcpy(obuf + 6+l, sp->importfile);
    obuf[6+l + l1] = l;
    strcpy(obuf + 7+l + l1, buf);

    emit_record(COMENT, obuf, 7+2 * l + l1);
}

//-------------------------------------------------------------------------

void omfImports(void)
{
    SYM *sp;
    int i;
    LIST *lf = localfuncs;
    while (lf)
    {
        sp = lf->data;
        if (sp->mainsym->importable && sp->mainsym->importfile && sp->mainsym->extflag)
        {
            omfputimport(sp);
        }
        lf = lf->link;
    }
    lf = localdata;
    while (lf)
    {
        sp = lf->data;
        if (sp->mainsym->importable && sp->mainsym->importfile && sp->mainsym->extflag)
        {
            omfputimport(sp);
        }
        lf = lf->link;
    }
    for (i = 0; i < HASHTABLESIZE; i++)
    {
        if ((sp = (SYM*)gsyms[i]) != 0)
        {
            while (sp)
            {
                if (sp->mainsym->importable && sp->mainsym->importfile && sp->mainsym->extflag)
                {
                    omfputimport(sp);
                }
                sp = sp->next;
            }
        }
    }
}

//-------------------------------------------------------------------------

int omfgetseg(SYM *sp)
{
    if (!sp->tp)
        return dataseg;
    switch (sp->storage_class)
    {
        case sc_member:
            if (sp->value.classdata.gdeclare)
                sp = sp->value.classdata.gdeclare;
            else
                if (sp->tp->type != bt_func && sp->tp->type != bt_ifunc)
                    DIAG("omfGetSeg - no static member initializer");
            // fall through

        case sc_static:
        case sc_global:
            if (sp->tp->type == bt_func || sp->tp->type == bt_ifunc)
                if (sp->mainsym->gennedvirtfunc)
                    return sp->mainsym->value.i;
                else
                    return codeseg;
            /* fall through */
        case sc_external:
            if (sp->tp->cflags &DF_CONST)
                return constseg;
            else
                if (sp->init || !prm_bss)
                    return dataseg;
                else
                    return bssxseg;
        case sc_externalfunc:
        case sc_label:
            if (sp->mainsym->gennedvirtfunc)
                return sp->mainsym->value.i;
            else
                return codeseg;
        case sc_type:
            if (sp->mainsym->gennedvirtfunc)
            {
                // vtab & xt

⌨️ 快捷键说明

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