windows-nt/Source/XPSP1/NT/sdktools/masm/asmdata.c
2020-09-26 16:20:57 +08:00

1320 lines
24 KiB
C

/* asmdata.c -- microsoft 80x86 assembler
**
** microsoft (r) macro assembler
** copyright (c) microsoft corp 1986. all rights reserved
**
** randy nevin
**
** 10/90 - Quick conversion to 32 bit by Jeff Spencer
*/
#include <stdio.h>
#include <string.h>
#include "asm86.h"
#include "asmfcn.h"
#include <ctype.h>
#include "asmindex.h"
#include "asmctype.h"
#include "asmmsg.h"
extern UCHAR mpRealType[];
/* Dup tree is organized left to right horizonatally for each
item in a DUP list at the same level( i. e. 5 DUP(1,2,3) ).
This is considered the 'list' part. Any item in the list
may be another DUP header instead of a data entry, in
which case you go down a level and have another list.
*/
char uninitialized[10];
char fInDup;
/*** scanstruc - scan structure tree and execute function
*
* scanstruc (dupr, disp);
*
* Entry *dupr = duprec structure entry
* disp = pointer to function to execute at each node
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
scanstruc (
struct duprec FARSYM *dupr,
VOID (PASCAL CODESIZE *disp) (struct duprec FARSYM *)
){
struct duprec FARSYM *ptr;
struct duprec FARSYM *iptr;
struct duprec FARSYM *fldptr;
struct duprec FARSYM *initptr;
OFFSET strucpc;
/* save starting address of structure */
strucpc = pcoffset;
if (dupr)
/* Output <n> DUP( */
(*disp) (dupr);
/* 1st default value for STRUC */
fldptr = recptr->symu.rsmsym.rsmtype.rsmstruc.strucbody->duptype.dupnext.dup;
/* 1st initialize value */
initptr = strucoveride;
if (initptr) {
/* process initialization fields for structure */
while (fldptr) {
if (fldptr->itemcnt == 1 && fldptr->duptype.dupnext.dup->itemcnt == 0
&& initptr->duptype.dupitem.ddata)
/* Use default */
ptr = initptr;
else
/* Can't override field */
ptr = fldptr;
iptr = ptr->itemlst;
ptr->itemlst = NULL;
if (displayflag && !dupr) {
offsetAscii (strucpc);
listindex = 1;
/* Display PC */
copyascii ();
listindex = LSTDATA;
if (highWord(strucpc))
listindex += 4;
}
if (ptr->rptcnt > 1 || ptr->itemcnt > 1)
/* Output <n> DUP( */
(*disp) (ptr);
/* Display field */
scanlist (ptr, disp);
if (ptr->rptcnt > 1 || ptr->itemcnt > 1)
enddupdisplay ();
if (displayflag && !dupr) {
/* Calc size of field */
clausesize = calcsize (ptr);
if (dupr)
clausesize *= dupr->rptcnt;
strucpc += clausesize;
}
/* Restore */
ptr->itemlst = iptr;
if (displayflag && (listbuffer[LSTDATA] != ' ' ||
listbuffer[14] != ' ')) {
resetobjidx ();
}
/* Advance default field */
fldptr = fldptr->itemlst;
/* Advance override field */
initptr = initptr->itemlst;
}
}
if (dupr)
enddupdisplay ();
}
/*** scandup - scan DUP tree and execute function
*
* scandup (tree, disp);
*
* Entry *tree = DUP tree
* *disp = function to execute at each node of tree
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
scandup (
struct duprec FARSYM *tree,
VOID (PASCAL CODESIZE *disp)(struct duprec FARSYM *)
){
if (tree)
if (strucflag && initflag)
/* Want to skip STRUC heading */
if (tree == recptr->symu.rsmsym.rsmtype.rsmstruc.strucbody)
/* This is not <n> DUP(<>) So no DUP prefix */
scanstruc ((struct duprec FARSYM *)NULL, disp);
else { /* must set itemcnt in DUP to # fields */
tree->itemcnt = recptr->symu.rsmsym.rsmtype.rsmstruc.strucfldnum;
scanstruc (tree, disp);
}
else /* Else is not STRUC */
scanlist (tree, disp);
}
/*** oblitdup - delete DUP entry
*
* oblitdup (node);
*
* Entry *node = DUP entry
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
oblitdup (
struct duprec FARSYM *node
){
switch (node->dupkind) {
case NEST:
_ffree ((char FARSYM *)node);
break;
case ITEM:
if (node->duptype.dupitem.ddata)
dfree ((char *)node->duptype.dupitem.ddata );
_ffree ((char FARSYM *)node);
break;
case LONG:
if (node->duptype.duplong.ldata != uninitialized)
free ((char *)node->duptype.duplong.ldata);
_ffree ((char FARSYM *)node);
break;
default:
TERMINATE(ER_FAT, 99);
}
}
/*** displlong - display long constant
*
* displaylong (dup);
*
* Entry *dup = dup entry
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
displlong (
struct duprec FARSYM *dup
){
register USHORT cnt;
register char *p;
p = dup->duptype.duplong.ldata;
for (cnt = dup->duptype.duplong.llen; cnt; cnt--) {
if (optyp == TDW || optyp == TDD)
emitopcode ((UCHAR)p[cnt-1]);
else
emitopcode ((UCHAR)*p++);
if (optyp != TDB)
listindex--;
}
if (optyp != TDB)
listindex++;
}
/*** begdupdisplay - begin DUP display
*
* begdupdisplay (dup);
*
* Entry *dup = DUP entry
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
begdupdisplay (
struct duprec FARSYM *dup
){
/* flush line if data already displayed */
if ((highWord(pcoffset) && listbuffer[LSTDATA+3] != ' ') ||
listbuffer[LSTDATA] != ' ')
resetobjidx ();
listindex = LSTDATA + duplevel; /* Indent for DUP clause */
if (highWord(pcoffset))
listindex += 4;
offsetAscii (dup->rptcnt); /* display repeat count in four bytes */
copyascii ();
listbuffer[listindex] = '[';
duplevel++; /* Indent another level */
resetobjidx (); /* Display DUP repeat line */
}
/*** enddupdisplay - end DUP display
*
* enddupdisplay ();
*
* Entry
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
enddupdisplay (
){
if (duplevel) {
duplevel--;
if (displayflag) {
listbuffer[LSTMAX - ((duplevel <= 8)? duplevel: 8)] = ']';
resetobjidx ();
}
}
}
/*** itemdisplay - display DUP data item
*
* itemdisplay (dup);
*
* Entry *dup = dup record
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
itemdisplay (
struct duprec FARSYM *dup
){
if (listindex > LSTMAX)
resetobjidx ();
if (dup->dupkind == ITEM)
emitOP (&dup->duptype.dupitem.ddata->dsckind.opnd);
else
displlong (dup);
if (duplevel)
resetobjidx ();
}
/*** dupdisplay - display DUP item on listing
*
* dupdisplay (ptr);
*
* Entry *ptr = DUP entry
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
dupdisplay (
struct duprec FARSYM *ptr
){
if (ptr->dupkind == NEST)
begdupdisplay (ptr);
else
itemdisplay (ptr);
}
/*** linkfield - add item to list of DUP for current STRUC
*
* linkfield (nitem);
*
* Entry
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
linkfield (
struct duprec FARSYM *nitem
){
struct duprec FARSYM *ptr;
if (strucprev->itemcnt++ == 0)/* 1st item in field */
strucprev->duptype.dupnext.dup = nitem;
else {
ptr = strucprev->duptype.dupnext.dup;
while (ptr->itemlst)
ptr = ptr->itemlst;
/* Add to end of list */
ptr->itemlst = nitem;
}
}
/*** longeval - evaluate long non-floating point, non-BCD constant
*
* longeval (base, p);
*
* Entry delim = delimiter character
* Exit
* Returns
* Calls
*/
#if !defined FLATMODEL
# pragma alloc_text (FA_TEXT, longeval)
#endif
VOID PASCAL
longeval (
USHORT base,
register struct realrec *p
){
register char cc;
char sign;
USHORT carry;
USHORT t;
USHORT i;
sign = ((cc = NEXTC ()) == '-')? TRUE: FALSE;
if (ISSIGN (cc))
cc = MAP (NEXTC ());
do {
if ((t = (cc - '0') - ('A' <= cc) * ('A' - '0' - 10)) >= base)
ferrorc (E_NDN);
carry = (t += p->num[0] * base) >> 8;
p->num[0] = t & 255;
for (i = 1; i < 10; i++) {
carry = (t = p->num[i] * base + carry) >> 8;
p->num[i] = t & 255;
}
if (carry)
/* Overflow */
ferrorc (E_DVZ);
} while ((cc = MAP (NEXTC ())) != delim);
if (cc == 0)
BACKC ();
if (sign) {
carry = 1;
for (i = 0; i < 10; i++) {
p->num[i] = (unsigned char)((t = (~p->num[i] & 0xff) + carry));
carry = t >> 8;
}
if (datadsize[optyp - TDB] < i && carry)
ferrorc (E_DVZ);
}
}
/*** bcddigit - evaluate bcd digit
*
* bcddigit (p);
*
* Entry
* Exit
* Returns
* Calls
*/
#if !defined FLATMODEL
# pragma alloc_text (FA_TEXT, bcddigit)
#endif
VOID PASCAL
bcddigit (
struct realrec *p
){
USHORT v;
register char cc;
v = (cc = NEXTC ()) - '0';
if (!isdigit (cc))
ferrorc (E_NDN);
if (isdigit (PEEKC ()))
bcddigit (p);
if (p->i & 1)
v <<= 4;
p->num[p->i / 2 ] = p->num[p->i / 2 ] + v;
if (p->i < 18)
p->i++;
}
/*** bcdeval - evaluate bcd constant
*
* bcdval (p);
*
* Entry
* Exit
* Returns
* Calls
* Note BCD numbers come out low digit 1st
*/
#if !defined FLATMODEL
# pragma alloc_text (FA_TEXT, bcdeval)
#endif
VOID PASCAL
bcdeval (
struct realrec *p
){
register char cc;
p->num[9] = ((cc = PEEKC ()) == '-')? 0x80: 0;
p->i = 0;
if (ISSIGN (cc))
SKIPC ();
bcddigit (p);
if (p->num[9] & 15)
ferrorc (E_DVZ);
}
/*** parselong - parse long constant
*
* parselong (p);
*
* Entry *p = data descriptor entry
* Exit p->longstr = TRUE if long data entry parsed
* Returns
* Calls
*/
VOID PASCAL CODESIZE
parselong (
register struct dsr *p
){
struct realrec a;
register UCHAR *cp;
register UCHAR cc;
register USHORT rbase;
register char expflag;
SHORT cb;
char dseen = 0;
char fNonZero;
char fSigned = FALSE;
if (ISBLANK (PEEKC ()))
skipblanks ();
p->dirscan = lbufp;
if (ISSIGN(cc = (NEXTC ()))) {
fSigned++;
cc = NEXTC ();
}
if (isdigit (cc) || (cc == '.')) {
/* Some numeric constant */
p->floatflag = (cc == '.');
expflag = FALSE;
do {
if ((cc = MAP (NEXTC ())) == 'E')
expflag = TRUE;
if (cc == '.')
p->floatflag = TRUE;
} while (isxdigit (cc) || isalpha (cc) ||
(expflag && ISSIGN (cc)) || cc == '.');
/* save address of end of string and check delimiter */
BACKC ();
cp = lbufp;
p->longstr = ISTERM (cc = skipblanks ()) || cc == ',' ||
cc == ')' || cc == '>';
lbufp = cp;
}
cb = datadsize[optyp - TDB];
if (p->longstr) {
memset(a.num, 0, 10);
BACKC ();
switch (delim = MAP (NEXTC ())) {
case 'B':
rbase = 2;
break;
case 'D':
rbase = 10;
dseen++;
break;
case 'H':
rbase = 16;
break;
case 'O':
case 'Q':
rbase = 8;
break;
case 'R':
/* check width of real constant */
rbase = (unsigned short)(lbufp - p->dirscan - 1);
if (*(p->dirscan) == '0')
rbase--;
if (rbase != cb*2)
errorc (E_IIS);
rbase = 16;
p->floatflag = TRUE;
break;
default:
delim = PEEKC ();
if (radixescape)
rbase = 10;
else {
rbase = radix;
if (p->floatflag)
rbase = 10;
else if (radix == 10 && expflag)
p->floatflag = TRUE;
}
break;
}
lbufp = p->dirscan;
if (p->floatflag && rbase != 16)
realeval (&a);
else if (rbase) {
if (rbase == 10 && optyp == TDT && !dseen)
bcdeval (&a);
else {
longeval (rbase, &a);
if (delim == '>' || delim == ')' || delim ==',')
BACKC ();
}
}
p->dupdsc =
(struct duprec FARSYM *) falloc( sizeof(*p->dupdsc), "parselong");
p->dupdsc->dupkind = LONG;
p->dupdsc->duptype.duplong.llen = (unsigned char)cb;
p->dupdsc->type = typeFet(cb);
if (fSigned)
p->dupdsc->type &= ~(BT_UNSIGNED << 2);
if (p->floatflag)
p->dupdsc->type = mpRealType[cb];
cp = nalloc( cb, "parselong");
p->dupdsc->duptype.duplong.ldata = cp;
for (a.i = 0; a.i < cb; a.i++)
*cp++ = a.num[a.i];
/* size check if something less the max allowable # */
if (cb != 10) {
fNonZero = FALSE;
for (cp = a.num,cc = 0; cc < cb; cc++, cp++)
fNonZero |= *cp;
/* Check for value that has overflowed the defined
data types length or values that are entirly
greater then the length - ie dw 0F0000H */
for (; cc < 10; cc++, cp++)
/* == 0xFF passes sign extended negative #'s */
if (*cp &&
(*cp != 0xFF || !fNonZero))
errorc (E_DVZ);
}
}
else
/* reset character pointer to allow rescan of line */
lbufp = p->dirscan;
}
/*** datadup - function
*
* datadup ();
*
* Entry
* Exit
* Returns
* Calls
*/
struct duprec FARSYM * PASCAL CODESIZE
datadup (
struct dsr *p
){
register char cc;
register struct psop *pso;
struct duprec FARSYM *dupptr;
struct duprec FARSYM *listend;
struct duprec FARSYM *dupdsc;
struct datarec drT;
/* dup count must be constant and not forward reference */
fInDup = TRUE;
forceimmed (p->valrec);
errorforward (p->valrec);
pso = &(p->valrec->dsckind.opnd);
if (pso->dsign || pso->doffset == 0) {
/* force repeat count to be > 0 */
pso->doffset = 1;
errorc (E_IDV);
}
dupptr = (struct duprec FARSYM *) falloc (sizeof (*dupptr), "datadup");
/* No items in DUP list */
dupptr->itemcnt = 0;
dupptr->type = 0;
dupptr->dupkind = NEST;
dupptr->itemlst = NULL;
dupptr->duptype.dupnext.dup = NULL;
/* copy repeat count and release parse stack descriptor */
dupptr->rptcnt = pso->doffset;
dfree ((char *)p->valrec );
listend = NULL;
if (ISBLANK (PEEKC ()))
skipblanks ();
if ((cc = NEXTC ()) != '(') {
error (E_EXP,"(");
BACKC ();
}
/* Now parse DUP list */
do {
dupdsc = datascan (&drT);
if (! dupptr->type)
dupptr->type = dupdsc->type;
if (!listend)
dupptr->duptype.dupnext.dup = dupdsc;
else
listend->itemlst = dupdsc;
listend = dupdsc;
dupptr->itemcnt++;
if (ISBLANK (PEEKC ()))
skipblanks ();
if ((cc = PEEKC ()) == ',')
SKIPC ();
else if (cc != ')') {
error (E_EXP,")");
if (!ISTERM(cc))
*lbufp = ' ';
}
} while ((cc != ')') && !ISTERM (cc));
if (ISTERM (cc))
error (E_EXP,")");
else
SKIPC ();
fInDup = FALSE;
return (dupptr);
}
/*** datacon - data constant not string
*
* datacon (p);
*
* Entry *p = parse stack entry
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
datacon (
struct dsr *p
){
register struct psop *psor;
/* See if expr or DUP */
/* Not <n> DUP() */
p->flag = FALSE;
if (initflag && (PEEKC () == '<'))
initrs (p);
else {
/* Not initialize list */
p->dirscan = lbufp;
p->valrec = expreval (&nilseg);
psor = &(p->valrec->dsckind.opnd);
if (strucflag && !initflag &&
(psor->dflag == FORREF || psor->dflag == UNDEFINED))
/* Forward in struc body */
errorc (E_IFR);
if (psor->mode !=4 && !isdirect(psor))
errorc (E_IOT);
if (psor->seg != NOSEG)
errorc (E_IOT);
if (dupflag) {
/* Have DUP operator */
getatom ();
p->flag = TRUE;
}
else if (strucflag && initflag && !p->initlist) {
lbufp = p->dirscan;
symptr = recptr;
p->dupdsc = strucparse ();
p->initlist = TRUE;
}
}
if (p->flag)
p->dupdsc = datadup (p);
else {
if (!p->initlist || !initflag)
subr1 (p);
}
}
/*** subr1 -
*
* subr1 (p);
*
* Entry
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
subr1 (
struct dsr *p
){
USHORT i;
register struct psop *psor;
char *cp;
long l;
psor = &(p->valrec->dsckind.opnd);
if (fSimpleSeg)
makeGrpRel (psor);
/* Not init list */
if (optyp == TDB)
valuecheck (&psor->doffset, 0xff);
else if (optyp == TDW)
valuecheck (&psor->doffset, (USHORT)0xffff);
if ((optyp != TDW) && (optyp != TDD) && optyp != TDF) {
if ((psor->mode != 3) && (psor->mode != 4))
errorc (E_CXP);
psor->mode = 4;
psor->w = FALSE;
psor->fixtype = FCONSTANT;
}
if (initflag)
errorc (E_OIL);
p->dupdsc = (struct duprec FARSYM *) falloc (sizeof(*p->dupdsc), "subr1");
if (!(fInDup && psor->dflag == INDETER) &&
!(psor->dsegment || psor->dflag == XTERNAL)) {
p->dupdsc->dupkind = LONG;
psor->dsize = p->dupdsc->duptype.duplong.llen = (unsigned char)(datadsize[optyp - TDB]);
p->dupdsc->type = typeFet(psor->dsize);
if (ISSIGN(*p->dirscan))
p->dupdsc->type &= ~(BT_UNSIGNED << 2);
if (psor->dflag == INDETER || psor->doffset == 0) {
p->dupdsc->duptype.duplong.ldata = uninitialized;
}
else {
cp = nalloc (p->dupdsc->duptype.duplong.llen, "subr1");
p->dupdsc->duptype.duplong.ldata = cp;
if (psor->dsign && psor->doffset)
psor->doffset = ~psor->doffset + 1;
l = psor->doffset;
for (i = 0; i < p->dupdsc->duptype.duplong.llen; i++){
*cp++ = (char)l;
l >>= 8;
}
}
dfree ((char *)p->valrec );
}
else {
if (psor->mode != 4 && !isdirect(psor))
/* Immediate or direct only */
errorc (E_IOT);
if ((psor->fixtype == FGROUPSEG || psor->fixtype == FOFFSET) &&
((optyp == TDD && wordsize == 2 && !(psor->dtype&M_EXPLOFFSET)) ||
optyp == TDF))
psor->fixtype = FPOINTER;
/* Size of item */
varsize = (unsigned short)psor->dsize;
psor->dsize = datadsize[optyp - TDB];
/* If item size is byte, make link output byte too */
psor->w = TRUE;
if (psor->dsize == 1) {
psor->w--;
if (psor->fixtype != FHIGH &&
(psor->dflag == XTERNAL || psor->dsegment ||
psor->dcontext))
psor->fixtype = FLOW;
}
mapFixup(psor);
*naim.pszName = NULL;
if (psor->fixtype == FCONSTANT)
p->dupdsc->type = typeFet(psor->dsize);
else
p->dupdsc->type = fnPtr(psor->dsize);
p->dupdsc->dupkind = ITEM;
p->dupdsc->duptype.dupitem.ddata = p->valrec;
}
}
/*** initrs - initialize record/structure
*
* initrs (p);
*
* Entry
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
initrs (
struct dsr *p
){
register char *cp;
SHORT cb;
/* Initializing RECORD/STRUC */
symptr = recptr;
if (strucflag)
p->dupdsc = strucparse ();
else {
/* Get value of record */
p->i = recordparse ();
/* Make long constant */
p->dupdsc =
(struct duprec FARSYM *)falloc (sizeof (*p->dupdsc), "initrs");
p->dupdsc->dupkind = LONG;
cb = recptr->symtype;
p->dupdsc->duptype.duplong.llen = (unsigned char) cb;
cp = nalloc (cb, "initrs");
p->dupdsc->duptype.duplong.ldata = cp;
p->dupdsc->type = typeFet(cb);
while(cb--){
*cp++ = (char)p->i;
p->i >>= 8;
}
}
p->initlist = TRUE;
}
/*** datadb - process <db> directive
*
* datadb ();
*
* Entry *lbufp = beginning quote (\'|\") of string
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
datadb (
register struct dsr *p
){
register USHORT i;
register char *cp;
/* Save ptr to start of string */
p->dirscan = lbufp;
delim = NEXTC ();
/* Compute string length */
i = 0;
while (!endstring ()) {
SKIPC ();
i++;
}
/* reset scan pointer */
lbufp = p->dirscan;
if (i == 0)
errorc (E_EMS);
else if (i > 1) {
SKIPC ();
/* Long string */
p->longstr = TRUE;
/* Create entry for long string */
p->dupdsc =
(struct duprec FARSYM *)falloc (sizeof (*p->dupdsc), "datadb");
/* Initialize text area for data */
p->dupdsc->dupkind = LONG;
p->dupdsc->type = makeType(BT_ASCII, BT_DIRECT, BT_sz1);
p->dupdsc->duptype.duplong.llen = (unsigned char)i;
cp = nalloc ( (USHORT)(p->dupdsc->duptype.duplong.llen + 1), "datadb");
p->dupdsc->duptype.duplong.ldata = cp;
for (; i; i--)
if (!endstring ())
*cp++ = NEXTC ();
*cp = 0;
SKIPC ();
}
}
/*** dataitem - parse next data item from line
*
* dataitem (p);
*
* Entry p = pointer to datarec structure
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
dataitem (
struct datarec *p
){
struct duprec FARSYM *topitem;
/* Scan , may recurse on DUP */
topitem = datascan (p);
/* Display scan now */
displayflag = TRUE;
/* Display data */
scandup (topitem, dupdisplay);
displayflag = FALSE;
if (p->datalen == 0)
p->datalen = topitem->rptcnt;
if (topitem->dupkind == NEST) {
/* This item was a DUP */
resvspace = TRUE;
/* Get size of DUP list */
clausesize = calcsize (topitem);
if (strucflag && initflag)
resvspace = FALSE;
if (pass2 && !(resvspace || p->buildfield))
/* Send to linker */
if (!emitdup (topitem))
errorc (E_DTL);
if (! p->type)
p->type = topitem->type;
if (p->buildfield)
linkfield (topitem);
else if (strucflag && initflag) {
/* Allocating STRUC */
strucflag = FALSE;
/* Free overrides */
scandup (strucoveride, oblitdup);
/* Turn back on */
strucflag = TRUE;
}
else /* Not STRUC allocate */
scandup (topitem, oblitdup);
}
else {
/* Some kind of list */
clausesize = (topitem->dupkind == ITEM)
? topitem->duptype.dupitem.ddata->dsckind.opnd.dsize
: topitem->duptype.duplong.llen;
if (pass2 && !p->buildfield) {
if (topitem->dupkind == ITEM)
emitobject (&topitem->duptype.dupitem.ddata->dsckind.opnd);
else
emitlong (topitem);
}
if (! p->type)
p->type = topitem->type;
if (p->buildfield)
linkfield (topitem);
else
oblitdup (topitem);
}
/* Add in size of this item */
pcoffset += clausesize;
skipblanks ();
}
/*** datadefine -
*
* datadefine ();
*
* Entry
* Exit
* Returns
* Calls
*/
VOID PASCAL CODESIZE
datadefine (
){
struct datarec a;
short cc;
strucoveride = NULL;
a.buildfield = (strucflag && !initflag)? TRUE: FALSE;
a.type = 0;
if (labelflag) { /* Have label */
labelcreate ( (USHORT)2, (UCHAR) (a.buildfield ? (UCHAR) STRUCFIELD : (UCHAR) CLABEL));
if (errorcode == (E_ERRMASK & E_SDK))
return;
if (strucflag && initflag){
a.type = recptr->symu.rsmsym.rsmtype.rsmstruc.type;
}
}
else
pcdisplay ();
a.labelptr = symptr; /* Save ptr to entry */
a.datalen = 0; /* Don't know length */
emittext = FALSE; /* Prevent link emitter */
duplevel = 0;
/* Scan item list */
if (ISTERM (PEEKC ()))
errorc (E_OPN);
else {
BACKC ();
do {
SKIPC ();
if ((cc = skipblanks ()) == ',' || cc == ';' || ISTERM(cc))
errorc(E_MDZ);
dataitem (&a);
} while (PEEKC () == ',');
}
if (labelflag) {
a.labelptr->symtype = datadsize[optyp - TDB];
if (a.buildfield) {
/* Making STRUC body */
if (a.labelptr->symkind == STRUCFIELD) {
if (struclabel)
struclabel->symu.struk.strucnxt = a.labelptr;
else
recptr->symu.rsmsym.rsmtype.rsmstruc.struclist = a.labelptr;
/* Constant, no segment */
a.labelptr->symsegptr = NULL;
/* End of named list */
a.labelptr->symu.struk.strucnxt = NULL;
a.labelptr->symu.struk.type = a.type;
struclabel = a.labelptr;
}
}
else
a.labelptr->symu.clabel.type = a.type;
/* Set length */
a.labelptr->length = (unsigned short)a.datalen;
}
emittext = TRUE;
}
/*** commDefine - define a communal variable
*
* Format: comm {far|near} name:size[:#Ofitems],....
*
*/
VOID PASCAL CODESIZE
commDefine (
){
USHORT distance;
char cT, *pT;
USHORT symtype;
SYMBOL FARSYM *pSY;
getatom ();
distance = (farData[10] > '0')? CSFAR: CSNEAR;
if (fnsize ()){ /* look for optional near | far */
distance = varsize;
getatom ();
if (distance < CSFAR)
errorc (E_UST);
}
cT = symFet (); /* fetch name and save for later */
pSY = symptr;
if (*naim.pszName == NULL){
errorc(E_OPN);
return;
}
if (NEXTC() != ':')
errorc (E_SYN);
/* get the size of the item */
pT = lbufp;
switchname ();
getatom();
if (symFet() && symptr->symkind == STRUC){
varsize = symptr->symtype;
}
else {
lbufp = pT;
if (pT = (char *)strchr(pT, ':'))
*pT = NULL;
varsize = (USHORT)exprconst();
if (pT)
*pT = ':';
}
if (!varsize)
errorc(E_IIS &~E_WARN1);
if (cT)
symptr = pSY;
externflag (DVAR, cT);
pSY = symptr;
pSY->symu.ext.length = 1;
pSY->symu.ext.commFlag++;
if (skipblanks() == ':'){ /* optional size given */
fArth32++; /* allow >64 items */
SKIPC();
if ((pSY->symu.ext.length = exprconst()) == 0) /* get the # items */
errorc(E_CXP);
fArth32--;
if (pSY->symu.ext.length * pSY->symtype > 0xffff)
pSY->symu.ext.commFlag++; /* for >64K convert to far */
}
if (distance == CSFAR)
pSY->symu.ext.commFlag++; /* 2 means far commdef */
}