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.

1040 lines
25 KiB

  1. /* asmirp.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 <fcntl.h>
  16. #define DMYBASE 0x80
  17. #define nextCH() {*pText=cbText; pText = pTextCur++; cbText = 0;}
  18. #define storeCH(c) {if (cbText>0x7f) nextCH() *pTextCur++=c; cbText++;}
  19. char * PASCAL CODESIZE growParm( char * );
  20. /*** irpxdir - process <irp> and <irpc> directives
  21. *
  22. * irpxdir ();
  23. *
  24. * Entry
  25. * Exit
  26. * Returns
  27. * Calls
  28. * Note Format is
  29. * IRPC <dummy>, text | <text>
  30. * IRP <dummy>,<param list>
  31. */
  32. VOID PASCAL CODESIZE
  33. irpxdir ()
  34. {
  35. register short cc; /* CHAR */
  36. USHORT bracklevel;
  37. char littext;
  38. register char *pT;
  39. char *pParmName;
  40. createMC (1); /* Make IRPC param block */
  41. scandummy (); /* Scan our only dummy param */
  42. if (NEXTC () != ','){
  43. error (E_EXP,"comma");
  44. return;
  45. }
  46. pMCur->cbParms = strlen(lbufp) << 1;
  47. pT = nalloc(pMCur->cbParms, "irpxdir: actuals");
  48. *pT = NULL;
  49. pMCur->rgPV[0].pActual = pMCur->pParmAct = pT;
  50. pParmName = pMCur->pParmNames;
  51. pMCur->pParmNames = pT;
  52. bracklevel = 0;
  53. if (littext = (skipblanks () == '<')) {
  54. SKIPC ();
  55. bracklevel = 1;
  56. }
  57. if (optyp == TIRP) {
  58. if (!littext)
  59. error (E_EXP,"<"); /* Must have < */
  60. if (skipblanks () != '>') {
  61. BACKC ();
  62. do {
  63. SKIPC ();
  64. scanparam (TRUE);
  65. } while (skipblanks () == ',');
  66. }
  67. if (NEXTC () != '>')
  68. error (E_EXP,">");
  69. }
  70. else {
  71. while (cc = NEXTC ()) {
  72. if (littext) {
  73. /* Only stop on > */
  74. if (cc == '<'){
  75. bracklevel++;
  76. continue;
  77. }
  78. else if (cc == '>'){
  79. if (--bracklevel == 0)
  80. break;
  81. continue;
  82. }
  83. }
  84. else if (ISBLANK (cc) || ISTERM (cc)) {
  85. BACKC ();
  86. break;
  87. }
  88. *pT++ = 1; /* arg of length 1 */
  89. *pT++ = (char)cc; /* and the arg */
  90. pMCur->count++;
  91. }
  92. *pT = NULL;
  93. }
  94. if (PEEKC () == '>' && littext)
  95. SKIPC ();
  96. swaphandler = TRUE;
  97. handler = HIRPX;
  98. blocklevel = 1;
  99. pMCur->count--; /* don't count arg in repeat count */
  100. pMCur->pParmNames = pParmName;
  101. pMCur->iLocal++;
  102. pMCur->svlastcondon = (char)lastcondon;
  103. pMCur->svcondlevel = (char)condlevel;
  104. pMCur->svelseflag = elseflag;
  105. }
  106. /*** reptdir - process repeat directive
  107. *
  108. * reptdir ();
  109. *
  110. * Entry
  111. * Exit
  112. * Returns
  113. * Calls
  114. */
  115. VOID PASCAL CODESIZE
  116. reptdir ()
  117. {
  118. char sign;
  119. createMC (1);
  120. pMCur->count = (USHORT)exprsmag (&sign);
  121. if (sign)
  122. errorc (E_VOR);
  123. if (errorcode)
  124. pMCur->count = 0;
  125. swaphandler = TRUE;
  126. handler = HIRPX;
  127. blocklevel = 1;
  128. pMCur->svcondlevel = (char)condlevel;
  129. pMCur->svlastcondon = (char)lastcondon;
  130. pMCur->svelseflag = elseflag;
  131. }
  132. /*** irpxbuild - build text for IRP/IRPC block
  133. *
  134. * irpxbuild ();
  135. *
  136. * Entry
  137. * Exit
  138. * Returns
  139. * Calls
  140. */
  141. VOID PASCAL CODESIZE
  142. irpxbuild ()
  143. {
  144. if (checkendm ()) {
  145. if (pMCur->flags == TMACRO) {
  146. /* Delete old text */
  147. listfree (macroptr->symu.rsmsym.rsmtype.rsmmac.macrotext);
  148. macroptr->symu.rsmsym.rsmtype.rsmmac.macrotext = pMCur->pTSHead;
  149. pMCur->pParmAct = pMCur->pParmNames;
  150. deleteMC (pMCur);
  151. }
  152. else {
  153. #ifdef BCBOPT
  154. if (fNotStored)
  155. storelinepb ();
  156. #endif
  157. pMCur->pTSCur = pMCur->pTSHead;
  158. if (!pMCur->pTSCur) /* empty macros go 0 times */
  159. pMCur->count = 0;
  160. macrolevel++;
  161. handler = HPARSE;
  162. /* Expand that body */
  163. lineprocess (RMACRO, pMCur);
  164. }
  165. handler = HPARSE;
  166. swaphandler = TRUE;
  167. }
  168. else {
  169. irpcopy ();
  170. listline ();
  171. }
  172. }
  173. /*** irpcopy - copy line of text into irp/irpc/macro
  174. *
  175. * irpcopy ();
  176. *
  177. * Entry
  178. * Exit
  179. * Returns
  180. * Calls
  181. */
  182. char *pText, *pTextEnd;
  183. UCHAR cbText;
  184. char inpasschar = FALSE;
  185. #if !defined XENIX286 && !defined FLATMODEL
  186. # pragma check_stack+
  187. #endif
  188. VOID PASCAL CODESIZE
  189. irpcopy ()
  190. {
  191. register char *pTextCur;
  192. register UCHAR cc;
  193. TEXTSTR FAR *bodyline;
  194. char hold[LINEMAX];
  195. USHORT siz;
  196. pText = pTextCur = hold;
  197. pTextEnd = pTextCur + LINEMAX - 2;
  198. pTextCur++;
  199. cbText = 0;
  200. lbufp = lbuf;
  201. if (!lsting) /* burn blanks if not listing */
  202. skipblanks();
  203. while ((cc = PEEKC ()) && pTextCur < pTextEnd) {
  204. ampersand = FALSE;
  205. if (cc == '\'' || cc == '"') {
  206. delim = cc;
  207. inpasschar = TRUE; /* '...' being parsed */
  208. do {
  209. if (cc == '&' || LEGAL1ST(cc)) { /* Could have &dummy or dummy& */
  210. pTextCur = passatom (pTextCur);
  211. }
  212. else {
  213. NEXTC();
  214. ampersand = FALSE;
  215. storeCH(cc);
  216. if (pTextCur >= pTextEnd)
  217. break;
  218. }
  219. } while ((cc = PEEKC ()) && (cc != delim));
  220. inpasschar = FALSE;
  221. if (!cc)
  222. break;
  223. }
  224. if (!LEGAL1ST (cc)) {
  225. SKIPC();
  226. if (cc != '&' || PEEKC() == '&')
  227. storeCH(cc);
  228. if (cc == ';'){ /* don't translate comment */
  229. if (PEEKC() != ';' && lsting) /* don't store ;; comment */
  230. while (cc = NEXTC ())
  231. storeCH(cc);
  232. break;
  233. }
  234. }
  235. else
  236. pTextCur = passatom (pTextCur);
  237. }
  238. /* trim trailing spaces */
  239. while (cbText && ISBLANK (pTextCur[-1])){
  240. cbText--;
  241. pTextCur--;
  242. }
  243. /* check to see if we ended up with a blank line */
  244. if (cbText == 0 && pText == hold)
  245. return;
  246. storeCH(' '); /* space and NULL terminated */
  247. storeCH(NULL);
  248. *pText = cbText;
  249. *pTextCur++ = NULL;
  250. siz = (USHORT)(pTextCur - hold);
  251. bodyline = (TEXTSTR FAR *)talloc ((USHORT)(sizeof(TEXTSTR)+siz));
  252. bodyline->size = (char) (sizeof(TEXTSTR)+siz);
  253. bodyline->strnext = (TEXTSTR FAR *)NULL;
  254. fMemcpy (bodyline->text, hold, siz);
  255. if (pMCur->pTSCur)
  256. pMCur->pTSCur->strnext = bodyline;
  257. else
  258. pMCur->pTSHead = bodyline;
  259. pMCur->pTSCur = bodyline;
  260. }
  261. #if !defined XENIX286 && !defined FLATMODEL
  262. # pragma check_stack-
  263. #endif
  264. /*** passatom - pass next atom to line
  265. *
  266. * ptr = passatom (ptr, lim);
  267. *
  268. * Entry ptr = pointer to line buffer
  269. * lim = limit address of buffer
  270. * Exit
  271. * Returns
  272. * Calls
  273. */
  274. char * PASCAL CODESIZE
  275. passatom (
  276. register char *pTextCur
  277. ){
  278. register UCHAR *pT, *svline;
  279. unsigned short number;
  280. UCHAR cbName;
  281. UCHAR cando = FALSE;
  282. UCHAR preconcat = FALSE; /* expanding SYM in "text&SYM" */
  283. UCHAR postconcat = FALSE; /* expanding SYM in "SYM&text" */
  284. if (preconcat = (PEEKC () == '&'))
  285. SKIPC ();
  286. svline = lbufp;
  287. getatomend ();
  288. cbName = (UCHAR)(lbufp - svline);
  289. if (pTextCur + cbName > pTextEnd){
  290. errorc (E_LNL);
  291. return(pTextCur);
  292. }
  293. if (inpasschar ) {
  294. if (ampersand) {
  295. ampersand = FALSE;
  296. cando = !preconcat;
  297. }
  298. if (PEEKC () == '&' && cbName) {
  299. SKIPC ();
  300. postconcat = TRUE;
  301. }
  302. else if (!preconcat && !cando)
  303. goto noSubsitute;
  304. }
  305. for (pT = pMCur->pParmNames, number = DMYBASE;
  306. *pT; pT += *pT+1, number++){
  307. if (cbName == *pT &&
  308. memcmp(naim.pszName, pT+1, *pT) == 0) {
  309. if (cbText)
  310. nextCH();
  311. pTextCur[-1] = (char)number; /* store dummy parameter index */
  312. pText = pTextCur++;
  313. if (postconcat && (preconcat || cando))
  314. ampersand = TRUE;
  315. return (pTextCur);
  316. }
  317. }
  318. noSubsitute:
  319. if (preconcat){
  320. storeCH('&');
  321. }
  322. if (postconcat)
  323. BACKC ();
  324. if (cbName + cbText >= 0x7f)
  325. nextCH();
  326. memcpy(pTextCur, svline, cbName);
  327. cbText += cbName;
  328. pTextCur += cbName;
  329. return (pTextCur);
  330. }
  331. /*** scandummy - add next atom to dummy list
  332. *
  333. * scandummy ();
  334. *
  335. * Entry
  336. * Exit
  337. * Returns
  338. * Calls
  339. */
  340. VOID PASCAL CODESIZE
  341. scandummy ()
  342. {
  343. register MC *pMC = pMCur;
  344. SHORT siz, offset;
  345. /* Scan dummy name */
  346. getatom ();
  347. if (*naim.pszName == 0) {
  348. if (!ISTERM (PEEKC ()))
  349. errorc (E_ECL);
  350. return;
  351. }
  352. pMC->count++;
  353. siz = naim.ucCount;
  354. if (pMC->cbParms < siz+2){
  355. /* relloc the string on overflow */
  356. pMC->cbParms = 32;
  357. offset = (short)(pMC->pParmAct - pMC->pParmNames);
  358. if (!(pMC->pParmNames = realloc(pMC->pParmNames, (USHORT)( offset + 32))))
  359. memerror("scandummy");
  360. pMC->pParmAct = pMC->pParmNames + offset;
  361. }
  362. *pMC->pParmAct++ = (char)siz;
  363. memcpy(pMC->pParmAct, naim.pszName, siz+1);
  364. pMC->pParmAct += siz;
  365. pMC->cbParms -= siz+1;
  366. }
  367. /*** growParm - grow the size of parmeter block
  368. *
  369. * Entry pTextCur: current text location
  370. * pText: start of currect arg
  371. * pTextEnd: end of string
  372. * Returns relloced pMCparm names
  373. */
  374. char * PASCAL CODESIZE
  375. growParm (
  376. char *pTextCur
  377. ){
  378. register MC *pMC = pMCur;
  379. long delta, i;
  380. char *pTNew;
  381. /* relloc the string on overflow */
  382. if (!(pTNew = realloc(pMC->pParmAct, (USHORT)( pTextEnd - pMC->pParmAct + 32))))
  383. memerror("growparm");
  384. delta = (long)(pTNew - pMC->pParmAct);
  385. /* Adjust all the pointers */
  386. pMC->cbParms += 32;
  387. for (i = 0; i <pMC->count; i++)
  388. pMC->rgPV[i].pActual += delta;
  389. pMC->pParmAct += delta;
  390. pTextEnd += delta + 32;
  391. pTextCur += delta;
  392. pText += delta;
  393. return (pTextCur);
  394. }
  395. /*** scanparam - scan a parameter for IRP and MACRO calls
  396. *
  397. * scanparm (irpp);
  398. *
  399. * Entry irpp = TRUE if parameters to be comma terminated
  400. * irpp = FALSE if parameters to be blank or comma terminated
  401. * Exit
  402. * Returns none
  403. * Calls
  404. */
  405. VOID PASCAL CODESIZE
  406. scanparam (
  407. UCHAR irpp
  408. ){
  409. register char *pTextCur;
  410. register UCHAR cc;
  411. USHORT bracklevel;
  412. pText = pTextCur = pMCur->pParmNames;
  413. pTextEnd = pTextCur + pMCur->cbParms;
  414. pTextCur++;
  415. bracklevel = 0;
  416. if (ISBLANK (PEEKC ()))
  417. skipblanks ();
  418. while(1) {
  419. if (pTextCur+1 >= pTextEnd)
  420. pTextCur = growParm(pTextCur);
  421. switch (cc = NEXTC ()) {
  422. case ';':
  423. if (bracklevel)
  424. break;
  425. case NULL:
  426. BACKC ();
  427. goto done;
  428. case '%': /* convert %expr to character string */
  429. pTextCur = scanvalue (pTextCur);
  430. break;
  431. case '\'':
  432. case '"':
  433. *pTextCur++ = delim = cc; /* store opening quote */
  434. while(1) {
  435. if (pTextCur >= pTextEnd)
  436. pTextCur = growParm(pTextCur);
  437. /* store next character of string */
  438. if (!(cc = NEXTC())){
  439. BACKC();
  440. goto done;
  441. }
  442. *pTextCur++ = cc;
  443. /* check for double quote character */
  444. if (cc == delim) {
  445. if (PEEKC () == delim) {
  446. *pTextCur++ = cc;
  447. SKIPC ();
  448. }
  449. else
  450. break;
  451. }
  452. }
  453. break;
  454. case '<': /* Have start of < xxx > */
  455. if (bracklevel)
  456. *pTextCur++ = cc;
  457. bracklevel++;
  458. break;
  459. case '>': /* Have end of < xxx > */
  460. if (bracklevel > 1)
  461. *pTextCur++ = cc;
  462. else{
  463. if (bracklevel == 0)
  464. BACKC();
  465. goto done;
  466. }
  467. bracklevel--;
  468. break;
  469. case '!': /* Next char is literal */
  470. *pTextCur++ = NEXTC ();
  471. break;
  472. case ' ':
  473. case '\t':
  474. case ',':
  475. if (bracklevel == 0 &&
  476. (cc == ',' || !irpp)) {
  477. BACKC ();
  478. goto done;
  479. }
  480. default:
  481. *pTextCur++ = cc;
  482. }
  483. }
  484. done:
  485. cbText = (UCHAR)(pTextCur - pText - 1); /* set byte prefix count */
  486. if (cbText > 0xfe)
  487. errorc(E_LNL);
  488. *pText = cbText;
  489. pMCur->cbParms -= cbText + 1;
  490. if (!irpp)
  491. pMCur->rgPV[pMCur->count].pActual = pText; /* point to arg */
  492. pMCur->pParmNames = pTextCur; /* set pointer to parm pool */
  493. pMCur->count++;
  494. }
  495. /*** scanvalue - evaluate expression and and store converted value
  496. *
  497. * p = scanvalue (p, lim);
  498. *
  499. * Entry p = pointer to location to store converted value
  500. * lim = limit address of buffer
  501. * Exit
  502. * Returns pointer to next character to store into
  503. * Calls exprconst, radixconvert, error
  504. */
  505. char * PASCAL CODESIZE
  506. scanvalue (
  507. char *pTextCur
  508. ){
  509. OFFSET value;
  510. register char *lastlbuf;
  511. SHORT errorIn;
  512. /* look for a text macro name thats not a constant */
  513. lastlbuf = lbufp;
  514. getatom();
  515. if (PEEKC() == ',' || ISTERM(PEEKC())) {
  516. /* try a text macro subsitution */
  517. if (symsrch () &&
  518. symptr->symkind == EQU &&
  519. symptr->symu.equ.equtyp == TEXTMACRO) {
  520. lastlbuf = symptr->symu.equ.equrec.txtmacro.equtext;
  521. while(*lastlbuf){
  522. if (pTextCur >= pTextEnd)
  523. pTextCur = growParm(pTextCur);
  524. *pTextCur++ = *lastlbuf++;
  525. }
  526. return(pTextCur);
  527. }
  528. }
  529. lbufp = lastlbuf;
  530. return(radixconvert (exprconst(), pTextCur));
  531. }
  532. /*** radixconvert - convert expression to value in current radix
  533. *
  534. * ptr = radixconvert (value, ptr, lim);
  535. *
  536. * Entry value = value to convert
  537. * ptr = location to store converted string
  538. * lim = limit address of buffer
  539. * Exit
  540. * Returns pointer to next character in store buffer
  541. * Calls error, radixconvert
  542. */
  543. #if !defined XENIX286 && !defined FLATMODEL
  544. # pragma check_stack+
  545. #endif
  546. char * PASCAL CODESIZE
  547. radixconvert (
  548. OFFSET valu,
  549. register char *p
  550. ){
  551. if (valu / radix) {
  552. p = radixconvert (valu / radix, p);
  553. valu = valu % radix;
  554. }
  555. else /* leading digit */
  556. if (valu > 9) /* do leading '0' for hex */
  557. *p++ = '0';
  558. if (p >= pTextEnd)
  559. p = growParm(p);
  560. *p++ = (char)(valu + ((valu > 9)? 'A' - 10 : '0'));
  561. return (p);
  562. }
  563. #if !defined XENIX286 && !defined FLATMODEL
  564. # pragma check_stack-
  565. #endif
  566. /*** macroexpand - expand IRP/IRPC/IRPT/MACRO
  567. *
  568. * buffer = irpxexpand ();
  569. *
  570. * Entry pMC = pointer to macro call block
  571. * Exit lbuf = next line of expansion
  572. * Returns pointer to expanded line
  573. * NULL if end of all expansions
  574. * Calls
  575. */
  576. VOID PASCAL CODESIZE
  577. macroexpand (
  578. register MC *pMC
  579. ){
  580. char FAR *lc;
  581. register USHORT cc;
  582. register UCHAR *lbp, *pParm;
  583. register USHORT cbLeft;
  584. if (pMC->count == 0) { /* Have reached end of expand */
  585. done:
  586. if (pMC->flags != TMACRO)
  587. listfree (pMC->pTSHead);
  588. deleteMC (pMC); /* Delete all params */
  589. macrolevel--;
  590. popcontext = TRUE;
  591. exitbody = FALSE;
  592. return;
  593. }
  594. while(1){
  595. if (!pMC->pTSCur) {
  596. /* End of this repeat */
  597. /* Move back to body start */
  598. pMC->pTSCur = pMC->pTSHead;
  599. if (--pMC->count == 0)
  600. goto done;
  601. if (pMC->flags <= TIRPC)
  602. pMC->rgPV[0].pActual += *pMC->rgPV[0].pActual + 1;
  603. }
  604. lineExpand(pMC, pMC->pTSCur->text);
  605. pMC->pTSCur = pMC->pTSCur->strnext;
  606. if (exitbody) { /* unroll nested if/else/endif */
  607. lastcondon = pMC->svlastcondon;
  608. condlevel = pMC->svcondlevel;
  609. elseflag = pMC->svelseflag;
  610. goto done;
  611. }
  612. break;
  613. }
  614. }
  615. #ifndef M8086OPT
  616. VOID CODESIZE
  617. lineExpand (
  618. MC *pMC,
  619. char FAR *lc /* Macro Line */
  620. ){
  621. register USHORT cc;
  622. register UCHAR *lbp, *pParm;
  623. register USHORT cbLeft;
  624. UCHAR fLenError;
  625. #ifdef BCBOPT
  626. fNoCompact = FALSE;
  627. #endif
  628. lbufp = lbp = lbuf;
  629. cbLeft = LBUFMAX - 1;
  630. fLenError = FALSE;
  631. while( cc = *lc++) {
  632. if (cc & 0x80) {
  633. cc &= 0x7F;
  634. if (cc >= pMC->iLocal) {
  635. pParm = pMC->rgPV[cc].localName;
  636. // Error if not enough room for 6 more bytes
  637. if( 6 > cbLeft ){
  638. fLenError = TRUE;
  639. break;
  640. }
  641. cbLeft -= 6;
  642. *lbp++ = '?'; /* Store "??" */
  643. *lbp++ = '?';
  644. if (pParm[0] == NULL) { /* must recreat the name */
  645. offsetAscii ((OFFSET) (pMC->localBase +
  646. cc - pMC->iLocal));
  647. *lbp++ = objectascii[0];
  648. *lbp++ = objectascii[1];
  649. *lbp++ = objectascii[2];
  650. *lbp++ = objectascii[3];
  651. }else{
  652. /* Copy 4 bytes from pParm */
  653. *lbp++ = pParm[0];
  654. *lbp++ = pParm[1];
  655. *lbp++ = pParm[2];
  656. *lbp++ = pParm[3];
  657. }
  658. }
  659. else {
  660. pParm = pMC->rgPV[cc].pActual;
  661. cc = *pParm;
  662. if( cc > cbLeft ){
  663. fLenError = TRUE;
  664. break;
  665. }
  666. cbLeft -= cc;
  667. memcpy(lbp, pParm+1, cc);
  668. lbp += cc;
  669. }
  670. }
  671. else {
  672. if( cc > cbLeft ){ /* if line too long */
  673. fLenError = TRUE;
  674. break;
  675. }
  676. cbLeft -= cc;
  677. fMemcpy(lbp, lc, cc);
  678. lc += cc;
  679. lbp += cc;
  680. }
  681. }
  682. if( fLenError ){
  683. *lbp++ = '\0'; /* Terminate the line */
  684. errorc( E_LTL & E_ERRMASK );
  685. }
  686. linebp = lbp - 1;
  687. linelength = (unsigned char)(linebp - lbufp);
  688. if( fNeedList ){
  689. strcpy( linebuffer, lbuf );
  690. }
  691. /* At exit (linebp - lbuf) == strlen( lbuf ) */
  692. }
  693. #endif
  694. /*** test4TM - tests if symbol is a text macro, and whether it is
  695. * preceded or followed by '&'
  696. *
  697. * flag = test4TM ();
  698. *
  699. * Entry lbufp points to beginning of symbol in lbuf
  700. * Exit lbufp is advanced by getatom
  701. * Returns TRUE if symbol is text macro, else FALSE
  702. * Calls getatom, symsrch
  703. */
  704. UCHAR PASCAL CODESIZE
  705. test4TM()
  706. {
  707. UCHAR ret = FALSE;
  708. if (!getatom ())
  709. return (ret);
  710. xcreflag--;
  711. if (symsrch() && (symptr->symkind == EQU)
  712. && (symptr->symu.equ.equtyp == TEXTMACRO)) {
  713. xcreflag++; /* cref reference to text macro symbol now */
  714. crefnew (REF); /* as it will be overwritten by expandTM */
  715. crefout ();
  716. /* '&' will be overwritten by equtext in lbuf */
  717. if (*(begatom - 1) == '&')
  718. begatom--;
  719. if (*endatom == '&')
  720. endatom++;
  721. ret = TRUE;
  722. } else
  723. xcreflag++;
  724. return (ret);
  725. }
  726. /*** substituteTMs - substitute equtext for each text macro symbol on line
  727. *
  728. * substituteTMs ();
  729. *
  730. * Entry lbufp points to first non-blank character after '%' in lbuf
  731. * Exit lbufp points to beginning of lbuf
  732. * Calls test4TM, expandTM, getatom, skipblanks
  733. */
  734. VOID PASCAL CODESIZE
  735. substituteTMs()
  736. {
  737. char cc;
  738. char delim;
  739. UCHAR inquote;
  740. while ((cc = PEEKC ()) && cc != ';') {
  741. inquote = FALSE;
  742. if (cc == '\'' || cc == '"') {
  743. delim = cc;
  744. cc = *(++lbufp);
  745. inquote = TRUE;
  746. }
  747. do {
  748. if (inquote && cc == '&')
  749. SKIPC ();
  750. if ((!inquote || cc == '&') && LEGAL1ST(PEEKC ())) {
  751. if (test4TM())
  752. expandTM (symptr->symu.equ.equrec.txtmacro.equtext);
  753. continue;
  754. }
  755. if (!(getatom())) {
  756. SKIPC ();
  757. skipblanks();
  758. }
  759. } while (inquote && (cc = PEEKC ()) && (cc != delim));
  760. if (inquote && (cc == delim))
  761. SKIPC ();
  762. }
  763. lbufp = lbuf;
  764. }
  765. #ifndef M8086OPT
  766. /*** expandTM - expand text macro in naim in lbuf/lbufp
  767. *
  768. * expandTM ( pReplace );
  769. *
  770. * Entry pReplace = replacement string
  771. * naim = text macro
  772. * begatom = first character in lbuf to replace
  773. * endatom = first character in lbuf after string to replace
  774. * linebp = points to null terminator in lbuf
  775. * Exit lbuf = new line to be parsed
  776. * lbufp = first character of new atom (replace string)
  777. * linebp = points to new position of null terminator in lbuf
  778. * Returns
  779. * Calls
  780. * Note Shifts characters from lbufp to make substitution of TM.
  781. * Inserts replacement string at begatom. This function could
  782. * be tweaked considerably for speed at the expense of readability.
  783. */
  784. VOID CODESIZE
  785. expandTM (
  786. register char *pReplace
  787. ){
  788. USHORT cbReplace; /* Length of the replacement string */
  789. USHORT cbNaim; /* Length of the atom to replace */
  790. USHORT cbLineEnd; /* Length of the line past the atom being replaced */
  791. cbReplace = (USHORT) strlen( pReplace );
  792. cbNaim = (USHORT)(endatom - begatom); /* Get length of the current atom */
  793. cbLineEnd = (USHORT)(linebp - endatom + 1); /* Get length of end of line */
  794. if ( (begatom - lbuf) + cbReplace + cbLineEnd > LBUFMAX) {
  795. errorc (E_LTL & E_ERRMASK);
  796. *begatom = '\0'; /* Truncate line */
  797. }else{
  798. if( cbReplace != cbNaim ){
  799. /* Shift end of line */
  800. memmove( begatom + cbReplace, endatom, cbLineEnd );
  801. }
  802. memcpy ( begatom, pReplace, cbReplace );
  803. }
  804. lbufp = begatom;
  805. linebp = begatom + cbReplace + cbLineEnd - 1;
  806. }
  807. #endif /* M8086OPT */