Leaked source code of windows server 2003
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.

544 lines
14 KiB

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