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.

1045 lines
26 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. SKIPC();
  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. {
  359. void *pv = realloc(pMC->pParmNames, (USHORT)( offset + 32));
  360. if (!pv)
  361. memerror("scandummy");
  362. else
  363. pMC->pParmNames = pv;
  364. }
  365. pMC->pParmAct = pMC->pParmNames + offset;
  366. }
  367. *pMC->pParmAct++ = (char)siz;
  368. memcpy(pMC->pParmAct, naim.pszName, siz+1);
  369. pMC->pParmAct += siz;
  370. pMC->cbParms -= siz+1;
  371. }
  372. /*** growParm - grow the size of parmeter block
  373. *
  374. * Entry pTextCur: current text location
  375. * pText: start of currect arg
  376. * pTextEnd: end of string
  377. * Returns relloced pMCparm names
  378. */
  379. char * PASCAL CODESIZE
  380. growParm (
  381. char *pTextCur
  382. ){
  383. register MC *pMC = pMCur;
  384. long delta, i;
  385. char *pTNew;
  386. /* relloc the string on overflow */
  387. if (!(pTNew = realloc(pMC->pParmAct, (USHORT)( pTextEnd - pMC->pParmAct + 32))))
  388. memerror("growparm");
  389. delta = (long)(pTNew - pMC->pParmAct);
  390. /* Adjust all the pointers */
  391. pMC->cbParms += 32;
  392. for (i = 0; i <pMC->count; i++)
  393. pMC->rgPV[i].pActual += delta;
  394. pMC->pParmAct += delta;
  395. pTextEnd += delta + 32;
  396. pTextCur += delta;
  397. pText += delta;
  398. return (pTextCur);
  399. }
  400. /*** scanparam - scan a parameter for IRP and MACRO calls
  401. *
  402. * scanparm (irpp);
  403. *
  404. * Entry irpp = TRUE if parameters to be comma terminated
  405. * irpp = FALSE if parameters to be blank or comma terminated
  406. * Exit
  407. * Returns none
  408. * Calls
  409. */
  410. VOID PASCAL CODESIZE
  411. scanparam (
  412. UCHAR irpp
  413. ){
  414. register char *pTextCur;
  415. register UCHAR cc;
  416. USHORT bracklevel;
  417. pText = pTextCur = pMCur->pParmNames;
  418. pTextEnd = pTextCur + pMCur->cbParms;
  419. pTextCur++;
  420. bracklevel = 0;
  421. if (ISBLANK (PEEKC ()))
  422. skipblanks ();
  423. while(1) {
  424. if (pTextCur+1 >= pTextEnd)
  425. pTextCur = growParm(pTextCur);
  426. switch (cc = NEXTC ()) {
  427. case ';':
  428. if (bracklevel)
  429. break;
  430. case NULL:
  431. BACKC ();
  432. goto done;
  433. case '%': /* convert %expr to character string */
  434. pTextCur = scanvalue (pTextCur);
  435. break;
  436. case '\'':
  437. case '"':
  438. *pTextCur++ = delim = cc; /* store opening quote */
  439. while(1) {
  440. if (pTextCur >= pTextEnd)
  441. pTextCur = growParm(pTextCur);
  442. /* store next character of string */
  443. if (!(cc = NEXTC())){
  444. BACKC();
  445. goto done;
  446. }
  447. *pTextCur++ = cc;
  448. /* check for double quote character */
  449. if (cc == delim) {
  450. if (PEEKC () == delim) {
  451. *pTextCur++ = cc;
  452. SKIPC ();
  453. }
  454. else
  455. break;
  456. }
  457. }
  458. break;
  459. case '<': /* Have start of < xxx > */
  460. if (bracklevel)
  461. *pTextCur++ = cc;
  462. bracklevel++;
  463. break;
  464. case '>': /* Have end of < xxx > */
  465. if (bracklevel > 1)
  466. *pTextCur++ = cc;
  467. else{
  468. if (bracklevel == 0)
  469. BACKC();
  470. goto done;
  471. }
  472. bracklevel--;
  473. break;
  474. case '!': /* Next char is literal */
  475. *pTextCur++ = NEXTC ();
  476. break;
  477. case ' ':
  478. case '\t':
  479. case ',':
  480. if (bracklevel == 0 &&
  481. (cc == ',' || !irpp)) {
  482. BACKC ();
  483. goto done;
  484. }
  485. default:
  486. *pTextCur++ = cc;
  487. }
  488. }
  489. done:
  490. cbText = (UCHAR)(pTextCur - pText - 1); /* set byte prefix count */
  491. if (cbText > 0xfe)
  492. errorc(E_LNL);
  493. *pText = cbText;
  494. pMCur->cbParms -= cbText + 1;
  495. if (!irpp)
  496. pMCur->rgPV[pMCur->count].pActual = pText; /* point to arg */
  497. pMCur->pParmNames = pTextCur; /* set pointer to parm pool */
  498. pMCur->count++;
  499. }
  500. /*** scanvalue - evaluate expression and and store converted value
  501. *
  502. * p = scanvalue (p, lim);
  503. *
  504. * Entry p = pointer to location to store converted value
  505. * lim = limit address of buffer
  506. * Exit
  507. * Returns pointer to next character to store into
  508. * Calls exprconst, radixconvert, error
  509. */
  510. char * PASCAL CODESIZE
  511. scanvalue (
  512. char *pTextCur
  513. ){
  514. OFFSET value;
  515. register char *lastlbuf;
  516. SHORT errorIn;
  517. /* look for a text macro name thats not a constant */
  518. lastlbuf = lbufp;
  519. getatom();
  520. if (PEEKC() == ',' || ISTERM(PEEKC())) {
  521. /* try a text macro subsitution */
  522. if (symsrch () &&
  523. symptr->symkind == EQU &&
  524. symptr->symu.equ.equtyp == TEXTMACRO) {
  525. lastlbuf = symptr->symu.equ.equrec.txtmacro.equtext;
  526. while(*lastlbuf){
  527. if (pTextCur >= pTextEnd)
  528. pTextCur = growParm(pTextCur);
  529. *pTextCur++ = *lastlbuf++;
  530. }
  531. return(pTextCur);
  532. }
  533. }
  534. lbufp = lastlbuf;
  535. return(radixconvert (exprconst(), pTextCur));
  536. }
  537. /*** radixconvert - convert expression to value in current radix
  538. *
  539. * ptr = radixconvert (value, ptr, lim);
  540. *
  541. * Entry value = value to convert
  542. * ptr = location to store converted string
  543. * lim = limit address of buffer
  544. * Exit
  545. * Returns pointer to next character in store buffer
  546. * Calls error, radixconvert
  547. */
  548. #if !defined XENIX286 && !defined FLATMODEL
  549. # pragma check_stack+
  550. #endif
  551. char * PASCAL CODESIZE
  552. radixconvert (
  553. OFFSET valu,
  554. register char *p
  555. ){
  556. if (valu / radix) {
  557. p = radixconvert (valu / radix, p);
  558. valu = valu % radix;
  559. }
  560. else /* leading digit */
  561. if (valu > 9) /* do leading '0' for hex */
  562. *p++ = '0';
  563. if (p >= pTextEnd)
  564. p = growParm(p);
  565. *p++ = (char)(valu + ((valu > 9)? 'A' - 10 : '0'));
  566. return (p);
  567. }
  568. #if !defined XENIX286 && !defined FLATMODEL
  569. # pragma check_stack-
  570. #endif
  571. /*** macroexpand - expand IRP/IRPC/IRPT/MACRO
  572. *
  573. * buffer = irpxexpand ();
  574. *
  575. * Entry pMC = pointer to macro call block
  576. * Exit lbuf = next line of expansion
  577. * Returns pointer to expanded line
  578. * NULL if end of all expansions
  579. * Calls
  580. */
  581. VOID PASCAL CODESIZE
  582. macroexpand (
  583. register MC *pMC
  584. ){
  585. char FAR *lc;
  586. register USHORT cc;
  587. register UCHAR *lbp, *pParm;
  588. register USHORT cbLeft;
  589. if (pMC->count == 0) { /* Have reached end of expand */
  590. done:
  591. if (pMC->flags != TMACRO)
  592. listfree (pMC->pTSHead);
  593. deleteMC (pMC); /* Delete all params */
  594. macrolevel--;
  595. popcontext = TRUE;
  596. exitbody = FALSE;
  597. return;
  598. }
  599. while(1){
  600. if (!pMC->pTSCur) {
  601. /* End of this repeat */
  602. /* Move back to body start */
  603. pMC->pTSCur = pMC->pTSHead;
  604. if (--pMC->count == 0)
  605. goto done;
  606. if (pMC->flags <= TIRPC)
  607. pMC->rgPV[0].pActual += *pMC->rgPV[0].pActual + 1;
  608. }
  609. lineExpand(pMC, pMC->pTSCur->text);
  610. pMC->pTSCur = pMC->pTSCur->strnext;
  611. if (exitbody) { /* unroll nested if/else/endif */
  612. lastcondon = pMC->svlastcondon;
  613. condlevel = pMC->svcondlevel;
  614. elseflag = pMC->svelseflag;
  615. goto done;
  616. }
  617. break;
  618. }
  619. }
  620. #ifndef M8086OPT
  621. VOID CODESIZE
  622. lineExpand (
  623. MC *pMC,
  624. char FAR *lc /* Macro Line */
  625. ){
  626. register USHORT cc;
  627. register UCHAR *lbp, *pParm;
  628. register USHORT cbLeft;
  629. UCHAR fLenError;
  630. #ifdef BCBOPT
  631. fNoCompact = FALSE;
  632. #endif
  633. lbufp = lbp = lbuf;
  634. cbLeft = LBUFMAX - 1;
  635. fLenError = FALSE;
  636. while( cc = *lc++) {
  637. if (cc & 0x80) {
  638. cc &= 0x7F;
  639. if (cc >= pMC->iLocal) {
  640. pParm = pMC->rgPV[cc].localName;
  641. // Error if not enough room for 6 more bytes
  642. if( 6 > cbLeft ){
  643. fLenError = TRUE;
  644. break;
  645. }
  646. cbLeft -= 6;
  647. *lbp++ = '?'; /* Store "??" */
  648. *lbp++ = '?';
  649. if (pParm[0] == NULL) { /* must recreat the name */
  650. offsetAscii ((OFFSET) (pMC->localBase +
  651. cc - pMC->iLocal));
  652. *lbp++ = objectascii[0];
  653. *lbp++ = objectascii[1];
  654. *lbp++ = objectascii[2];
  655. *lbp++ = objectascii[3];
  656. }else{
  657. /* Copy 4 bytes from pParm */
  658. *lbp++ = pParm[0];
  659. *lbp++ = pParm[1];
  660. *lbp++ = pParm[2];
  661. *lbp++ = pParm[3];
  662. }
  663. }
  664. else {
  665. pParm = pMC->rgPV[cc].pActual;
  666. cc = *pParm;
  667. if( cc > cbLeft ){
  668. fLenError = TRUE;
  669. break;
  670. }
  671. cbLeft -= cc;
  672. memcpy(lbp, pParm+1, cc);
  673. lbp += cc;
  674. }
  675. }
  676. else {
  677. if( cc > cbLeft ){ /* if line too long */
  678. fLenError = TRUE;
  679. break;
  680. }
  681. cbLeft -= cc;
  682. fMemcpy(lbp, lc, cc);
  683. lc += cc;
  684. lbp += cc;
  685. }
  686. }
  687. if( fLenError ){
  688. *lbp++ = '\0'; /* Terminate the line */
  689. errorc( E_LTL & E_ERRMASK );
  690. }
  691. linebp = lbp - 1;
  692. linelength = (unsigned char)(linebp - lbufp);
  693. if( fNeedList ){
  694. strcpy( linebuffer, lbuf );
  695. }
  696. /* At exit (linebp - lbuf) == strlen( lbuf ) */
  697. }
  698. #endif
  699. /*** test4TM - tests if symbol is a text macro, and whether it is
  700. * preceded or followed by '&'
  701. *
  702. * flag = test4TM ();
  703. *
  704. * Entry lbufp points to beginning of symbol in lbuf
  705. * Exit lbufp is advanced by getatom
  706. * Returns TRUE if symbol is text macro, else FALSE
  707. * Calls getatom, symsrch
  708. */
  709. UCHAR PASCAL CODESIZE
  710. test4TM()
  711. {
  712. UCHAR ret = FALSE;
  713. if (!getatom ())
  714. return (ret);
  715. xcreflag--;
  716. if (symsrch() && (symptr->symkind == EQU)
  717. && (symptr->symu.equ.equtyp == TEXTMACRO)) {
  718. xcreflag++; /* cref reference to text macro symbol now */
  719. crefnew (REF); /* as it will be overwritten by expandTM */
  720. crefout ();
  721. /* '&' will be overwritten by equtext in lbuf */
  722. if (*(begatom - 1) == '&')
  723. begatom--;
  724. if (*endatom == '&')
  725. endatom++;
  726. ret = TRUE;
  727. } else
  728. xcreflag++;
  729. return (ret);
  730. }
  731. /*** substituteTMs - substitute equtext for each text macro symbol on line
  732. *
  733. * substituteTMs ();
  734. *
  735. * Entry lbufp points to first non-blank character after '%' in lbuf
  736. * Exit lbufp points to beginning of lbuf
  737. * Calls test4TM, expandTM, getatom, skipblanks
  738. */
  739. VOID PASCAL CODESIZE
  740. substituteTMs()
  741. {
  742. char cc;
  743. char L_delim = '/0';
  744. UCHAR inquote;
  745. while ((cc = PEEKC ()) && cc != ';') {
  746. inquote = FALSE;
  747. if (cc == '\'' || cc == '"') {
  748. L_delim = cc;
  749. cc = *(++lbufp);
  750. inquote = TRUE;
  751. }
  752. do {
  753. if (inquote && cc == '&')
  754. SKIPC ();
  755. if ((!inquote || cc == '&') && LEGAL1ST(PEEKC ())) {
  756. if (test4TM())
  757. expandTM (symptr->symu.equ.equrec.txtmacro.equtext);
  758. continue;
  759. }
  760. if (!(getatom())) {
  761. SKIPC ();
  762. skipblanks();
  763. }
  764. } while (inquote && (cc = PEEKC ()) && (cc != L_delim));
  765. if (inquote && (cc == L_delim))
  766. SKIPC ();
  767. }
  768. lbufp = lbuf;
  769. }
  770. #ifndef M8086OPT
  771. /*** expandTM - expand text macro in naim in lbuf/lbufp
  772. *
  773. * expandTM ( pReplace );
  774. *
  775. * Entry pReplace = replacement string
  776. * naim = text macro
  777. * begatom = first character in lbuf to replace
  778. * endatom = first character in lbuf after string to replace
  779. * linebp = points to null terminator in lbuf
  780. * Exit lbuf = new line to be parsed
  781. * lbufp = first character of new atom (replace string)
  782. * linebp = points to new position of null terminator in lbuf
  783. * Returns
  784. * Calls
  785. * Note Shifts characters from lbufp to make substitution of TM.
  786. * Inserts replacement string at begatom. This function could
  787. * be tweaked considerably for speed at the expense of readability.
  788. */
  789. VOID CODESIZE
  790. expandTM (
  791. register char *pReplace
  792. ){
  793. USHORT cbReplace; /* Length of the replacement string */
  794. USHORT cbNaim; /* Length of the atom to replace */
  795. USHORT cbLineEnd; /* Length of the line past the atom being replaced */
  796. cbReplace = (USHORT) strlen( pReplace );
  797. cbNaim = (USHORT)(endatom - begatom); /* Get length of the current atom */
  798. cbLineEnd = (USHORT)(linebp - endatom + 1); /* Get length of end of line */
  799. if ( (begatom - lbuf) + cbReplace + cbLineEnd > LBUFMAX) {
  800. errorc (E_LTL & E_ERRMASK);
  801. *begatom = '\0'; /* Truncate line */
  802. }else{
  803. if( cbReplace != cbNaim ){
  804. /* Shift end of line */
  805. memmove( begatom + cbReplace, endatom, cbLineEnd );
  806. }
  807. memcpy ( begatom, pReplace, cbReplace );
  808. }
  809. lbufp = begatom;
  810. linebp = begatom + cbReplace + cbLineEnd - 1;
  811. }
  812. #endif /* M8086OPT */