/* asmequ.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 #include #include "asm86.h" #include "asmfcn.h" #include "asmctype.h" #include "asmmsg.h" /* EQU statement : There are 3 basic kinds of EQU: 1. To expression 2. To symbol( synonym ) 3. All others are text macros */ VOID PASCAL CODESIZE assignconst ( USHORT ); char isGolbal; /* flag indicating if equ symbol was global */ /*** assignvalue - assign value to symbol * * assignvalue (); * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE assignvalue () { struct eqar a; register struct psop *pso; register SYMBOL FARSYM *sym; register DSCREC *dsc; switchname (); if (createequ(EXPR)) { sym = symptr; sym->attr |= M_BACKREF; /* Set we have DEFINED */ dsc = (equflag)? itemptr: expreval (&nilseg); pso = &(dsc->dsckind.opnd); if (noexp) errorc (E_OPN); /* If error, set undefined */ if (errorcode && errorcode != E_RES) sym->attr &= ~(M_DEFINED | M_BACKREF); if (equflag && equdef) { if (sym->offset != pso->doffset || sym->symu.equ.equrec.expr.esign != pso->dsign || sym->symsegptr != pso->dsegment) muldef (); } /* If = involves forward, don't set BACKREF */ if (M_FORTYPE & pso->dtype){ sym->attr &= ~M_BACKREF; if (sym->attr & M_GLOBAL) sym->attr &= ~M_GLOBAL; } if (pso->mode != 4 && !(pso->mode == 0 && pso->rm == 6) && !(pso->mode == 5 && pso->rm == 5) || pso->dflag == XTERNAL) /* Not right kind of result */ errorc (E_IOT); sym->symsegptr = pso->dsegment; sym->symu.equ.equrec.expr.eassume = NULL; if (pso->dtype == M_CODE) sym->symu.equ.equrec.expr.eassume = pso->dcontext; sym->length = 0; sym->offset = pso->doffset; /* Note: change sign */ sym->symu.equ.equrec.expr.esign = pso->dsign; sym->symtype = pso->dsize; if ((pso->dtype == M_RCONST || !pso->dsegment) && !(M_PTRSIZE & pso->dtype)) sym->symtype = 0; if (fNeedList) { listbuffer[1] = '='; listindex = 3; if (sym->symu.equ.equrec.expr.esign) listbuffer[2] = '-'; offsetAscii (sym->offset); copyascii (); } dfree ((char *)dsc ); } } /*** createequ - create entry for equ * * flag = createequ (typ, p) * * Entry typ = type of equ * Exit * Returns TRUE if equ created or found of right type * FALSE if equ not created or found and wrong type * Calls labelcreate, switchname */ UCHAR PASCAL CODESIZE createequ ( UCHAR typ ){ equsel = typ; switchname (); labelcreate (0, EQU); /* Make sure not set set fields if wrong type, flag to caller */ if (symptr->symkind != EQU || symptr->symu.equ.equtyp != typ) { errorn (E_SDK); return (FALSE); } else { switchname (); isGolbal = 0; if (equsel == ALIAS){ /* lose public on pointer to alias */ isGolbal = symptr->attr & M_GLOBAL ? M_GLOBAL : 0; symptr->attr &= ~M_GLOBAL; } if (typ != EXPR) symptr->symsegptr = NULL; return (TRUE); } } /*** equtext - make remainder of line into text form of EQU * * equtext (); * * Entry * Exit * Returns * Calls error, skipblanks */ VOID PASCAL CODESIZE equtext ( USHORT cb ){ register UCHAR *pFirst, *pT, *pOld; if (createequ (TEXTMACRO)) { /* find end of line & then delete trailing blanks */ pFirst = lbufp; if (cb == ((USHORT)-1)) { for (pT = pFirst; *pT && *pT != ';'; pT++); for (; pT > pFirst && ISBLANK (pT[-1]) ; pT--); lbufp = pT; cb = (USHORT)(pT - pFirst); } pOld = symptr->symu.equ.equrec.txtmacro.equtext; pT = nalloc((USHORT)(cb+1), "equtext"); pT[cb] = NULL; symptr->symu.equ.equrec.txtmacro.equtext = (char *) memcpy(pT, pFirst, cb); if (pOld) free (pOld); copystring (pT); } } /*** equdefine - define EQU * * equdefine (); * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE equdefine () { register SYMBOL FARSYM *pSY; struct eqar a; register char *p; USHORT cb; UCHAR opc = FALSE; listbuffer[1] = '='; switchname (); a.dirscan = lbufp; if (PEEKC () == '<') { /* look for */ p = getTMstring(); a.dirscan = lbufp; lbufp = p; equtext ((USHORT)(a.dirscan - p - 1)); lbufp = a.dirscan; return; } getatom (); if ((*naim.pszName == '$') && (naim.pszName[1] == 0)) *naim.pszName = 0; /*Need to check if 1st atom is an operator, otherwise will make OFFSET an alias instead of text. */ if (fnoper ()) *naim.pszName = 0; if (*naim.pszName && ISTERM (PEEKC ()) && !(opc = opcodesearch ())) { /* Alias */ if (createequ (ALIAS)) { pSY = symptr; if (!symsrch ()) { if (pass2) /* Undefined */ errorn (E_SND); /* Don't know symbol yet */ pSY->symu.equ.equrec.alias.equptr = NULL; } else { /* Alias symbol is DEFINED */ pSY->attr = (unsigned char)(pSY->attr&~M_BACKREF | symptr->attr&M_BACKREF); if (!pSY->symu.equ.equrec.alias.equptr) pSY->symu.equ.equrec.alias.equptr = symptr; if (pSY->symu.equ.equrec.alias.equptr != symptr) { /* This is multiple definition */ symptr = pSY; muldef (); } else { /* See if good */ if (pSY = chasealias (pSY)) pSY->attr |= isGolbal; } } } } else { /* Must be text form or expr */ #ifdef BCBOPT goodlbufp = FALSE; #endif lbufp = a.dirscan; xcreflag--; emittext = FALSE; if (opc) { /* quick patch to allow i.e. SYM equ MOV */ equtext ((USHORT)-1); emittext = TRUE; xcreflag++; return; } a.dsc = expreval (&nilseg); emittext = TRUE; xcreflag++; /* So don't see double ref */ /* force text if OFFSET or : */ if (a.dsc->dsckind.opnd.mode != 4 && !(a.dsc->dsckind.opnd.mode == 0 && a.dsc->dsckind.opnd.rm == 6) && !(a.dsc->dsckind.opnd.mode == 5 && a.dsc->dsckind.opnd.rm == 5) || (errorcode && errorcode != E_SND && errorcode != E_RES) || (M_EXPLOFFSET|M_EXPLCOLON|M_HIGH|M_LOW) & a.dsc->dsckind.opnd.dtype || a.dsc->dsckind.opnd.seg != NOSEG || a.dsc->dsckind.opnd.dflag == XTERNAL) { /* Not good expression */ if (errorcode != E_LTL) errorcode = 0; dfree ((char *)a.dsc ); lbufp = a.dirscan; equtext ((USHORT)-1); } else { /* This is expression */ itemptr = a.dsc; switchname (); equflag = TRUE; assignvalue (); equflag = FALSE; } } } /*** definesym - define symbol from command line * * definesym (p); * * Entry *p = symbol text * Exit symbol define as EQU with value of 0 * Returns none * Calls */ void PASCAL definesym ( UCHAR *p ){ struct eqar a; fCheckRes++; fSkipList++; #ifdef BCBOPT goodlbufp = FALSE; #endif strcpy (lbufp = save, p); getatom (); if ((PEEKC() == 0 || PEEKC() == '=') && *naim.pszName) { if (PEEKC() == '=') SKIPC(); switchname (); equtext ((USHORT)-1); } else errorcode++; fSkipList--; fCheckRes--; } /*** defwordsize - define @WordSize using definesym() * * defwordsize ( ); * * Entry * Exit * Returns * Calls definesym() */ VOID PASCAL defwordsize () { static char wstext[] = "@WordSize=0D"; wstext[10] = wordsize + '0'; definesym(wstext); symptr->attr |= M_NOCREF; /* don't cref @WordSize */ } /*** chasealias - return value of alias list * * symb = chasealias (equsym); * * Entry * Exit * Returns * Calls */ SYMBOL FARSYM * PASCAL CODESIZE chasealias ( SYMBOL FARSYM *equsym ){ register SYMBOL FARSYM *endalias; endalias = equsym; do { /* Must check to see if EQU to self */ if (endalias->symu.equ.equrec.alias.equptr == equsym) { endalias->symu.equ.equrec.alias.equptr = NULL; errorc (E_CEA); return (NULL); } endalias = endalias->symu.equ.equrec.alias.equptr; if (!endalias) { errorn (E_SND); return(NULL); /* This is undefined */ } } while (!(endalias->symkind != EQU || endalias->symu.equ.equtyp != ALIAS)); /* Now check final is ok - Only constant allowed */ if (endalias->symkind == EQU && endalias->symu.equ.equtyp != EXPR){ errorc (E_IOT); return (NULL); } return (endalias); } /*** getTMstring - process a string or text macro * used by substring, catstring, sizestring, & instring * * char * getTMstring (); * * Entry lbufp points to beginning of string or TM * Exit * Returns Pointer to string or equtext of TM * Calls */ char * PASCAL CODESIZE getTMstring () { char cc; register char * p; static char tms [] = "text macro"; static char digitsT[33]; char * ret = NULL; skipblanks (); p = lbufp; if ((cc = *p) == '<' ) { ret = p + 1; while (*(++p) && (*p != '>')) ; if (!*p) error(E_EXP,tms); else *(p++) = 0; lbufp = p; } else if (test4TM()) { ret = symptr->symu.equ.equrec.txtmacro.equtext; } else if (cc == '%') { pTextEnd = (char *) -1; lbufp = p+1; *xxradixconvert (exprconst(), digitsT) = NULL; return (digitsT); } else error(E_EXP,tms ); return (ret); } /*** substring - process the subStr directive * * substring (); * * Syntax: * * subStr , {, } * * Defines as a TEXTMACRO. * must be a TEXTMACRO or a string: " ", < >, ' ' * : constant expression between 1 and strlen(subjectString) * Optional : constant expression between 0 and * (strlen(subjectString) - startIndex + 1) * * Entry lbufp points to beginning of subjectString * Exit * Returns * Calls getTMstring */ VOID PASCAL CODESIZE substring () { struct eqar a; char *p; register USHORT cb; char cc; register char *subjtext; USHORT slength; USHORT startindex = 0; listbuffer[1] = '='; switchname (); /* First find string or text macro */ if (!(subjtext = getTMstring () )) return; cb = (USHORT) strlen(subjtext); /* then check for start index */ if (skipblanks () == ',') { SKIPC (); startindex = (USHORT)(exprconst() - 1); /* get start index */ } else error(E_EXP,"comma"); /* then check for length */ if (skipblanks () == ',') { SKIPC (); slength = (USHORT)exprconst(); /* get start index */ } else slength = cb - startindex; if (startindex > cb || slength > cb - startindex) { errorc (E_VOR); return; } p = lbufp; lbufp = subjtext + startindex; /* set lbufp to start of substring */ equtext(slength); /* end of string index */ lbufp = p; if (errorcode && symptr) symptr->attr &= ~(M_DEFINED | M_BACKREF); } /*** catstring - process the catstr directive * * catstring (); * * Syntax: * * catStr {, } ... * * Defines as a TEXTMACRO. * Each must be a TEXTMACRO or a string: " ", < >, ' ' * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE catstring () { struct eqar a; register USHORT cb; char *subjtext; char resulttext[LBUFMAX]; USHORT cbresult = 0; register char *p = resulttext; listbuffer[1] = '='; switchname (); *p = '\0'; /* First find string or text macro */ do { if (!(subjtext = getTMstring () )) break; cb = (USHORT) strlen (subjtext); cbresult += cb; if(cbresult > LBUFMAX) { errorc(E_LTL); break; } memcpy (p, subjtext, cb + 1); /* + 1 copies NULL */ p += cb; } while (skipblanks() && NEXTC () == ','); p = --lbufp; lbufp = resulttext; equtext(cbresult); lbufp = p; if (errorcode) symptr->attr &= ~(M_DEFINED | M_BACKREF); } /*** assignconst - like assignvalue, only takes value as argument * * assignconst (cb); * * Entry USHORT cb == value to assign * Exit * Returns * Calls */ VOID PASCAL CODESIZE assignconst ( USHORT cb ){ register SYMBOL FARSYM *sym; struct eqar a; if (createequ(EXPR)) { sym = symptr; if (errorcode) sym->attr &= ~(M_DEFINED | M_BACKREF); else sym->attr |= M_BACKREF; /* Set we have DEFINED */ sym->symsegptr = NULL; sym->symu.equ.equrec.expr.eassume = NULL; sym->length = 0; sym->offset = cb; sym->symu.equ.equrec.expr.esign = 0; sym->symtype = 0; if (fNeedList) { listbuffer[1] = '='; listindex = 3; offsetAscii (sym->offset); copyascii (); } } } /*** sizestring - process the sizeStr directive * * sizestring (); * * Syntax: * * sizeStr * * Defines as a EXPR. * The must be a TEXTMACRO or a string: " ", < >, ' ' * * Entry * Exit * Returns * Calls */ VOID PASCAL CODESIZE sizestring () { register USHORT cb = 0; char *p; switchname (); /* First find string or text macro */ if (p = getTMstring () ) cb = (USHORT) strlen (p); assignconst (cb); } /*** instring - process the instr directive * * instring (); * * Syntax: * * inStr { } , , * * Defines as a TEXTMACRO. * : constant expression between 1 and strlen(subjectString) * must be a TEXTMACRO or a string: " ", < >, ' ' * must be a TEXTMACRO or a string: " ", < >, ' ' * * Entry lbufp points to beginning of subjectString * Exit * Returns * Calls getTMstring */ //char * strstr(); VOID PASCAL CODESIZE instring () { register char *p; register USHORT cb = 0; register char cc; char *subjtext; char *searchtext; USHORT startindex = 1; switchname (); /* First find start index */ p = lbufp; if ((cc = *p) != '"' && cc != '\'' && cc != '<' && !test4TM ()) { lbufp = p; startindex = (USHORT)exprconst(); /* get start index */ if (lbufp != p) if (skipblanks () == ',') SKIPC (); else error(E_EXP,"comma"); } else lbufp = p; if (subjtext = getTMstring () ) { cb = (USHORT) strlen(subjtext); if (startindex < 1 || startindex > cb) errorc (E_VOR); if (skipblanks () == ',') SKIPC (); else error(E_EXP,"comma"); /* then check for searchtext */ if (searchtext = getTMstring () ) { p = subjtext + startindex - 1; if (p = strstr (p, searchtext)) cb = (USHORT)(p - subjtext + 1); else cb = 0; } } assignconst (cb); }