?? oxccb.c
字號:
/*
oxccb.c -- v1.430 architecture neutral format (anf) to bytecode generator
Copyright (c) 1995
Norman D. Culver dba
Oxbow Software
1323 S.E. 17th Street #662
Ft. Lauderdale, FL 33316
(954) 463-4754
ndc@icanect.net
All rights reserved.
* Redistribution and use in source and binary forms are permitted
* provided that: (1) source distributions retain this entire copyright
* notice and comment, and (2) distributions including binaries display
* the following acknowledgement: ``This product includes software
* developed by Norman D. Culver dba Oxbow Software''
* in the documentation or other materials provided with the distribution
* and in all advertising materials mentioning features or use of this
* software.
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
*/
#define MAJOR_VERSION 1
#define MINOR_VERSION 433
void oxcc_debug();
int __builtin_iv();
void bterpdebug(void);
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <setjmp.h>
#include <time.h>
#define SUPPORT_LONG_DOUBLE 1
#define SUPPORT_LONG_LONG 1
#define NEED_SPELLING 1
#define NEED_BYTECODES 1
#define NEED_AOUT_FORMAT 1
#include "oxbytes.h"
#define NEED_FUNCTHUNK 1
#define NEED_ANFDEFS 1
#include "oxanf.h"
#define PROG oxccb
#define USING_FRAMEWORK 1
#define HOST_IS_LITTLE_ENDIAN 1
#define REALLY_NEED_OFFSETS 1
#define FUNCDATA (iv->category+1)
#define VFPRINTF(a,b) vfprintf(stderr,a,b)
#define PERROR prerror
#define PWARN prwarn
#define PRINTF info
static void prerror(const char *, ...);
static void prwarn(const char *, ...);
static void info(const char *, ...);
int cfeprintf(const char *, ...);
#define FILEWRITE(buf, cnt)\
{if(!iv->errors){if(fwrite(buf, 1, cnt, iv->outfile) != cnt)iv->errors = 12;}}
#define ROUNDING(a,b) ((a+(b-1))&~(b-1))
#define ROUNDUP(a,b) a += ROUNDING(a,b)
#define KEYEQ(a,b) ((a)[0] == (b)[0] && (a)[1] == (b)[1])
#define KEYLT(a,b) (((a)[1] < (b)[1]) || ((a)[1] == (b)[1] && (a)[0] < (b)[0]))
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
/* ======================== CONCATENIZATION MACROS ==================== */
#define _cat2_(a, b) a##b
#define _cat_(a, b) _cat2_(a, b)
#define Global(a) _cat_(PROG, a)
#define _pname2_(x) #x
#define _pname1_(x) _pname2_(x)
#define pName _pname1_(PROG)
/* ============== ENDIAN MACROS (input format is litle endian) ==== */
#if HOST_IS_LITTLE_ENDIAN
#define GL(a) a
#define GS(a) a
#define PL(a) a
#define PS(a) a
#else
#endif
/* =================== INPUT DATA FORMATS ========================== */
#define INFILE_SYMNUM 1
#define OUTFILE_SYMNUM 2
static unsigned char binops[] = {0,0,
ADD,SUB,MUL,DIV,LSH,RSH,MOD,OR,XOR,AND,EQ,NE,LT,GT,LE,GE,
NEG,COMP,NOT
};
/* ====================== STRUCTURES AND TYPEDEFS ======================== */
typedef struct _jl {
struct _jl *next;
void *p;
char *q;
long *plabelval;
long offset;
} *PJL;
typedef struct _el {
struct _el *next;
long spot;
short symnum;
} *PEL;
typedef struct _afile {
unsigned char *file_p;
PopI header_p;
PopI size_p;
unsigned char *symtext_p;
unsigned char *prog_p;
unsigned char *data_p;
unsigned char *switch_p;
unsigned char *decl_p;
unsigned char *maxtemp_p;
unsigned char *seg_p;
unsigned char **symaddr;
unsigned char **decladdr;
unsigned long thunk_offset;
unsigned long bss_offset;
int maxtemp;
int maxtempclass;
void *datatbl;
short *symtran;
unsigned short *decltran;
int filenum;
int numsyms;
int numdecls;
int numrelocs;
int numsegs;
} *Pafile;
typedef struct _iv {
int category;
FILE *outfile;
struct exec *header;
unsigned char **symaddr;
unsigned char **decladdr;
int remove_infile;
int argc;
char **argv;
int numfiles;
int lastlabel;
int errors;
int numsyms;
int numdecls;
int numsegs;
int maxtemp;
int maxtempclass;
unsigned long total_size;
unsigned long thunk_offset;
unsigned long bss_offset;
struct _nodeO *ob_usedhead;
struct _nodeO *ob_usedtail;
struct _nodeO *ob;
unsigned char *ob_buf;
int ob_bufcnt;
struct _nodeO *first_ob;
struct _nodeC *cod_usedhead;
struct _nodeC *cod_usedtail;
struct _nodeC *cod;
unsigned char *cod_buf;
int cod_bufcnt;
struct _nodeC *first_cod;
struct _nodeC *regcode;
long first_temp;
long killop;
long stackdepth;
long maxdepth;
long mindepth;
long numnested;
long lastline;
void *reloctbl;
void *extrntbl;
void *gbltbl;
void *symtbl;
void *labeltbl;
void *newlabeltbl;
void *tmptbl;
void *segtbl;
void *functbl;
void *finalsymtbl;
void *finalstringpack;
long finalpacksize;
void *datatbl;
void *builtintbl;
int in_builtin;
int has_structret;
int temps_written;
unsigned char *obuf;
unsigned char *obufstart;
PEL extbuf;
void *extbufstart;
int extcnt;
int extbufcnt;
PEL finextbuf;
void *finextbufstart;
int finextcnt;
int finextbufcnt;
PJL jbuf;
void *jbufstart;
int jmpcnt;
int jbufcnt;
long obufcnt;
long out_offset;
long func_offset;
int extmark;
short markedsym[10];
char *markedbuf[10];
int filenum;
Pafile files[1024];
char debug;
char only_debug;
char strip;
char listing_wanted;
} *Piv;
struct _gloval {
char *symname;
int symnum;
unsigned char *p;
Pafile pf;
};
struct _rkey {/* key area of reloctbl node */
unsigned long spot;
short fileno;
unsigned char opcode;
char rsize;
};
struct _rval {/* value area of reloctbl node */
unsigned char *p;
unsigned long *base;
long offset;
short rsym;
};
/* Internal User API */
static void *Cmalloc(int category, unsigned amount);
static void *Ccalloc(int category, unsigned nelems, unsigned elemsize);
static void *Crealloc(int category, void* buf, unsigned newsize);
static void Cfree(int category, void* buf);
static void Cfreecat(int category);
static int Cmemrange(int category, unsigned* minp, unsigned* maxp);
static int Cusedrange(int category, unsigned* minp, unsigned* maxp);
static void Ctotrange(unsigned* minp,unsigned* maxp);
static int Cnewcat(void);
static void Cguard(int category);
static void* NewSymTable(int category, int nbins);
static int SymFind(void *tbl, void *key, void *result);
static int SymFindRange(void *tbl, void *key, void *result);
static void *SymInsert(void *tbl, void *key, void *value, int datsiz);
static int StringInsert(void *tbl, char *string, void *result);
static int StringFind(void *tbl, char *string, void *result);
static void SymDelete(void *tbl, void *key);
static int SymHead(void *tbl);
static int SymNext(void *tbl);
static void SymGetMark(void *tbl, void *markptr);
static int SymMarkNext(void *tbl, void *mark);
static void SymSetMark(void *tbl, void *markptr);
static void SymKey(void *tbl, void *keyptr);
static void SymValue(void *tbl, void *datptr);
static void *seg_find(Piv iv, int id);
static char *filenameof(char *path);
static char *propernameof(Piv iv, char *name);
/* END: User API */
/* ====================== PUT UNIQUE CODE HERE ========================= */
static void newlabel_insert(Piv iv, long label);
static long newlabel_fix(Piv iv, long label);
static void *do_stmt(Piv iv, unsigned char *p);
static void *do_expr(Piv iv, unsigned char *p);
static void do_bracket(Piv iv, unsigned char *p, unsigned char *q);
static void *do_something(Piv iv, unsigned char *p);
extern char *ctime();
/* ===================== BYTECODE OUTPUT GENERATOR ======================= */
struct _nodeOBUF
{
struct _nodeOBUF *next;
long cnt;
char buf[1];
};
typedef struct _nodeC
{
struct _nodeC *next;
struct _nodeOBUF *ee;
} NODEC, *PNODEC;
typedef struct _nodeO
{
struct _nodeO *next;
unsigned char *p;
ND d;
ND l;
ND r;
PNODEC startinst;
PNODEC endinst;
} NODEO, *PNODEO;
static unsigned char get_datasize(unsigned char, PND);
static void link_cod(Piv);
static char *notice =
" Generated by Oxbow Software Bytecode Backend version %d.%d\n*/\n\n";
static struct _nd longtype = {D_SIGNED,0,B4,0,4,0,0};
static struct _nd longlongtype = {D_SIGNED,0,B8,0,8,0,0};
static char padit[8]; /* in bss */
void
bterpdebug(){}
static long
symnumof(Piv iv, char *symb)
{
struct _gloval *valp;
if(StringFind(iv->gbltbl, symb, &valp))
return (long)valp->pf->symtran[valp->symnum];
return 0;
}
static void
buildin(Piv iv, char *symb, unsigned char code)
{
long key[2];
if((key[0] = symnumof(iv, symb)))
{
key[1] = 0;
SymInsert(iv->builtintbl, key, &code, 1);
}
}
static void
install_builtins(Piv iv)
{/* USE THIS TO INSTALL WHATEVER BUILTINS ARE IN THE TARGET INTERPRETER */
#define BUILDIN(a,b) buildin(iv,#a,b)
iv->builtintbl = NewSymTable(iv->category, 191);
BUILDIN(alloca,ALLOCA);
BUILDIN(strlen,STRLEN);
BUILDIN(strcpy,STRCPY);
BUILDIN(strcat,STRCAT);
BUILDIN(memcpy,MEMCPY);
BUILDIN(memmove,MEMMOVE);
BUILDIN(bzero,BZERO);
BUILDIN(malloc,MALLOC);
BUILDIN(calloc,CALLOC);
BUILDIN(realloc,REALLOC);
BUILDIN(setjmp,SETJMP);
BUILDIN(longjmp,LONGJMP);
BUILDIN(abort,ABORT);
BUILDIN(exit, EXIT);
BUILDIN(_exit,EXIT);
BUILDIN(bterpdebug,DEBUG);
BUILDIN(bterpnodebug,NODEBUG);
#undef BUILDIN
}
static long
final_strofs(Piv iv, char *string)
{
long *result;
if(StringFind(iv->finalsymtbl, string, &result))
return result[2];
return 0;
}
static short
final_symnum(Piv iv, short symnum)
{
long *result;
if(StringFind(iv->finalsymtbl, iv->symaddr[symnum], &result)) {
return result[1]-1;
}
return 0;
}
static void
make_final_symtab(Piv iv)
{
int i;
iv->finalsymtbl = NewSymTable(iv->category, 0);
if(SymHead(iv->gbltbl))
{
i = 0;
while(SymNext(iv->gbltbl))
{
long *result;
struct _gloval *valp;
SymValue(iv->gbltbl, &valp);
if(*(valp->p))
{
long key[2];
key[0] = valp->pf->symtran[valp->symnum];
key[1] = 0;
if(!SymFind(iv->builtintbl, key, NULL))
{
if(!StringInsert(iv->finalsymtbl, valp->symname, &result))
{/* New Entry */
result[1] = ++i;
}
}
}
}
}
}
static void
adjust_labels(Piv iv, long base, long adjust)
{
long *key;
long *val;
if(SymHead(iv->newlabeltbl))
{
while(SymNext(iv->newlabeltbl))
{
SymKey(iv->newlabeltbl, &key);
SymValue(iv->newlabeltbl, &val);
if(key[1] == iv->filenum && val[0] > base) {
val[0] += adjust;
}
}
}
}
static void
addto_extlist(Piv iv, char *buf)
{
void *next;
while(iv->extmark > 0)
{
long offset = iv->markedbuf[iv->extmark] - buf;
next = iv->extbuf;
if(iv->extbufcnt >= sizeof(struct _el))
{
iv->extbuf++;
}
else
{
iv->extbufcnt = 4080;
iv->extbuf = Ccalloc(FUNCDATA, 1, iv->extbufcnt);
}
*((void**)next) = iv->extbuf;
iv->extbuf->spot = iv->out_offset+iv->func_offset+offset;
iv->extbuf->symnum = iv->markedsym[iv->extmark];
++iv->extcnt;
--iv->extmark;
iv->extbufcnt -= sizeof(struct _el);
}
}
static void
save_extlocs(Piv iv)
{
PEL pel = iv->extbufstart;
void *next;
while(pel)
{
next = iv->finextbuf;
if(iv->finextbufcnt >= sizeof(struct _el))
{
iv->finextbuf++;
}
else
{
iv->finextbufcnt = 4080;
iv->finextbuf = Ccalloc(iv->category, 1, iv->finextbufcnt);
}
*((void**)next) = iv->finextbuf;
iv->finextbuf->spot = pel->spot;
iv->finextbuf->symnum = pel->symnum;
++iv->finextcnt;
iv->finextbufcnt -= sizeof(struct _el);
pel = pel->next;
}
}
static void
adjust_externs(Piv iv, long base, long adjust)
{
PEL pel = iv->extbufstart;
while(pel)
{
if(pel->spot > base)
pel->spot += adjust;
pel = pel->next;
}
}
static int
shorten_jmps(Piv iv)
{
int scnt;
PJL jp;
long jmp_offset;
long label_offset;
long diff;
long offset_adjust;
int sign;
unsigned char *q, *osiz;
int cursize, newsize;
scnt = 0;
jp = iv->jbufstart;
offset_adjust = 0;
while(jp)
{
osiz = jp->q+4; /* points to size in obuf */
q = osiz+4; /* points to the JMP inst in obuf */
cursize = *q & 3; /* from the output bytecode */
jmp_offset = jp->offset + offset_adjust;
jp->offset = jmp_offset; /* reset the offset for this inst */
label_offset = *jp->plabelval;
diff = label_offset - jmp_offset;
sign = 1;
if(diff < 0)
{
sign = -1;
diff = -diff;
}
if(diff < 0x7fL)
newsize = 0;
else if(diff < 0x7fffL)
newsize = 1;
else if(diff < 0x007fffffL)
newsize = 2;
else
newsize = 3;
if(cursize != newsize)
{/* DO SOMETHING */
long adj;
static long codesize[4] = {2L,3L,4L,5L};
++scnt; /* something changed */
*q &= 0xfc; /* mask opcode */
*q |= newsize; /* set size in opcode */
*((long*)osiz) = codesize[newsize]; /* set new output size */
adj = codesize[newsize] - codesize[cursize];
offset_adjust += adj; /* jmps below this point have new offset */
if(sign > 0) diff += adj; /* label is below this point */
/* Adjust all labels below this point */
adjust_labels(iv, jmp_offset, adj);
/* adjust all external address spots (text relocs) below this point */
adjust_externs(iv, jmp_offset, adj);
}
diff *= sign; /* restore sign to the relative address */
/* generate the pc relative address */
++q; /* points the the address field of the JMP inst */
if(newsize == 0)
*((signed char*)q) = (signed char)(diff & 0xff);
else if(newsize == 1)
*((short*)q) = (short)(diff & 0xffff);
else if(newsize == 2)
*((long*)q) = diff<<8;
else
*((long*)q) = diff;
jp = jp->next;
}/* END: while (jp) */
return scnt;
}
static void
setup_jmps(Piv iv, unsigned char *pdef)
{
struct {
long k1;
long k2;
} key;
long *result;
PJL jp;
unsigned char *p;
jp = iv->jbufstart;
while(jp)
{
p = jp->p;
key.k1 = GL( POP->data ); /* label number from source code */
key.k2 = iv->filenum; /* source file number */
if(SymFind(iv->newlabeltbl, &key, &result))
{
jp->plabelval = result; /* save pointer to label value */
}
else
{
PERROR(pName ":SYSERROR: jmp setup failed for `%s' label=%d file=%d p=%x code=%d\n",
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -