Digital Research
This commit is contained in:
2020-11-06 18:50:37 +01:00
parent 621ed8ccaf
commit 31738079c4
8481 changed files with 1888323 additions and 0 deletions

View File

@@ -0,0 +1,642 @@
/*
Copyright 1982, 1983
Alcyon Corporation
8716 Production Ave.
San Diego, Ca. 92121
@(#)init.c 1.13 1/3/84
*/
#include "parser.h"
#define NULL (char *)0
short inittype;
short bfield_ty; /* [vlh] 4.2 type of bit field currently initializing */
short bits_init; /* [vlh] 4.2 current bit field init value */
short in_bitinit; /* [vlh] 4.2 are we currently initializing a bit field ?? */
short lst_boffset; /* [vlh] 4.2 new bit field entity ?? */
#define BCHK(plus) {plus = out_bfield(CHAR); nbout += plus; nbleft += plus;}
/*
* doinit - do external definition initialization
* Handles following C syntax:
* initializer:
* = constant_expression
* = { initializer_list }
* = { initializer_list , }
* initializer_list:
* constant_expression
* initializer_list , initializer_list
* { initializer_list }
*/
doinit(sp) /* returns number of elements init'ed*/
struct symbol *sp; /* pointer to symbol to init*/
{
register short type;
long isize, datasize;
type = sp->s_type;
datasize = dsize(type,sp->s_dp,sp->s_ssp);
if( PEEK(COMMA) || PEEK(SEMI) ) { /*no initialization*/
isize = WALIGN(datasize);
#ifdef DEBUG
if(initdebug)
printf("%s sc %x attrib %x\n",sp->s_symbol,sp->s_sc,sp->s_attrib);
#endif
if( sp->s_sc == EXTERNAL )
OUTCOMMON(sp->s_symbol,isize);
else if (sp->s_sc == DEXTERN) /* explicitly EXTERN */
sp->s_sc = EXTERNAL;
else {
OUTBSS(); /*bss segment*/
OUTLAB(sp->s_offset);
OUTRESMEM(isize);
OUTTEXT(); /*resume text segment*/
}
}
else {
if (!(next(ASSIGN))) /*ignore '=' if there*/
warning("old fashion initialization");
if( type == LONG || ISPOINTER(type) )
outldata();
else if(type == DOUBLE || type == FLOAT) /*[vlh] 3.4*/
outfpdata();
else
outdata();
if( sp->s_sc == EXTERNAL )
OUTDLAB(sp->s_symbol);
else
OUTLAB(sp->s_offset);
isize = initlist(sp, sp->s_type, sp->s_dp, sp->s_ssp);
if( isize < datasize ) {
OUTRESMEM(datasize-isize);
isize = datasize;
}
if( WALIGN(isize) != isize )
OUTPAD();
if( isize > datasize ) {
if( ISARRAY(sp->s_type) ) {
for( type = sp->s_type; ISARRAY(type); type = delsp(type) )
;
dtab[sp->s_dp] = (isize / dsize(type,sp->s_dp,sp->s_ssp));
}
else
error("too many initializers");
}
if( sp->s_sc == STATIC )
OUTTEXT();
}
}
/*
* initlist - handles initializer lists
* This handles multi-level braces, and a character pointer pointing
* to a string. Most of the work is in keeping track of how many
* bytes are left on the current "row", and outputting padding if
* necessary.
*/
long
initlist(sp,type,dp,ssp) /* returns size of initializers in bytes*/
struct symbol *sp; /* [vlh] 4.2 for use in struct init */
int type, dp, ssp;
{
register short onetype, plus, atype;
long datasize, i, j, elsize, nbleft, nbout; /* [vlh] 3.4 int=>long */
#ifdef SYM_TO_DSK
struct symbol par_str; /* parent structure.... */
#endif
i = (next(LCURBR));
for( onetype = type; ISARRAY(onetype); onetype = delsp(onetype) )
;
#ifdef DEBUG
if (initdebug) {
printf("type: %d BTYPE %d ISARRAY %d ",type,BTYPE(type),ISARRAY(type));
printf("POINTER %d\n",ISPOINTER(type));
printf("onetype: %d BTYPE %d ",onetype,BTYPE(onetype));
printf("ISARRAY %d POINTER %d\n",ISARRAY(onetype),ISPOINTER(onetype));
}
#endif
nbout = 0;
datasize = dsize(type,dp,ssp);
nbleft = 0; /*keep track of no. of bytes left*/
atype = (ISARRAY(type)) ? delsp(type) : type; /*[vlh]4.2 multi dimens */
if(type==(ARRAY|CHAR) || type==(ARRAY|INT) || type==(ARRAY|LONG))
nbout = str_init(datasize,type);
else if(atype==(ARRAY|CHAR) || atype==(ARRAY|INT) || atype==(ARRAY|LONG)) {
datasize = dsize(atype,dp,ssp);
elsize = dsize(atype,dp+1,ssp);
if( !i )
error("missing { in initialization");
do {
j = (next(LCURBR));
nbout += str_init(elsize,atype);
if (j && !(next(RCURBR)))
error("missing } in initialization");
next(COMMA); /* skip over comma... */
} while(!PEEK(RCURBR) && !PEEK(SEMI));
nbleft = datasize - nbout;
if ((elsize==INTSIZE && (onetype==INT) || (onetype==SHORT)) ||
(elsize==CHARSIZE && (onetype==CHAR)) ||
(elsize==LONGSIZE && (onetype==LONG)) ||
(datasize==elsize)) /*undimensioned array*/
nbleft = 0;
if (nbleft < 0) {
error("initializer list too long");
nbleft = 0;
}
} /* multi-dimensional array */
else if (BTYPE(type)==STRUCT && NOTPOINTER(type) && ISPOINTER(onetype)) {
nbleft = elsize = PTRSIZE; /* [vlh] 4.2.f */
if( !i )
error("missing { in initialization");
do {
nbleft = s_or_a(POINTER|CHAR,elsize,&nbout,nbleft,NULL,NULL);
next(COMMA); /* skip over comma... */
} while(!PEEK(RCURBR) && !PEEK(SEMI));
}
else if (ISARRAY(type) || (BTYPE(type)==STRUCT && NOTPOINTER(type))) {
nbleft = elsize = dsize(delsp(type),dp,ssp); /* was dp+1 */
/* [vlh] 4.2, added proper handling of structure init... */
if( !i && BTYPE(type)==STRUCT )
error("missing { in initialization");
do {
#ifndef SYM_TO_DSK
nbleft = s_or_a(onetype,elsize,&nbout,nbleft,sp->s_par,NULL);
#else
read_st(&par_str,sp->s_par);
nbleft = s_or_a(onetype,elsize,&nbout,nbleft,&par_str,NULL);
#endif
next(COMMA); /* skip over comma... */
} while(!PEEK(RCURBR) && !PEEK(SEMI));
}
else {
indecl = 0; /* [vlh] 4.2 */
nbout = oneinit(onetype,dp,(int)sp->s_sc); /* [vlh] 4.2.c add 2 args */
}
if (in_bitinit)
BCHK(plus) /* [vlh] 4.2 bit field initialization */
if( nbleft && (nbleft != elsize)) { /*pad current row*/
OUTRESMEM(nbleft);
nbout += nbleft;
}
if (i) {
next(COMMA); /* [vlh] 4.2 skip over extra comma */
if (!(next(RCURBR)))
error("missing } in initialization");
}
return(nbout);
}
#ifndef SYM_TO_DSK
# define COPY(c,s) c = s
# define HCOPY(c,s) c = s
#else
# define COPY(c,s) c_addr = s; c = &child_str; read_st(c,c_addr)
# define HCOPY(c,s) c_addr = s; c = &hold_str; read_st(c,c_addr)
#endif
#define BASIC_AR(x) (x==(ARRAY|CHAR)||x==(ARRAY|INT)||x==(ARRAY|LONG))
/**
* s_or_a - initialize structure or array
* routine to deal with initializing structures and arrays and
* assure that structures are aligned properly. Checks initializers
* with the expected type.
* Attempts to match structure initializations against the
* elements of the structure.
* sp -- pointer to structure symbol table entry
**/
long
s_or_a(original,elsize,pnbout,bleft,sp,child) /* returns nbleft */
int original; /* [vlh] original type... */
long elsize, bleft, *pnbout;
struct symbol *sp; /* [vlh] 4.2 for use in struct init */
struct symbol *child; /* [vlh] 4.2 for use in struct init */
{
register long nbleft, nbout;
register short onetype, plus;
long i, temp, datasize, addup, x;
short nest, snest; /* [vlh] 4.2 nest <= number of LCURBR */
struct symbol *hold;
#ifdef SYM_TO_DSK
long c_addr;
struct symbol child_str; /* child structure */
struct symbol hold_str; /* hold structure */
#endif
nbleft = bleft; nbout = *pnbout; onetype = original; nest = i = 0;
#ifdef DEBUG
if (initdebug)
printf("s_or_a: [%s] elsize %ld\n",(sp) ? sp->s_symbol : "",elsize);
#endif
do { /*in current row.*/
restart:
if (BTYPE(original) == STRUCT) { /* [vlh] 4.3 */
if(!child) {
if (!sp->s_child)
break;
else {
COPY(child,sp->s_child);
}
}
onetype = child->s_type;
#ifdef DEBUG
if (initdebug)
printf("s_or_a: child %s type %d\n",child->s_symbol,onetype);
#endif
}
if( PEEK(SEMI) || PEEK(EOF) || PEEK(RCURBR) )
break;
if(child && onetype == STRUCT) { /* [vlh] 4.3 */
#ifdef DEBUG
if(initdebug) printf("s_or_a recurse onetype STRUCT\n");
#endif
snest = (next(LCURBR));
temp = nbout;
HCOPY(hold,child->s_par); /* was s_child */
i = dsize(onetype,(hold->s_dp)+1,hold->s_ssp);
s_or_a(onetype,i,&temp,i,hold,NULL);
if(snest) {
if (!next(RCURBR)) /* force release of matched curbr */
error("mismatched curly braces");
}
else if (!peektok)
peektok = COMMA; /* [vlh] 4.2 put it back.... */
goto past;
}
else if( next(LCURBR) ) { /*recurse down one level?*/
nest++;
if (in_bitinit)
BCHK(plus) /* [vlh] 4.2 bit field initialization */
if( nbout && nbleft && (nbleft<elsize)) {
OUTRESMEM(nbleft); /*pad rest of current row*/
nbout += nbleft;
nbleft = 0;
}
if (!nbout && !nbleft)
goto restart;
if( i > elsize )
error("initializer list too long");
child = 0; /* force restart of structure match up */
goto restart;
}
else if( PEEK(RCURBR) ) {
if (nest) {
next(RCURBR);
nest--;
continue; /* goes to next comma... */
}
else
break;
}
else {
if ( BASIC_AR(onetype) ) { /* [vlh]4.2 simple arrays */
#ifdef DEBUG
if(initdebug) printf("BASIC_AR onetype 0%o\n",onetype);
#endif
datasize = dsize(onetype,child->s_dp,child->s_ssp);
i = str_init(datasize, onetype);
}
else if ( BASIC_AR(original) ) { /* [vlh]4.2 simple arrays */
#ifdef DEBUG
if(initdebug) printf("BASIC_AR original 0%o\n",original);
#endif
datasize = dsize(original,child->s_dp,child->s_ssp);
i = str_init(datasize, original);
}
else if (ISARRAY(onetype)) { /* [vlh] 4.2 */
#ifdef DEBUG
if(initdebug) printf("ISARRAY onetype 0%o\n",onetype);
#endif
addup = 0; /* array of structures or arrays */
temp = nbout;
i = dsize(onetype,child->s_dp,child->s_ssp);
onetype = delsp(onetype);
datasize = dsize(onetype,child->s_dp+1,child->s_ssp);
HCOPY(hold,child->s_par); /* was s_child */
x = onetype & ~POINTER; /* [vlh] 4.3, simple pointer */
if( SIMPLE_TYP(x) ) {
#ifdef DEBUG
if(initdebug) printf("simple type 0%o 0%o\n",onetype,x);
#endif
for(addup=0; addup != i; addup += datasize) {
if (PEEK(RCURBR) || PEEK(SEMI)) {
OUTRESMEM(i);
break;
} /*[vlh] 4.3, no more initializers */
oneinit(onetype,hold->s_dp,(int)hold->s_sc);
next(COMMA);
}
if (!peektok)
peektok = COMMA; /* [vlh] 4.2 put it back.... */
#ifdef DEBUG
if(initdebug) printf("peektok %d addup %ld\n",peektok,addup);
#endif
}
else
for(addup=0; addup != i; addup += datasize) {
x = s_or_a(onetype,datasize,&temp,datasize,hold,NULL);
if(x) { /*[vlh] 4.3, no initializer for current item*/
OUTRESMEM(i - (addup + datasize - x));
break;
}
}
}
else { /* simple type....... */
if ((nbleft & 1) && onetype != CHAR) {
nbleft--;
nbout++;
OUTEVEN();
}
if (!child) /* mra/vlh4.2+ don't access off of zero !!! */
i = oneinit(onetype,0,0);
else
i = oneinit(onetype,child->s_dp,(int)child->s_sc);
}
past:
nbout += i;
if ( !nbleft && !SIMPLE_TYP(original) )
nbleft = elsize;
if( i > nbleft )
error("initializer alignment");
nbleft = (i >= nbleft) ? 0 : nbleft - i;
if (BTYPE(original)==STRUCT) { /* [vlh] 4.2, get next child */
if (!child->s_sib) { /* [vlh] 4.2 at end... */
plus = (in_bitinit) ? out_bfield(CHAR) : 0;
nbleft -= plus;
nbout += nbleft;
if ( nbleft ) { /* was checking against elsize */
OUTRESMEM(nbleft);
nbleft = 0;
}
if (SUPTYPE(original) != ARRAY)
break;
#ifdef DEBUG
if(initdebug) printf("last child out...\n");
#endif
}
else {
COPY(child,child->s_sib);
}
}
}
#ifdef DEBUG
if(initdebug && child)
printf("child [%s] PEEKTOK comma %d\n",child->s_symbol,PEEK(COMMA));
#endif
} while( next(COMMA) );
#ifdef DEBUG
if(initdebug) printf("exiting s_or_a: nbleft %ld\n",nbleft);
#endif
if (BTYPE(original)==STRUCT) { /* [vlh] 4.2, ensure padding... */
plus = (in_bitinit) ? out_bfield(CHAR) : 0;
nbout += nbleft;
if ( nbleft ) { /* was checking against elsize */
OUTRESMEM(nbleft);
nbleft = 0;
}
}
*pnbout = nbout;
while(nest--) {
next(COMMA); /* comma's may separate.... */
if (!next(RCURBR)) /* force release of matched curbr */
error("mismatched curly braces");
}
next(COMMA); /* comma's may separate.... */
return(nbleft);
}
/**
* str_init - string (array) initialization [vlh] 4.2
* initialize a character array, truncating or padding as required
**/
long
str_init(datasize,type)
long datasize;
int type; /* should not get a bit field here..... */
{
register long maxsize, output;
#ifdef DEBUG
if (initdebug) printf("str_init: type %d, datasize %ld\n",type,datasize);
if (initdebug) printf("str_init: SUPTYPE %d, ",SUPTYPE(type));
if (initdebug) printf("BTYPE %d\n",BTYPE(type));
#endif
output = 0L;
if ((datasize==CHARSIZE && (BTYPE(type)==CHAR)) || /*undimensioned array*/
(datasize==INTSIZE && (BTYPE(type)==INT) || (BTYPE(type)==SHORT)) ||
(datasize==LONGSIZE && (BTYPE(type)==LONG))) {
datasize = 0;
maxsize = 0x7fff; /* max 32 bit positive value */
#ifdef DEBUG
if (initdebug) printf("undimensioned type %d datasize %ld\n",type,datasize);
#endif
}
else
maxsize = datasize;
do {
if (next(STRING)) {
output += (!datasize) ? outstr((long)cstrsize,(long)cstrsize) :
outstr(maxsize-output,(long)cstrsize);
return(output);
}
output += oneinit(BTYPE(type)|ARRAY,0,0);
#ifdef DEBUG
if (initdebug) printf("output %ld, ",output);
if (initdebug) printf("maxsize %ld, ",maxsize);
#endif
if (maxsize <= output) {
if (maxsize < output)
error("character array initializer alignment");
return(output);
}
} while (next(COMMA) && !PEEK(SEMI) && !PEEK(RCURBR));
if (datasize) {
OUTRESMEM(maxsize-output);
return(maxsize);
}
return(output);
}
/**
* oneinit - get one initializer expression or constant
* This checks the type of the data item expected against the
* type obtained from expr.
**/
oneinit(type,dp,sc) /* returns size of initializer*/
int type; /* type of initializer*/
int dp, sc; /* [vlh] 4.2.c add for bit field init */
{
register short op, plus, ivalue;
register struct tnode *tp;
register long value;
commastop++;
#ifdef DEBUG
if (initdebug) printf("oneinit: type = %d\n",type);
#endif
if ((tp = (struct tnode *)expr(0)) == 0) {
error("invalid initializer");
commastop--;
return(0);
}
commastop--;
if ((op = tp->t_op) == CINT)
clvalue = ((struct conode *)tp)->t_value;
else if (op == CLONG)
clvalue = ((struct lconode *)tp)->t_lvalue;
ivalue = value = clvalue;
if (sc == BFIELDCL)
return(one_binit(type,dp,value));
plus = (in_bitinit) ? out_bfield(type) : 0;
switch( ISALLTYPE(type) ) {
case UCHAR:
if( op == CINT || op == CLONG ) { /* [vlh] 4.2, added CLONG */
outc(CHAR,((int)(ivalue&0xff)));
if ((ivalue&0xff00) && ((ivalue&0xff00) != 0xff00))
warning("initializer truncated");
return(1+plus);
}
if( op == ADDR ) { /* [vlh] 4.2, STRING.... */
outc(CHAR,((int)(*cstr&0xff)));
warning("string used to initialize character value");
return(1+plus);
}
break;
case CHAR:
if( op == CINT || op == CLONG ) { /* [vlh] 4.2, added CLONG */
outc(CHAR,((int)ivalue)&0xff);
#ifdef DEBUG
if (initdebug) printf("ivalue %d\n",ivalue);
#endif
if ((ivalue>255) || (ivalue<-128))
warning("initializer truncated");
return(1+plus);
}
if( op == ADDR ) { /* [vlh] 4.2, STRING.... */
outc(CHAR,((int)*cstr)&0xff);
warning("string used to initialize character value");
return(1+plus);
}
break;
case ARRAY|CHAR:
if( op == CINT || op == CLONG ) { /* [vlh] 4.2, added CLONG */
if (ccbytes < 2) {
outc(CHAR,((int)ivalue)&0xff);
if ((ivalue>255) || (ivalue<-128))
warning("initializer truncated");
return(1+plus);
}
else { /* 2 character charconst eg. 'ab' */
outc(INT,ivalue);
return(2+plus);
}
}
break;
case INT:
case ARRAY|INT:
if (op == ADDR)
break;
if( op == CINT || op == CLONG ) { /* [vlh] 4.2, added CLONG */
outc(INT,(int)value);
if ((value&0xffff0000) && ((value&0xffff0000) != 0xffff0000))
warning("initializer truncated");
}
else
outinit(tp,inittype);
return(2+plus);
case UNSIGNED: /* [vlh] 4.0 split from INT... */
case USHORT: /* [vlh] 4.2 added... */
case ARRAY|UNSIGNED:
if (op == ADDR)
break;
if( op == CLONG || op == CINT ) { /* [vlh] 4.2, rewrote */
if ((value&0xffff0000) && ((value&0xffff0000) != 0xffff0000))
warning("initializer truncated");
ivalue = value & 0xffff;
outc(INT,ivalue);
}
else
outinit(tp,inittype);
return(2+plus);
case LONG:
case ULONG:
case ARRAY|LONG:
case POINTER|CHAR:
case POINTER|UCHAR:
case POINTER|INT:
case POINTER|LONG:
case POINTER|ULONG:
case POINTER|STRUCT:
case POINTER|UNSIGNED:
case POINTER|DOUBLE: /* [vlh] 4.2 */
case POINTER|FLOAT: /* [vlh] 4.2 */
if( op!=CINT && op!=CLONG ) {
outinit(tp,inittype);
return(4+plus);
}
case DOUBLE: /* [vlh] 3.4 */
case FLOAT:
outfp_or_l(value);
return(4+plus);
}
error("invalid initializer type=%d",ISALLTYPE(type));
return(plus);
}
/**
* one_binit - individula element bit field initialization. [vlh] 4.2
* returns the number of bytes actually initialize 1, 2 or 0
**/
one_binit(type,dp,value)
int type,dp;
long value;
{
register short plus, mask, op;
op = (BTYPE(type) == CHAR) ? BITSPCHAR : BITSPWORD;
op = (dp>>8)%op;
if (in_bitinit && ((bfield_ty != BTYPE(type)) || (op < lst_boffset)))
plus = out_bfield(type);
else
plus = 0;
lst_boffset = op;
bfield_ty = BTYPE(type);
mask = (1 << (dp & 0xff)) - 1;
bits_init |= ((value & mask) << op);
in_bitinit++;
return(plus);
}
/* out_bfield - last item was a bit field output it [vlh] 4.2 */
out_bfield(type) /* return number of bytes output */
int type;
{
in_bitinit = 0;
if (bfield_ty == CHAR) { /* char bit field type */
outc(CHAR,(int)bits_init);
bits_init = 0;
if (ISALLTYPE(type) != CHAR) /* returns 2 */
OUTEVEN();
else
return(1);
}
else { /* int/unsigned bit field type */
outc(INT,(int)bits_init);
bits_init = 0;
}
return(2);
}