|
|
/* 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>
extern void closefile(void);
#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 = (unsigned char)(lptr - naim.pszLowerCase); naim.usHash = h; lbufp = rlbp; tokLen = (long)(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); fputs (__NMSG_TEXT(ER_EO2),ERRFILE);
if (fSimpleSeg && pcsegment) endCurSeg();
longjmp(forceContext, 1);
} else {
popcontext = TRUE;
closefile();
if (crefing && pass2) fprintf( crf.fil, "%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 L_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 */ L_count = (int)((p - pFCBCur->ptmpbuf) + 1); fFoundEOL = TRUE; }else{ L_count = pFCBCur->ctmpbuf; }
/* Check if physical or logical line too long */ if( (pchTmp - lbuf) + L_count >= LBUFMAX || (pchTmp - pchPhysLine) + L_count >= LINEMAX-4 ){
/* Update the position in the buffer */ pFCBCur->ptmpbuf += L_count; // Update where copying from
pFCBCur->ctmpbuf -= (USHORT)L_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, L_count ); pchTmp += L_count; // Update where copying to
pFCBCur->ctmpbuf -= (USHORT)L_count; // Update # bytes left in buffer
pFCBCur->ptmpbuf += L_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 = (unsigned char)(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 = (SHORT)_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, ';', (size_t)(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, (size_t)(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 */
void closefile(void) { 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 */ }
|