Source code of Windows XP (NT5)
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.

830 lines
14 KiB

  1. /* asmequ.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. #include <stdio.h>
  11. #include <string.h>
  12. #include "asm86.h"
  13. #include "asmfcn.h"
  14. #include "asmctype.h"
  15. #include "asmmsg.h"
  16. /* EQU statement : There are 3 basic kinds of EQU:
  17. 1. To expression
  18. 2. To symbol( synonym )
  19. 3. All others are text macros
  20. */
  21. VOID PASCAL CODESIZE assignconst ( USHORT );
  22. char isGolbal; /* flag indicating if equ symbol was global */
  23. /*** assignvalue - assign value to symbol
  24. *
  25. * assignvalue ();
  26. *
  27. * Entry
  28. * Exit
  29. * Returns
  30. * Calls
  31. */
  32. VOID PASCAL CODESIZE
  33. assignvalue ()
  34. {
  35. struct eqar a;
  36. register struct psop *pso;
  37. register SYMBOL FARSYM *sym;
  38. register DSCREC *dsc;
  39. switchname ();
  40. if (createequ(EXPR)) {
  41. sym = symptr;
  42. sym->attr |= M_BACKREF; /* Set we have DEFINED */
  43. dsc = (equflag)? itemptr: expreval (&nilseg);
  44. pso = &(dsc->dsckind.opnd);
  45. if (noexp)
  46. errorc (E_OPN);
  47. /* If error, set undefined */
  48. if (errorcode && errorcode != E_RES)
  49. sym->attr &= ~(M_DEFINED | M_BACKREF);
  50. if (equflag && equdef) {
  51. if (sym->offset != pso->doffset ||
  52. sym->symu.equ.equrec.expr.esign != pso->dsign ||
  53. sym->symsegptr != pso->dsegment)
  54. muldef ();
  55. }
  56. /* If = involves forward, don't set BACKREF */
  57. if (M_FORTYPE & pso->dtype){
  58. sym->attr &= ~M_BACKREF;
  59. if (sym->attr & M_GLOBAL)
  60. sym->attr &= ~M_GLOBAL;
  61. }
  62. if (pso->mode != 4 &&
  63. !(pso->mode == 0 && pso->rm == 6) &&
  64. !(pso->mode == 5 && pso->rm == 5) ||
  65. pso->dflag == XTERNAL)
  66. /* Not right kind of result */
  67. errorc (E_IOT);
  68. sym->symsegptr = pso->dsegment;
  69. sym->symu.equ.equrec.expr.eassume = NULL;
  70. if (pso->dtype == M_CODE)
  71. sym->symu.equ.equrec.expr.eassume = pso->dcontext;
  72. sym->length = 0;
  73. sym->offset = pso->doffset;
  74. /* Note: change sign */
  75. sym->symu.equ.equrec.expr.esign = pso->dsign;
  76. sym->symtype = pso->dsize;
  77. if ((pso->dtype == M_RCONST || !pso->dsegment) &&
  78. !(M_PTRSIZE & pso->dtype))
  79. sym->symtype = 0;
  80. if (fNeedList) {
  81. listbuffer[1] = '=';
  82. listindex = 3;
  83. if (sym->symu.equ.equrec.expr.esign)
  84. listbuffer[2] = '-';
  85. offsetAscii (sym->offset);
  86. copyascii ();
  87. }
  88. dfree ((char *)dsc );
  89. }
  90. }
  91. /*** createequ - create entry for equ
  92. *
  93. * flag = createequ (typ, p)
  94. *
  95. * Entry typ = type of equ
  96. * Exit
  97. * Returns TRUE if equ created or found of right type
  98. * FALSE if equ not created or found and wrong type
  99. * Calls labelcreate, switchname
  100. */
  101. UCHAR PASCAL CODESIZE
  102. createequ (
  103. UCHAR typ
  104. ){
  105. equsel = typ;
  106. switchname ();
  107. labelcreate (0, EQU);
  108. /* Make sure not set set fields if wrong type, flag to caller */
  109. if (symptr->symkind != EQU || symptr->symu.equ.equtyp != typ) {
  110. errorn (E_SDK);
  111. return (FALSE);
  112. }
  113. else {
  114. switchname ();
  115. isGolbal = 0;
  116. if (equsel == ALIAS){ /* lose public on pointer to alias */
  117. isGolbal = symptr->attr & M_GLOBAL ? M_GLOBAL : 0;
  118. symptr->attr &= ~M_GLOBAL;
  119. }
  120. if (typ != EXPR)
  121. symptr->symsegptr = NULL;
  122. return (TRUE);
  123. }
  124. }
  125. /*** equtext - make remainder of line into text form of EQU
  126. *
  127. * equtext ();
  128. *
  129. * Entry
  130. * Exit
  131. * Returns
  132. * Calls error, skipblanks
  133. */
  134. VOID PASCAL CODESIZE
  135. equtext (
  136. USHORT cb
  137. ){
  138. register UCHAR *pFirst, *pT, *pOld;
  139. if (createequ (TEXTMACRO)) {
  140. /* find end of line & then delete trailing blanks */
  141. pFirst = lbufp;
  142. if (cb == ((USHORT)-1)) {
  143. for (pT = pFirst; *pT && *pT != ';'; pT++);
  144. for (; pT > pFirst && ISBLANK (pT[-1]) ; pT--);
  145. lbufp = pT;
  146. cb = (USHORT)(pT - pFirst);
  147. }
  148. pOld = symptr->symu.equ.equrec.txtmacro.equtext;
  149. pT = nalloc((USHORT)(cb+1), "equtext");
  150. pT[cb] = NULL;
  151. symptr->symu.equ.equrec.txtmacro.equtext =
  152. (char *) memcpy(pT, pFirst, cb);
  153. if (pOld)
  154. free (pOld);
  155. copystring (pT);
  156. }
  157. }
  158. /*** equdefine - define EQU
  159. *
  160. * equdefine ();
  161. *
  162. * Entry
  163. * Exit
  164. * Returns
  165. * Calls
  166. */
  167. VOID PASCAL CODESIZE
  168. equdefine ()
  169. {
  170. register SYMBOL FARSYM *pSY;
  171. struct eqar a;
  172. register char *p;
  173. USHORT cb;
  174. UCHAR opc = FALSE;
  175. listbuffer[1] = '=';
  176. switchname ();
  177. a.dirscan = lbufp;
  178. if (PEEKC () == '<') { /* look for <text macro> */
  179. p = getTMstring();
  180. a.dirscan = lbufp;
  181. lbufp = p;
  182. equtext ((USHORT)(a.dirscan - p - 1));
  183. lbufp = a.dirscan;
  184. return;
  185. }
  186. getatom ();
  187. if ((*naim.pszName == '$') && (naim.pszName[1] == 0))
  188. *naim.pszName = 0;
  189. /*Need to check if 1st atom is an operator, otherwise
  190. will make OFFSET an alias instead of text. */
  191. if (fnoper ())
  192. *naim.pszName = 0;
  193. if (*naim.pszName && ISTERM (PEEKC ()) && !(opc = opcodesearch ())) {
  194. /* Alias */
  195. if (createequ (ALIAS)) {
  196. pSY = symptr;
  197. if (!symsrch ()) {
  198. if (pass2)
  199. /* Undefined */
  200. errorn (E_SND);
  201. /* Don't know symbol yet */
  202. pSY->symu.equ.equrec.alias.equptr = NULL;
  203. }
  204. else {
  205. /* Alias symbol is DEFINED */
  206. pSY->attr = (unsigned char)(pSY->attr&~M_BACKREF | symptr->attr&M_BACKREF);
  207. if (!pSY->symu.equ.equrec.alias.equptr)
  208. pSY->symu.equ.equrec.alias.equptr = symptr;
  209. if (pSY->symu.equ.equrec.alias.equptr != symptr) {
  210. /* This is multiple definition */
  211. symptr = pSY;
  212. muldef ();
  213. }
  214. else {
  215. /* See if good */
  216. if (pSY = chasealias (pSY))
  217. pSY->attr |= isGolbal;
  218. }
  219. }
  220. }
  221. }
  222. else {
  223. /* Must be text form or expr */
  224. #ifdef BCBOPT
  225. goodlbufp = FALSE;
  226. #endif
  227. lbufp = a.dirscan;
  228. xcreflag--;
  229. emittext = FALSE;
  230. if (opc) { /* quick patch to allow i.e. SYM equ MOV */
  231. equtext ((USHORT)-1);
  232. emittext = TRUE;
  233. xcreflag++;
  234. return;
  235. }
  236. a.dsc = expreval (&nilseg);
  237. emittext = TRUE;
  238. xcreflag++;
  239. /* So don't see double ref */
  240. /* force text if OFFSET or : */
  241. if (a.dsc->dsckind.opnd.mode != 4 &&
  242. !(a.dsc->dsckind.opnd.mode == 0 && a.dsc->dsckind.opnd.rm == 6) &&
  243. !(a.dsc->dsckind.opnd.mode == 5 && a.dsc->dsckind.opnd.rm == 5) ||
  244. (errorcode && errorcode != E_SND && errorcode != E_RES) ||
  245. (M_EXPLOFFSET|M_EXPLCOLON|M_HIGH|M_LOW) & a.dsc->dsckind.opnd.dtype ||
  246. a.dsc->dsckind.opnd.seg != NOSEG ||
  247. a.dsc->dsckind.opnd.dflag == XTERNAL) {
  248. /* Not good expression */
  249. if (errorcode != E_LTL)
  250. errorcode = 0;
  251. dfree ((char *)a.dsc );
  252. lbufp = a.dirscan;
  253. equtext ((USHORT)-1);
  254. }
  255. else {
  256. /* This is expression */
  257. itemptr = a.dsc;
  258. switchname ();
  259. equflag = TRUE;
  260. assignvalue ();
  261. equflag = FALSE;
  262. }
  263. }
  264. }
  265. /*** definesym - define symbol from command line
  266. *
  267. * definesym (p);
  268. *
  269. * Entry *p = symbol text
  270. * Exit symbol define as EQU with value of 0
  271. * Returns none
  272. * Calls
  273. */
  274. void PASCAL
  275. definesym (
  276. UCHAR *p
  277. ){
  278. struct eqar a;
  279. fCheckRes++;
  280. fSkipList++;
  281. #ifdef BCBOPT
  282. goodlbufp = FALSE;
  283. #endif
  284. strcpy (lbufp = save, p);
  285. getatom ();
  286. if ((PEEKC() == 0 || PEEKC() == '=') && *naim.pszName) {
  287. if (PEEKC() == '=')
  288. SKIPC();
  289. switchname ();
  290. equtext ((USHORT)-1);
  291. }
  292. else
  293. errorcode++;
  294. fSkipList--;
  295. fCheckRes--;
  296. }
  297. /*** defwordsize - define @WordSize using definesym()
  298. *
  299. * defwordsize ( );
  300. *
  301. * Entry
  302. * Exit
  303. * Returns
  304. * Calls definesym()
  305. */
  306. VOID PASCAL
  307. defwordsize ()
  308. {
  309. static char wstext[] = "@WordSize=0D";
  310. wstext[10] = wordsize + '0';
  311. definesym(wstext);
  312. symptr->attr |= M_NOCREF; /* don't cref @WordSize */
  313. }
  314. /*** chasealias - return value of alias list
  315. *
  316. * symb = chasealias (equsym);
  317. *
  318. * Entry
  319. * Exit
  320. * Returns
  321. * Calls
  322. */
  323. SYMBOL FARSYM * PASCAL CODESIZE
  324. chasealias (
  325. SYMBOL FARSYM *equsym
  326. ){
  327. register SYMBOL FARSYM *endalias;
  328. endalias = equsym;
  329. do {
  330. /* Must check to see if EQU to self */
  331. if (endalias->symu.equ.equrec.alias.equptr == equsym) {
  332. endalias->symu.equ.equrec.alias.equptr = NULL;
  333. errorc (E_CEA);
  334. return (NULL);
  335. }
  336. endalias = endalias->symu.equ.equrec.alias.equptr;
  337. if (!endalias) {
  338. errorn (E_SND);
  339. return(NULL); /* This is undefined */
  340. }
  341. } while (!(endalias->symkind != EQU ||
  342. endalias->symu.equ.equtyp != ALIAS));
  343. /* Now check final is ok - Only constant allowed */
  344. if (endalias->symkind == EQU &&
  345. endalias->symu.equ.equtyp != EXPR){
  346. errorc (E_IOT);
  347. return (NULL);
  348. }
  349. return (endalias);
  350. }
  351. /*** getTMstring - process a string or text macro
  352. * used by substring, catstring, sizestring, & instring
  353. *
  354. * char * getTMstring ();
  355. *
  356. * Entry lbufp points to beginning of string or TM
  357. * Exit
  358. * Returns Pointer to string or equtext of TM
  359. * Calls
  360. */
  361. char * PASCAL CODESIZE
  362. getTMstring ()
  363. {
  364. char cc;
  365. register char * p;
  366. static char tms [] = "text macro";
  367. static char digitsT[33];
  368. char * ret = NULL;
  369. skipblanks ();
  370. p = lbufp;
  371. if ((cc = *p) == '<' ) {
  372. ret = p + 1;
  373. while (*(++p) && (*p != '>'))
  374. ;
  375. if (!*p)
  376. error(E_EXP,tms);
  377. else
  378. *(p++) = 0;
  379. lbufp = p;
  380. }
  381. else if (test4TM()) {
  382. ret = symptr->symu.equ.equrec.txtmacro.equtext;
  383. }
  384. else if (cc == '%') {
  385. pTextEnd = (char *) -1;
  386. lbufp = p+1;
  387. *xxradixconvert (exprconst(), digitsT) = NULL;
  388. return (digitsT);
  389. }
  390. else
  391. error(E_EXP,tms );
  392. return (ret);
  393. }
  394. /*** substring - process the subStr directive
  395. *
  396. * substring ();
  397. *
  398. * Syntax:
  399. *
  400. * <ident> subStr <subjectString> , <startIndex> {, <length> }
  401. *
  402. * Defines <ident> as a TEXTMACRO.
  403. * <subjectString> must be a TEXTMACRO or a string: " ", < >, ' '
  404. * <startIndex>: constant expression between 1 and strlen(subjectString)
  405. * Optional <length>: constant expression between 0 and
  406. * (strlen(subjectString) - startIndex + 1)
  407. *
  408. * Entry lbufp points to beginning of subjectString
  409. * Exit
  410. * Returns
  411. * Calls getTMstring
  412. */
  413. VOID PASCAL CODESIZE
  414. substring ()
  415. {
  416. struct eqar a;
  417. char *p;
  418. register USHORT cb;
  419. char cc;
  420. register char *subjtext;
  421. USHORT slength;
  422. USHORT startindex = 0;
  423. listbuffer[1] = '=';
  424. switchname ();
  425. /* First find string or text macro */
  426. if (!(subjtext = getTMstring () ))
  427. return;
  428. cb = (USHORT) strlen(subjtext);
  429. /* then check for start index */
  430. if (skipblanks () == ',') {
  431. SKIPC ();
  432. startindex = (USHORT)(exprconst() - 1); /* get start index */
  433. } else
  434. error(E_EXP,"comma");
  435. /* then check for length */
  436. if (skipblanks () == ',') {
  437. SKIPC ();
  438. slength = (USHORT)exprconst(); /* get start index */
  439. } else
  440. slength = cb - startindex;
  441. if (startindex > cb || slength > cb - startindex) {
  442. errorc (E_VOR);
  443. return;
  444. }
  445. p = lbufp;
  446. lbufp = subjtext + startindex; /* set lbufp to start of substring */
  447. equtext(slength); /* end of string index */
  448. lbufp = p;
  449. if (errorcode && symptr)
  450. symptr->attr &= ~(M_DEFINED | M_BACKREF);
  451. }
  452. /*** catstring - process the catstr directive
  453. *
  454. * catstring ();
  455. *
  456. * Syntax:
  457. *
  458. * <ident> catStr <subjectString> {, <subjectString> } ...
  459. *
  460. * Defines <ident> as a TEXTMACRO.
  461. * Each <subjectString> must be a TEXTMACRO or a string: " ", < >, ' '
  462. *
  463. * Entry
  464. * Exit
  465. * Returns
  466. * Calls
  467. */
  468. VOID PASCAL CODESIZE
  469. catstring ()
  470. {
  471. struct eqar a;
  472. register USHORT cb;
  473. char *subjtext;
  474. char resulttext[LBUFMAX];
  475. USHORT cbresult = 0;
  476. register char *p = resulttext;
  477. listbuffer[1] = '=';
  478. switchname ();
  479. *p = '\0';
  480. /* First find string or text macro */
  481. do {
  482. if (!(subjtext = getTMstring () ))
  483. break;
  484. cb = (USHORT) strlen (subjtext);
  485. cbresult += cb;
  486. if(cbresult > LBUFMAX) {
  487. errorc(E_LTL);
  488. break;
  489. }
  490. memcpy (p, subjtext, cb + 1); /* + 1 copies NULL */
  491. p += cb;
  492. } while (skipblanks() && NEXTC () == ',');
  493. p = --lbufp;
  494. lbufp = resulttext;
  495. equtext(cbresult);
  496. lbufp = p;
  497. if (errorcode)
  498. symptr->attr &= ~(M_DEFINED | M_BACKREF);
  499. }
  500. /*** assignconst - like assignvalue, only takes value as argument
  501. *
  502. * assignconst (cb);
  503. *
  504. * Entry USHORT cb == value to assign
  505. * Exit
  506. * Returns
  507. * Calls
  508. */
  509. VOID PASCAL CODESIZE
  510. assignconst (
  511. USHORT cb
  512. ){
  513. register SYMBOL FARSYM *sym;
  514. struct eqar a;
  515. if (createequ(EXPR)) {
  516. sym = symptr;
  517. if (errorcode)
  518. sym->attr &= ~(M_DEFINED | M_BACKREF);
  519. else
  520. sym->attr |= M_BACKREF; /* Set we have DEFINED */
  521. sym->symsegptr = NULL;
  522. sym->symu.equ.equrec.expr.eassume = NULL;
  523. sym->length = 0;
  524. sym->offset = cb;
  525. sym->symu.equ.equrec.expr.esign = 0;
  526. sym->symtype = 0;
  527. if (fNeedList) {
  528. listbuffer[1] = '=';
  529. listindex = 3;
  530. offsetAscii (sym->offset);
  531. copyascii ();
  532. }
  533. }
  534. }
  535. /*** sizestring - process the sizeStr directive
  536. *
  537. * sizestring ();
  538. *
  539. * Syntax:
  540. *
  541. * <ident> sizeStr <subjectString>
  542. *
  543. * Defines <ident> as a EXPR.
  544. * The <subjectString> must be a TEXTMACRO or a string: " ", < >, ' '
  545. *
  546. * Entry
  547. * Exit
  548. * Returns
  549. * Calls
  550. */
  551. VOID PASCAL CODESIZE
  552. sizestring ()
  553. {
  554. register USHORT cb = 0;
  555. char *p;
  556. switchname ();
  557. /* First find string or text macro */
  558. if (p = getTMstring () )
  559. cb = (USHORT) strlen (p);
  560. assignconst (cb);
  561. }
  562. /*** instring - process the instr directive
  563. *
  564. * instring ();
  565. *
  566. * Syntax:
  567. *
  568. * <ident> inStr { <startIndex> } , <subjectString> , <searchString>
  569. *
  570. * Defines <ident> as a TEXTMACRO.
  571. * <startIndex>: constant expression between 1 and strlen(subjectString)
  572. * <subjectString> must be a TEXTMACRO or a string: " ", < >, ' '
  573. * <searchString> must be a TEXTMACRO or a string: " ", < >, ' '
  574. *
  575. * Entry lbufp points to beginning of subjectString
  576. * Exit
  577. * Returns
  578. * Calls getTMstring
  579. */
  580. //char * strstr();
  581. VOID PASCAL CODESIZE
  582. instring ()
  583. {
  584. register char *p;
  585. register USHORT cb = 0;
  586. register char cc;
  587. char *subjtext;
  588. char *searchtext;
  589. USHORT startindex = 1;
  590. switchname ();
  591. /* First find start index */
  592. p = lbufp;
  593. if ((cc = *p) != '"' && cc != '\'' && cc != '<' && !test4TM ()) {
  594. lbufp = p;
  595. startindex = (USHORT)exprconst(); /* get start index */
  596. if (lbufp != p)
  597. if (skipblanks () == ',')
  598. SKIPC ();
  599. else
  600. error(E_EXP,"comma");
  601. } else
  602. lbufp = p;
  603. if (subjtext = getTMstring () ) {
  604. cb = (USHORT) strlen(subjtext);
  605. if (startindex < 1 || startindex > cb)
  606. errorc (E_VOR);
  607. if (skipblanks () == ',')
  608. SKIPC ();
  609. else
  610. error(E_EXP,"comma");
  611. /* then check for searchtext */
  612. if (searchtext = getTMstring () ) {
  613. p = subjtext + startindex - 1;
  614. if (p = strstr (p, searchtext))
  615. cb = (USHORT)(p - subjtext + 1);
  616. else
  617. cb = 0;
  618. }
  619. }
  620. assignconst (cb);
  621. }