From e611b132f9b8abe35b362e5870b74bce94a1e58e Mon Sep 17 00:00:00 2001 From: Adam Date: Sat, 16 May 2020 20:51:50 -0700 Subject: initial commit --- private/sdktools/masm/asmirp.c | 1039 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1039 insertions(+) create mode 100644 private/sdktools/masm/asmirp.c (limited to 'private/sdktools/masm/asmirp.c') diff --git a/private/sdktools/masm/asmirp.c b/private/sdktools/masm/asmirp.c new file mode 100644 index 000000000..6ff593c1b --- /dev/null +++ b/private/sdktools/masm/asmirp.c @@ -0,0 +1,1039 @@ +/* asmirp.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 "asm86.h" +#include "asmfcn.h" +#include "asmctype.h" +#include + +#define DMYBASE 0x80 + +#define nextCH() {*pText=cbText; pText = pTextCur++; cbText = 0;} +#define storeCH(c) {if (cbText>0x7f) nextCH() *pTextCur++=c; cbText++;} + +char * PASCAL CODESIZE growParm( char * ); + +/*** irpxdir - process and directives + * + * irpxdir (); + * + * Entry + * Exit + * Returns + * Calls + * Note Format is + * IRPC , text | + * IRP , + */ + +VOID PASCAL CODESIZE +irpxdir () +{ + register short cc; /* CHAR */ + USHORT bracklevel; + char littext; + register char *pT; + char *pParmName; + + + createMC (1); /* Make IRPC param block */ + scandummy (); /* Scan our only dummy param */ + + if (NEXTC () != ','){ + error (E_EXP,"comma"); + return; + } + + pMCur->cbParms = strlen(lbufp) << 1; + pT = nalloc(pMCur->cbParms, "irpxdir: actuals"); + + *pT = NULL; + pMCur->rgPV[0].pActual = pMCur->pParmAct = pT; + + pParmName = pMCur->pParmNames; + pMCur->pParmNames = pT; + + bracklevel = 0; + + if (littext = (skipblanks () == '<')) { + + SKIPC (); + bracklevel = 1; + } + + if (optyp == TIRP) { + + if (!littext) + error (E_EXP,"<"); /* Must have < */ + + + if (skipblanks () != '>') { + + BACKC (); + do { + SKIPC (); + scanparam (TRUE); + } while (skipblanks () == ','); + + } + if (NEXTC () != '>') + error (E_EXP,">"); + } + else { + while (cc = NEXTC ()) { + + if (littext) { + /* Only stop on > */ + + if (cc == '<'){ + bracklevel++; + continue; + } + else if (cc == '>'){ + + if (--bracklevel == 0) + break; + + continue; + } + } + else if (ISBLANK (cc) || ISTERM (cc)) { + + BACKC (); + break; + } + *pT++ = 1; /* arg of length 1 */ + *pT++ = cc; /* and the arg */ + + pMCur->count++; + } + *pT = NULL; + } + if (PEEKC () == '>' && littext) + SKIPC (); + + swaphandler = TRUE; + handler = HIRPX; + blocklevel = 1; + pMCur->count--; /* don't count arg in repeat count */ + pMCur->pParmNames = pParmName; + pMCur->iLocal++; + pMCur->svlastcondon = lastcondon; + pMCur->svcondlevel = condlevel; + pMCur->svelseflag = elseflag; +} + +/*** reptdir - process repeat directive + * + * reptdir (); + * + * Entry + * Exit + * Returns + * Calls + */ + + +VOID PASCAL CODESIZE +reptdir () +{ + char sign; + + createMC (1); + pMCur->count = exprsmag (&sign); + + if (sign) + errorc (E_VOR); + if (errorcode) + pMCur->count = 0; + + swaphandler = TRUE; + handler = HIRPX; + blocklevel = 1; + pMCur->svcondlevel = condlevel; + pMCur->svlastcondon = lastcondon; + pMCur->svelseflag = elseflag; +} + + + +/*** irpxbuild - build text for IRP/IRPC block + * + * irpxbuild (); + * + * Entry + * Exit + * Returns + * Calls + */ + + +VOID PASCAL CODESIZE +irpxbuild () +{ + if (checkendm ()) { + if (pMCur->flags == TMACRO) { + /* Delete old text */ + listfree (macroptr->symu.rsmsym.rsmtype.rsmmac.macrotext); + macroptr->symu.rsmsym.rsmtype.rsmmac.macrotext = pMCur->pTSHead; + + pMCur->pParmAct = pMCur->pParmNames; + deleteMC (pMCur); + } + else { + +#ifdef BCBOPT + if (fNotStored) + storelinepb (); +#endif + + pMCur->pTSCur = pMCur->pTSHead; + + if (!pMCur->pTSCur) /* empty macros go 0 times */ + pMCur->count = 0; + + macrolevel++; + handler = HPARSE; + /* Expand that body */ + lineprocess (RMACRO, pMCur); + } + handler = HPARSE; + swaphandler = TRUE; + } + else { + irpcopy (); + listline (); + } +} + + +/*** irpcopy - copy line of text into irp/irpc/macro + * + * irpcopy (); + * + * Entry + * Exit + * Returns + * Calls + */ + +char *pText, *pTextEnd; +UCHAR cbText; +char inpasschar = FALSE; + +#if !defined XENIX286 && !defined FLATMODEL +# pragma check_stack+ +#endif + +VOID PASCAL CODESIZE +irpcopy () +{ + register char *pTextCur; + register UCHAR cc; + TEXTSTR FAR *bodyline; + char hold[LINEMAX]; + USHORT siz; + + pText = pTextCur = hold; + pTextEnd = pTextCur + LINEMAX - 2; + pTextCur++; + cbText = 0; + lbufp = lbuf; + + if (!lsting) /* burn blanks if not listing */ + skipblanks(); + + while ((cc = PEEKC ()) && pTextCur < pTextEnd) { + + ampersand = FALSE; + if (cc == '\'' || cc == '"') { + + delim = cc; + inpasschar = TRUE; /* '...' being parsed */ + do { + + if (cc == '&' || LEGAL1ST(cc)) { /* Could have &dummy or dummy& */ + pTextCur = passatom (pTextCur); + } + else { + NEXTC(); + ampersand = FALSE; + storeCH(cc); + + if (pTextCur >= pTextEnd) + break; + } + + } while ((cc = PEEKC ()) && (cc != delim)); + + inpasschar = FALSE; + + if (!cc) + break; + } + if (!LEGAL1ST (cc)) { + SKIPC(); + + if (cc != '&' || PEEKC() == '&') + storeCH(cc); + + if (cc == ';'){ /* don't translate comment */ + + if (PEEKC() != ';' && lsting) /* don't store ;; comment */ + + while (cc = NEXTC ()) + storeCH(cc); + break; + } + } + else + pTextCur = passatom (pTextCur); + } + + /* trim trailing spaces */ + + while (cbText && ISBLANK (pTextCur[-1])){ + cbText--; + pTextCur--; + } + /* check to see if we ended up with a blank line */ + + if (cbText == 0 && pText == hold) + return; + + storeCH(' '); /* space and NULL terminated */ + storeCH(NULL); + *pText = cbText; + *pTextCur++ = NULL; + + siz = pTextCur - hold; + bodyline = (TEXTSTR FAR *)talloc ((USHORT)(sizeof(TEXTSTR)+siz)); + + bodyline->size = sizeof(TEXTSTR)+siz; + bodyline->strnext = (TEXTSTR FAR *)NULL; + fMemcpy (bodyline->text, hold, siz); + + if (pMCur->pTSCur) + pMCur->pTSCur->strnext = bodyline; + else + pMCur->pTSHead = bodyline; + + pMCur->pTSCur = bodyline; +} + +#if !defined XENIX286 && !defined FLATMODEL +# pragma check_stack- +#endif + + +/*** passatom - pass next atom to line + * + * ptr = passatom (ptr, lim); + * + * Entry ptr = pointer to line buffer + * lim = limit address of buffer + * Exit + * Returns + * Calls + */ + +char * PASCAL CODESIZE +passatom ( + register char *pTextCur +){ + register UCHAR *pT, *svline; + unsigned short number; + UCHAR cbName; + UCHAR cando = FALSE; + UCHAR preconcat = FALSE; /* expanding SYM in "text&SYM" */ + UCHAR postconcat = FALSE; /* expanding SYM in "SYM&text" */ + + + if (preconcat = (PEEKC () == '&')) + SKIPC (); + + svline = lbufp; + getatomend (); + cbName = lbufp - svline; + + if (pTextCur + cbName > pTextEnd){ + errorc (E_LNL); + return(pTextCur); + } + + if (inpasschar ) { + + if (ampersand) { + ampersand = FALSE; + cando = !preconcat; + } + + if (PEEKC () == '&' && cbName) { + SKIPC (); + postconcat = TRUE; + } + else if (!preconcat && !cando) + goto noSubsitute; + } + + for (pT = pMCur->pParmNames, number = DMYBASE; + *pT; pT += *pT+1, number++){ + + if (cbName == *pT && + memcmp(naim.pszName, pT+1, *pT) == 0) { + + if (cbText) + nextCH(); + + pTextCur[-1] = number; /* store dummy parameter index */ + pText = pTextCur++; + + if (postconcat && (preconcat || cando)) + ampersand = TRUE; + + return (pTextCur); + } + } + +noSubsitute: + + if (preconcat){ + storeCH('&'); + } + if (postconcat) + BACKC (); + + if (cbName + cbText >= 0x7f) + nextCH(); + + memcpy(pTextCur, svline, cbName); + + cbText += cbName; + pTextCur += cbName; + + return (pTextCur); +} + + +/*** scandummy - add next atom to dummy list + * + * scandummy (); + * + * Entry + * Exit + * Returns + * Calls + */ + +VOID PASCAL CODESIZE +scandummy () +{ + register MC *pMC = pMCur; + SHORT siz, offset; + + /* Scan dummy name */ + + getatom (); + if (*naim.pszName == 0) { + if (!ISTERM (PEEKC ())) + errorc (E_ECL); + + return; + } + + pMC->count++; + siz = naim.ucCount; + if (pMC->cbParms < siz+2){ + + /* relloc the string on overflow */ + + pMC->cbParms = 32; + offset = pMC->pParmAct - pMC->pParmNames; + if (!(pMC->pParmNames = realloc(pMC->pParmNames, (USHORT)( offset + 32)))) + memerror("scandummy"); + pMC->pParmAct = pMC->pParmNames + offset; + } + *pMC->pParmAct++ = siz; + memcpy(pMC->pParmAct, naim.pszName, siz+1); + pMC->pParmAct += siz; + pMC->cbParms -= siz+1; +} + +/*** growParm - grow the size of parmeter block + * + * Entry pTextCur: current text location + * pText: start of currect arg + * pTextEnd: end of string + * Returns relloced pMCparm names + */ + +char * PASCAL CODESIZE +growParm ( + char *pTextCur +){ + register MC *pMC = pMCur; + long delta, i; + char *pTNew; + + /* relloc the string on overflow */ + + if (!(pTNew = realloc(pMC->pParmAct, (USHORT)( pTextEnd - pMC->pParmAct + 32)))) + memerror("growparm"); + delta = pTNew - pMC->pParmAct; + + /* Adjust all the pointers */ + + pMC->cbParms += 32; + for (i = 0; i count; i++) + pMC->rgPV[i].pActual += delta; + + pMC->pParmAct += delta; + pTextEnd += delta + 32; + pTextCur += delta; + pText += delta; + + return (pTextCur); +} + + +/*** scanparam - scan a parameter for IRP and MACRO calls + * + * scanparm (irpp); + * + * Entry irpp = TRUE if parameters to be comma terminated + * irpp = FALSE if parameters to be blank or comma terminated + * Exit + * Returns none + * Calls + */ + +VOID PASCAL CODESIZE +scanparam ( + UCHAR irpp +){ + register char *pTextCur; + register UCHAR cc; + USHORT bracklevel; + + pText = pTextCur = pMCur->pParmNames; + pTextEnd = pTextCur + pMCur->cbParms; + pTextCur++; + + bracklevel = 0; + if (ISBLANK (PEEKC ())) + skipblanks (); + + while(1) { + + if (pTextCur+1 >= pTextEnd) + pTextCur = growParm(pTextCur); + + switch (cc = NEXTC ()) { + + case ';': + if (bracklevel) + break; + + case NULL: + BACKC (); + goto done; + + case '%': /* convert %expr to character string */ + + pTextCur = scanvalue (pTextCur); + break; + + case '\'': + case '"': + + *pTextCur++ = delim = cc; /* store opening quote */ + + while(1) { + if (pTextCur >= pTextEnd) + pTextCur = growParm(pTextCur); + + /* store next character of string */ + + if (!(cc = NEXTC())){ + BACKC(); + goto done; + } + + *pTextCur++ = cc; + + /* check for double quote character */ + + if (cc == delim) { + if (PEEKC () == delim) { + *pTextCur++ = cc; + SKIPC (); + } + else + break; + } + } + break; + + case '<': /* Have start of < xxx > */ + + if (bracklevel) + *pTextCur++ = cc; + + bracklevel++; + break; + + case '>': /* Have end of < xxx > */ + + if (bracklevel > 1) + *pTextCur++ = cc; + + else{ + if (bracklevel == 0) + BACKC(); + + goto done; + } + + bracklevel--; + break; + + case '!': /* Next char is literal */ + + *pTextCur++ = NEXTC (); + break; + + case ' ': + case '\t': + case ',': + if (bracklevel == 0 && + (cc == ',' || !irpp)) { + + BACKC (); + goto done; + } + + default: + + *pTextCur++ = cc; + } + } +done: + cbText = pTextCur - pText - 1; /* set byte prefix count */ + if (cbText > 0xfe) + errorc(E_LNL); + + *pText = cbText; + pMCur->cbParms -= cbText + 1; + + if (!irpp) + pMCur->rgPV[pMCur->count].pActual = pText; /* point to arg */ + + pMCur->pParmNames = pTextCur; /* set pointer to parm pool */ + pMCur->count++; + +} + + + +/*** scanvalue - evaluate expression and and store converted value + * + * p = scanvalue (p, lim); + * + * Entry p = pointer to location to store converted value + * lim = limit address of buffer + * Exit + * Returns pointer to next character to store into + * Calls exprconst, radixconvert, error + */ + +char * PASCAL CODESIZE +scanvalue ( + char *pTextCur +){ + OFFSET value; + register char *lastlbuf; + SHORT errorIn; + + /* look for a text macro name thats not a constant */ + + lastlbuf = lbufp; + getatom(); + if (PEEKC() == ',' || ISTERM(PEEKC())) { + + /* try a text macro subsitution */ + + if (symsrch () && + symptr->symkind == EQU && + symptr->symu.equ.equtyp == TEXTMACRO) { + + lastlbuf = symptr->symu.equ.equrec.txtmacro.equtext; + + while(*lastlbuf){ + + if (pTextCur >= pTextEnd) + pTextCur = growParm(pTextCur); + + *pTextCur++ = *lastlbuf++; + } + + return(pTextCur); + } + } + lbufp = lastlbuf; + + return(radixconvert (exprconst(), pTextCur)); +} + +/*** radixconvert - convert expression to value in current radix + * + * ptr = radixconvert (value, ptr, lim); + * + * Entry value = value to convert + * ptr = location to store converted string + * lim = limit address of buffer + * Exit + * Returns pointer to next character in store buffer + * Calls error, radixconvert + */ + +#if !defined XENIX286 && !defined FLATMODEL +# pragma check_stack+ +#endif + + +char * PASCAL CODESIZE +radixconvert ( + OFFSET valu, + register char *p +){ + if (valu / radix) { + p = radixconvert (valu / radix, p); + valu = valu % radix; + } + else /* leading digit */ + if (valu > 9) /* do leading '0' for hex */ + *p++ = '0'; + + if (p >= pTextEnd) + p = growParm(p); + + *p++ = valu + ((valu > 9)? 'A' - 10 : '0'); + + return (p); +} + +#if !defined XENIX286 && !defined FLATMODEL +# pragma check_stack- +#endif + + +/*** macroexpand - expand IRP/IRPC/IRPT/MACRO + * + * buffer = irpxexpand (); + * + * Entry pMC = pointer to macro call block + * Exit lbuf = next line of expansion + * Returns pointer to expanded line + * NULL if end of all expansions + * Calls + */ + +VOID PASCAL CODESIZE +macroexpand ( + register MC *pMC +){ + char FAR *lc; + register USHORT cc; + register UCHAR *lbp, *pParm; + register USHORT cbLeft; + + if (pMC->count == 0) { /* Have reached end of expand */ +done: + if (pMC->flags != TMACRO) + listfree (pMC->pTSHead); + + deleteMC (pMC); /* Delete all params */ + macrolevel--; + popcontext = TRUE; + exitbody = FALSE; + return; + } + + while(1){ + + if (!pMC->pTSCur) { + + /* End of this repeat */ + /* Move back to body start */ + + pMC->pTSCur = pMC->pTSHead; + if (--pMC->count == 0) + goto done; + + if (pMC->flags <= TIRPC) + pMC->rgPV[0].pActual += *pMC->rgPV[0].pActual + 1; + } + + lineExpand(pMC, pMC->pTSCur->text); + + pMC->pTSCur = pMC->pTSCur->strnext; + + if (exitbody) { /* unroll nested if/else/endif */ + lastcondon = pMC->svlastcondon; + condlevel = pMC->svcondlevel; + elseflag = pMC->svelseflag; + goto done; + } + break; + } +} + + + +#ifndef M8086OPT + +VOID CODESIZE +lineExpand ( + MC *pMC, + char FAR *lc /* Macro Line */ +){ + register USHORT cc; + register UCHAR *lbp, *pParm; + register USHORT cbLeft; + UCHAR fLenError; + + #ifdef BCBOPT + fNoCompact = FALSE; + #endif + lbufp = lbp = lbuf; + cbLeft = LBUFMAX - 1; + fLenError = FALSE; + while( cc = *lc++) { + + if (cc & 0x80) { + + cc &= 0x7F; + + if (cc >= pMC->iLocal) { + pParm = pMC->rgPV[cc].localName; + + // Error if not enough room for 6 more bytes + if( 6 > cbLeft ){ + fLenError = TRUE; + break; + } + cbLeft -= 6; + + *lbp++ = '?'; /* Store "??" */ + *lbp++ = '?'; + + if (pParm[0] == NULL) { /* must recreat the name */ + offsetAscii ((OFFSET) (pMC->localBase + + cc - pMC->iLocal)); + + *lbp++ = objectascii[0]; + *lbp++ = objectascii[1]; + *lbp++ = objectascii[2]; + *lbp++ = objectascii[3]; + }else{ + /* Copy 4 bytes from pParm */ + *lbp++ = pParm[0]; + *lbp++ = pParm[1]; + *lbp++ = pParm[2]; + *lbp++ = pParm[3]; + } + } + else { + pParm = pMC->rgPV[cc].pActual; + cc = *pParm; + if( cc > cbLeft ){ + fLenError = TRUE; + break; + } + cbLeft -= cc; + memcpy(lbp, pParm+1, cc); + lbp += cc; + } + } + else { + if( cc > cbLeft ){ /* if line too long */ + fLenError = TRUE; + break; + } + cbLeft -= cc; + fMemcpy(lbp, lc, cc); + lc += cc; + lbp += cc; + } + } + if( fLenError ){ + *lbp++ = '\0'; /* Terminate the line */ + errorc( E_LTL & E_ERRMASK ); + } + linebp = lbp - 1; + linelength = linebp - lbufp; + if( fNeedList ){ + strcpy( linebuffer, lbuf ); + } + + /* At exit (linebp - lbuf) == strlen( lbuf ) */ +} + +#endif + + +/*** test4TM - tests if symbol is a text macro, and whether it is + * preceded or followed by '&' + * + * flag = test4TM (); + * + * Entry lbufp points to beginning of symbol in lbuf + * Exit lbufp is advanced by getatom + * Returns TRUE if symbol is text macro, else FALSE + * Calls getatom, symsrch + */ + +UCHAR PASCAL CODESIZE +test4TM() +{ + UCHAR ret = FALSE; + + if (!getatom ()) + return (ret); + + xcreflag--; + + if (symsrch() && (symptr->symkind == EQU) + && (symptr->symu.equ.equtyp == TEXTMACRO)) { + + xcreflag++; /* cref reference to text macro symbol now */ + crefnew (REF); /* as it will be overwritten by expandTM */ + crefout (); + + /* '&' will be overwritten by equtext in lbuf */ + + if (*(begatom - 1) == '&') + begatom--; + + if (*endatom == '&') + endatom++; + + ret = TRUE; + + } else + xcreflag++; + + return (ret); +} + + + +/*** substituteTMs - substitute equtext for each text macro symbol on line + * + * substituteTMs (); + * + * Entry lbufp points to first non-blank character after '%' in lbuf + * Exit lbufp points to beginning of lbuf + * Calls test4TM, expandTM, getatom, skipblanks + */ + +VOID PASCAL CODESIZE +substituteTMs() +{ + char cc; + char delim; + UCHAR inquote; + + while ((cc = PEEKC ()) && cc != ';') { + + inquote = FALSE; + + if (cc == '\'' || cc == '"') { + + delim = cc; + cc = *(++lbufp); + inquote = TRUE; + } + + do { + + if (inquote && cc == '&') + SKIPC (); + + if ((!inquote || cc == '&') && LEGAL1ST(PEEKC ())) { + if (test4TM()) + expandTM (symptr->symu.equ.equrec.txtmacro.equtext); + continue; + } + + if (!(getatom())) { + SKIPC (); + skipblanks(); + } + + } while (inquote && (cc = PEEKC ()) && (cc != delim)); + + if (inquote && (cc == delim)) + SKIPC (); + } + + lbufp = lbuf; +} + + +#ifndef M8086OPT +/*** expandTM - expand text macro in naim in lbuf/lbufp + * + * expandTM ( pReplace ); + * + * Entry pReplace = replacement string + * naim = text macro + * begatom = first character in lbuf to replace + * endatom = first character in lbuf after string to replace + * linebp = points to null terminator in lbuf + * Exit lbuf = new line to be parsed + * lbufp = first character of new atom (replace string) + * linebp = points to new position of null terminator in lbuf + * Returns + * Calls + * Note Shifts characters from lbufp to make substitution of TM. + * Inserts replacement string at begatom. This function could + * be tweaked considerably for speed at the expense of readability. + */ + + +VOID CODESIZE +expandTM ( + register char *pReplace +){ + USHORT cbReplace; /* Length of the replacement string */ + USHORT cbNaim; /* Length of the atom to replace */ + USHORT cbLineEnd; /* Length of the line past the atom being replaced */ + + cbReplace = strlen( pReplace ); + cbNaim = endatom - begatom; /* Get length of the current atom */ + cbLineEnd = linebp - endatom + 1; /* Get length of end of line */ + + if ( (begatom - lbuf) + cbReplace + cbLineEnd > LBUFMAX) { + errorc (E_LTL & E_ERRMASK); + *begatom = '\0'; /* Truncate line */ + }else{ + if( cbReplace != cbNaim ){ + /* Shift end of line */ + memmove( begatom + cbReplace, endatom, cbLineEnd ); + } + memcpy ( begatom, pReplace, cbReplace ); + } + lbufp = begatom; + linebp = begatom + cbReplace + cbLineEnd - 1; +} + +#endif /* M8086OPT */ -- cgit v1.2.3