diff options
Diffstat (limited to 'private/sdktools/masm/asmequ.c')
-rw-r--r-- | private/sdktools/masm/asmequ.c | 829 |
1 files changed, 829 insertions, 0 deletions
diff --git a/private/sdktools/masm/asmequ.c b/private/sdktools/masm/asmequ.c new file mode 100644 index 000000000..e122d9668 --- /dev/null +++ b/private/sdktools/masm/asmequ.c @@ -0,0 +1,829 @@ +/* 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 <stdio.h> +#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; + 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 = 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 <text macro> */ + + 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 = 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: + * + * <ident> subStr <subjectString> , <startIndex> {, <length> } + * + * Defines <ident> as a TEXTMACRO. + * <subjectString> must be a TEXTMACRO or a string: " ", < >, ' ' + * <startIndex>: constant expression between 1 and strlen(subjectString) + * Optional <length>: 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 = strlen(subjtext); + + /* then check for start index */ + + if (skipblanks () == ',') { + SKIPC (); + startindex = exprconst() - 1; /* get start index */ + + } else + error(E_EXP,"comma"); + + + /* then check for length */ + + if (skipblanks () == ',') { + SKIPC (); + + slength = 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: + * + * <ident> catStr <subjectString> {, <subjectString> } ... + * + * Defines <ident> as a TEXTMACRO. + * Each <subjectString> 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 = 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: + * + * <ident> sizeStr <subjectString> + * + * Defines <ident> as a EXPR. + * The <subjectString> 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 = strlen (p); + + assignconst (cb); +} + + + +/*** instring - process the instr directive + * + * instring (); + * + * Syntax: + * + * <ident> inStr { <startIndex> } , <subjectString> , <searchString> + * + * Defines <ident> as a TEXTMACRO. + * <startIndex>: constant expression between 1 and strlen(subjectString) + * <subjectString> must be a TEXTMACRO or a string: " ", < >, ' ' + * <searchString> 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 = exprconst(); /* get start index */ + + if (lbufp != p) + if (skipblanks () == ',') + SKIPC (); + else + error(E_EXP,"comma"); + + } else + lbufp = p; + + if (subjtext = getTMstring () ) { + + cb = 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 = p - subjtext + 1; + else + cb = 0; + } + } + + assignconst (cb); +} |