Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

542 lines
14 KiB

4 years ago
  1. /* asminp.c -- microsoft 80x86 assembler
  2. **
  3. ** microsoft (r) macro assembler
  4. ** copyright (c) microsoft corp 1986. all rights reserved
  5. **
  6. ** randy nevin
  7. **
  8. ** 10/90 - Quick conversion to 32 bit by Jeff Spencer
  9. */
  10. #define ASMINP /* prevent external declaration of _asmctype_ */
  11. #include <stdio.h>
  12. #include <io.h>
  13. #include <dos.h>
  14. #include <share.h>
  15. #include <memory.h>
  16. #include "asm86.h"
  17. #include "asmfcn.h"
  18. #include "asmctype.h"
  19. #include "asmmsg.h"
  20. #include "asmfcn.h"
  21. #include <fcntl.h>
  22. #define DEBFLAG F_INP
  23. #if defined CPDOS && !defined OS2_2 && !defined OS2_NT
  24. unsigned short _far _pascal DosRead( unsigned short, unsigned char far *, unsigned short, unsigned short far *);
  25. #endif
  26. VOID PASCAL getphysline (void);
  27. SHORT PASCAL CODESIZE readmore (void);
  28. SHORT PASCAL CODESIZE incomment( char * );
  29. extern UCHAR _asmctype_[];
  30. extern char _asmcupper_[];
  31. extern char _asmTokenMap_[];
  32. /*** skipblanks - skip blanks
  33. *
  34. * skipblanks ()
  35. *
  36. * Returns - the terminating character
  37. */
  38. #ifndef M8086OPT
  39. UCHAR CODESIZE
  40. skipblanks ()
  41. {
  42. while (ISBLANK (NEXTC ()))
  43. ;
  44. return(*--lbufp);
  45. }
  46. #endif
  47. /*** scanatom - extract next atom into name
  48. *
  49. * hash = scanatom (pos)
  50. *
  51. * Entry pos = SCEND if position at first character after token
  52. * SCSKIP if position before terminator and not set delim
  53. * Exit naim.pszName = next token zero terminated
  54. * upper case if caseflag = CASEU or CASEX
  55. * case read from file if caseflag = CASEL
  56. * naim.pszLowerCase = name in case read from file
  57. * naim.usHash = hash value of token in naim.pszName
  58. * naim.ucCount = length of string
  59. * begatom = pointer to first character of token
  60. * endatom = pointer to character after end of token
  61. * Returns void
  62. * Calls skipblanks
  63. */
  64. #ifndef M8086OPT
  65. #define rNEXTC() (*rlbp++)
  66. #define rPEEKC() (*rlbp)
  67. #define rBACKC() (rlbp--)
  68. #define rSKIPC() (rlbp++)
  69. SHORT PASCAL CODESIZE
  70. scanatom (
  71. char pos
  72. ){
  73. register char *ptr = naim.pszName;
  74. register char *lptr = naim.pszLowerCase;
  75. register char *rlbp = lbufp;
  76. register char cc;
  77. register char *n;
  78. register SHORT h;
  79. long tokLen;
  80. while (ISBLANK (rNEXTC ()))
  81. ;
  82. rBACKC ();
  83. h = 0;
  84. /* Start of atom */
  85. begatom = rlbp;
  86. if (LEGAL1ST (rPEEKC ())) {
  87. n = lptr + SYMMAX;
  88. cc = rNEXTC ();
  89. if( cc == '.' ){ /* Special case token starting with dot */
  90. h = *ptr++ = *lptr++ = cc;
  91. cc = rNEXTC ();
  92. }
  93. if (caseflag == CASEL)
  94. do {
  95. h += MAP(*ptr++ = *lptr++ = cc);
  96. } while (TOKLEGAL( cc = rNEXTC() ) && lptr < n);
  97. else
  98. do {
  99. h += (*ptr++ = MAP( *lptr++ = cc ));
  100. } while (TOKLEGAL( cc = rNEXTC() ) && lptr < n);
  101. if (TOKLEGAL (cc))
  102. /* Atom longer than table entry, discard remaining chars */
  103. while (TOKLEGAL (cc = rNEXTC ()))
  104. ;
  105. rBACKC ();
  106. endatom = rlbp;
  107. if (ISBLANK (cc) && pos != SCEND) { /* skipblanks() */
  108. while (ISBLANK (rNEXTC ()))
  109. ;
  110. rBACKC ();
  111. }
  112. }
  113. *ptr = *lptr = '\0';
  114. naim.ucCount = lptr - naim.pszLowerCase;
  115. naim.usHash = h;
  116. lbufp = rlbp;
  117. tokLen = lptr - naim.pszLowerCase; /* Using tokLen gets around a C386 6.00.60 bug */
  118. return( (SHORT) tokLen ); /* Return length of token */
  119. }
  120. #endif /* M8086OPT */
  121. /*** readfile - read from input or include file
  122. *
  123. * ptr = readfile ();
  124. *
  125. * Entry none
  126. * Exit lbuf = next input line
  127. * lbufp = start of lbuf
  128. * line counter for file incremented
  129. * linessrc incremented
  130. * Returns pointer to end of line
  131. * Calls error
  132. */
  133. VOID PASCAL CODESIZE
  134. readfile ()
  135. {
  136. register FCB * pFCBT;
  137. getline();
  138. pFCBCur->line++;
  139. if (srceof) {
  140. if (!pFCBCur->pFCBParent) {
  141. errorc (E_EOF);
  142. fprintf (ERRFILE,__NMSG_TEXT(ER_EO2));
  143. if (fSimpleSeg && pcsegment)
  144. endCurSeg();
  145. longjmp(forceContext, 1);
  146. } else {
  147. popcontext = TRUE;
  148. closefile();
  149. if (crefing && pass2)
  150. fprintf( crf.fil, "\8%s", pFCBCur->fname );
  151. }
  152. srceof = 0;
  153. }
  154. else
  155. linessrc++;
  156. }
  157. /*** getline - read from input or include file
  158. *
  159. * getline()
  160. *
  161. * Returns in lbuf the next complete logical line. A logical line
  162. * may consist of one or more lines connected via the \ continuation
  163. * character. This is done as follows. Data is copied from
  164. * pFCBCur->tmpbuf. If necessary more data is copied into the
  165. * buffer via readmore(). After an entire physical line is read
  166. * it is tested as to whether the line is continued on the next
  167. * physical line. If not the line is returned in lbuf. Otherwise
  168. * the physical line is copied to linebuffer and a call to listline
  169. * is made. At which point another physical line is cancatenated
  170. * to the line or lines already in lbuf.
  171. *
  172. * Entry pFCBCur = File currently reading from.
  173. * pFCBCur->ctmpbuf = Number of bytes available in buffer
  174. * 0 = necessary to read data from disk.
  175. * pFCBCur->ptmpbuf = Next position in buffer to copy from.
  176. * pFCBCur->line = Number of physical line in file
  177. *
  178. * Exit - lbuf[] holds a complete logical line, with a space appended.
  179. * - linebuffer[] holds last physical line.
  180. * - lbufp points to the beginning of lbuf.
  181. * - linebp points to null terminator at the end
  182. * of the logical line in lbuf.
  183. * - linelength is number of bytes of last physical line.
  184. * - pFCBCur->ctmpbuf & ptmpbuf & line are updated.
  185. * - srceof is true if the end of file was encountered, in
  186. * which case the physical line is a null string, and
  187. * the logical line is a single space character.
  188. */
  189. VOID CODESIZE
  190. getline()
  191. {
  192. char FAR *p;
  193. register char *pchTmp;
  194. char *pchPhysLine;
  195. INT fFoundEOL; /* True, if endof line copied */
  196. register INT count;
  197. INT fLineContinued;
  198. INT fGotSome;
  199. lbufp = lbuf; /* Init lbufp for other routines */
  200. pchPhysLine = lbuf;
  201. fGotSome = FALSE; // nothing seen yet
  202. errorlineno = pFCBCur->line + 1;
  203. pchTmp = lbuf; // Where to copy the line
  204. //if( pFCBMain->line == 126-1 ){
  205. // _asm int 3
  206. //}
  207. do{
  208. fFoundEOL = FALSE;
  209. do{
  210. /* If the buffer is empty fill it */
  211. if( !pFCBCur->ctmpbuf ){
  212. if( readmore() ){ // TRUE if at EOF
  213. if( !fGotSome ){
  214. srceof = TRUE;
  215. linebuffer[0] = '\0';
  216. linelength = 0;
  217. linebp = lbuf;
  218. lbuf[0] = '\0';
  219. return;
  220. }else{
  221. pchTmp++; /* Negate pchTmp-- following this loop */
  222. break; /* Break fFoundEOL loop */
  223. }
  224. }
  225. }
  226. fGotSome = TRUE;
  227. /* Find next LF in buffer */
  228. p = _fmemchr( pFCBCur->ptmpbuf, '\n', pFCBCur->ctmpbuf );
  229. if( p ){ /* If LF was found */
  230. count = (p - pFCBCur->ptmpbuf) + 1;
  231. fFoundEOL = TRUE;
  232. }else{
  233. count = pFCBCur->ctmpbuf;
  234. }
  235. /* Check if physical or logical line too long */
  236. if( (pchTmp - lbuf) + count >= LBUFMAX ||
  237. (pchTmp - pchPhysLine) + count >= LINEMAX-4 ){
  238. /* Update the position in the buffer */
  239. pFCBCur->ptmpbuf += count; // Update where copying from
  240. pFCBCur->ctmpbuf -= count;
  241. errorc( E_LNL ); /* Log the error */
  242. /* Return a null string line */
  243. linebuffer[0] = '\0';
  244. linelength = 0;
  245. linebp = lbuf;
  246. lbuf[0] = ' ';
  247. lbuf[1] = '\0';
  248. return;
  249. }else{
  250. /* Copy the line, and update pointers */
  251. fMemcpy( pchTmp, pFCBCur->ptmpbuf, count );
  252. pchTmp += count; // Update where copying to
  253. pFCBCur->ctmpbuf -= count; // Update # bytes left in buffer
  254. pFCBCur->ptmpbuf += count; // Update where copying from
  255. }
  256. }while( !fFoundEOL );
  257. pchTmp--; /* Move back to last character (LF) */
  258. /* Strip Carriage Returns that precede LFs */
  259. if( *(pchTmp-1) == '\r' ){
  260. pchTmp--; /* Throw out Carriage return */
  261. }
  262. #ifdef MSDOS
  263. /* Strip Multiple Control-Zs */
  264. while( *(pchTmp - 1) == 0x1A ){ /* Check for ^Z */
  265. pchTmp--;
  266. }
  267. #endif
  268. if( pchTmp < lbuf ){ /* Remotely possible if Blank line */
  269. pchTmp = lbuf;
  270. }
  271. linelength = pchTmp - pchPhysLine;
  272. if( !pass2 || listconsole || lsting ){
  273. memcpy( linebuffer, pchPhysLine, linelength );
  274. }
  275. *( linebuffer + linelength ) = '\0'; //Null terminate the physical line
  276. if( *(pchTmp - 1) == '\\' && !incomment( pchTmp ) ){
  277. pchPhysLine = --pchTmp; /* Overwrite the '\' */
  278. fCrefline = FALSE;
  279. listline();
  280. fCrefline = TRUE;
  281. pFCBCur->line++; /* Line count it physical line count */
  282. fLineContinued = TRUE;
  283. }else{
  284. fLineContinued = FALSE;
  285. }
  286. }while( fLineContinued );
  287. *pchTmp++ = ' '; /* Replace line feed with space */
  288. *pchTmp = '\0'; /* Null terminate line */
  289. linebp = pchTmp;
  290. if( lbuf[0] == 12 ){ /* Overwrite leading ctrl-L with space */
  291. lbuf[0] = ' ';
  292. }
  293. /* At this point linebp - lbuf == strlen( lbuf ) */
  294. }
  295. /*** readmore - read from disk into buffer
  296. *
  297. *
  298. *
  299. * Entry pFCBCur = File currently reading from.
  300. * pFCBCur->cbbuf = Size of buffer to read into.
  301. * pFCBCur->buf = Address of buffer to read into.
  302. * pFCBCur->fh = File handle to read from.
  303. *
  304. * Exit return = TRUE: Not at end of file
  305. * pFCBCur->ptmpbuf = First byte of buffer.
  306. * pFCBCur->ctmpbuf = Number of bytes in buffer.
  307. * return = FALSE: At end of file
  308. * No other variables changed.
  309. */
  310. SHORT PASCAL CODESIZE
  311. readmore ()
  312. {
  313. SHORT cb;
  314. SHORT fEOF = FALSE;
  315. /* If the file has been temporarily closed reopen it */
  316. if( pFCBCur->fh == FH_CLOSED ){
  317. if( (pFCBCur->fh = tryOneFile( pFCBCur->fname )) == -1 ){ /* Open the file */
  318. TERMINATE1(ER_ULI, EX_UINP, save); /* Report unable to access file */
  319. }
  320. /* Seek to old position */
  321. if( _lseek( pFCBCur->fh, pFCBCur->savefilepos, SEEK_SET ) == -1L ){
  322. TERMINATE1(ER_ULI, EX_UINP, save); /* Report unable to access file */
  323. }
  324. }
  325. #if !defined CPDOS || defined OS2_2 || defined OS2_NT
  326. cb = _read( pFCBCur->fh, pFCBCur->buf, pFCBCur->cbbuf );
  327. #else
  328. if( DosRead( pFCBCur->fh, pFCBCur->buf, pFCBCur->cbbuf, &cb ) ){
  329. cb = -1;
  330. }
  331. #endif
  332. if( cb == 0 ){
  333. fEOF = TRUE; /* End of file found */
  334. }else if( cb == (SHORT)-1 ){
  335. TERMINATE1(ER_ULI, EX_UINP, save); /* Report unable to access file error */
  336. }else{
  337. /* Setup the buffer pointers */
  338. pFCBCur->ptmpbuf = pFCBCur->buf; /* Init ptr to start of buffer */
  339. pFCBCur->ctmpbuf = cb;
  340. }
  341. return( fEOF );
  342. }
  343. /*** incomment - Checks a line ending in \ to determine if the \ is in a
  344. * comment and is therefore not a comment line.
  345. *
  346. * Entry Assumes lbuf contains partial logical line ending in a \.
  347. * pchEnd - points within lbuf to the terminating LF.
  348. * Methode Checks that line is not in a COMMENT directive's scope.
  349. * Then checks if the line contains a semicolon. If not, \
  350. * IS continuation. If a semicolon is found, line must be
  351. * scanned carefully to determine if the semicolon is a
  352. * comment delimeter or is in a string or is a character
  353. * constant If it is not a comment delimeter, \ IS continuation.
  354. * Otherwise, \ is part of comment, and is NOT a continuation.
  355. * Exit Returns true if the \ is in a comment
  356. * Returns false if the \ is not in a comment, and is therefore
  357. * a continuation character.
  358. *
  359. * Calls memchr
  360. *
  361. * Created: 9/90 - Jeff Spencer, translated from asm code in asmhelp.asm
  362. */
  363. SHORT PASCAL CODESIZE
  364. incomment(
  365. char * pchTmp /* Points to terminating LF in lbuf */
  366. ){
  367. SHORT fContSearch;
  368. unsigned char * pchSearch;
  369. unsigned char * pchSemi;
  370. unsigned char chClose;
  371. static unsigned char szComment[] = "COMMENT";
  372. pchTmp--; /* Point to '\' character */
  373. if( handler == HCOMMENT ){ /* If within comment directive */
  374. return( TRUE );
  375. }
  376. fContSearch = TRUE;
  377. pchSearch = lbuf;
  378. do{
  379. if( pchSemi = memchr( pchSearch, ';', pchTmp - pchSearch )){ /* Check for a semicolon */
  380. do{
  381. chClose = '\0';
  382. switch( *pchSearch++ ){
  383. case ';':
  384. /* Semicolon is not in quotes, return in comment */
  385. return( TRUE );
  386. case '\"':
  387. chClose = '\"';
  388. break;
  389. case '\'':
  390. chClose = '\'';
  391. break;
  392. case '<':
  393. chClose = '>';
  394. break;
  395. }
  396. /* Below the word quote is used to mean the chClose character */
  397. if( chClose ){
  398. if( !(pchSearch = memchr( pchSearch, chClose, pchTmp - pchSearch ) ) ){
  399. fContSearch = FALSE; /* No matching quote, not a comment */
  400. }else{
  401. if( pchSearch < pchSemi){
  402. /* Semicolon is in quotes */
  403. pchSearch++; /* Move past quote just found
  404. break; // Look for another semicolon */
  405. }else{
  406. /* Semicolon is past this set of quotes */
  407. /* Continue, Scanning */
  408. }
  409. }
  410. }
  411. }while( fContSearch && pchSearch < pchTmp );
  412. }else{
  413. /* No Semicolon in the line, or it's in quotes */
  414. fContSearch = FALSE;
  415. }
  416. }while( fContSearch );
  417. /* At this point we know that the \ is not in a semicolon **
  418. ** delimited comment. However, we still have to make sure **
  419. ** that the comment keyword doesn't appear at the begining **
  420. ** of the line. */
  421. /* Skip leading white space */
  422. pchSearch = lbuf;
  423. while( *pchSearch == ' ' || *pchSearch == '\t' ){
  424. pchSearch++;
  425. }
  426. for( pchTmp = szComment; *pchTmp; ){
  427. if( *pchSearch++ != _asmTokenMap_[*pchTmp++] ){
  428. return( FALSE ); /* First word isn't "comment" */
  429. }
  430. }
  431. return( TRUE ); /* comment keyword at start of line, return in comment */
  432. }
  433. /**** closeFile
  434. *
  435. * closeFile ()
  436. *
  437. * Entry Assumes valid pFCBCur->fh or FH_CLOSED
  438. * Returns
  439. * Calls close()
  440. * Note Closes current file - i.e. pFCBCur
  441. * and marks all fields in pFCBCur appropriately
  442. */
  443. closefile()
  444. {
  445. register FCB *pFCBOld;
  446. #ifdef BCBOPT
  447. BCB * pBCBT;
  448. if ((pBCBT = pFCBCur->pBCBCur) && pBCBT->pbuf)
  449. pBCBT->filepos = 0; /* EOF */
  450. #endif
  451. if( pFCBCur->fh != FH_CLOSED ){ /* Check to see if the file is already closed */
  452. _close(pFCBCur->fh);
  453. }
  454. pFCBOld = pFCBCur;
  455. pFCBCur = pFCBCur->pFCBParent; /* Remove from bidirectional linked list */
  456. pFCBCur->pFCBChild = NULL;
  457. _ffree( pFCBOld->buf); /* Free FCB buffer */
  458. _ffree( (UCHAR *)pFCBOld ); /* Free FCB */
  459. }