/branches/sdcc-221/sdcc/link/z80/lklist.c

# · C · 1272 lines · 740 code · 60 blank · 472 comment · 266 complexity · 05ff0bb50b81d64ff9cbd4ad0456a8b2 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 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 area *op;
  321. register struct areax *oxp;
  322. register c, i, j;
  323. register char *ptr;
  324. int nmsym;
  325. addr_t a0, ai, aj;
  326. struct sym *sp;
  327. struct sym **p;
  328. /*
  329. * Find number of symbols in area
  330. */
  331. nmsym = 0;
  332. oxp = xp->a_axp;
  333. while (oxp) {
  334. for (i=0; i<NHASH; i++) {
  335. sp = symhash[i];
  336. while (sp != NULL) {
  337. if (oxp == sp->s_axp)
  338. ++nmsym;
  339. sp = sp->s_sp;
  340. }
  341. }
  342. oxp = oxp->a_axp;
  343. }
  344. /*
  345. * Symbol Table Output
  346. */
  347. if (!((xp->a_size==0)&&(xp->a_addr==0)&&(nmsym==0))) {
  348. fprintf(mfp, "AREA %s\n", xp->a_id );
  349. switch (xflag) {
  350. case 1:
  351. fprintf(mfp, "\tRADIX OCTAL\n" );
  352. break;
  353. case 2:
  354. fprintf(mfp, "\tRADIX DEC\n" );
  355. break;
  356. default:
  357. fprintf(mfp, "\tRADIX HEX\n" );
  358. break;
  359. }
  360. fprintf( mfp, "\tBASE %04X\n"
  361. "\tSIZE %04X\n"
  362. "\tATTRIB "
  363. , xp->a_addr, xp->a_size );
  364. if (xp->a_flag & A_ABS) {
  365. fprintf(mfp, "ABS");
  366. } else {
  367. fprintf(mfp, "REL");
  368. }
  369. if (xp->a_flag & A_OVR) {
  370. fprintf(mfp, " OVR");
  371. } else {
  372. fprintf(mfp, " CON");
  373. }
  374. if (xp->a_flag & A_PAG) {
  375. fprintf(mfp, " PAG");
  376. }
  377. if (xp->a_flag & A_PAG) {
  378. ai = (ai & 0xFF);
  379. aj = (aj > 256);
  380. if (ai || aj) { fprintf(mfp, " "); }
  381. if (ai) { fprintf(mfp, " Boundary"); }
  382. if (ai & aj) { fprintf(mfp, " /"); }
  383. if (aj) { fprintf(mfp, " Length"); }
  384. if (ai || aj) { fprintf(mfp, " Error"); }
  385. }
  386. fprintf( mfp,"\n");
  387. if (nmsym>0) {
  388. /*
  389. * Allocate space for an array of pointers to symbols
  390. * and load array.
  391. */
  392. if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
  393. == NULL) {
  394. fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
  395. return;
  396. }
  397. nmsym = 0;
  398. oxp = xp->a_axp;
  399. while (oxp) {
  400. for (i=0; i<NHASH; i++) {
  401. sp = symhash[i];
  402. while (sp != NULL) {
  403. if (oxp == sp->s_axp) {
  404. p[nmsym++] = sp;
  405. }
  406. sp = sp->s_sp;
  407. }
  408. }
  409. oxp = oxp->a_axp;
  410. }
  411. /*
  412. * Bubble Sort of Addresses in Symbol Table Array
  413. */
  414. j = 1;
  415. while (j) {
  416. j = 0;
  417. sp = p[0];
  418. a0 = sp->s_addr + sp->s_axp->a_addr;
  419. for (i=1; i<nmsym; ++i) {
  420. sp = p[i];
  421. ai = sp->s_addr + sp->s_axp->a_addr;
  422. if (a0 > ai) {
  423. j = 1;
  424. p[i] = p[i-1];
  425. p[i-1] = sp;
  426. }
  427. a0 = ai;
  428. }
  429. }
  430. fprintf( mfp, "\tGLOBALS\n");
  431. i = 0;
  432. while (i < nmsym) {
  433. fprintf(mfp, "\t\t%s\t%04X\n", p[i]->s_id, p[i]->s_addr + p[i]->s_axp->a_addr );
  434. i++;
  435. }
  436. free(p);
  437. }
  438. }
  439. }
  440. #endif /* MLH_MAP */
  441. #else
  442. /* NCPS == 8 */
  443. /*)Function VOID lstarea(xp)
  444. *
  445. * area * xp pointer to an area structure
  446. *
  447. * The function lstarea() creates the linker map output for
  448. * the area specified by pointer xp. The generated output
  449. * area header includes the area name, starting address,
  450. * size of area, number of words (in decimal), and the
  451. * area attributes. The symbols defined in this area are
  452. * sorted by ascending address and output four per line
  453. * in the selected radix.
  454. *
  455. * local variables:
  456. * areax * oxp pointer to an area extension structure
  457. * int c character value
  458. * int i loop counter
  459. * int j bubble sort update status
  460. * char * ptr pointer to an id string
  461. * int nmsym number of symbols in area
  462. * addr_t a0 temporary
  463. * addr_t ai temporary
  464. * addr_t aj temporary
  465. * sym * sp pointer to a symbol structure
  466. * sym ** p pointer to an array of
  467. * pointers to symbol structures
  468. *
  469. * global variables:
  470. * FILE *mfp Map output file handle
  471. * sym *symhash[NHASH] array of pointers to NHASH
  472. * linked symbol lists
  473. * int xflag Map file radix type flag
  474. *
  475. * functions called:
  476. * int fprintf() c_library
  477. * VOID free() c_library
  478. * char * malloc() c_library
  479. * char putc() c_library
  480. * VOID slew() lklist.c
  481. *
  482. * side effects:
  483. * Map output generated.
  484. */
  485. VOID
  486. lstarea(xp)
  487. struct area *xp;
  488. {
  489. register struct areax *oxp;
  490. register c, i, j;
  491. register char *ptr;
  492. int nmsym;
  493. addr_t a0, ai, aj;
  494. struct sym *sp;
  495. struct sym **p;
  496. putc('\n', mfp);
  497. slew(mfp);
  498. /*
  499. * Output Area Header
  500. */
  501. ptr = &xp->a_id[0];
  502. while (ptr < &xp->a_id[NCPS]) {
  503. if ((c = *ptr++) != 0) {
  504. putc(c, mfp);
  505. } else {
  506. putc(' ', mfp);
  507. }
  508. }
  509. ai = xp->a_addr;
  510. aj = xp->a_size;
  511. if (xflag == 0) {
  512. fprintf(mfp, " %04X %04X", ai, aj);
  513. } else
  514. if (xflag == 1) {
  515. fprintf(mfp, " %06o %06o", ai, aj);
  516. } else
  517. if (xflag == 2) {
  518. fprintf(mfp, " %05u %05u", ai, aj);
  519. }
  520. fprintf(mfp, " = %6u. bytes ", aj);
  521. if (xp->a_flag & A_ABS) {
  522. fprintf(mfp, "(ABS");
  523. } else {
  524. fprintf(mfp, "(REL");
  525. }
  526. if (xp->a_flag & A_OVR) {
  527. fprintf(mfp, ",OVR");
  528. } else {
  529. fprintf(mfp, ",CON");
  530. }
  531. if (xp->a_flag & A_PAG) {
  532. fprintf(mfp, ",PAG");
  533. }
  534. fprintf(mfp, ")");
  535. if (xp->a_flag & A_PAG) {
  536. ai = (ai & 0xFF);
  537. aj = (aj > 256);
  538. if (ai || aj) { fprintf(mfp, " "); }
  539. if (ai) { fprintf(mfp, " Boundary"); }
  540. if (ai & aj) { fprintf(mfp, " /"); }
  541. if (aj) { fprintf(mfp, " Length"); }
  542. if (ai || aj) { fprintf(mfp, " Error"); }
  543. }
  544. /*
  545. * Find number of symbols in area
  546. */
  547. nmsym = 0;
  548. oxp = xp->a_axp;
  549. while (oxp) {
  550. for (i=0; i<NHASH; i++) {
  551. sp = symhash[i];
  552. while (sp != NULL) {
  553. if (oxp == sp->s_axp)
  554. ++nmsym;
  555. sp = sp->s_sp;
  556. }
  557. }
  558. oxp = oxp->a_axp;
  559. }
  560. if (nmsym == 0) {
  561. putc('\n', mfp);
  562. slew(mfp);
  563. return;
  564. }
  565. /*
  566. * Allocate space for an array of pointers to symbols
  567. * and load array.
  568. */
  569. if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
  570. == NULL) {
  571. fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
  572. slew(mfp);
  573. return;
  574. }
  575. nmsym = 0;
  576. oxp = xp->a_axp;
  577. while (oxp) {
  578. for (i=0; i<NHASH; i++) {
  579. sp = symhash[i];
  580. while (sp != NULL) {
  581. if (oxp == sp->s_axp) {
  582. p[nmsym++] = sp;
  583. }
  584. sp = sp->s_sp;
  585. }
  586. }
  587. oxp = oxp->a_axp;
  588. }
  589. /*
  590. * Bubble Sort of Addresses in Symbol Table Array
  591. */
  592. j = 1;
  593. while (j) {
  594. j = 0;
  595. sp = p[0];
  596. a0 = sp->s_addr + sp->s_axp->a_addr;
  597. for (i=1; i<nmsym; ++i) {
  598. sp = p[i];
  599. ai = sp->s_addr + sp->s_axp->a_addr;
  600. if (a0 > ai) {
  601. j = 1;
  602. p[i] = p[i-1];
  603. p[i-1] = sp;
  604. }
  605. a0 = ai;
  606. }
  607. }
  608. /*
  609. * Symbol Table Output
  610. */
  611. i = 0;
  612. while (i < nmsym) {
  613. if (i % 4 == 0) {
  614. fprintf(mfp, "\n");
  615. slew(mfp);
  616. fprintf(mfp, " ");
  617. }
  618. sp = p[i];
  619. aj = sp->s_addr + sp->s_axp->a_addr;
  620. if (xflag == 0) {
  621. fprintf(mfp, " %04X ", aj);
  622. } else
  623. if (xflag == 1) {
  624. fprintf(mfp, "%06o ", aj);
  625. } else
  626. if (xflag == 2) {
  627. fprintf(mfp, " %05u ", aj);
  628. }
  629. ptr = &sp->s_id[0];
  630. while (ptr < &sp->s_id[NCPS]) {
  631. if ((c = *ptr++) != 0) {
  632. putc(c, mfp);
  633. } else {
  634. putc(' ', mfp);
  635. }
  636. }
  637. if (++i < nmsym)
  638. if (i % 4 != 0)
  639. fprintf(mfp, " | ");
  640. }
  641. putc('\n', mfp);
  642. free(p);
  643. slew(mfp);
  644. }
  645. #endif
  646. #ifdef SDK
  647. VOID lstareatosym(struct area *xp)
  648. {
  649. /* Output the current area symbols to a NO$GMB .sym file */
  650. register struct areax *oxp;
  651. register i, j;
  652. int nmsym;
  653. addr_t a0, ai;
  654. struct sym *sp;
  655. struct sym **p;
  656. /*
  657. * Find number of symbols in area
  658. */
  659. nmsym = 0;
  660. oxp = xp->a_axp;
  661. while (oxp) {
  662. for (i=0; i<NHASH; i++) {
  663. sp = symhash[i];
  664. while (sp != NULL) {
  665. if (oxp == sp->s_axp)
  666. ++nmsym;
  667. sp = sp->s_sp;
  668. }
  669. }
  670. oxp = oxp->a_axp;
  671. }
  672. /*
  673. * Symbol Table Output
  674. */
  675. if (!((xp->a_size==0)&&(xp->a_addr==0)&&(nmsym==0))) {
  676. /* Dont worry about any area information */
  677. fprintf(mfp, "; Area: %s\n", xp->a_id );
  678. if (nmsym>0) {
  679. /*
  680. * Allocate space for an array of pointers to symbols
  681. * and load array.
  682. */
  683. if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
  684. == NULL) {
  685. fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
  686. return;
  687. }
  688. nmsym = 0;
  689. oxp = xp->a_axp;
  690. while (oxp) {
  691. for (i=0; i<NHASH; i++) {
  692. sp = symhash[i];
  693. while (sp != NULL) {
  694. if (oxp == sp->s_axp) {
  695. p[nmsym++] = sp;
  696. }
  697. sp = sp->s_sp;
  698. }
  699. }
  700. oxp = oxp->a_axp;
  701. }
  702. /*
  703. * Bubble Sort of Addresses in Symbol Table Array
  704. */
  705. j = 1;
  706. while (j) {
  707. j = 0;
  708. sp = p[0];
  709. a0 = sp->s_addr + sp->s_axp->a_addr;
  710. for (i=1; i<nmsym; ++i) {
  711. sp = p[i];
  712. ai = sp->s_addr + sp->s_axp->a_addr;
  713. if (a0 > ai) {
  714. j = 1;
  715. p[i] = p[i-1];
  716. p[i-1] = sp;
  717. }
  718. a0 = ai;
  719. }
  720. }
  721. i = 0;
  722. while (i < nmsym) {
  723. /* no$gmb requires the symbol names to be less than 32 chars long. Truncate. */
  724. char name[32];
  725. strncpy(name, p[i]->s_id, 31);
  726. name[31] = '\0';
  727. if ((strncmp("l__", name, 3)!=0)&&(strchr(name,' ')==NULL)) {
  728. a0=p[i]->s_addr + p[i]->s_axp->a_addr;
  729. if (a0>0x7FFFU) {
  730. /* Not inside the ROM, so treat as being in bank zero */
  731. fprintf(mfp, "00:%04X %s\n", a0, name);
  732. }
  733. else {
  734. fprintf(mfp, "%02X:%04X %s\n", a0/16384, a0, name);
  735. }
  736. }
  737. i++;
  738. }
  739. free(p);
  740. }
  741. }
  742. }
  743. #endif
  744. /*)Function VOID lkulist(i)
  745. *
  746. * int i i # 0 process LST to RST file
  747. * i = 0 copy remainder of LST file
  748. * to RST file and close files
  749. *
  750. * The function lkulist() creates a relocated listing (.rst)
  751. * output file from the ASxxxx assembler listing (.lst)
  752. * files. The .lst file's program address and code bytes
  753. * are changed to reflect the changes made by ASlink as
  754. * the .rel files are combined into a single relocated
  755. * output file.
  756. *
  757. * local variables:
  758. * addr_t pc current program counter address
  759. *
  760. * global variables:
  761. * int hilo byte order
  762. * int gline get a line from the LST file
  763. * to translate for the RST file
  764. * char rb[] read listing file text line
  765. * FILE *rfp The file handle to the current
  766. * output RST file
  767. * int rtcnt count of data words
  768. * int rtflg[] output the data flag
  769. * addr_t rtval[] relocated data
  770. * FILE *tfp The file handle to the current
  771. * LST file being scanned
  772. *
  773. * functions called:
  774. * int fclose() c_library
  775. * int fgets() c_library
  776. * int fprintf() c_library
  777. * VOID lkalist() lklist.c
  778. * VOID lkglist() lklist.c
  779. *
  780. * side effects:
  781. * A .rst file is created for each available .lst
  782. * file associated with a .rel file.
  783. */
  784. VOID
  785. lkulist(i)
  786. int i;
  787. {
  788. addr_t pc;
  789. /*
  790. * Exit if listing file is not open
  791. */
  792. if (tfp == NULL)
  793. return;
  794. /*
  795. * Normal processing of LST to RST
  796. */
  797. if (i) {
  798. /*
  799. * Evaluate current code address
  800. */
  801. if (hilo == 0) {
  802. pc = ((rtval[1] & 0xFF) << 8) + (rtval[0] & 0xFF);
  803. } else {
  804. pc = ((rtval[0] & 0xFF) << 8) + (rtval[1] & 0xFF);
  805. }
  806. /*
  807. * Line with only address
  808. */
  809. if (rtcnt == 2) {
  810. lkalist(pc);
  811. /*
  812. * Line with address and code
  813. */
  814. } else {
  815. for (i=2; i < rtcnt; i++) {
  816. if (rtflg[i]) {
  817. lkglist(pc++, rtval[i] & 0xFF);
  818. }
  819. }
  820. }
  821. /*
  822. * Copy remainder of LST to RST
  823. */
  824. } else {
  825. if (gline == 0)
  826. fprintf(rfp, rb);
  827. while (fgets(rb, sizeof(rb), tfp) != 0) {
  828. fprintf(rfp, rb);
  829. }
  830. fclose(tfp);
  831. tfp = NULL;
  832. fclose(rfp);
  833. rfp = NULL;
  834. }
  835. }
  836. /*)Function VOID lkalist(pc)
  837. *
  838. * int pc current program counter value
  839. *
  840. * The function lkalist() performs the following functions:
  841. *
  842. * (1) if the value of gline = 0 then the current listing
  843. * file line is copied to the relocated listing file output.
  844. *
  845. * (2) the listing file is read line by line and copied to
  846. * the relocated listing file until a valid source
  847. * line number and a program counter value of the correct
  848. * radix is found. The new relocated pc value is substituted
  849. * and the line is written to the RST file.
  850. *
  851. * local variables:
  852. * int i loop counter
  853. * char str[] temporary string
  854. *
  855. * global variables:
  856. * int gcntr data byte counter
  857. * int gline get a line from the LST file
  858. * to translate for the RST file
  859. * char rb[] read listing file text line
  860. * char *rp pointer to listing file text line
  861. * FILE *rfp The file handle to the current
  862. * output RST file
  863. * FILE *tfp The file handle to the current
  864. * LST file being scanned
  865. *
  866. * functions called:
  867. * int dgt() lklist.c
  868. * int fclose() c_library
  869. * int fgets() c_library
  870. * int fprintf() c_library
  871. * int sprintf() c_library
  872. * char * strncpy() c_library
  873. *
  874. * side effects:
  875. * Lines of the LST file are copied to the RST file,
  876. * the last line copied has the code address
  877. * updated to reflect the program relocation.
  878. */
  879. VOID
  880. lkalist(pc)
  881. addr_t pc;
  882. {
  883. char str[8];
  884. int i;
  885. /*
  886. * Exit if listing file is not open
  887. */
  888. loop: if (tfp == NULL)
  889. return;
  890. /*
  891. * Copy current LST to RST
  892. */
  893. if (gline == 0) {
  894. fprintf(rfp, rb);
  895. gline = 1;
  896. }
  897. /*
  898. * Clear text line buffer
  899. */
  900. for (i=0,rp=rb; i<sizeof(rb); i++) {
  901. *rp++ = 0;
  902. }
  903. /*
  904. * Get next LST text line
  905. */
  906. if (fgets(rb, sizeof(rb), tfp) == NULL) {
  907. fclose(tfp);
  908. tfp = NULL;
  909. fclose(rfp);
  910. rfp = NULL;
  911. return;
  912. }
  913. /*
  914. * Must have an ASxxxx Listing line number
  915. */
  916. if (!dgt(RAD10, &rb[30], 1)) {
  917. fprintf(rfp, rb);
  918. goto loop;
  919. }
  920. /*
  921. * Must have an address in the expected radix
  922. */
  923. if (radix == 16) {
  924. if (!dgt(RAD16, &rb[3], 4)) {
  925. fprintf(rfp, rb);
  926. goto loop;
  927. }
  928. sprintf(str, "%04X", pc);
  929. strncpy(&rb[3], str, 4);
  930. } else
  931. if (radix == 10) {
  932. if (!dgt(RAD10, &rb[3], 5)) {
  933. fprintf(rfp, rb);
  934. goto loop;
  935. }
  936. sprintf(str, "%05d", pc);
  937. strncpy(&rb[3], str, 5);
  938. } else
  939. if (radix == 8) {
  940. if (!dgt(RAD8, &rb[3], 6)) {
  941. fprintf(rfp, rb);
  942. goto loop;
  943. }
  944. sprintf(str, "%06o", pc);
  945. strncpy(&rb[3], str, 6);
  946. }
  947. /*
  948. * Copy updated LST text line to RST
  949. */
  950. fprintf(rfp, rb);
  951. gcntr = 0;
  952. }
  953. /*)Function VOID lkglist(pc,v)
  954. *
  955. * int pc current program counter value
  956. * int v value of byte at this address
  957. *
  958. * The function lkglist() performs the following functions:
  959. *
  960. * (1) if the value of gline = 1 then the listing file
  961. * is read line by line and copied to the
  962. * relocated listing file until a valid source
  963. * line number and a program counter value of the correct
  964. * radix is found.
  965. *
  966. * (2) The new relocated values and code address are
  967. * substituted and the line may be written to the RST file.
  968. *
  969. * local variables:
  970. * int i loop counter
  971. * char str[] temporary string
  972. *
  973. * global variables:
  974. * int gcntr data byte counter
  975. * set to -1 for a continuation line
  976. * int gline get a line from the LST file
  977. * to translate for the RST file
  978. * char rb[] read listing file text line
  979. * char *rp pointer to listing file text line
  980. * FILE *rfp The file handle to the current
  981. * output RST file
  982. * FILE *tfp The file handle to the current
  983. * LST file being scanned
  984. *
  985. * functions called:
  986. * int dgt() lklist.c
  987. * int fclose() c_library
  988. * int fgets() c_library
  989. * int fprintf() c_library
  990. * int sprintf() c_library
  991. * char * strncpy() c_library
  992. *
  993. * side effects:
  994. * Lines of the LST file are copied to the RST file
  995. * with updated data values and code addresses.
  996. */
  997. VOID
  998. lkglist(pc,v)
  999. addr_t pc;
  1000. int v;
  1001. {
  1002. char str[8];
  1003. int i;
  1004. /*
  1005. * Exit if listing file is not open
  1006. */
  1007. loop: if (tfp == NULL)
  1008. return;
  1009. /*
  1010. * Get next LST text line
  1011. */
  1012. if (gline) {
  1013. /*
  1014. * Clear text line buffer
  1015. */
  1016. for (i=0,rp=rb; i<sizeof(rb); i++) {
  1017. *rp++ = 0;
  1018. }
  1019. /*
  1020. * Get next LST text line
  1021. */
  1022. if (fgets(rb, sizeof(rb), tfp) == NULL) {
  1023. fclose(tfp);
  1024. tfp = NULL;
  1025. fclose(rfp);
  1026. rfp = NULL;
  1027. return;
  1028. }
  1029. /*
  1030. * Check for a listing line number if required
  1031. */
  1032. if (gcntr != -1) {
  1033. if (!dgt(RAD10, &rb[30], 1)) {
  1034. fprintf(rfp, rb);
  1035. goto loop;
  1036. }
  1037. gcntr = 0;
  1038. }
  1039. gline = 0;
  1040. }
  1041. /*
  1042. * Hex Listing
  1043. */
  1044. if (radix == 16) {
  1045. /*
  1046. * Data Byte Pointer
  1047. */
  1048. if (gcntr == -1) {
  1049. rp = &rb[8];
  1050. } else {
  1051. rp = &rb[8 + (3 * gcntr)];
  1052. }
  1053. /*
  1054. * Number must be of proper radix
  1055. */
  1056. if (!dgt(RAD16, rp, 2)) {
  1057. fprintf(rfp, rb);
  1058. gline = 1;
  1059. goto loop;
  1060. }
  1061. /*
  1062. * Output new data value, overwrite relocation codes
  1063. */
  1064. sprintf(str, " %02X", v);
  1065. strncpy(rp-1, str, 3);
  1066. if (gcntr == -1) {
  1067. gcntr = 0;
  1068. }
  1069. /*
  1070. * Output relocated code address
  1071. */
  1072. if (gcntr == 0) {
  1073. if (dgt(RAD16, &rb[3], 4)) {
  1074. sprintf(str, "%04X", pc);
  1075. strncpy(&rb[3], str, 4);
  1076. }
  1077. }
  1078. /*
  1079. * Output text line when updates finished
  1080. */
  1081. if (++gcntr == 6) {
  1082. fprintf(rfp, rb);
  1083. gline = 1;
  1084. gcntr = -1;
  1085. }
  1086. } else
  1087. /*
  1088. * Decimal Listing
  1089. */
  1090. if (radix == 10) {
  1091. /*
  1092. * Data Byte Pointer
  1093. */
  1094. if (gcntr == -1) {
  1095. rp = &rb[9];
  1096. } else {
  1097. rp = &rb[9 + (3 * gcntr)];
  1098. }
  1099. /*
  1100. * Number must be of proper radix
  1101. */
  1102. if (!dgt(RAD10, rp, 3)) {
  1103. fprintf(rfp, rb);
  1104. gline = 1;
  1105. goto loop;
  1106. }
  1107. /*
  1108. * Output new data value, overwrite relocation codes
  1109. */
  1110. sprintf(str, " %03d", v);
  1111. strncpy(rp-1, str, 4);
  1112. if (gcntr == -1) {
  1113. gcntr = 0;
  1114. }
  1115. /*
  1116. * Output relocated code address
  1117. */
  1118. if (gcntr == 0) {
  1119. if (dgt(RAD10, &rb[3], 5)) {
  1120. sprintf(str, "%05d", pc);
  1121. strncpy(&rb[3], str, 5);
  1122. }
  1123. }
  1124. /*
  1125. * Output text line when updates finished
  1126. */
  1127. if (++gcntr == 4) {
  1128. fprintf(rfp, rb);
  1129. gline = 1;
  1130. gcntr = -1;
  1131. }
  1132. } else
  1133. /*
  1134. * Octal Listing
  1135. */
  1136. if (radix == 8) {
  1137. /*
  1138. * Data Byte Pointer
  1139. */
  1140. if (gcntr == -1) {
  1141. rp = &rb[10];
  1142. } else {
  1143. rp = &rb[10 + (3 * gcntr)];
  1144. }
  1145. /*
  1146. * Number must be of proper radix
  1147. */
  1148. if (!dgt(RAD8, rp, 3)) {
  1149. fprintf(rfp, rb);
  1150. gline = 1;
  1151. goto loop;
  1152. }
  1153. /*
  1154. * Output new data value, overwrite relocation codes
  1155. */
  1156. sprintf(str, " %03o", v);
  1157. strncpy(rp-1, str, 4);
  1158. if (gcntr == -1) {
  1159. gcntr = 0;
  1160. }
  1161. /*
  1162. * Output relocated code address
  1163. */
  1164. if (gcntr == 0) {
  1165. if (dgt(RAD8, &rb[3], 6)) {
  1166. sprintf(str, "%06o", pc);
  1167. strncpy(&rb[3], str, 6);
  1168. }
  1169. }
  1170. /*
  1171. * Output text line when updates finished
  1172. */
  1173. if (++gcntr == 4) {
  1174. fprintf(rfp, rb);
  1175. gline = 1;
  1176. gcntr = -1;
  1177. }
  1178. }
  1179. }
  1180. /*)Function int dgt(rdx,str,n)
  1181. *
  1182. * int rdx radix bit code
  1183. * char *str pointer to the test string
  1184. * int n number of characters to check
  1185. *
  1186. * The function dgt() verifies that the string under test
  1187. * is of the specified radix.
  1188. *
  1189. * local variables:
  1190. * int i loop counter
  1191. *
  1192. * global variables:
  1193. * ctype[] array of character types
  1194. *
  1195. * functions called:
  1196. * none
  1197. *
  1198. * side effects:
  1199. * none
  1200. */
  1201. int
  1202. dgt(rdx, str, n)
  1203. int rdx, n;
  1204. char *str;
  1205. {
  1206. int i;
  1207. for (i=0; i<n; i++) {
  1208. if ((ctype[*str++] & rdx) == 0)
  1209. return(0);
  1210. }
  1211. return(1);
  1212. }