/tags/sdcc-222-pre1/sdcc/link/z80/lklist.c

# · C · 1270 lines · 738 code · 60 blank · 472 comment · 266 complexity · 5342477dad90fc4bc6231c5186e8ae32 MD5 · raw file

  1. /* lklist.c */
  2. /*
  3. * (C) Copyright 1989-1995
  4. * All Rights Reserved
  5. *
  6. * Alan R. Baldwin
  7. * 721 Berkeley St.
  8. * Kent, Ohio 44240
  9. */
  10. #include <stdio.h>
  11. #include <string.h>
  12. #include <alloc.h>
  13. #include "aslink.h"
  14. /*)Module lklist.c
  15. *
  16. * The module lklist.c contains the functions which
  17. * output the linker .map file and produce a relocated
  18. * listing .rst file.
  19. *
  20. * lklist.c contains the following functions:
  21. * int dgt()
  22. * VOID lstarea()
  23. * VOID lkulist()
  24. * VOID lkalist()
  25. * VOID lkglist()
  26. * VOID newpag()
  27. * VOID slew()
  28. *
  29. * lklist.c contains no local variables.
  30. */
  31. /*)Function VOID slew(fp)
  32. *
  33. * FILE * fp output file handle
  34. *
  35. * The function slew() increments the page line counter.
  36. * If the number of lines exceeds the maximum number of
  37. * lines per page then a page skip and a page header are
  38. * output.
  39. *
  40. * local variables:
  41. * int i loop counter
  42. *
  43. * global variables:
  44. * int lop current line number on page
  45. * int xflag Map file radix type flag
  46. *
  47. * functions called:
  48. * int fprintf() c_library
  49. * VOID newpag() lklist.c
  50. *
  51. * side effects:
  52. * The page line and the page count may be updated.
  53. */
  54. VOID
  55. slew(fp)
  56. FILE *fp;
  57. {
  58. register int i;
  59. if (lop++ >= NLPP) {
  60. newpag(fp);
  61. if (xflag == 0) {
  62. fprintf(fp, "Hexidecimal\n\n");
  63. } else
  64. if (xflag == 1) {
  65. fprintf(fp, "Octal\n\n");
  66. } else
  67. if (xflag == 2) {
  68. fprintf(fp, "Decimal\n\n");
  69. }
  70. fprintf(fp, "Area Addr Size");
  71. fprintf(fp, " Decimal Bytes (Attributes)\n");
  72. for(i=0;i<4;++i)
  73. fprintf(fp, " Value--Global");
  74. fprintf(fp, "\n\n");
  75. lop += 6;
  76. }
  77. }
  78. /*)Function VOID newpag()
  79. *
  80. * The function newpag() outputs a page skip, writes the
  81. * first page header line, sets the line count to 1, and
  82. * increments the page counter.
  83. *
  84. * local variables:
  85. * none
  86. *
  87. * global variables:
  88. * int lop current line number on page
  89. * int page current page number
  90. *
  91. * functions called:
  92. * int fprintf() c_library
  93. *
  94. * side effects:
  95. * The page and line counters are updated.
  96. */
  97. VOID
  98. newpag(fp)
  99. FILE *fp;
  100. {
  101. fprintf(fp, "\fASxxxx Linker %s, page %u.\n", VERSION, ++page);
  102. lop = 1;
  103. }
  104. #if NCPS-8
  105. /* NCPS != 8 */
  106. /*)Function VOID lstarea(xp)
  107. *
  108. * area * xp pointer to an area structure
  109. *
  110. * The function lstarea() creates the linker map output for
  111. * the area specified by pointer xp. The generated output
  112. * area header includes the area name, starting address,
  113. * size of area, number of words (in decimal), and the
  114. * area attributes. The symbols defined in this area are
  115. * sorted by ascending address and output one per line
  116. * in the selected radix.
  117. *
  118. * local variables:
  119. * areax * oxp pointer to an area extension structure
  120. * int c character value
  121. * int i loop counter
  122. * int j bubble sort update status
  123. * char * ptr pointer to an id string
  124. * int nmsym number of symbols in area
  125. * addr_t a0 temporary
  126. * addr_t ai temporary
  127. * addr_t aj temporary
  128. * sym * sp pointer to a symbol structure
  129. * sym ** p pointer to an array of
  130. * pointers to symbol structures
  131. *
  132. * global variables:
  133. * FILE *mfp Map output file handle
  134. * sym *symhash[NHASH] array of pointers to NHASH
  135. * linked symbol lists
  136. * int xflag Map file radix type flag
  137. *
  138. * functions called:
  139. * int fprintf() c_library
  140. * VOID free() c_library
  141. * char * malloc() c_library
  142. * char putc() c_library
  143. * VOID slew() lklist.c
  144. *
  145. * side effects:
  146. * Map output generated.
  147. */
  148. #ifndef MLH_MAP
  149. VOID
  150. lstarea(xp)
  151. struct area *xp;
  152. {
  153. register struct area *op;
  154. register struct areax *oxp;
  155. register c, i, j;
  156. register char *ptr;
  157. int nmsym;
  158. addr_t a0, ai, aj;
  159. struct sym *sp;
  160. struct sym **p;
  161. putc('\n', mfp);
  162. if (xflag == 0) {
  163. fprintf(mfp, "Hexidecimal\n\n");
  164. } else
  165. if (xflag == 1) {
  166. fprintf(mfp, "Octal\n\n");
  167. } else
  168. if (xflag == 2) {
  169. fprintf(mfp, "Decimal\n\n");
  170. }
  171. fprintf(mfp, "Area ");
  172. fprintf(mfp, "Addr Size Decimal Bytes (Attributes)\n");
  173. fprintf(mfp, "-------------------------------- ");
  174. fprintf(mfp, "---- ---- ------- ----- ------------\n");
  175. /*
  176. * Output Area Header
  177. */
  178. ptr = &xp->a_id[0];
  179. while (ptr < &xp->a_id[NCPS]) {
  180. if ((c = *ptr++) != 0) {
  181. putc(c, mfp);
  182. } else {
  183. putc(' ', mfp);
  184. }
  185. }
  186. ai = xp->a_addr;
  187. aj = xp->a_size;
  188. if (xflag == 0) {
  189. fprintf(mfp, " %04X %04X", ai, aj);
  190. } else
  191. if (xflag == 1) {
  192. fprintf(mfp, " %06o %06o", ai, aj);
  193. } else
  194. if (xflag == 2) {
  195. fprintf(mfp, " %05u %05u", ai, aj);
  196. }
  197. fprintf(mfp, " = %6u. bytes ", aj);
  198. if (xp->a_flag & A_ABS) {
  199. fprintf(mfp, "(ABS");
  200. } else {
  201. fprintf(mfp, "(REL");
  202. }
  203. if (xp->a_flag & A_OVR) {
  204. fprintf(mfp, ",OVR");
  205. } else {
  206. fprintf(mfp, ",CON");
  207. }
  208. if (xp->a_flag & A_PAG) {
  209. fprintf(mfp, ",PAG");
  210. }
  211. fprintf(mfp, ")");
  212. if (xp->a_flag & A_PAG) {
  213. ai = (ai & 0xFF);
  214. aj = (aj > 256);
  215. if (ai || aj) { fprintf(mfp, " "); }
  216. if (ai) { fprintf(mfp, " Boundary"); }
  217. if (ai & aj) { fprintf(mfp, " /"); }
  218. if (aj) { fprintf(mfp, " Length"); }
  219. if (ai || aj) { fprintf(mfp, " Error"); }
  220. }
  221. /*
  222. * Find number of symbols in area
  223. */
  224. nmsym = 0;
  225. oxp = xp->a_axp;
  226. while (oxp) {
  227. for (i=0; i<NHASH; i++) {
  228. sp = symhash[i];
  229. while (sp != NULL) {
  230. if (oxp == sp->s_axp)
  231. ++nmsym;
  232. sp = sp->s_sp;
  233. }
  234. }
  235. oxp = oxp->a_axp;
  236. }
  237. if (nmsym == 0) {
  238. putc('\n', mfp);
  239. return;
  240. }
  241. /*
  242. * Allocate space for an array of pointers to symbols
  243. * and load array.
  244. */
  245. if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
  246. == NULL) {
  247. fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
  248. return;
  249. }
  250. nmsym = 0;
  251. oxp = xp->a_axp;
  252. while (oxp) {
  253. for (i=0; i<NHASH; i++) {
  254. sp = symhash[i];
  255. while (sp != NULL) {
  256. if (oxp == sp->s_axp) {
  257. p[nmsym++] = sp;
  258. }
  259. sp = sp->s_sp;
  260. }
  261. }
  262. oxp = oxp->a_axp;
  263. }
  264. /*
  265. * Bubble Sort of Addresses in Symbol Table Array
  266. */
  267. j = 1;
  268. while (j) {
  269. j = 0;
  270. sp = p[0];
  271. a0 = sp->s_addr + sp->s_axp->a_addr;
  272. for (i=1; i<nmsym; ++i) {
  273. sp = p[i];
  274. ai = sp->s_addr + sp->s_axp->a_addr;
  275. if (a0 > ai) {
  276. j = 1;
  277. p[i] = p[i-1];
  278. p[i-1] = sp;
  279. }
  280. a0 = ai;
  281. }
  282. }
  283. /*
  284. * Symbol Table Output
  285. */
  286. i = 0;
  287. fprintf(mfp, "\n\n");
  288. fprintf(mfp, " Value Global\n");
  289. fprintf(mfp, " ----- --------------------------------");
  290. while (i < nmsym) {
  291. fprintf(mfp, "\n");
  292. fprintf(mfp, " ");
  293. sp = p[i];
  294. aj = sp->s_addr + sp->s_axp->a_addr;
  295. if (xflag == 0) {
  296. fprintf(mfp, " %04X ", aj);
  297. } else
  298. if (xflag == 1) {
  299. fprintf(mfp, "%06o ", aj);
  300. } else
  301. if (xflag == 2) {
  302. fprintf(mfp, " %05u ", aj);
  303. }
  304. ptr = &sp->s_id[0];
  305. while (ptr < &sp->s_id[NCPS]) {
  306. if ((c = *ptr++) != 0) {
  307. putc(c, mfp);
  308. } else {
  309. putc(' ', mfp);
  310. }
  311. }
  312. i++;
  313. }
  314. putc('\n', mfp);
  315. free(p);
  316. }
  317. #else
  318. VOID lstarea(struct area *xp)
  319. {
  320. register struct areax *oxp;
  321. register int i, j;
  322. int nmsym;
  323. addr_t a0, ai, aj;
  324. struct sym *sp;
  325. struct sym **p;
  326. /*
  327. * Find number of symbols in area
  328. */
  329. nmsym = 0;
  330. oxp = xp->a_axp;
  331. while (oxp) {
  332. for (i=0; i<NHASH; i++) {
  333. sp = symhash[i];
  334. while (sp != NULL) {
  335. if (oxp == sp->s_axp)
  336. ++nmsym;
  337. sp = sp->s_sp;
  338. }
  339. }
  340. oxp = oxp->a_axp;
  341. }
  342. /*
  343. * Symbol Table Output
  344. */
  345. if (!((xp->a_size==0)&&(xp->a_addr==0)&&(nmsym==0))) {
  346. fprintf(mfp, "AREA %s\n", xp->a_id );
  347. switch (xflag) {
  348. case 1:
  349. fprintf(mfp, "\tRADIX OCTAL\n" );
  350. break;
  351. case 2:
  352. fprintf(mfp, "\tRADIX DEC\n" );
  353. break;
  354. default:
  355. fprintf(mfp, "\tRADIX HEX\n" );
  356. break;
  357. }
  358. fprintf( mfp, "\tBASE %04X\n"
  359. "\tSIZE %04X\n"
  360. "\tATTRIB "
  361. , xp->a_addr, xp->a_size );
  362. if (xp->a_flag & A_ABS) {
  363. fprintf(mfp, "ABS");
  364. } else {
  365. fprintf(mfp, "REL");
  366. }
  367. if (xp->a_flag & A_OVR) {
  368. fprintf(mfp, " OVR");
  369. } else {
  370. fprintf(mfp, " CON");
  371. }
  372. if (xp->a_flag & A_PAG) {
  373. fprintf(mfp, " PAG");
  374. }
  375. if (xp->a_flag & A_PAG) {
  376. ai = (ai & 0xFF);
  377. aj = (aj > 256);
  378. if (ai || aj) { fprintf(mfp, " "); }
  379. if (ai) { fprintf(mfp, " Boundary"); }
  380. if (ai & aj) { fprintf(mfp, " /"); }
  381. if (aj) { fprintf(mfp, " Length"); }
  382. if (ai || aj) { fprintf(mfp, " Error"); }
  383. }
  384. fprintf( mfp,"\n");
  385. if (nmsym>0) {
  386. /*
  387. * Allocate space for an array of pointers to symbols
  388. * and load array.
  389. */
  390. if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
  391. == NULL) {
  392. fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
  393. return;
  394. }
  395. nmsym = 0;
  396. oxp = xp->a_axp;
  397. while (oxp) {
  398. for (i=0; i<NHASH; i++) {
  399. sp = symhash[i];
  400. while (sp != NULL) {
  401. if (oxp == sp->s_axp) {
  402. p[nmsym++] = sp;
  403. }
  404. sp = sp->s_sp;
  405. }
  406. }
  407. oxp = oxp->a_axp;
  408. }
  409. /*
  410. * Bubble Sort of Addresses in Symbol Table Array
  411. */
  412. j = 1;
  413. while (j) {
  414. j = 0;
  415. sp = p[0];
  416. a0 = sp->s_addr + sp->s_axp->a_addr;
  417. for (i=1; i<nmsym; ++i) {
  418. sp = p[i];
  419. ai = sp->s_addr + sp->s_axp->a_addr;
  420. if (a0 > ai) {
  421. j = 1;
  422. p[i] = p[i-1];
  423. p[i-1] = sp;
  424. }
  425. a0 = ai;
  426. }
  427. }
  428. fprintf( mfp, "\tGLOBALS\n");
  429. i = 0;
  430. while (i < nmsym) {
  431. fprintf(mfp, "\t\t%s\t%04X\n", p[i]->s_id, p[i]->s_addr + p[i]->s_axp->a_addr );
  432. i++;
  433. }
  434. free(p);
  435. }
  436. }
  437. }
  438. #endif /* MLH_MAP */
  439. #else
  440. /* NCPS == 8 */
  441. /*)Function VOID lstarea(xp)
  442. *
  443. * area * xp pointer to an area structure
  444. *
  445. * The function lstarea() creates the linker map output for
  446. * the area specified by pointer xp. The generated output
  447. * area header includes the area name, starting address,
  448. * size of area, number of words (in decimal), and the
  449. * area attributes. The symbols defined in this area are
  450. * sorted by ascending address and output four per line
  451. * in the selected radix.
  452. *
  453. * local variables:
  454. * areax * oxp pointer to an area extension structure
  455. * int c character value
  456. * int i loop counter
  457. * int j bubble sort update status
  458. * char * ptr pointer to an id string
  459. * int nmsym number of symbols in area
  460. * addr_t a0 temporary
  461. * addr_t ai temporary
  462. * addr_t aj temporary
  463. * sym * sp pointer to a symbol structure
  464. * sym ** p pointer to an array of
  465. * pointers to symbol structures
  466. *
  467. * global variables:
  468. * FILE *mfp Map output file handle
  469. * sym *symhash[NHASH] array of pointers to NHASH
  470. * linked symbol lists
  471. * int xflag Map file radix type flag
  472. *
  473. * functions called:
  474. * int fprintf() c_library
  475. * VOID free() c_library
  476. * char * malloc() c_library
  477. * char putc() c_library
  478. * VOID slew() lklist.c
  479. *
  480. * side effects:
  481. * Map output generated.
  482. */
  483. VOID
  484. lstarea(xp)
  485. struct area *xp;
  486. {
  487. register struct areax *oxp;
  488. register c, i, j;
  489. register char *ptr;
  490. int nmsym;
  491. addr_t a0, ai, aj;
  492. struct sym *sp;
  493. struct sym **p;
  494. putc('\n', mfp);
  495. slew(mfp);
  496. /*
  497. * Output Area Header
  498. */
  499. ptr = &xp->a_id[0];
  500. while (ptr < &xp->a_id[NCPS]) {
  501. if ((c = *ptr++) != 0) {
  502. putc(c, mfp);
  503. } else {
  504. putc(' ', mfp);
  505. }
  506. }
  507. ai = xp->a_addr;
  508. aj = xp->a_size;
  509. if (xflag == 0) {
  510. fprintf(mfp, " %04X %04X", ai, aj);
  511. } else
  512. if (xflag == 1) {
  513. fprintf(mfp, " %06o %06o", ai, aj);
  514. } else
  515. if (xflag == 2) {
  516. fprintf(mfp, " %05u %05u", ai, aj);
  517. }
  518. fprintf(mfp, " = %6u. bytes ", aj);
  519. if (xp->a_flag & A_ABS) {
  520. fprintf(mfp, "(ABS");
  521. } else {
  522. fprintf(mfp, "(REL");
  523. }
  524. if (xp->a_flag & A_OVR) {
  525. fprintf(mfp, ",OVR");
  526. } else {
  527. fprintf(mfp, ",CON");
  528. }
  529. if (xp->a_flag & A_PAG) {
  530. fprintf(mfp, ",PAG");
  531. }
  532. fprintf(mfp, ")");
  533. if (xp->a_flag & A_PAG) {
  534. ai = (ai & 0xFF);
  535. aj = (aj > 256);
  536. if (ai || aj) { fprintf(mfp, " "); }
  537. if (ai) { fprintf(mfp, " Boundary"); }
  538. if (ai & aj) { fprintf(mfp, " /"); }
  539. if (aj) { fprintf(mfp, " Length"); }
  540. if (ai || aj) { fprintf(mfp, " Error"); }
  541. }
  542. /*
  543. * Find number of symbols in area
  544. */
  545. nmsym = 0;
  546. oxp = xp->a_axp;
  547. while (oxp) {
  548. for (i=0; i<NHASH; i++) {
  549. sp = symhash[i];
  550. while (sp != NULL) {
  551. if (oxp == sp->s_axp)
  552. ++nmsym;
  553. sp = sp->s_sp;
  554. }
  555. }
  556. oxp = oxp->a_axp;
  557. }
  558. if (nmsym == 0) {
  559. putc('\n', mfp);
  560. slew(mfp);
  561. return;
  562. }
  563. /*
  564. * Allocate space for an array of pointers to symbols
  565. * and load array.
  566. */
  567. if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
  568. == NULL) {
  569. fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
  570. slew(mfp);
  571. return;
  572. }
  573. nmsym = 0;
  574. oxp = xp->a_axp;
  575. while (oxp) {
  576. for (i=0; i<NHASH; i++) {
  577. sp = symhash[i];
  578. while (sp != NULL) {
  579. if (oxp == sp->s_axp) {
  580. p[nmsym++] = sp;
  581. }
  582. sp = sp->s_sp;
  583. }
  584. }
  585. oxp = oxp->a_axp;
  586. }
  587. /*
  588. * Bubble Sort of Addresses in Symbol Table Array
  589. */
  590. j = 1;
  591. while (j) {
  592. j = 0;
  593. sp = p[0];
  594. a0 = sp->s_addr + sp->s_axp->a_addr;
  595. for (i=1; i<nmsym; ++i) {
  596. sp = p[i];
  597. ai = sp->s_addr + sp->s_axp->a_addr;
  598. if (a0 > ai) {
  599. j = 1;
  600. p[i] = p[i-1];
  601. p[i-1] = sp;
  602. }
  603. a0 = ai;
  604. }
  605. }
  606. /*
  607. * Symbol Table Output
  608. */
  609. i = 0;
  610. while (i < nmsym) {
  611. if (i % 4 == 0) {
  612. fprintf(mfp, "\n");
  613. slew(mfp);
  614. fprintf(mfp, " ");
  615. }
  616. sp = p[i];
  617. aj = sp->s_addr + sp->s_axp->a_addr;
  618. if (xflag == 0) {
  619. fprintf(mfp, " %04X ", aj);
  620. } else
  621. if (xflag == 1) {
  622. fprintf(mfp, "%06o ", aj);
  623. } else
  624. if (xflag == 2) {
  625. fprintf(mfp, " %05u ", aj);
  626. }
  627. ptr = &sp->s_id[0];
  628. while (ptr < &sp->s_id[NCPS]) {
  629. if ((c = *ptr++) != 0) {
  630. putc(c, mfp);
  631. } else {
  632. putc(' ', mfp);
  633. }
  634. }
  635. if (++i < nmsym)
  636. if (i % 4 != 0)
  637. fprintf(mfp, " | ");
  638. }
  639. putc('\n', mfp);
  640. free(p);
  641. slew(mfp);
  642. }
  643. #endif
  644. #ifdef SDK
  645. VOID lstareatosym(struct area *xp)
  646. {
  647. /* Output the current area symbols to a NO$GMB .sym file */
  648. register struct areax *oxp;
  649. register int i, j;
  650. int nmsym;
  651. addr_t a0, ai;
  652. struct sym *sp;
  653. struct sym **p;
  654. /*
  655. * Find number of symbols in area
  656. */
  657. nmsym = 0;
  658. oxp = xp->a_axp;
  659. while (oxp) {
  660. for (i=0; i<NHASH; i++) {
  661. sp = symhash[i];
  662. while (sp != NULL) {
  663. if (oxp == sp->s_axp)
  664. ++nmsym;
  665. sp = sp->s_sp;
  666. }
  667. }
  668. oxp = oxp->a_axp;
  669. }
  670. /*
  671. * Symbol Table Output
  672. */
  673. if (!((xp->a_size==0)&&(xp->a_addr==0)&&(nmsym==0))) {
  674. /* Dont worry about any area information */
  675. fprintf(mfp, "; Area: %s\n", xp->a_id );
  676. if (nmsym>0) {
  677. /*
  678. * Allocate space for an array of pointers to symbols
  679. * and load array.
  680. */
  681. if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
  682. == NULL) {
  683. fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
  684. return;
  685. }
  686. nmsym = 0;
  687. oxp = xp->a_axp;
  688. while (oxp) {
  689. for (i=0; i<NHASH; i++) {
  690. sp = symhash[i];
  691. while (sp != NULL) {
  692. if (oxp == sp->s_axp) {
  693. p[nmsym++] = sp;
  694. }
  695. sp = sp->s_sp;
  696. }
  697. }
  698. oxp = oxp->a_axp;
  699. }
  700. /*
  701. * Bubble Sort of Addresses in Symbol Table Array
  702. */
  703. j = 1;
  704. while (j) {
  705. j = 0;
  706. sp = p[0];
  707. a0 = sp->s_addr + sp->s_axp->a_addr;
  708. for (i=1; i<nmsym; ++i) {
  709. sp = p[i];
  710. ai = sp->s_addr + sp->s_axp->a_addr;
  711. if (a0 > ai) {
  712. j = 1;
  713. p[i] = p[i-1];
  714. p[i-1] = sp;
  715. }
  716. a0 = ai;
  717. }
  718. }
  719. i = 0;
  720. while (i < nmsym) {
  721. /* no$gmb requires the symbol names to be less than 32 chars long. Truncate. */
  722. char name[32];
  723. strncpy(name, p[i]->s_id, 31);
  724. name[31] = '\0';
  725. if ((strncmp("l__", name, 3)!=0)&&(strchr(name,' ')==NULL)) {
  726. a0=p[i]->s_addr + p[i]->s_axp->a_addr;
  727. if (a0>0x7FFFU) {
  728. /* Not inside the ROM, so treat as being in bank zero */
  729. fprintf(mfp, "00:%04X %s\n", a0, name);
  730. }
  731. else {
  732. fprintf(mfp, "%02X:%04X %s\n", a0/16384, a0, name);
  733. }
  734. }
  735. i++;
  736. }
  737. free(p);
  738. }
  739. }
  740. }
  741. #endif
  742. /*)Function VOID lkulist(i)
  743. *
  744. * int i i # 0 process LST to RST file
  745. * i = 0 copy remainder of LST file
  746. * to RST file and close files
  747. *
  748. * The function lkulist() creates a relocated listing (.rst)
  749. * output file from the ASxxxx assembler listing (.lst)
  750. * files. The .lst file's program address and code bytes
  751. * are changed to reflect the changes made by ASlink as
  752. * the .rel files are combined into a single relocated
  753. * output file.
  754. *
  755. * local variables:
  756. * addr_t pc current program counter address
  757. *
  758. * global variables:
  759. * int hilo byte order
  760. * int gline get a line from the LST file
  761. * to translate for the RST file
  762. * char rb[] read listing file text line
  763. * FILE *rfp The file handle to the current
  764. * output RST file
  765. * int rtcnt count of data words
  766. * int rtflg[] output the data flag
  767. * addr_t rtval[] relocated data
  768. * FILE *tfp The file handle to the current
  769. * LST file being scanned
  770. *
  771. * functions called:
  772. * int fclose() c_library
  773. * int fgets() c_library
  774. * int fprintf() c_library
  775. * VOID lkalist() lklist.c
  776. * VOID lkglist() lklist.c
  777. *
  778. * side effects:
  779. * A .rst file is created for each available .lst
  780. * file associated with a .rel file.
  781. */
  782. VOID
  783. lkulist(i)
  784. int i;
  785. {
  786. addr_t pc;
  787. /*
  788. * Exit if listing file is not open
  789. */
  790. if (tfp == NULL)
  791. return;
  792. /*
  793. * Normal processing of LST to RST
  794. */
  795. if (i) {
  796. /*
  797. * Evaluate current code address
  798. */
  799. if (hilo == 0) {
  800. pc = ((rtval[1] & 0xFF) << 8) + (rtval[0] & 0xFF);
  801. } else {
  802. pc = ((rtval[0] & 0xFF) << 8) + (rtval[1] & 0xFF);
  803. }
  804. /*
  805. * Line with only address
  806. */
  807. if (rtcnt == 2) {
  808. lkalist(pc);
  809. /*
  810. * Line with address and code
  811. */
  812. } else {
  813. for (i=2; i < rtcnt; i++) {
  814. if (rtflg[i]) {
  815. lkglist(pc++, rtval[i] & 0xFF);
  816. }
  817. }
  818. }
  819. /*
  820. * Copy remainder of LST to RST
  821. */
  822. } else {
  823. if (gline == 0)
  824. fprintf(rfp, rb);
  825. while (fgets(rb, sizeof(rb), tfp) != 0) {
  826. fprintf(rfp, rb);
  827. }
  828. fclose(tfp);
  829. tfp = NULL;
  830. fclose(rfp);
  831. rfp = NULL;
  832. }
  833. }
  834. /*)Function VOID lkalist(pc)
  835. *
  836. * int pc current program counter value
  837. *
  838. * The function lkalist() performs the following functions:
  839. *
  840. * (1) if the value of gline = 0 then the current listing
  841. * file line is copied to the relocated listing file output.
  842. *
  843. * (2) the listing file is read line by line and copied to
  844. * the relocated listing file until a valid source
  845. * line number and a program counter value of the correct
  846. * radix is found. The new relocated pc value is substituted
  847. * and the line is written to the RST file.
  848. *
  849. * local variables:
  850. * int i loop counter
  851. * char str[] temporary string
  852. *
  853. * global variables:
  854. * int gcntr data byte counter
  855. * int gline get a line from the LST file
  856. * to translate for the RST file
  857. * char rb[] read listing file text line
  858. * char *rp pointer to listing file text line
  859. * FILE *rfp The file handle to the current
  860. * output RST file
  861. * FILE *tfp The file handle to the current
  862. * LST file being scanned
  863. *
  864. * functions called:
  865. * int dgt() lklist.c
  866. * int fclose() c_library
  867. * int fgets() c_library
  868. * int fprintf() c_library
  869. * int sprintf() c_library
  870. * char * strncpy() c_library
  871. *
  872. * side effects:
  873. * Lines of the LST file are copied to the RST file,
  874. * the last line copied has the code address
  875. * updated to reflect the program relocation.
  876. */
  877. VOID
  878. lkalist(pc)
  879. addr_t pc;
  880. {
  881. char str[8];
  882. int i;
  883. /*
  884. * Exit if listing file is not open
  885. */
  886. loop: if (tfp == NULL)
  887. return;
  888. /*
  889. * Copy current LST to RST
  890. */
  891. if (gline == 0) {
  892. fprintf(rfp, rb);
  893. gline = 1;
  894. }
  895. /*
  896. * Clear text line buffer
  897. */
  898. for (i=0,rp=rb; i<sizeof(rb); i++) {
  899. *rp++ = 0;
  900. }
  901. /*
  902. * Get next LST text line
  903. */
  904. if (fgets(rb, sizeof(rb), tfp) == NULL) {
  905. fclose(tfp);
  906. tfp = NULL;
  907. fclose(rfp);
  908. rfp = NULL;
  909. return;
  910. }
  911. /*
  912. * Must have an ASxxxx Listing line number
  913. */
  914. if (!dgt(RAD10, &rb[30], 1)) {
  915. fprintf(rfp, rb);
  916. goto loop;
  917. }
  918. /*
  919. * Must have an address in the expected radix
  920. */
  921. if (radix == 16) {
  922. if (!dgt(RAD16, &rb[3], 4)) {
  923. fprintf(rfp, rb);
  924. goto loop;
  925. }
  926. sprintf(str, "%04X", pc);
  927. strncpy(&rb[3], str, 4);
  928. } else
  929. if (radix == 10) {
  930. if (!dgt(RAD10, &rb[3], 5)) {
  931. fprintf(rfp, rb);
  932. goto loop;
  933. }
  934. sprintf(str, "%05d", pc);
  935. strncpy(&rb[3], str, 5);
  936. } else
  937. if (radix == 8) {
  938. if (!dgt(RAD8, &rb[3], 6)) {
  939. fprintf(rfp, rb);
  940. goto loop;
  941. }
  942. sprintf(str, "%06o", pc);
  943. strncpy(&rb[3], str, 6);
  944. }
  945. /*
  946. * Copy updated LST text line to RST
  947. */
  948. fprintf(rfp, rb);
  949. gcntr = 0;
  950. }
  951. /*)Function VOID lkglist(pc,v)
  952. *
  953. * int pc current program counter value
  954. * int v value of byte at this address
  955. *
  956. * The function lkglist() performs the following functions:
  957. *
  958. * (1) if the value of gline = 1 then the listing file
  959. * is read line by line and copied to the
  960. * relocated listing file until a valid source
  961. * line number and a program counter value of the correct
  962. * radix is found.
  963. *
  964. * (2) The new relocated values and code address are
  965. * substituted and the line may be written to the RST file.
  966. *
  967. * local variables:
  968. * int i loop counter
  969. * char str[] temporary string
  970. *
  971. * global variables:
  972. * int gcntr data byte counter
  973. * set to -1 for a continuation line
  974. * int gline get a line from the LST file
  975. * to translate for the RST file
  976. * char rb[] read listing file text line
  977. * char *rp pointer to listing file text line
  978. * FILE *rfp The file handle to the current
  979. * output RST file
  980. * FILE *tfp The file handle to the current
  981. * LST file being scanned
  982. *
  983. * functions called:
  984. * int dgt() lklist.c
  985. * int fclose() c_library
  986. * int fgets() c_library
  987. * int fprintf() c_library
  988. * int sprintf() c_library
  989. * char * strncpy() c_library
  990. *
  991. * side effects:
  992. * Lines of the LST file are copied to the RST file
  993. * with updated data values and code addresses.
  994. */
  995. VOID
  996. lkglist(pc,v)
  997. addr_t pc;
  998. int v;
  999. {
  1000. char str[8];
  1001. int i;
  1002. /*
  1003. * Exit if listing file is not open
  1004. */
  1005. loop: if (tfp == NULL)
  1006. return;
  1007. /*
  1008. * Get next LST text line
  1009. */
  1010. if (gline) {
  1011. /*
  1012. * Clear text line buffer
  1013. */
  1014. for (i=0,rp=rb; i<sizeof(rb); i++) {
  1015. *rp++ = 0;
  1016. }
  1017. /*
  1018. * Get next LST text line
  1019. */
  1020. if (fgets(rb, sizeof(rb), tfp) == NULL) {
  1021. fclose(tfp);
  1022. tfp = NULL;
  1023. fclose(rfp);
  1024. rfp = NULL;
  1025. return;
  1026. }
  1027. /*
  1028. * Check for a listing line number if required
  1029. */
  1030. if (gcntr != -1) {
  1031. if (!dgt(RAD10, &rb[30], 1)) {
  1032. fprintf(rfp, rb);
  1033. goto loop;
  1034. }
  1035. gcntr = 0;
  1036. }
  1037. gline = 0;
  1038. }
  1039. /*
  1040. * Hex Listing
  1041. */
  1042. if (radix == 16) {
  1043. /*
  1044. * Data Byte Pointer
  1045. */
  1046. if (gcntr == -1) {
  1047. rp = &rb[8];
  1048. } else {
  1049. rp = &rb[8 + (3 * gcntr)];
  1050. }
  1051. /*
  1052. * Number must be of proper radix
  1053. */
  1054. if (!dgt(RAD16, rp, 2)) {
  1055. fprintf(rfp, rb);
  1056. gline = 1;
  1057. goto loop;
  1058. }
  1059. /*
  1060. * Output new data value, overwrite relocation codes
  1061. */
  1062. sprintf(str, " %02X", v);
  1063. strncpy(rp-1, str, 3);
  1064. if (gcntr == -1) {
  1065. gcntr = 0;
  1066. }
  1067. /*
  1068. * Output relocated code address
  1069. */
  1070. if (gcntr == 0) {
  1071. if (dgt(RAD16, &rb[3], 4)) {
  1072. sprintf(str, "%04X", pc);
  1073. strncpy(&rb[3], str, 4);
  1074. }
  1075. }
  1076. /*
  1077. * Output text line when updates finished
  1078. */
  1079. if (++gcntr == 6) {
  1080. fprintf(rfp, rb);
  1081. gline = 1;
  1082. gcntr = -1;
  1083. }
  1084. } else
  1085. /*
  1086. * Decimal Listing
  1087. */
  1088. if (radix == 10) {
  1089. /*
  1090. * Data Byte Pointer
  1091. */
  1092. if (gcntr == -1) {
  1093. rp = &rb[9];
  1094. } else {
  1095. rp = &rb[9 + (3 * gcntr)];
  1096. }
  1097. /*
  1098. * Number must be of proper radix
  1099. */
  1100. if (!dgt(RAD10, rp, 3)) {
  1101. fprintf(rfp, rb);
  1102. gline = 1;
  1103. goto loop;
  1104. }
  1105. /*
  1106. * Output new data value, overwrite relocation codes
  1107. */
  1108. sprintf(str, " %03d", v);
  1109. strncpy(rp-1, str, 4);
  1110. if (gcntr == -1) {
  1111. gcntr = 0;
  1112. }
  1113. /*
  1114. * Output relocated code address
  1115. */
  1116. if (gcntr == 0) {
  1117. if (dgt(RAD10, &rb[3], 5)) {
  1118. sprintf(str, "%05d", pc);
  1119. strncpy(&rb[3], str, 5);
  1120. }
  1121. }
  1122. /*
  1123. * Output text line when updates finished
  1124. */
  1125. if (++gcntr == 4) {
  1126. fprintf(rfp, rb);
  1127. gline = 1;
  1128. gcntr = -1;
  1129. }
  1130. } else
  1131. /*
  1132. * Octal Listing
  1133. */
  1134. if (radix == 8) {
  1135. /*
  1136. * Data Byte Pointer
  1137. */
  1138. if (gcntr == -1) {
  1139. rp = &rb[10];
  1140. } else {
  1141. rp = &rb[10 + (3 * gcntr)];
  1142. }
  1143. /*
  1144. * Number must be of proper radix
  1145. */
  1146. if (!dgt(RAD8, rp, 3)) {
  1147. fprintf(rfp, rb);
  1148. gline = 1;
  1149. goto loop;
  1150. }
  1151. /*
  1152. * Output new data value, overwrite relocation codes
  1153. */
  1154. sprintf(str, " %03o", v);
  1155. strncpy(rp-1, str, 4);
  1156. if (gcntr == -1) {
  1157. gcntr = 0;
  1158. }
  1159. /*
  1160. * Output relocated code address
  1161. */
  1162. if (gcntr == 0) {
  1163. if (dgt(RAD8, &rb[3], 6)) {
  1164. sprintf(str, "%06o", pc);
  1165. strncpy(&rb[3], str, 6);
  1166. }
  1167. }
  1168. /*
  1169. * Output text line when updates finished
  1170. */
  1171. if (++gcntr == 4) {
  1172. fprintf(rfp, rb);
  1173. gline = 1;
  1174. gcntr = -1;
  1175. }
  1176. }
  1177. }
  1178. /*)Function int dgt(rdx,str,n)
  1179. *
  1180. * int rdx radix bit code
  1181. * char *str pointer to the test string
  1182. * int n number of characters to check
  1183. *
  1184. * The function dgt() verifies that the string under test
  1185. * is of the specified radix.
  1186. *
  1187. * local variables:
  1188. * int i loop counter
  1189. *
  1190. * global variables:
  1191. * ctype[] array of character types
  1192. *
  1193. * functions called:
  1194. * none
  1195. *
  1196. * side effects:
  1197. * none
  1198. */
  1199. int
  1200. dgt(rdx, str, n)
  1201. int rdx, n;
  1202. char *str;
  1203. {
  1204. int i;
  1205. for (i=0; i<n; i++) {
  1206. if ((ctype[*str++] & rdx) == 0)
  1207. return(0);
  1208. }
  1209. return(1);
  1210. }