diff options
Diffstat (limited to 'private/sdktools/masm/asminp.c')
-rw-r--r-- | private/sdktools/masm/asminp.c | 542 |
1 files changed, 542 insertions, 0 deletions
diff --git a/private/sdktools/masm/asminp.c b/private/sdktools/masm/asminp.c new file mode 100644 index 000000000..b78670135 --- /dev/null +++ b/private/sdktools/masm/asminp.c @@ -0,0 +1,542 @@ +/* asminp.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 +*/ + +#define ASMINP /* prevent external declaration of _asmctype_ */ + +#include <stdio.h> +#include <io.h> +#include <dos.h> +#include <share.h> +#include <memory.h> +#include "asm86.h" +#include "asmfcn.h" +#include "asmctype.h" +#include "asmmsg.h" +#include "asmfcn.h" +#include <fcntl.h> + +#define DEBFLAG F_INP + +#if defined CPDOS && !defined OS2_2 && !defined OS2_NT +unsigned short _far _pascal DosRead( unsigned short, unsigned char far *, unsigned short, unsigned short far *); +#endif + + +VOID PASCAL getphysline (void); +SHORT PASCAL CODESIZE readmore (void); +SHORT PASCAL CODESIZE incomment( char * ); + +extern UCHAR _asmctype_[]; +extern char _asmcupper_[]; +extern char _asmTokenMap_[]; + + +/*** skipblanks - skip blanks + * + * skipblanks () + * + * Returns - the terminating character + */ + + +#ifndef M8086OPT + +UCHAR CODESIZE +skipblanks () +{ + while (ISBLANK (NEXTC ())) + ; + return(*--lbufp); +} + +#endif + + +/*** scanatom - extract next atom into name + * + * hash = scanatom (pos) + * + * Entry pos = SCEND if position at first character after token + * SCSKIP if position before terminator and not set delim + * Exit naim.pszName = next token zero terminated + * upper case if caseflag = CASEU or CASEX + * case read from file if caseflag = CASEL + * naim.pszLowerCase = name in case read from file + * naim.usHash = hash value of token in naim.pszName + * naim.ucCount = length of string + * begatom = pointer to first character of token + * endatom = pointer to character after end of token + * Returns void + * Calls skipblanks + */ + +#ifndef M8086OPT + +#define rNEXTC() (*rlbp++) +#define rPEEKC() (*rlbp) +#define rBACKC() (rlbp--) +#define rSKIPC() (rlbp++) + + +SHORT PASCAL CODESIZE +scanatom ( + char pos +){ + register char *ptr = naim.pszName; + register char *lptr = naim.pszLowerCase; + register char *rlbp = lbufp; + register char cc; + register char *n; + register SHORT h; + long tokLen; + + while (ISBLANK (rNEXTC ())) + ; + rBACKC (); + h = 0; + /* Start of atom */ + begatom = rlbp; + if (LEGAL1ST (rPEEKC ())) { + n = lptr + SYMMAX; + cc = rNEXTC (); + if( cc == '.' ){ /* Special case token starting with dot */ + h = *ptr++ = *lptr++ = cc; + cc = rNEXTC (); + } + if (caseflag == CASEL) + + do { + h += MAP(*ptr++ = *lptr++ = cc); + } while (TOKLEGAL( cc = rNEXTC() ) && lptr < n); + else + do { + h += (*ptr++ = MAP( *lptr++ = cc )); + } while (TOKLEGAL( cc = rNEXTC() ) && lptr < n); + + if (TOKLEGAL (cc)) + /* Atom longer than table entry, discard remaining chars */ + while (TOKLEGAL (cc = rNEXTC ())) + ; + rBACKC (); + endatom = rlbp; + if (ISBLANK (cc) && pos != SCEND) { /* skipblanks() */ + while (ISBLANK (rNEXTC ())) + ; + rBACKC (); + } + } + *ptr = *lptr = '\0'; + naim.ucCount = lptr - naim.pszLowerCase; + naim.usHash = h; + lbufp = rlbp; + tokLen = lptr - naim.pszLowerCase; /* Using tokLen gets around a C386 6.00.60 bug */ + return( (SHORT) tokLen ); /* Return length of token */ +} + +#endif /* M8086OPT */ + + + + +/*** readfile - read from input or include file + * + * ptr = readfile (); + * + * Entry none + * Exit lbuf = next input line + * lbufp = start of lbuf + * line counter for file incremented + * linessrc incremented + * Returns pointer to end of line + * Calls error + */ + + +VOID PASCAL CODESIZE +readfile () +{ + register FCB * pFCBT; + + getline(); + + pFCBCur->line++; + + if (srceof) { + + if (!pFCBCur->pFCBParent) { + errorc (E_EOF); + fprintf (ERRFILE,__NMSG_TEXT(ER_EO2)); + + if (fSimpleSeg && pcsegment) + endCurSeg(); + + longjmp(forceContext, 1); + + } else { + + popcontext = TRUE; + + closefile(); + + if (crefing && pass2) + fprintf( crf.fil, "\8%s", pFCBCur->fname ); + } + srceof = 0; + } + else + linessrc++; +} + + + + +/*** getline - read from input or include file + * + * getline() + * + * Returns in lbuf the next complete logical line. A logical line + * may consist of one or more lines connected via the \ continuation + * character. This is done as follows. Data is copied from + * pFCBCur->tmpbuf. If necessary more data is copied into the + * buffer via readmore(). After an entire physical line is read + * it is tested as to whether the line is continued on the next + * physical line. If not the line is returned in lbuf. Otherwise + * the physical line is copied to linebuffer and a call to listline + * is made. At which point another physical line is cancatenated + * to the line or lines already in lbuf. + * + * Entry pFCBCur = File currently reading from. + * pFCBCur->ctmpbuf = Number of bytes available in buffer + * 0 = necessary to read data from disk. + * pFCBCur->ptmpbuf = Next position in buffer to copy from. + * pFCBCur->line = Number of physical line in file + * + * Exit - lbuf[] holds a complete logical line, with a space appended. + * - linebuffer[] holds last physical line. + * - lbufp points to the beginning of lbuf. + * - linebp points to null terminator at the end + * of the logical line in lbuf. + * - linelength is number of bytes of last physical line. + * - pFCBCur->ctmpbuf & ptmpbuf & line are updated. + * - srceof is true if the end of file was encountered, in + * which case the physical line is a null string, and + * the logical line is a single space character. + */ + +VOID CODESIZE +getline() +{ + char FAR *p; + register char *pchTmp; + char *pchPhysLine; + INT fFoundEOL; /* True, if endof line copied */ + register INT count; + INT fLineContinued; + INT fGotSome; + + lbufp = lbuf; /* Init lbufp for other routines */ + pchPhysLine = lbuf; + fGotSome = FALSE; // nothing seen yet + errorlineno = pFCBCur->line + 1; + pchTmp = lbuf; // Where to copy the line + + //if( pFCBMain->line == 126-1 ){ + // _asm int 3 + //} + + do{ + + fFoundEOL = FALSE; + do{ + + /* If the buffer is empty fill it */ + if( !pFCBCur->ctmpbuf ){ + if( readmore() ){ // TRUE if at EOF + if( !fGotSome ){ + srceof = TRUE; + linebuffer[0] = '\0'; + linelength = 0; + linebp = lbuf; + lbuf[0] = '\0'; + return; + }else{ + pchTmp++; /* Negate pchTmp-- following this loop */ + break; /* Break fFoundEOL loop */ + } + } + } + fGotSome = TRUE; + + /* Find next LF in buffer */ + p = _fmemchr( pFCBCur->ptmpbuf, '\n', pFCBCur->ctmpbuf ); + if( p ){ /* If LF was found */ + count = (p - pFCBCur->ptmpbuf) + 1; + fFoundEOL = TRUE; + }else{ + count = pFCBCur->ctmpbuf; + } + + /* Check if physical or logical line too long */ + if( (pchTmp - lbuf) + count >= LBUFMAX || + (pchTmp - pchPhysLine) + count >= LINEMAX-4 ){ + + /* Update the position in the buffer */ + pFCBCur->ptmpbuf += count; // Update where copying from + pFCBCur->ctmpbuf -= count; + + errorc( E_LNL ); /* Log the error */ + + /* Return a null string line */ + linebuffer[0] = '\0'; + linelength = 0; + linebp = lbuf; + lbuf[0] = ' '; + lbuf[1] = '\0'; + return; + }else{ + /* Copy the line, and update pointers */ + fMemcpy( pchTmp, pFCBCur->ptmpbuf, count ); + pchTmp += count; // Update where copying to + pFCBCur->ctmpbuf -= count; // Update # bytes left in buffer + pFCBCur->ptmpbuf += count; // Update where copying from + } + + }while( !fFoundEOL ); + + pchTmp--; /* Move back to last character (LF) */ + + +/* Strip Carriage Returns that precede LFs */ + if( *(pchTmp-1) == '\r' ){ + pchTmp--; /* Throw out Carriage return */ + } + +#ifdef MSDOS + /* Strip Multiple Control-Zs */ + while( *(pchTmp - 1) == 0x1A ){ /* Check for ^Z */ + pchTmp--; + } +#endif + if( pchTmp < lbuf ){ /* Remotely possible if Blank line */ + pchTmp = lbuf; + } + + linelength = pchTmp - pchPhysLine; + if( !pass2 || listconsole || lsting ){ + memcpy( linebuffer, pchPhysLine, linelength ); + } + *( linebuffer + linelength ) = '\0'; //Null terminate the physical line + + if( *(pchTmp - 1) == '\\' && !incomment( pchTmp ) ){ + pchPhysLine = --pchTmp; /* Overwrite the '\' */ + fCrefline = FALSE; + listline(); + fCrefline = TRUE; + pFCBCur->line++; /* Line count it physical line count */ + fLineContinued = TRUE; + }else{ + fLineContinued = FALSE; + } + }while( fLineContinued ); + *pchTmp++ = ' '; /* Replace line feed with space */ + *pchTmp = '\0'; /* Null terminate line */ + linebp = pchTmp; + if( lbuf[0] == 12 ){ /* Overwrite leading ctrl-L with space */ + lbuf[0] = ' '; + } + /* At this point linebp - lbuf == strlen( lbuf ) */ +} + +/*** readmore - read from disk into buffer + * + * + * + * Entry pFCBCur = File currently reading from. + * pFCBCur->cbbuf = Size of buffer to read into. + * pFCBCur->buf = Address of buffer to read into. + * pFCBCur->fh = File handle to read from. + * + * Exit return = TRUE: Not at end of file + * pFCBCur->ptmpbuf = First byte of buffer. + * pFCBCur->ctmpbuf = Number of bytes in buffer. + * return = FALSE: At end of file + * No other variables changed. + */ + +SHORT PASCAL CODESIZE +readmore () +{ + SHORT cb; + SHORT fEOF = FALSE; + + /* If the file has been temporarily closed reopen it */ + if( pFCBCur->fh == FH_CLOSED ){ + if( (pFCBCur->fh = tryOneFile( pFCBCur->fname )) == -1 ){ /* Open the file */ + TERMINATE1(ER_ULI, EX_UINP, save); /* Report unable to access file */ + } + /* Seek to old position */ + if( _lseek( pFCBCur->fh, pFCBCur->savefilepos, SEEK_SET ) == -1L ){ + TERMINATE1(ER_ULI, EX_UINP, save); /* Report unable to access file */ + } + } + +#if !defined CPDOS || defined OS2_2 || defined OS2_NT + cb = _read( pFCBCur->fh, pFCBCur->buf, pFCBCur->cbbuf ); +#else + if( DosRead( pFCBCur->fh, pFCBCur->buf, pFCBCur->cbbuf, &cb ) ){ + cb = -1; + } +#endif + if( cb == 0 ){ + fEOF = TRUE; /* End of file found */ + }else if( cb == (SHORT)-1 ){ + TERMINATE1(ER_ULI, EX_UINP, save); /* Report unable to access file error */ + }else{ + /* Setup the buffer pointers */ + pFCBCur->ptmpbuf = pFCBCur->buf; /* Init ptr to start of buffer */ + pFCBCur->ctmpbuf = cb; + } + return( fEOF ); +} + + + + +/*** incomment - Checks a line ending in \ to determine if the \ is in a + * comment and is therefore not a comment line. + * + * Entry Assumes lbuf contains partial logical line ending in a \. + * pchEnd - points within lbuf to the terminating LF. + * Methode Checks that line is not in a COMMENT directive's scope. + * Then checks if the line contains a semicolon. If not, \ + * IS continuation. If a semicolon is found, line must be + * scanned carefully to determine if the semicolon is a + * comment delimeter or is in a string or is a character + * constant If it is not a comment delimeter, \ IS continuation. + * Otherwise, \ is part of comment, and is NOT a continuation. + * Exit Returns true if the \ is in a comment + * Returns false if the \ is not in a comment, and is therefore + * a continuation character. + * + * Calls memchr + * + * Created: 9/90 - Jeff Spencer, translated from asm code in asmhelp.asm + */ + +SHORT PASCAL CODESIZE +incomment( + char * pchTmp /* Points to terminating LF in lbuf */ +){ + SHORT fContSearch; + unsigned char * pchSearch; + unsigned char * pchSemi; + unsigned char chClose; + static unsigned char szComment[] = "COMMENT"; + + + + pchTmp--; /* Point to '\' character */ + if( handler == HCOMMENT ){ /* If within comment directive */ + return( TRUE ); + } + + fContSearch = TRUE; + pchSearch = lbuf; + + do{ + if( pchSemi = memchr( pchSearch, ';', pchTmp - pchSearch )){ /* Check for a semicolon */ + do{ + chClose = '\0'; + switch( *pchSearch++ ){ + case ';': + /* Semicolon is not in quotes, return in comment */ + return( TRUE ); + case '\"': + chClose = '\"'; + break; + case '\'': + chClose = '\''; + break; + case '<': + chClose = '>'; + break; + } + /* Below the word quote is used to mean the chClose character */ + if( chClose ){ + if( !(pchSearch = memchr( pchSearch, chClose, pchTmp - pchSearch ) ) ){ + fContSearch = FALSE; /* No matching quote, not a comment */ + }else{ + if( pchSearch < pchSemi){ + /* Semicolon is in quotes */ + pchSearch++; /* Move past quote just found + break; // Look for another semicolon */ + }else{ + /* Semicolon is past this set of quotes */ + /* Continue, Scanning */ + } + } + } + }while( fContSearch && pchSearch < pchTmp ); + }else{ + /* No Semicolon in the line, or it's in quotes */ + fContSearch = FALSE; + } + }while( fContSearch ); + + /* At this point we know that the \ is not in a semicolon ** + ** delimited comment. However, we still have to make sure ** + ** that the comment keyword doesn't appear at the begining ** + ** of the line. */ + + /* Skip leading white space */ + pchSearch = lbuf; + while( *pchSearch == ' ' || *pchSearch == '\t' ){ + pchSearch++; + } + for( pchTmp = szComment; *pchTmp; ){ + if( *pchSearch++ != _asmTokenMap_[*pchTmp++] ){ + return( FALSE ); /* First word isn't "comment" */ + } + } + return( TRUE ); /* comment keyword at start of line, return in comment */ +} + +/**** closeFile + * + * closeFile () + * + * Entry Assumes valid pFCBCur->fh or FH_CLOSED + * Returns + * Calls close() + * Note Closes current file - i.e. pFCBCur + * and marks all fields in pFCBCur appropriately + */ + +closefile() +{ + register FCB *pFCBOld; + + #ifdef BCBOPT + BCB * pBCBT; + + if ((pBCBT = pFCBCur->pBCBCur) && pBCBT->pbuf) + pBCBT->filepos = 0; /* EOF */ + #endif + + if( pFCBCur->fh != FH_CLOSED ){ /* Check to see if the file is already closed */ + _close(pFCBCur->fh); + } + pFCBOld = pFCBCur; + pFCBCur = pFCBCur->pFCBParent; /* Remove from bidirectional linked list */ + pFCBCur->pFCBChild = NULL; + + _ffree( pFCBOld->buf); /* Free FCB buffer */ + _ffree( (UCHAR *)pFCBOld ); /* Free FCB */ +} |