diff options
author | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
---|---|---|
committer | Adam <you@example.com> | 2020-05-17 05:51:50 +0200 |
commit | e611b132f9b8abe35b362e5870b74bce94a1e58e (patch) | |
tree | a5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/sdktools/masm/asmpars.c | |
download | NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2 NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip |
Diffstat (limited to 'private/sdktools/masm/asmpars.c')
-rw-r--r-- | private/sdktools/masm/asmpars.c | 1009 |
1 files changed, 1009 insertions, 0 deletions
diff --git a/private/sdktools/masm/asmpars.c b/private/sdktools/masm/asmpars.c new file mode 100644 index 000000000..9eae76d64 --- /dev/null +++ b/private/sdktools/masm/asmpars.c @@ -0,0 +1,1009 @@ +/* asmpars.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" + + +static char parsedflag; +char fNeedList; +static char iod[] = "instruction, directive, or label"; +char cputext[22] = "@Cpu="; +char tempText[32]; +USHORT coprocproc; + +/* an array of pointers to the function parsers */ + +VOID (PASCAL CODESIZE * rgpHandler[])(void) = { + + parse, + macrobuild, + irpxbuild, + commentbuild, + strucbuild +}; + +/*** dopass - initialize and execute pass + * + * dopass (); + * + * Entry + * Exit + * Returns + * Calls + */ + + +VOID PASCAL +dopass () +{ + + /* Common pass initialize */ + + cputype = DEF_CPU; + X87type = DEF_X87; + radix = 10; + +#ifdef XENIX287 + definesym("@Cpu=0507h"); +#else + definesym("@Cpu=0101h"); +#endif + definesym("@Version=510"); + + pagewidth = DEF_LISTWIDTH; + condflag = origcond; + crefinc = 0; + fSkipList = 0; + errorlineno = 1; + fCrefline = 1; + fCheckRes = (pass2 && warnlevel >= 1); + fNeedList = listconsole || (lsting && (pass2 | debug)); + + subttlbuf[0] = NULL; + modulename = NULL; + pcsegment = NULL; + pcproc = NULL; + startaddr = NULL; + localbase = 0; + macrolevel = 0; + linessrc = 0; + linestot = 0; + condlevel = 0; + lastcondon = 0; + pcoffset = 0; + pageminor = 0; + errorcode = 0; + fPass1Err = 0; + iProc = 0; + iProcCur = 0; + + radixescape = FALSE; + titleflag = FALSE; + elseflag = FALSE; + initflag = FALSE; + strucflag = FALSE; + fPutFirstOp = FALSE; + fArth32 = FALSE; + + listflag = TRUE; + generate = TRUE; + xcreflag = TRUE; + + pagemajor = 1; + crefcount = 1; + expandflag = LISTGEN; + pagelength = NUMLIN; + pageline = NUMLIN - 1; + + memset(listbuffer, ' ', LISTMAX); + memset(regsegment, 0, sizeof(regsegment));/* No segments assumed*/ + + strcpy(tempText, "@F=@0"); + + if (tempLabel){ + definesym(tempText); + tempText[1] = 'B'; + tempText[4] = '@'; + definesym(tempText); + tempText[4] = '0'; + } + + tempLabel = 0; + + + /* Dispatch to do pass */ + + handler = HPARSE; + if (! setjmp(forceContext)) + lineprocess (RREADSOURCE, NULL); + + while (pFCBCur->pFCBParent) + closefile (); +} + + + + +/*** lineprocess - processs next line + * + * lineprocess (tread); + * + * Entry tread = reader routine + * Exit + * Returns + * Calls + * Note Uses handler to decide which parsing routine to use + */ + +#if !defined XENIX286 && !defined FLATMODEL +# pragma check_stack+ +#endif + +VOID CODESIZE +lineprocess ( + char tread, + MC *pMC +){ + VOID (PASCAL CODESIZE * pHandler)(void); + + lastreader = tread; + pHandler = rgpHandler[handler]; + + do { + /* dispatch to reader to put line into lbuf */ + + /* Clear opcode area if listing */ + + if (crefinc) { + crefcount += crefinc - 1; + crefline (); + crefcount++; + crefinc = 0; + } + + if (tread == RREADSOURCE) + + readfile (); + else + macroexpand (pMC); + + if (popcontext) + break; + + linestot++; + + (*pHandler)(); + + if (swaphandler) { + + swaphandler = FALSE; + pHandler = rgpHandler[handler]; + } + + } while (1); + + popcontext = FALSE; + if (macrolevel == 0) + fPutFirstOp = FALSE; +} + +#if !defined XENIX286 && !defined FLATMODEL +# pragma check_stack- +#endif + + + +/*** parse - parse line and dispatch + * + * parse (); + * + * Entry + * Exit + * Returns + * Calls + */ + + +VOID PASCAL CODESIZE +parse () +{ + static SHORT ret, i; + static char *nextAtom; + +startscan: + opcref = REF_OTHER << 4 | REF_OTHER; + listindex = 1; + optyp = -1; /* Haven't looked up first token */ + + /* Scan 1st atom on line and check delimiter */ + + if (!getatom () && ISTERM(PEEKC())) { /* quick out for comment line */ + listline (); + return; + } + + if (naim.pszName[0] == '%' && naim.pszName[1] == 0) { /* expand all text macros */ + *begatom = ' '; + substituteTMs(); + getatom(); + } + + parsedflag = labelflag = FALSE; /* Have not recognized line yet */ + + if (generate) + switch (PEEKC ()) { + case ':': + /* Form: <name>: xxxxx */ + /* name */ + + nextAtom = lbufp; + + if (*naim.pszName == 0) + + errorcSYN (); + else { + + /* create a temporary label of the form @@: */ + + if (fProcArgs > 0) {/* build stack frame for procs */ + buildFrame(); + return; + } + + if (naim.ucCount == 2 && *(SHORT *)naim.pszName == ('@'<<8 | '@')) { + + tempText[1] = 'B'; + definesym(tempText); + symptr->attr |= M_NOCREF; + + lbufp = &tempText[3]; + getatom(); + labelcreate (CSNEAR, CLABEL); + symptr->symu.clabel.iProc = iProcCur; + + pTextEnd = (char *)-1; + *xxradixconvert((long)++tempLabel, &tempText[4]) = NULL; + + tempText[1] = 'F'; + definesym(tempText); + symptr->attr |= M_NOCREF; + } + else { + + /* define NEAR label */ + labelcreate (CSNEAR, CLABEL); + + if (lbufp[1] == ':') + + nextAtom++; + + else if (!errorcode) { /* don't add if redef */ + + symptr->symu.clabel.iProc = iProcCur; + symptr->alpha = NULL; + + /* addLocal needs takes a null-terminated list */ + addLocal(symptr); + } + } + } + + /* get next token on line after label */ + + lbufp = nextAtom+1; + + if (!getatom ()) + goto Done; + + break; + + case '=': + SKIPC (); + assignvalue (); + goto Done; + + default: + /* Form: <name> xxxxx + * Could have <name> <DIR2 directive> so + * check 2nd atom */ + + secondDirect (); + break; + } + + /* If PARSEDflag is off, then statement has not been recognized so + see if atom is a macro name, directive or opcode */ + + if (!parsedflag){ + + /* look up Macros & struc only when in true part of condition */ + + if (generate) { + + xcreflag--; + ret = symsrch(); + xcreflag++; + + if (ret) + + switch (symptr->symkind) { + + case EQU: + if (symptr->symu.equ.equtyp == TEXTMACRO) { + +#ifdef BCBOPT + goodlbufp = FALSE; +#endif + + /* cref reference to text macro symbol now */ + /* as it will be overwritten by expandTM */ + crefnew (REF); + crefout (); + + /* replaces text macro with text */ + + expandTM (symptr->symu.equ.equrec.txtmacro.equtext); + goto startscan; + } + break; + + case MACRO: + macrocall (); + return; + + case STRUC: + strucinit (); + goto Done; + + case REC: + recordinit (); + goto Done; + + } + } + + if (! firstDirect() && generate) { + + if (fProcArgs > 0){ /* build stack frame for procs */ + buildFrame(); + return; + } + + emitline(); + + if (opcodesearch ()) + if (opctype < OPCODPARSERS) + opcode (); + + else if (X87type & cpu) { + fltopcode (); + } + else + error(E_EXP,iod); + + else if (*naim.pszName != '\0') + error (E_EXP,iod); + + } + } + + /* When we get here, the statement has been parsed and all that is + * left to do is make sure that the line ends with ; or <cr>. If + * we are currently under a FALSE conditional, don't bother to check + * for proper line end since won't have scanned it. */ +Done: + if (generate) { + if (!ISTERM (skipblanks())) + errorc (E_ECL); /* Questionable syntax(bad line end)*/ +#ifdef BCBOPT + } else { + goodlbufp = FALSE; +#endif + } + listline (); +} + + + + +/*** secondDirect - parse those instructions which require a label + * + * secondDirect + * + * Entry + * Exit + * Returns + * Calls + */ + + +VOID PASCAL CODESIZE +secondDirect () +{ + static char *oldlbufp; + static char *saveBegatom; + static char *saveEndatom; + + optyp = 0; + fndir (); /* sets to non zero if found */ + + if (generate && optyp == (char)0) { + + saveBegatom = begatom; + saveEndatom = endatom; + oldlbufp = lbufp; + + switchname (); + getatom (); + if (fndir2 ()) { + /* Have recognized */ + parsedflag = TRUE; + /* Switch back to 1st atom and dispatch */ + switchname (); + labelflag = TRUE; + + switch (optyp) { + case TCATSTR: + catstring (); + break; + case TENDP: + procend (); + break; + case TENDS: + /* End segment */ + ptends (); + break; + case TEQU: + equdefine (); + break; + case TGROUP: + groupdefine (); + break; + case TINSTR: + instring (); + break; + case TLABEL: + /* <name> LABEL <type> Type is one of + NEAR, FAR | BYTE, WORD, DWORD, QWORD, TBYTE Also can be + record or structure name in which + case set type = length */ + + switchname (); + getatom (); + if (fnsize ()) + if (varsize) { + switchname (); + /* Label in name */ + labelcreate (varsize, CLABEL); + symptr->symu.clabel.type = typeFet(varsize); + } + else + errorc (E_TIL); + else if (!symFet () || + !(symptr->symkind == STRUC || + symptr->symkind == REC)) + errorc (E_UST); + else { + switchname (); + labelcreate (symptr->symtype, CLABEL); + symptr->symu.clabel.type = typeFet(varsize); + } + break; + case TMACRO: + macrodefine (); + break; + case TPROC: + procdefine (); + break; + case TRECORD: + recorddefine (); + break; + case TSEGMENT: + segdefine (); + break; + case TSIZESTR: + sizestring (); + break; + case TSTRUC: + strucdefine (); + break; + case TSUBSTR: + substring (); + break; + case TDB: + case TDD: + case TDQ: + case TDT: + case TDW: + case TDF: + datadefine (); + break; + } + labelflag = FALSE; + } + else { + /* Is not a legal 2nd atom directive, but could be + <strucname> or <recordname> */ + + if (symFetNoXref () && + (symptr->symkind == STRUC || + symptr->symkind == REC)) { + + switchname (); /* Get 1st token back */ + + parsedflag = TRUE; + labelflag = TRUE; + + /* Atom is a skeleton name for + * RECORD or STRUC so have form: + * <name> <skel> */ + + if (symptr->symkind == STRUC) + strucinit (); + else + recordinit (); + } + else { + begatom = saveBegatom; + endatom = saveEndatom; + lbufp = oldlbufp; + + switchname (); + /* must be directive or opcode in 1st atom, so get + back to that state be rescanning */ + } + } + } +} + +/*** firstDirect - parse a first token directive + * + * + * Entry optyp maybe set, via pars2 + * 0 - not a token + * -1 - haven't looked up token yet + * other - valid token # of dir + * + * Returns TRUE if it processed a directive + */ + + + +SHORT PASCAL CODESIZE +firstDirect () +{ + + if (optyp == (char)0 || (optyp == ((char)-1) && !fndir ())) + return(FALSE); + + if (generate || + (opkind & CONDBEG) || + optyp == TCOMMENT || + optyp == TFPO) { + + switch (optyp) { + case TASSUME: + BACKC (); + do { + SKIPC (); + assumeitem (); + } while (PEEKC () == ','); + break; + + case TCOMMENT: + comdir (); + break; + case TOUT: + outdir (); + break; + case TELSE: + elsedir (); + break; + case TEND: + enddir (); + break; + case TENDIF: + endifdir (); + break; + case TENDM: + /* Block nesting */ + errorc (E_BNE); + break; + case TERR: + case TERR1: + case TERR2: + case TERRDIF: + case TERRIDN: + case TERRB: + case TERRDEF: + case TERRE: + case TERRNZ: + case TERRNB: + case TERRNDEF: + errdir (); + break; + case TEVEN: + evendir (2); + break; + case TALIGN: + evendir (0); + break; + case TEXITM: + exitmdir (); + break; + case TEXTRN: + BACKC (); + do { + SKIPC (); + externitem (); + } while (PEEKC() == ','); + break; + case TIF: + case TIF1: + case TIF2: + case TIFDIF: + case TIFIDN: + case TIFB: + case TIFDEF: + case TIFE: + case TIFNB: + case TIFNDEF: + conddir (); + break; + case TINCLUDE: + includedir (); + break; + case TIRP: + case TIRPC: + irpxdir (); + break; + case TLOCAL: + if (langType) + defineLocals(); + break; + case TNAME: + namedir (); + break; + case TORG: + orgdir (); + break; + case TPAGE: + setpage (); + break; + case TPUBLIC: + BACKC (); + do { + SKIPC (); + publicitem (); + } while (PEEKC () == ','); + break; + case TPURGE: + BACKC (); + do { + SKIPC (); + purgemacro (); + } while (PEEKC () == ','); + break; + case TREPT: + reptdir (); + break; + case TCREF: + xcreflag = TRUE; + break; + case TLALL: + expandflag = LIST; + break; + case TLFCOND: + condflag = TRUE; + break; + case TLIST: + listflag = TRUE; + break; + case TRADIX: + radixdir (); + break; + case TSALL: + expandflag = SUPPRESS; + break; + case TSFCOND: + condflag = FALSE; + break; + case TSUBTTL: + storetitle (subttlbuf); + break; + case TTFCOND: + if (pass2) { + condflag = (origcond? FALSE: TRUE); + origcond = condflag; + } + break; + case TTITLE: + if (titleflag) + errorc (E_RSY); + else + storetitle (titlebuf); + titleflag = TRUE; + break; + case TXALL: + expandflag = LISTGEN; + break; + case TXCREF: + if (ISTERM (PEEKC ())) + xcreflag = loption; + else { + BACKC (); + do { + SKIPC (); + xcrefitem (); + } while (PEEKC () == ','); + } + break; + case TXLIST: + listflag = FALSE; + break; + case TDB: + case TDD: + case TDQ: + case TDT: + case TDW: + case TDF: + datadefine (); + break; + + case T8087: + X87type = PX87; + goto setatcpu; + + case T287: + X87type = PX87|PX287; + goto setX; + + case T387: + X87type = PX87|PX287|PX387; + setX: + if (X87type > cputype) + errorc(E_TIL); + + goto setatcpu; + + case T8086: + + cputype = P86; + X87type = PX87; + goto setcpudef; + + case T186: + + cputype = P186; + X87type = PX87; + goto setcpudef; + + case T286C: + + cputype = P186|P286; + X87type = PX87|PX287; + goto setcpudef; + + case T286P: + + cputype = P186|P286|PROT; + X87type = PX87|PX287; + goto setcpudef; + +#ifdef V386 + case T386C: + + init386(0); + + cputype = P186|P286|P386; + goto set386; + + case T386P: + init386(1); + + cputype = P186|P286|P386|PROT; + set386: + X87type = PX87|PX287|PX387; + fltemulate = FALSE; + fArth32 |= TRUE; +#endif + setcpudef: +#ifdef V386 + wordszdefault = wordsize = (cputype&P386)? 4: 2; + defwordsize(); + + if (pcsegment) + if (pcsegment->symu.segmnt.use32 > wordsize) + errorc(E_CPU); + else + wordsize = pcsegment->symu.segmnt.use32; +#endif + setatcpu: + coprocproc = (X87type << 8) + (cputype | 1); + pTextEnd = (UCHAR *) -1; + *xxradixconvert((OFFSET)coprocproc, cputext + 5) = 0; + definesym(cputext); + + break; + + case TSEQ: + segalpha = FALSE; + break; + case TALPHA: + segalpha = TRUE; + break; + + case TDOSSEG: + fDosSeg++; + break; + + case TMODEL: + model(); + break; + + case TMSEG: + openSeg(); + break; + + case TMSTACK: + createStack(); + break; + + case TINCLIB: + includeLib(); + break; + + case TFPO: + fpoRecord(); + break; + + case TCOMM: + BACKC (); + do { + SKIPC (); + commDefine (); + + } while (PEEKC() == ','); + break; + } + } + return(TRUE); +} + + + +/*** setpage - set page length and width + * + * setpage (); + * + * Entry + * Exit + * Returns + * Calls + */ + + +VOID PASCAL CODESIZE +setpage () +{ + register char cc; + SHORT i; + + if (ISTERM (cc = PEEKC ())) { + /* position to bottom of page if no operands */ + if (listflag) + pageline = pagelength - 1; + } + else if (cc == '+') { + if (ISBLANK (NEXTC ())) + skipblanks (); + if (listflag) + newpage (); + } + else { + if (cc != ',') { + /* set page length */ + if ((i = exprconst ()) > 9 && i < 256) + pagelength = i; + else + errorc (E_VOR); + if (pageminor + pagemajor == 1) + /* Adjust so page length right */ + pageline = (pagelength - NUMLIN) + pageline; + } + if (PEEKC () == ',') { + SKIPC (); + /* set page width */ + if ((i = exprconst ()) > LINEMAX || i < 60) + errorc (E_VOR); + else + pagewidth = i; + } + } +} + + + + +/*** ptends - process ends statement + * + * ptends (); + * + * Entry + * Exit + * Returns + * Calls + */ + + +VOID PASCAL CODESIZE +ptends () +{ + if (!symFet() || !pcsegment) + errorc (E_BNE); + + /* Make sure segname is correct */ + else if (pcsegment != symptr) + errorc (E_BNE); + else { + if (symptr->symkind != SEGMENT) + errorc (E_BNE); + else { + if (pcmax <= pcoffset) + symptr->symu.segmnt.seglen = pcoffset; + else + symptr->symu.segmnt.seglen = pcmax; + /* S a v e s e g me n t P C */ + symptr->offset = pcoffset; + + if (pcsegment->symu.segmnt.use32 == 2) { + + if (pcoffset > 0x10000) + errorc(E_286 & ~E_WARN1); + + if (pcsegment->symu.segmnt.hascode && + pcsegment->symu.segmnt.seglen > 0xFFDC) + errorc( E_286 ); + } + + + pcdisplay (); /* must do before lose pcsegment */ + pcsegment = symptr->symu.segmnt.lastseg; +#ifdef V386 + if (pcsegment) + wordsize = pcsegment->symu.segmnt.use32; + else + wordsize = wordszdefault; +#endif + symptr->symu.segmnt.lastseg = NULL; + /* Replace later pcsegment <> NULL block with following + block. pcmax must be reset on leaving seg. */ + if (pcsegment) { + /* Restore PC and max offset so far in + segment */ + pcoffset = (*pcsegment).offset; + pcmax = pcsegment->symu.segmnt.seglen; + + strnfcpy(&segName[8], pcsegment->nampnt->id); + } + else { + /* If no seg, PC and max are 0 */ + pcoffset = 0; + pcmax = 0; + segName[8] = NULL; + } + } + definesym(segName); + } + defwordsize(); +} |