4 * (C) Copyright 1989-1995
12 * - lstarea: show s_id as string rather than array [NCPS]
13 * - lstarea: show a_id as string rather than array [NCPS]
14 * 31-Oct-97 JLH: add NoICE output file genration in lstarea
15 * 02-Apr-98 JLH: add XDATA, DATA, BIT flags to area output
25 * The module lklist.c contains the functions which
26 * output the linker .map file and produce a relocated
29 * lklist.c contains the following functions:
38 * lklist.c contains no local variables.
41 /*)Function VOID slew(fp)
43 * FILE * fp output file handle
45 * The function slew() increments the page line counter.
46 * If the number of lines exceeds the maximum number of
47 * lines per page then a page skip and a page header are
54 * int lop current line number on page
55 * int xflag Map file radix type flag
58 * int fprintf() c_library
59 * VOID newpag() lklist.c
62 * The page line and the page count may be updated.
74 fprintf(fp, "Hexadecimal\n\n");
77 fprintf(fp, "Octal\n\n");
80 fprintf(fp, "Decimal\n\n");
82 fprintf(fp, "Area Addr Size");
83 fprintf(fp, " Decimal Bytes (Attributes)\n");
85 fprintf(fp, " Value--Global");
91 /*)Function VOID newpag()
93 * The function newpag() outputs a page skip, writes the
94 * first page header line, sets the line count to 1, and
95 * increments the page counter.
101 * int lop current line number on page
102 * int page current page number
105 * int fprintf() c_library
108 * The page and line counters are updated.
115 fprintf(fp, "\fASxxxx Linker %s, page %u.\n", VERSION, ++page);
119 /* Used for qsort call in lstsym */
120 static int _cmpSymByAddr(const void *p1, const void *p2)
122 struct sym **s1 = (struct sym **)(p1);
123 struct sym **s2 = (struct sym **)(p2);
124 int delta = ((*s1)->s_addr + (*s1)->s_axp->a_addr) -
125 ((*s2)->s_addr + (*s2)->s_axp->a_addr);
127 /* Sort first by address, then by name. */
132 return strcmp((*s1)->s_id,(*s2)->s_id);
139 /*)Function VOID lstarea(xp)
141 * area * xp pointer to an area structure
143 * The function lstarea() creates the linker map output for
144 * the area specified by pointer xp. The generated output
145 * area header includes the area name, starting address,
146 * size of area, number of words (in decimal), and the
147 * area attributes. The symbols defined in this area are
148 * sorted by ascending address and output one per line
149 * in the selected radix.
152 * areax * oxp pointer to an area extension structure
153 * int c character value
155 * int j bubble sort update status
156 * char * ptr pointer to an id string
157 * int nmsym number of symbols in area
158 * Addr_T a0 temporary
159 * Addr_T ai temporary
160 * Addr_T aj temporary
161 * sym * sp pointer to a symbol structure
162 * sym ** p pointer to an array of
163 * pointers to symbol structures
166 * FILE *mfp Map output file handle
167 * sym *symhash[NHASH] array of pointers to NHASH
168 * linked symbol lists
169 * int xflag Map file radix type flag
172 * int fprintf() c_library
173 * VOID free() c_library
174 * char * malloc() c_library
175 * char putc() c_library
176 * VOID slew() lklist.c
179 * Map output generated.
186 register struct areax *oxp;
199 fprintf(mfp, "Hexadecimal\n\n");
202 fprintf(mfp, "Octal\n\n");
205 fprintf(mfp, "Decimal\n\n");
207 fprintf(mfp, "Area ");
208 fprintf(mfp, "Addr Size Decimal Bytes (Attributes)\n");
209 fprintf(mfp, "-------------------------------- ");
210 fprintf(mfp, "---- ---- ------- ----- ------------\n");
215 fprintf(mfp, "%-32s", ptr ); /* JLH: width matches --- above */
219 fprintf(mfp, " %04X %04X", ai, aj);
222 fprintf(mfp, " %06o %06o", ai, aj);
225 fprintf(mfp, " %05u %05u", ai, aj);
227 fprintf(mfp, " = %6u. bytes ", aj);
228 if (xp->a_flag & A_ABS) {
229 fprintf(mfp, "(ABS");
231 fprintf(mfp, "(REL");
233 if (xp->a_flag & A_OVR) {
234 fprintf(mfp, ",OVR");
236 fprintf(mfp, ",CON");
238 if (xp->a_flag & A_PAG) {
239 fprintf(mfp, ",PAG");
243 if (xp->a_flag & A_CODE) {
244 fprintf(mfp, ",CODE");
247 if (xp->a_flag & A_XDATA) {
248 fprintf(mfp, ",XDATA");
251 if (xp->a_flag & A_BIT) {
252 fprintf(mfp, ",BIT");
256 if (xp->a_flag & A_PAG) {
259 if (ai || aj) { fprintf(mfp, " "); }
260 if (ai) { fprintf(mfp, " Boundary"); }
261 if (ai & aj) { fprintf(mfp, " /"); }
262 if (aj) { fprintf(mfp, " Length"); }
263 if (ai || aj) { fprintf(mfp, " Error"); }
267 * Find number of symbols in area
272 for (i=0; i<NHASH; i++) {
275 if (oxp == sp->s_axp)
288 * Allocate space for an array of pointers to symbols
291 if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
293 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
299 for (i=0; i<NHASH; i++) {
302 if (oxp == sp->s_axp) {
313 * Bubble Sort of Addresses in Symbol Table Array
319 a0 = sp->s_addr + sp->s_axp->a_addr;
320 for (i=1; i<nmsym; ++i) {
322 ai = sp->s_addr + sp->s_axp->a_addr;
332 qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr);
336 * Symbol Table Output
340 fprintf(mfp, "\n\n");
341 fprintf(mfp, " Value Global\n");
342 fprintf(mfp, " -------- --------------------------------");
346 fprintf(mfp, " %02X:", memPage);
351 aj = sp->s_addr + sp->s_axp->a_addr;
353 fprintf(mfp, "%04X ", aj);
356 fprintf(mfp, "%06o ", aj);
359 fprintf(mfp, "%05u ", aj);
362 fprintf(mfp, "%s", ptr );
364 /* if cdb flag set the output cdb Information
365 and the symbol has a '$' sign in it then */
368 fprintf(dfp,"L:%s:%X\n",ptr,aj);
369 /* NoICE output of symbol */
370 if (jflag) DefineNoICE( ptr, aj, memPage );
381 /*)Function VOID lstarea(xp)
383 * area * xp pointer to an area structure
385 * The function lstarea() creates the linker map output for
386 * the area specified by pointer xp. The generated output
387 * area header includes the area name, starting address,
388 * size of area, number of words (in decimal), and the
389 * area attributes. The symbols defined in this area are
390 * sorted by ascending address and output four per line
391 * in the selected radix.
394 * areax * oxp pointer to an area extension structure
395 * int c character value
397 * int j bubble sort update status
398 * char * ptr pointer to an id string
399 * int nmsym number of symbols in area
400 * Addr_T a0 temporary
401 * Addr_T ai temporary
402 * Addr_T aj temporary
403 * sym * sp pointer to a symbol structure
404 * sym ** p pointer to an array of
405 * pointers to symbol structures
408 * FILE *mfp Map output file handle
409 * sym *symhash[NHASH] array of pointers to NHASH
410 * linked symbol lists
411 * int xflag Map file radix type flag
414 * int fprintf() c_library
415 * VOID free() c_library
416 * char * malloc() c_library
417 * char putc() c_library
418 * VOID slew() lklist.c
421 * Map output generated.
428 register struct areax *oxp;
443 while (ptr < &xp->a_id[NCPS]) {
444 if ((c = *ptr++) != 0) {
453 fprintf(mfp, " %04X %04X", ai, aj);
456 fprintf(mfp, " %06o %06o", ai, aj);
459 fprintf(mfp, " %05u %05u", ai, aj);
461 fprintf(mfp, " = %6u. bytes ", aj);
462 if (xp->a_flag & A_ABS) {
463 fprintf(mfp, "(ABS");
465 fprintf(mfp, "(REL");
467 if (xp->a_flag & A_OVR) {
468 fprintf(mfp, ",OVR");
470 fprintf(mfp, ",CON");
472 if (xp->a_flag & A_PAG) {
473 fprintf(mfp, ",PAG");
477 if (xp->a_flag & A_CODE) {
478 fprintf(mfp, ",CODE");
481 if (xp->a_flag & A_XDATA) {
482 fprintf(mfp, ",XDATA");
485 if (xp->a_flag & A_BIT) {
486 fprintf(mfp, ",BIT");
490 if (xp->a_flag & A_PAG) {
493 if (ai || aj) { fprintf(mfp, " "); }
494 if (ai) { fprintf(mfp, " Boundary"); }
495 if (ai & aj) { fprintf(mfp, " /"); }
496 if (aj) { fprintf(mfp, " Length"); }
497 if (ai || aj) { fprintf(mfp, " Error"); }
501 * Find number of symbols in area
506 for (i=0; i<NHASH; i++) {
509 if (oxp == sp->s_axp)
523 * Allocate space for an array of pointers to symbols
526 if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
528 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
535 for (i=0; i<NHASH; i++) {
538 if (oxp == sp->s_axp) {
549 * Bubble Sort of Addresses in Symbol Table Array
555 a0 = sp->s_addr + sp->s_axp->a_addr;
556 for (i=1; i<nmsym; ++i) {
558 ai = sp->s_addr + sp->s_axp->a_addr;
568 qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr);
572 * Symbol Table Output
580 aj = sp->s_addr + sp->s_axp->a_addr;
582 fprintf(mfp, " %04X ", aj);
585 fprintf(mfp, "%06o ", aj);
588 fprintf(mfp, " %05u ", aj);
591 fprintf(mfp, "%s", ptr );
593 /* NoICE output of symbol */
594 if (jflag) DefineNoICE( ptr, aj, memPage );
602 /*)Function VOID lkulist(i)
604 * int i i # 0 process LST to RST file
605 * i = 0 copy remainder of LST file
606 * to RST file and close files
608 * The function lkulist() creates a relocated listing (.rst)
609 * output file from the ASxxxx assembler listing (.lst)
610 * files. The .lst file's program address and code bytes
611 * are changed to reflect the changes made by ASlink as
612 * the .rel files are combined into a single relocated
616 * Addr_T pc current program counter address
619 * int hilo byte order
620 * int gline get a line from the LST file
621 * to translate for the RST file
622 * char rb[] read listing file text line
623 * FILE *rfp The file handle to the current
625 * int rtcnt count of data words
626 * int rtflg[] output the data flag
627 * Addr_T rtval[] relocated data
628 * FILE *tfp The file handle to the current
629 * LST file being scanned
632 * int fclose() c_library
633 * int fgets() c_library
634 * int fprintf() c_library
635 * VOID lkalist() lklist.c
636 * VOID lkglist() lklist.c
639 * A .rst file is created for each available .lst
640 * file associated with a .rel file.
650 * Exit if listing file is not open
656 * Normal processing of LST to RST
660 * Evaluate current code address
663 pc = ((rtval[1] & 0xFF) << 8) + (rtval[0] & 0xFF);
665 pc = ((rtval[0] & 0xFF) << 8) + (rtval[1] & 0xFF);
669 * Line with only address
675 * Line with address and code
678 for (i=2; i < rtcnt; i++) {
680 lkglist(pc++, rtval[i] & 0xFF);
686 * Copy remainder of LST to RST
690 fprintf(rfp, "%s", rb);
692 while (fgets(rb, sizeof(rb), tfp) != 0) {
693 fprintf(rfp, "%s", rb);
702 /*)Function VOID lkalist(pc)
704 * int pc current program counter value
706 * The function lkalist() performs the following functions:
708 * (1) if the value of gline = 0 then the current listing
709 * file line is copied to the relocated listing file output.
711 * (2) the listing file is read line by line and copied to
712 * the relocated listing file until a valid source
713 * line number and a program counter value of the correct
714 * radix is found. The new relocated pc value is substituted
715 * and the line is written to the RST file.
719 * char str[] temporary string
722 * int gcntr data byte counter
723 * int gline get a line from the LST file
724 * to translate for the RST file
725 * char rb[] read listing file text line
726 * char *rp pointer to listing file text line
727 * FILE *rfp The file handle to the current
729 * FILE *tfp The file handle to the current
730 * LST file being scanned
734 * int fclose() c_library
735 * int fgets() c_library
736 * int fprintf() c_library
737 * int sprintf() c_library
738 * char * strncpy() c_library
741 * Lines of the LST file are copied to the RST file,
742 * the last line copied has the code address
743 * updated to reflect the program relocation.
754 * Exit if listing file is not open
756 loop: if (tfp == NULL)
760 * Copy current LST to RST
763 fprintf(rfp, "%s", rb);
768 * Clear text line buffer
770 for (i=0,rp=rb; i<sizeof(rb); i++) {
775 * Get next LST text line
777 if (fgets(rb, sizeof(rb), tfp) == NULL) {
786 * Must have an ASxxxx Listing line number
788 if (!dgt(RAD10, &rb[30], 1)) {
789 fprintf(rfp, "%s", rb);
794 * Must have an address in the expected radix
797 if (!dgt(RAD16, &rb[3], 4)) {
798 fprintf(rfp, "%s", rb);
801 sprintf(str, "%04X", pc);
802 strncpy(&rb[3], str, 4);
805 if (!dgt(RAD10, &rb[3], 5)) {
806 fprintf(rfp, "%s", rb);
809 sprintf(str, "%05d", pc);
810 strncpy(&rb[3], str, 5);
813 if (!dgt(RAD8, &rb[3], 6)) {
814 fprintf(rfp, "%s", rb);
817 sprintf(str, "%06o", pc);
818 strncpy(&rb[3], str, 6);
822 * Copy updated LST text line to RST
824 fprintf(rfp, "%s", rb);
828 /*)Function VOID lkglist(pc,v)
830 * int pc current program counter value
831 * int v value of byte at this address
833 * The function lkglist() performs the following functions:
835 * (1) if the value of gline = 1 then the listing file
836 * is read line by line and copied to the
837 * relocated listing file until a valid source
838 * line number and a program counter value of the correct
841 * (2) The new relocated values and code address are
842 * substituted and the line may be written to the RST file.
846 * char str[] temporary string
849 * int gcntr data byte counter
850 * set to -1 for a continuation line
851 * int gline get a line from the LST file
852 * to translate for the RST file
853 * char rb[] read listing file text line
854 * char *rp pointer to listing file text line
855 * FILE *rfp The file handle to the current
857 * FILE *tfp The file handle to the current
858 * LST file being scanned
862 * int fclose() c_library
863 * int fgets() c_library
864 * int fprintf() c_library
865 * int sprintf() c_library
866 * char * strncpy() c_library
869 * Lines of the LST file are copied to the RST file
870 * with updated data values and code addresses.
882 * Exit if listing file is not open
884 loop: if (tfp == NULL)
888 * Get next LST text line
892 * Clear text line buffer
894 for (i=0,rp=rb; i<sizeof(rb); i++) {
899 * Get next LST text line
901 if (fgets(rb, sizeof(rb), tfp) == NULL) {
910 * Check for a listing line number if required
913 if (!dgt(RAD10, &rb[30], 1)) {
914 fprintf(rfp, "%s", rb);
932 rp = &rb[8 + (3 * gcntr)];
935 * Number must be of proper radix
937 if (!dgt(RAD16, rp, 2)) {
938 fprintf(rfp, "%s", rb);
943 * Output new data value, overwrite relocation codes
945 sprintf(str, " %02X", v);
946 strncpy(rp-1, str, 3);
951 * Output relocated code address
954 if (dgt(RAD16, &rb[3], 4)) {
955 sprintf(str, "%04X", pc);
956 strncpy(&rb[3], str, 4);
960 * Output text line when updates finished
963 fprintf(rfp, "%s", rb);
978 rp = &rb[9 + (3 * gcntr)];
981 * Number must be of proper radix
983 if (!dgt(RAD10, rp, 3)) {
984 fprintf(rfp, "%s", rb);
989 * Output new data value, overwrite relocation codes
991 sprintf(str, " %03d", v);
992 strncpy(rp-1, str, 4);
997 * Output relocated code address
1000 if (dgt(RAD10, &rb[3], 5)) {
1001 sprintf(str, "%05d", pc);
1002 strncpy(&rb[3], str, 5);
1006 * Output text line when updates finished
1009 fprintf(rfp, "%s", rb);
1024 rp = &rb[10 + (3 * gcntr)];
1027 * Number must be of proper radix
1029 if (!dgt(RAD8, rp, 3)) {
1030 fprintf(rfp, "%s", rb);
1035 * Output new data value, overwrite relocation codes
1037 sprintf(str, " %03o", v);
1038 strncpy(rp-1, str, 4);
1043 * Output relocated code address
1046 if (dgt(RAD8, &rb[3], 6)) {
1047 sprintf(str, "%06o", pc);
1048 strncpy(&rb[3], str, 6);
1052 * Output text line when updates finished
1055 fprintf(rfp, "%s", rb);
1062 /*)Function int dgt(rdx,str,n)
1064 * int rdx radix bit code
1065 * char *str pointer to the test string
1066 * int n number of characters to check
1068 * The function dgt() verifies that the string under test
1069 * is of the specified radix.
1072 * int i loop counter
1075 * ctype[] array of character types
1091 for (i=0; i<n; i++) {
1092 if ((ctype[(int)*str++] & rdx) == 0)