📄 init.c
字号:
/*
* 68K/386 32-bit C compiler.
*
* copyright (c) 1997, David Lindauer
*
* This compiler is intended for educational use. It may not be used
* for profit without the express written consent of the author.
*
* It may be freely redistributed, as long as this notice remains intact
* and either the original sources or derived sources
* are distributed along with any executables derived from the originals.
*
* The author is not responsible for any damages that may arise from use
* of this software, either idirect or consequential.
*
* v1.35 March 1997
* David Lindauer, gclind01@starbase.spd.louisville.edu
*
* Credits to Mathew Brandt for original K&R C compiler
*
*/
/*
* handles initialization of module-scoped declarations
*/
#include <stdio.h>
#include <limits.h>
#include "expr.h"
#include "c.h"
#include "errors.h"
extern int stdldoublesize;
extern enum e_sym lastst;
extern char lastid[], laststr[];
extern TABLE gsyms;
extern int skm_declend[];
extern long bittab[];
extern int nextlabel;
extern TYP stdmatch;
extern int skm_closebr[];
extern int prm_cplusplus;
extern SYM *currentfunc;
extern int prm_bss;
static SYM *locsp;
static short cursize;
static short startbit,bits;
static long totbits;
static int allocated;
static ENODE *cpprefhead;
static ENODE **cppreftail;
static int baseoffs = 0;
static struct decldata **sptr;
static struct declares {
struct declares *link;
SYM *sp;
} *declarations, *decltail;
void initini(void)
{
cpprefhead = 0;
declarations = decltail = 0;
}
void initrundown(void)
/*
* Dump out C++ pointer and reference initializations functions
*/
{
struct declares *q;
long nbytes,obytes,val,onbytes;
#ifdef CPLUSPLUS
if (cpprefhead) {
int lbl = nextlabel++;
SNODE stmt;
currentfunc = xalloc(sizeof(SYM));
currentfunc->tp = maketype(bt_func,0);
currentfunc->tp->btp = maketype(bt_void,0);
currentfunc->tp->lst.head = 0;
currentfunc->intflag = 0;
stmt.stype = st_expr;
stmt.next = 0;
stmt.exp = cpprefhead;
cseg();
gen_label(lbl);
genfunc(&stmt);
flush_peep();
cppseg();
gen_labref(lbl);
currentfunc = 0;
cpprefhead = 0;
}
#endif
nl();
dseg();
q = declarations;
nbytes = 0;
while (q) {
SYM *sp = q->sp;
if ((sp->init || !prm_bss) && !sp->absflag) {
int align = getalign(sc_global,sp->tp);
val = align - (nbytes % align);
if (val != align) {
genstorage(val);
nbytes += val;
nl();
}
onbytes = nbytes;
nbytes += gen(sp);
sp->value.i = onbytes;
}
q = q->link;
}
if (prm_bss) {
obytes = nbytes;
nbytes = 0;
bssseg();
q = declarations;
while (q) {
SYM *sp = q->sp;
if (!sp->init && !sp->absflag) {
int align = getalign(sc_global,sp->tp);
val = align - (nbytes % align);
if (val != align) {
genstorage(val);
nbytes += val;
nl();
}
onbytes = nbytes;
nbytes += gen(sp);
sp->value.i = onbytes + obytes;
}
q = q->link;
}
}
}
static long gen(SYM *sp)
{
struct decldata *decldata = sp->init;
long nbytes=0;
if (sp->storage_class == sc_global) {
globaldef(sp);
}
if (sp->staticlabel)
put_staticlabel(sp->value.i);
else
gen_strlab(sp);
if (decldata) {
while (decldata) {
switch (decldata->mode) {
case dd_byte:
genbyte(decldata->val.i);
nbytes++;;
break;
case dd_word:
genword(decldata->val.i);
nbytes += 2;
break;
case dd_long:
genlong(decldata->val.i);
nbytes += 4;
break;
case dd_float:
genfloat(decldata->val.f);
nbytes += 4;
break;
case dd_double:
gendouble(decldata->val.f);
nbytes += 8;
break;
case dd_ldouble:
genlongdouble(decldata->val.f);
nbytes += stdldoublesize;
break;
case dd_pcname:
genpcref(decldata->val.sp,decldata->offset);
nbytes += 4;
break;
case dd_dataname:
genref(decldata->val.sp,decldata->offset);
nbytes += 4;
break;
case dd_storage:
genstorage(decldata->val.i);
nbytes += decldata->val.i;
break;
case dd_label:
gen_labref(decldata->val.i);
nbytes += 4;
break;
}
decldata = decldata->link;
}
}
else {
if (sp->tp->size == 0)
gensymerror(ERR_ZEROSTORAGE,sp->name);
else
genstorage(nbytes += sp->tp->size);
}
nl();
return nbytes;
}
#ifdef CPLUSPLUS
void cppinitinsert(ENODE *node)
/*
* insert an initialization function on the list
*/
{
if (!cpprefhead) {
cpprefhead = node;
cppreftail = &cpprefhead;
}
else {
*cppreftail = makenode(en_void,*cppreftail,node);
cppreftail = & (*cppreftail)->v.p[1];
}
}
#endif
void doinit(SYM *sp)
/*
* Handle static variable initialize
*/
{
sp->tp->uflags |= UF_DEFINED;
allocated = FALSE;
baseoffs = 0;
totbits = 0;
cursize = -1;
bits = -1;
locsp = sp;
sptr = &sp->init;
if (!sp->indecltable) {
struct declares * p = xalloc(sizeof(struct declares));
p -> sp = sp;
p->link = 0;
if (declarations)
decltail = decltail->link = p;
else
decltail = declarations = p;
sp->indecltable = TRUE;
}
if( lastst == assign) {
if (sp->init)
gensymerror(ERR_MULTIPLEINIT,sp->name);
if (sp->absflag) {
generror(ERR_NOINIT,0,skm_declend);
return;
}
getsym();
inittype(sp->tp);
*sptr = 0;
}
endinit();
}
int inittype(TYP *tp)
/*
* Init for basic types
*/
{ int nbytes;
switch(tp->type) {
case bt_float:
nbytes = initfloat();
break;
case bt_longdouble:
nbytes = initlongdouble();
break;
case bt_double:
nbytes = initdouble();
break;
case bt_char:
nbytes = initchar();
break;
case bt_unsignedchar:
nbytes = inituchar();
break;
case bt_unsignedshort:
nbytes = initushort();
break;
case bt_short:
case bt_enum:
nbytes = initshort();
break;
case bt_ptrfunc:
nbytes = initpointerfunc();
break;
case bt_pointer:
if( tp->val_flag)
nbytes = initarray(tp);
else
nbytes = initpointer();
break;
#ifdef CPLUSPLUS
case bt_ref:
nbytes = initref(tp->btp);
break;
#endif
case bt_unsigned:
nbytes = initulong();
break;
case bt_long:
case bt_matchall:
nbytes = initlong();
break;
case bt_struct:
nbytes = initstruct(tp);
break;
default:
gensymerror(ERR_NOINIT,locsp->name);
nbytes = 0;
}
baseoffs+=nbytes;
return nbytes;
}
int initarray(TYP *tp)
/*
* Init for arrays
*/
{ int nbytes;
int canpad = FALSE;
char *p;
int needend = FALSE;
nbytes = 0;
if( lastst == begin) {
getsym(); /* skip past the brace */
needend = TRUE;
if ((tp->btp->type == bt_char || tp->btp->type ==bt_unsignedchar)&& lastst == sconst)
goto grabchar;
if ((tp->btp->type == bt_short || tp->btp->type ==bt_unsignedshort)&& lastst == lsconst)
goto grabchar;
while(lastst != end) {
nbytes += inittype(tp->btp);
if( lastst == comma)
getsym();
else if( lastst != end) {
expecttoken(end,0);
break;
}
}
getsym(); /* skip closing brace */
}
else {
grabchar:
allocated = TRUE;
nbytes = 0;
if ((tp->btp->type == bt_char || tp->btp->type ==bt_unsignedchar)&& lastst == sconst) {
canpad = TRUE;
while (lastst == sconst) {
p = laststr;
while (*p) {
nbytes++;
agflush(1,*p++);
}
getsym();
}
if (needend)
needpunc(end,skm_declend);
agflush(1,0);
nbytes++;
} else if ((tp->btp->type == bt_short || tp->btp->type ==bt_unsignedshort)&& lastst == lsconst) {
while (lastst == lsconst) {
p = laststr;
while (*p) {
nbytes+=2;
agflush(2,*p++);
}
getsym();
}
if (needend)
needpunc(end,skm_declend);
agflush(2,0);
nbytes +=2;
}
else generror(ERR_PUNCT,semicolon,0);
}
if( nbytes < tp->size) {
nl();
makestorage( tp->size - nbytes);
nbytes = tp->size;
}
else if (tp->size == 0)
tp->size = nbytes;
else if( nbytes > tp->size && (!canpad || nbytes > tp->size+1))
generror(ERR_INITSIZE,0,0); /* too many initializers */
return nbytes;
}
int initstruct(TYP *tp)
/*
* Init for structures
*/
{ SYM *sp;
int nbytes;
needpunc(begin,0);
nbytes = 0;
sp = tp->lst.head; /* start at top of symbol table */
while(sp != 0 && lastst != end) {
startbit = sp->tp->startbit;
bits = sp->tp->bits;
if (nbytes < sp->value.i)
makestorage(sp->value.i - nbytes);
nbytes = sp->value.i;
nbytes += inittype(sp->tp);
if( lastst == comma)
getsym();
else if(lastst == end)
break;
else
expecttoken(end,0);
sp = sp->next;
}
nbytes += agbits(-1,0);
if( nbytes < tp->size) {
makestorage(tp->size - nbytes);
}
needpunc(end,skm_declend);
return tp->size;
}
int makelabel(void)
{
struct decldata *q = *sptr = xalloc(sizeof(struct decldata));
q->val.i = tostring();
sptr = &(*sptr)->link;
q->mode = dd_label;
}
int makeref(int ispc, SYM *sp, long val)
{
struct decldata *q = *sptr = xalloc(sizeof(struct decldata));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -