4 * (C) Copyright 1989-1995
19 * The module lklist.c contains the functions which
20 * output the linker .map file and produce a relocated
23 * lklist.c contains the following functions:
32 * lklist.c contains no local variables.
35 /*)Function VOID slew(fp)
37 * FILE * fp output file handle
39 * The function slew() increments the page line counter.
40 * If the number of lines exceeds the maximum number of
41 * lines per page then a page skip and a page header are
48 * int lop current line number on page
49 * int xflag Map file radix type flag
52 * int fprintf() c_library
53 * VOID newpag() lklist.c
56 * The page line and the page count may be updated.
68 fprintf(fp, "Hexidecimal\n\n");
71 fprintf(fp, "Octal\n\n");
74 fprintf(fp, "Decimal\n\n");
76 fprintf(fp, "Area Addr Size");
77 fprintf(fp, " Decimal Bytes (Attributes)\n");
79 fprintf(fp, " Value--Global");
85 /*)Function VOID newpag()
87 * The function newpag() outputs a page skip, writes the
88 * first page header line, sets the line count to 1, and
89 * increments the page counter.
95 * int lop current line number on page
96 * int page current page number
99 * int fprintf() c_library
102 * The page and line counters are updated.
109 fprintf(fp, "\fASxxxx Linker %s, page %u.\n", VERSION, ++page);
116 /*)Function VOID lstarea(xp)
118 * area * xp pointer to an area structure
120 * The function lstarea() creates the linker map output for
121 * the area specified by pointer xp. The generated output
122 * area header includes the area name, starting address,
123 * size of area, number of words (in decimal), and the
124 * area attributes. The symbols defined in this area are
125 * sorted by ascending address and output one per line
126 * in the selected radix.
129 * areax * oxp pointer to an area extension structure
130 * int c character value
132 * int j bubble sort update status
133 * char * ptr pointer to an id string
134 * int nmsym number of symbols in area
135 * addr_t a0 temporary
136 * addr_t ai temporary
137 * addr_t aj temporary
138 * sym * sp pointer to a symbol structure
139 * sym ** p pointer to an array of
140 * pointers to symbol structures
143 * FILE *mfp Map output file handle
144 * sym *symhash[NHASH] array of pointers to NHASH
145 * linked symbol lists
146 * int xflag Map file radix type flag
149 * int fprintf() c_library
150 * VOID free() c_library
151 * char * malloc() c_library
152 * char putc() c_library
153 * VOID slew() lklist.c
156 * Map output generated.
164 register struct area *op;
165 register struct areax *oxp;
175 fprintf(mfp, "Hexidecimal\n\n");
178 fprintf(mfp, "Octal\n\n");
181 fprintf(mfp, "Decimal\n\n");
183 fprintf(mfp, "Area ");
184 fprintf(mfp, "Addr Size Decimal Bytes (Attributes)\n");
185 fprintf(mfp, "-------------------------------- ");
186 fprintf(mfp, "---- ---- ------- ----- ------------\n");
191 while (ptr < &xp->a_id[NCPS]) {
192 if ((c = *ptr++) != 0) {
201 fprintf(mfp, " %04X %04X", ai, aj);
204 fprintf(mfp, " %06o %06o", ai, aj);
207 fprintf(mfp, " %05u %05u", ai, aj);
209 fprintf(mfp, " = %6u. bytes ", aj);
210 if (xp->a_flag & A_ABS) {
211 fprintf(mfp, "(ABS");
213 fprintf(mfp, "(REL");
215 if (xp->a_flag & A_OVR) {
216 fprintf(mfp, ",OVR");
218 fprintf(mfp, ",CON");
220 if (xp->a_flag & A_PAG) {
221 fprintf(mfp, ",PAG");
224 if (xp->a_flag & A_PAG) {
227 if (ai || aj) { fprintf(mfp, " "); }
228 if (ai) { fprintf(mfp, " Boundary"); }
229 if (ai & aj) { fprintf(mfp, " /"); }
230 if (aj) { fprintf(mfp, " Length"); }
231 if (ai || aj) { fprintf(mfp, " Error"); }
235 * Find number of symbols in area
240 for (i=0; i<NHASH; i++) {
243 if (oxp == sp->s_axp)
256 * Allocate space for an array of pointers to symbols
259 if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
261 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
267 for (i=0; i<NHASH; i++) {
270 if (oxp == sp->s_axp) {
280 * Bubble Sort of Addresses in Symbol Table Array
286 a0 = sp->s_addr + sp->s_axp->a_addr;
287 for (i=1; i<nmsym; ++i) {
289 ai = sp->s_addr + sp->s_axp->a_addr;
300 * Symbol Table Output
303 fprintf(mfp, "\n\n");
304 fprintf(mfp, " Value Global\n");
305 fprintf(mfp, " ----- --------------------------------");
311 aj = sp->s_addr + sp->s_axp->a_addr;
313 fprintf(mfp, " %04X ", aj);
316 fprintf(mfp, "%06o ", aj);
319 fprintf(mfp, " %05u ", aj);
322 while (ptr < &sp->s_id[NCPS]) {
323 if ((c = *ptr++) != 0) {
335 VOID lstarea(struct area *xp)
337 register struct area *op;
338 register struct areax *oxp;
347 * Find number of symbols in area
352 for (i=0; i<NHASH; i++) {
355 if (oxp == sp->s_axp)
364 * Symbol Table Output
366 if (!((xp->a_size==0)&&(xp->a_addr==0)&&(nmsym==0))) {
367 fprintf(mfp, "AREA %s\n", xp->a_id );
370 fprintf(mfp, "\tRADIX OCTAL\n" );
373 fprintf(mfp, "\tRADIX DEC\n" );
376 fprintf(mfp, "\tRADIX HEX\n" );
379 fprintf( mfp, "\tBASE %04X\n"
382 , xp->a_addr, xp->a_size );
383 if (xp->a_flag & A_ABS) {
388 if (xp->a_flag & A_OVR) {
389 fprintf(mfp, " OVR");
391 fprintf(mfp, " CON");
393 if (xp->a_flag & A_PAG) {
394 fprintf(mfp, " PAG");
396 if (xp->a_flag & A_PAG) {
399 if (ai || aj) { fprintf(mfp, " "); }
400 if (ai) { fprintf(mfp, " Boundary"); }
401 if (ai & aj) { fprintf(mfp, " /"); }
402 if (aj) { fprintf(mfp, " Length"); }
403 if (ai || aj) { fprintf(mfp, " Error"); }
409 * Allocate space for an array of pointers to symbols
412 if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
414 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
420 for (i=0; i<NHASH; i++) {
423 if (oxp == sp->s_axp) {
433 * Bubble Sort of Addresses in Symbol Table Array
439 a0 = sp->s_addr + sp->s_axp->a_addr;
440 for (i=1; i<nmsym; ++i) {
442 ai = sp->s_addr + sp->s_axp->a_addr;
452 fprintf( mfp, "\tGLOBALS\n");
455 fprintf(mfp, "\t\t%s\t%04X\n", p[i]->s_id, p[i]->s_addr + p[i]->s_axp->a_addr );
466 /*)Function VOID lstarea(xp)
468 * area * xp pointer to an area structure
470 * The function lstarea() creates the linker map output for
471 * the area specified by pointer xp. The generated output
472 * area header includes the area name, starting address,
473 * size of area, number of words (in decimal), and the
474 * area attributes. The symbols defined in this area are
475 * sorted by ascending address and output four per line
476 * in the selected radix.
479 * areax * oxp pointer to an area extension structure
480 * int c character value
482 * int j bubble sort update status
483 * char * ptr pointer to an id string
484 * int nmsym number of symbols in area
485 * addr_t a0 temporary
486 * addr_t ai temporary
487 * addr_t aj temporary
488 * sym * sp pointer to a symbol structure
489 * sym ** p pointer to an array of
490 * pointers to symbol structures
493 * FILE *mfp Map output file handle
494 * sym *symhash[NHASH] array of pointers to NHASH
495 * linked symbol lists
496 * int xflag Map file radix type flag
499 * int fprintf() c_library
500 * VOID free() c_library
501 * char * malloc() c_library
502 * char putc() c_library
503 * VOID slew() lklist.c
506 * Map output generated.
513 register struct areax *oxp;
527 while (ptr < &xp->a_id[NCPS]) {
528 if ((c = *ptr++) != 0) {
537 fprintf(mfp, " %04X %04X", ai, aj);
540 fprintf(mfp, " %06o %06o", ai, aj);
543 fprintf(mfp, " %05u %05u", ai, aj);
545 fprintf(mfp, " = %6u. bytes ", aj);
546 if (xp->a_flag & A_ABS) {
547 fprintf(mfp, "(ABS");
549 fprintf(mfp, "(REL");
551 if (xp->a_flag & A_OVR) {
552 fprintf(mfp, ",OVR");
554 fprintf(mfp, ",CON");
556 if (xp->a_flag & A_PAG) {
557 fprintf(mfp, ",PAG");
560 if (xp->a_flag & A_PAG) {
563 if (ai || aj) { fprintf(mfp, " "); }
564 if (ai) { fprintf(mfp, " Boundary"); }
565 if (ai & aj) { fprintf(mfp, " /"); }
566 if (aj) { fprintf(mfp, " Length"); }
567 if (ai || aj) { fprintf(mfp, " Error"); }
571 * Find number of symbols in area
576 for (i=0; i<NHASH; i++) {
579 if (oxp == sp->s_axp)
593 * Allocate space for an array of pointers to symbols
596 if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
598 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
605 for (i=0; i<NHASH; i++) {
608 if (oxp == sp->s_axp) {
618 * Bubble Sort of Addresses in Symbol Table Array
624 a0 = sp->s_addr + sp->s_axp->a_addr;
625 for (i=1; i<nmsym; ++i) {
627 ai = sp->s_addr + sp->s_axp->a_addr;
638 * Symbol Table Output
648 aj = sp->s_addr + sp->s_axp->a_addr;
650 fprintf(mfp, " %04X ", aj);
653 fprintf(mfp, "%06o ", aj);
656 fprintf(mfp, " %05u ", aj);
659 while (ptr < &sp->s_id[NCPS]) {
660 if ((c = *ptr++) != 0) {
677 VOID lstareatosym(struct area *xp)
679 /* Output the current area symbols to a NO$GMB .sym file */
680 register struct areax *oxp;
688 * Find number of symbols in area
693 for (i=0; i<NHASH; i++) {
696 if (oxp == sp->s_axp)
705 * Symbol Table Output
707 if (!((xp->a_size==0)&&(xp->a_addr==0)&&(nmsym==0))) {
708 /* Dont worry about any area information */
709 fprintf(mfp, "; Area: %s\n", xp->a_id );
712 * Allocate space for an array of pointers to symbols
715 if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
717 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
723 for (i=0; i<NHASH; i++) {
726 if (oxp == sp->s_axp) {
736 * Bubble Sort of Addresses in Symbol Table Array
742 a0 = sp->s_addr + sp->s_axp->a_addr;
743 for (i=1; i<nmsym; ++i) {
745 ai = sp->s_addr + sp->s_axp->a_addr;
756 if ((strncmp("l__", p[i]->s_id, 3)!=0)&&(strchr(p[i]->s_id,' ')==NULL)) {
757 a0=p[i]->s_addr + p[i]->s_axp->a_addr;
759 /* Not inside the ROM, so treat as being in bank zero */
760 fprintf(mfp, "00:%04X %s\n", a0, p[i]->s_id);
763 fprintf(mfp, "%02X:%04X %s\n", a0/16384, a0, p[i]->s_id );
774 /*)Function VOID lkulist(i)
776 * int i i # 0 process LST to RST file
777 * i = 0 copy remainder of LST file
778 * to RST file and close files
780 * The function lkulist() creates a relocated listing (.rst)
781 * output file from the ASxxxx assembler listing (.lst)
782 * files. The .lst file's program address and code bytes
783 * are changed to reflect the changes made by ASlink as
784 * the .rel files are combined into a single relocated
788 * addr_t pc current program counter address
791 * int hilo byte order
792 * int gline get a line from the LST file
793 * to translate for the RST file
794 * char rb[] read listing file text line
795 * FILE *rfp The file handle to the current
797 * int rtcnt count of data words
798 * int rtflg[] output the data flag
799 * addr_t rtval[] relocated data
800 * FILE *tfp The file handle to the current
801 * LST file being scanned
804 * int fclose() c_library
805 * int fgets() c_library
806 * int fprintf() c_library
807 * VOID lkalist() lklist.c
808 * VOID lkglist() lklist.c
811 * A .rst file is created for each available .lst
812 * file associated with a .rel file.
822 * Exit if listing file is not open
828 * Normal processing of LST to RST
832 * Evaluate current code address
835 pc = ((rtval[1] & 0xFF) << 8) + (rtval[0] & 0xFF);
837 pc = ((rtval[0] & 0xFF) << 8) + (rtval[1] & 0xFF);
841 * Line with only address
847 * Line with address and code
850 for (i=2; i < rtcnt; i++) {
852 lkglist(pc++, rtval[i] & 0xFF);
858 * Copy remainder of LST to RST
864 while (fgets(rb, sizeof(rb), tfp) != 0) {
874 /*)Function VOID lkalist(pc)
876 * int pc current program counter value
878 * The function lkalist() performs the following functions:
880 * (1) if the value of gline = 0 then the current listing
881 * file line is copied to the relocated listing file output.
883 * (2) the listing file is read line by line and copied to
884 * the relocated listing file until a valid source
885 * line number and a program counter value of the correct
886 * radix is found. The new relocated pc value is substituted
887 * and the line is written to the RST file.
891 * char str[] temporary string
894 * int gcntr data byte counter
895 * int gline get a line from the LST file
896 * to translate for the RST file
897 * char rb[] read listing file text line
898 * char *rp pointer to listing file text line
899 * FILE *rfp The file handle to the current
901 * FILE *tfp The file handle to the current
902 * LST file being scanned
906 * int fclose() c_library
907 * int fgets() c_library
908 * int fprintf() c_library
909 * int sprintf() c_library
910 * char * strncpy() c_library
913 * Lines of the LST file are copied to the RST file,
914 * the last line copied has the code address
915 * updated to reflect the program relocation.
926 * Exit if listing file is not open
928 loop: if (tfp == NULL)
932 * Copy current LST to RST
940 * Clear text line buffer
942 for (i=0,rp=rb; i<sizeof(rb); i++) {
947 * Get next LST text line
949 if (fgets(rb, sizeof(rb), tfp) == NULL) {
958 * Must have an ASxxxx Listing line number
960 if (!dgt(RAD10, &rb[30], 1)) {
966 * Must have an address in the expected radix
969 if (!dgt(RAD16, &rb[3], 4)) {
973 sprintf(str, "%04X", pc);
974 strncpy(&rb[3], str, 4);
977 if (!dgt(RAD10, &rb[3], 5)) {
981 sprintf(str, "%05d", pc);
982 strncpy(&rb[3], str, 5);
985 if (!dgt(RAD8, &rb[3], 6)) {
989 sprintf(str, "%06o", pc);
990 strncpy(&rb[3], str, 6);
994 * Copy updated LST text line to RST
1000 /*)Function VOID lkglist(pc,v)
1002 * int pc current program counter value
1003 * int v value of byte at this address
1005 * The function lkglist() performs the following functions:
1007 * (1) if the value of gline = 1 then the listing file
1008 * is read line by line and copied to the
1009 * relocated listing file until a valid source
1010 * line number and a program counter value of the correct
1013 * (2) The new relocated values and code address are
1014 * substituted and the line may be written to the RST file.
1017 * int i loop counter
1018 * char str[] temporary string
1021 * int gcntr data byte counter
1022 * set to -1 for a continuation line
1023 * int gline get a line from the LST file
1024 * to translate for the RST file
1025 * char rb[] read listing file text line
1026 * char *rp pointer to listing file text line
1027 * FILE *rfp The file handle to the current
1029 * FILE *tfp The file handle to the current
1030 * LST file being scanned
1033 * int dgt() lklist.c
1034 * int fclose() c_library
1035 * int fgets() c_library
1036 * int fprintf() c_library
1037 * int sprintf() c_library
1038 * char * strncpy() c_library
1041 * Lines of the LST file are copied to the RST file
1042 * with updated data values and code addresses.
1054 * Exit if listing file is not open
1056 loop: if (tfp == NULL)
1060 * Get next LST text line
1064 * Clear text line buffer
1066 for (i=0,rp=rb; i<sizeof(rb); i++) {
1071 * Get next LST text line
1073 if (fgets(rb, sizeof(rb), tfp) == NULL) {
1082 * Check for a listing line number if required
1085 if (!dgt(RAD10, &rb[30], 1)) {
1104 rp = &rb[8 + (3 * gcntr)];
1107 * Number must be of proper radix
1109 if (!dgt(RAD16, rp, 2)) {
1115 * Output new data value, overwrite relocation codes
1117 sprintf(str, " %02X", v);
1118 strncpy(rp-1, str, 3);
1123 * Output relocated code address
1126 if (dgt(RAD16, &rb[3], 4)) {
1127 sprintf(str, "%04X", pc);
1128 strncpy(&rb[3], str, 4);
1132 * Output text line when updates finished
1150 rp = &rb[9 + (3 * gcntr)];
1153 * Number must be of proper radix
1155 if (!dgt(RAD10, rp, 3)) {
1161 * Output new data value, overwrite relocation codes
1163 sprintf(str, " %03d", v);
1164 strncpy(rp-1, str, 4);
1169 * Output relocated code address
1172 if (dgt(RAD10, &rb[3], 5)) {
1173 sprintf(str, "%05d", pc);
1174 strncpy(&rb[3], str, 5);
1178 * Output text line when updates finished
1196 rp = &rb[10 + (3 * gcntr)];
1199 * Number must be of proper radix
1201 if (!dgt(RAD8, rp, 3)) {
1207 * Output new data value, overwrite relocation codes
1209 sprintf(str, " %03o", v);
1210 strncpy(rp-1, str, 4);
1215 * Output relocated code address
1218 if (dgt(RAD8, &rb[3], 6)) {
1219 sprintf(str, "%06o", pc);
1220 strncpy(&rb[3], str, 6);
1224 * Output text line when updates finished
1234 /*)Function int dgt(rdx,str,n)
1236 * int rdx radix bit code
1237 * char *str pointer to the test string
1238 * int n number of characters to check
1240 * The function dgt() verifies that the string under test
1241 * is of the specified radix.
1244 * int i loop counter
1247 * ctype[] array of character types
1263 for (i=0; i<n; i++) {
1264 if ((ctype[*str++] & rdx) == 0)