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);
122 /*)Function VOID lstarea(xp)
124 * area * xp pointer to an area structure
126 * The function lstarea() creates the linker map output for
127 * the area specified by pointer xp. The generated output
128 * area header includes the area name, starting address,
129 * size of area, number of words (in decimal), and the
130 * area attributes. The symbols defined in this area are
131 * sorted by ascending address and output one per line
132 * in the selected radix.
135 * areax * oxp pointer to an area extension structure
136 * int c character value
138 * int j bubble sort update status
139 * char * ptr pointer to an id string
140 * int nmsym number of symbols in area
141 * addr_t a0 temporary
142 * addr_t ai temporary
143 * addr_t aj temporary
144 * sym * sp pointer to a symbol structure
145 * sym ** p pointer to an array of
146 * pointers to symbol structures
149 * FILE *mfp Map output file handle
150 * sym *symhash[NHASH] array of pointers to NHASH
151 * linked symbol lists
152 * int xflag Map file radix type flag
155 * int fprintf() c_library
156 * VOID free() c_library
157 * char * malloc() c_library
158 * char putc() c_library
159 * VOID slew() lklist.c
162 * Map output generated.
169 register struct areax *oxp;
180 fprintf(mfp, "Hexadecimal\n\n");
183 fprintf(mfp, "Octal\n\n");
186 fprintf(mfp, "Decimal\n\n");
188 fprintf(mfp, "Area ");
189 fprintf(mfp, "Addr Size Decimal Bytes (Attributes)\n");
190 fprintf(mfp, "-------------------------------- ");
191 fprintf(mfp, "---- ---- ------- ----- ------------\n");
196 fprintf(mfp, "%-32s", ptr ); /* JLH: width matches --- above */
200 fprintf(mfp, " %04X %04X", ai, aj);
203 fprintf(mfp, " %06o %06o", ai, aj);
206 fprintf(mfp, " %05u %05u", ai, aj);
208 fprintf(mfp, " = %6u. bytes ", aj);
209 if (xp->a_flag & A_ABS) {
210 fprintf(mfp, "(ABS");
212 fprintf(mfp, "(REL");
214 if (xp->a_flag & A_OVR) {
215 fprintf(mfp, ",OVR");
217 fprintf(mfp, ",CON");
219 if (xp->a_flag & A_PAG) {
220 fprintf(mfp, ",PAG");
224 if (xp->a_flag & A_CODE) {
225 fprintf(mfp, ",CODE");
228 if (xp->a_flag & A_XDATA) {
229 fprintf(mfp, ",XDATA");
232 if (xp->a_flag & A_BIT) {
233 fprintf(mfp, ",BIT");
237 if (xp->a_flag & A_PAG) {
240 if (ai || aj) { fprintf(mfp, " "); }
241 if (ai) { fprintf(mfp, " Boundary"); }
242 if (ai & aj) { fprintf(mfp, " /"); }
243 if (aj) { fprintf(mfp, " Length"); }
244 if (ai || aj) { fprintf(mfp, " Error"); }
248 * Find number of symbols in area
253 for (i=0; i<NHASH; i++) {
256 if (oxp == sp->s_axp)
269 * Allocate space for an array of pointers to symbols
272 if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
274 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
280 for (i=0; i<NHASH; i++) {
283 if (oxp == sp->s_axp) {
293 * Bubble Sort of Addresses in Symbol Table Array
299 a0 = sp->s_addr + sp->s_axp->a_addr;
300 for (i=1; i<nmsym; ++i) {
302 ai = sp->s_addr + sp->s_axp->a_addr;
313 * Symbol Table Output
317 fprintf(mfp, "\n\n");
318 fprintf(mfp, " Value Global\n");
319 fprintf(mfp, " -------- --------------------------------");
323 fprintf(mfp, " %02X:", memPage);
328 aj = sp->s_addr + sp->s_axp->a_addr;
330 fprintf(mfp, "%04X ", aj);
333 fprintf(mfp, "%06o ", aj);
336 fprintf(mfp, "%05u ", aj);
339 fprintf(mfp, "%s", ptr );
341 /* if cdb flag set the output cdb Information
342 and the symbol has a '$' sign in it then */
345 fprintf(dfp,"L:%s:%X\n",ptr,aj);
346 /* NoICE output of symbol */
347 if (jflag) DefineNoICE( ptr, aj, memPage );
358 /*)Function VOID lstarea(xp)
360 * area * xp pointer to an area structure
362 * The function lstarea() creates the linker map output for
363 * the area specified by pointer xp. The generated output
364 * area header includes the area name, starting address,
365 * size of area, number of words (in decimal), and the
366 * area attributes. The symbols defined in this area are
367 * sorted by ascending address and output four per line
368 * in the selected radix.
371 * areax * oxp pointer to an area extension structure
372 * int c character value
374 * int j bubble sort update status
375 * char * ptr pointer to an id string
376 * int nmsym number of symbols in area
377 * addr_t a0 temporary
378 * addr_t ai temporary
379 * addr_t aj temporary
380 * sym * sp pointer to a symbol structure
381 * sym ** p pointer to an array of
382 * pointers to symbol structures
385 * FILE *mfp Map output file handle
386 * sym *symhash[NHASH] array of pointers to NHASH
387 * linked symbol lists
388 * int xflag Map file radix type flag
391 * int fprintf() c_library
392 * VOID free() c_library
393 * char * malloc() c_library
394 * char putc() c_library
395 * VOID slew() lklist.c
398 * Map output generated.
405 register struct areax *oxp;
420 while (ptr < &xp->a_id[NCPS]) {
421 if ((c = *ptr++) != 0) {
430 fprintf(mfp, " %04X %04X", ai, aj);
433 fprintf(mfp, " %06o %06o", ai, aj);
436 fprintf(mfp, " %05u %05u", ai, aj);
438 fprintf(mfp, " = %6u. bytes ", aj);
439 if (xp->a_flag & A_ABS) {
440 fprintf(mfp, "(ABS");
442 fprintf(mfp, "(REL");
444 if (xp->a_flag & A_OVR) {
445 fprintf(mfp, ",OVR");
447 fprintf(mfp, ",CON");
449 if (xp->a_flag & A_PAG) {
450 fprintf(mfp, ",PAG");
454 if (xp->a_flag & A_CODE) {
455 fprintf(mfp, ",CODE");
458 if (xp->a_flag & A_XDATA) {
459 fprintf(mfp, ",XDATA");
462 if (xp->a_flag & A_BIT) {
463 fprintf(mfp, ",BIT");
467 if (xp->a_flag & A_PAG) {
470 if (ai || aj) { fprintf(mfp, " "); }
471 if (ai) { fprintf(mfp, " Boundary"); }
472 if (ai & aj) { fprintf(mfp, " /"); }
473 if (aj) { fprintf(mfp, " Length"); }
474 if (ai || aj) { fprintf(mfp, " Error"); }
478 * Find number of symbols in area
483 for (i=0; i<NHASH; i++) {
486 if (oxp == sp->s_axp)
500 * Allocate space for an array of pointers to symbols
503 if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
505 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
512 for (i=0; i<NHASH; i++) {
515 if (oxp == sp->s_axp) {
525 * Bubble Sort of Addresses in Symbol Table Array
531 a0 = sp->s_addr + sp->s_axp->a_addr;
532 for (i=1; i<nmsym; ++i) {
534 ai = sp->s_addr + sp->s_axp->a_addr;
545 * Symbol Table Output
553 aj = sp->s_addr + sp->s_axp->a_addr;
555 fprintf(mfp, " %04X ", aj);
558 fprintf(mfp, "%06o ", aj);
561 fprintf(mfp, " %05u ", aj);
564 fprintf(mfp, "%s", ptr );
566 /* NoICE output of symbol */
567 if (jflag) DefineNoICE( ptr, aj, memPage );
575 /*)Function VOID lkulist(i)
577 * int i i # 0 process LST to RST file
578 * i = 0 copy remainder of LST file
579 * to RST file and close files
581 * The function lkulist() creates a relocated listing (.rst)
582 * output file from the ASxxxx assembler listing (.lst)
583 * files. The .lst file's program address and code bytes
584 * are changed to reflect the changes made by ASlink as
585 * the .rel files are combined into a single relocated
589 * addr_t pc current program counter address
592 * int hilo byte order
593 * int gline get a line from the LST file
594 * to translate for the RST file
595 * char rb[] read listing file text line
596 * FILE *rfp The file handle to the current
598 * int rtcnt count of data words
599 * int rtflg[] output the data flag
600 * addr_t rtval[] relocated data
601 * FILE *tfp The file handle to the current
602 * LST file being scanned
605 * int fclose() c_library
606 * int fgets() c_library
607 * int fprintf() c_library
608 * VOID lkalist() lklist.c
609 * VOID lkglist() lklist.c
612 * A .rst file is created for each available .lst
613 * file associated with a .rel file.
623 * Exit if listing file is not open
629 * Normal processing of LST to RST
633 * Evaluate current code address
636 pc = ((rtval[1] & 0xFF) << 8) + (rtval[0] & 0xFF);
638 pc = ((rtval[0] & 0xFF) << 8) + (rtval[1] & 0xFF);
642 * Line with only address
648 * Line with address and code
651 for (i=2; i < rtcnt; i++) {
653 lkglist(pc++, rtval[i] & 0xFF);
659 * Copy remainder of LST to RST
663 fprintf(rfp, "%s", rb);
665 while (fgets(rb, sizeof(rb), tfp) != 0) {
666 fprintf(rfp, "%s", rb);
675 /*)Function VOID lkalist(pc)
677 * int pc current program counter value
679 * The function lkalist() performs the following functions:
681 * (1) if the value of gline = 0 then the current listing
682 * file line is copied to the relocated listing file output.
684 * (2) the listing file is read line by line and copied to
685 * the relocated listing file until a valid source
686 * line number and a program counter value of the correct
687 * radix is found. The new relocated pc value is substituted
688 * and the line is written to the RST file.
692 * char str[] temporary string
695 * int gcntr data byte counter
696 * int gline get a line from the LST file
697 * to translate for the RST file
698 * char rb[] read listing file text line
699 * char *rp pointer to listing file text line
700 * FILE *rfp The file handle to the current
702 * FILE *tfp The file handle to the current
703 * LST file being scanned
707 * int fclose() c_library
708 * int fgets() c_library
709 * int fprintf() c_library
710 * int sprintf() c_library
711 * char * strncpy() c_library
714 * Lines of the LST file are copied to the RST file,
715 * the last line copied has the code address
716 * updated to reflect the program relocation.
727 * Exit if listing file is not open
729 loop: if (tfp == NULL)
733 * Copy current LST to RST
736 fprintf(rfp, "%s", rb);
741 * Clear text line buffer
743 for (i=0,rp=rb; i<sizeof(rb); i++) {
748 * Get next LST text line
750 if (fgets(rb, sizeof(rb), tfp) == NULL) {
759 * Must have an ASxxxx Listing line number
761 if (!dgt(RAD10, &rb[30], 1)) {
762 fprintf(rfp, "%s", rb);
767 * Must have an address in the expected radix
770 if (!dgt(RAD16, &rb[3], 4)) {
771 fprintf(rfp, "%s", rb);
774 sprintf(str, "%04X", pc);
775 strncpy(&rb[3], str, 4);
778 if (!dgt(RAD10, &rb[3], 5)) {
779 fprintf(rfp, "%s", rb);
782 sprintf(str, "%05d", pc);
783 strncpy(&rb[3], str, 5);
786 if (!dgt(RAD8, &rb[3], 6)) {
787 fprintf(rfp, "%s", rb);
790 sprintf(str, "%06o", pc);
791 strncpy(&rb[3], str, 6);
795 * Copy updated LST text line to RST
797 fprintf(rfp, "%s", rb);
801 /*)Function VOID lkglist(pc,v)
803 * int pc current program counter value
804 * int v value of byte at this address
806 * The function lkglist() performs the following functions:
808 * (1) if the value of gline = 1 then the listing file
809 * is read line by line and copied to the
810 * relocated listing file until a valid source
811 * line number and a program counter value of the correct
814 * (2) The new relocated values and code address are
815 * substituted and the line may be written to the RST file.
819 * char str[] temporary string
822 * int gcntr data byte counter
823 * set to -1 for a continuation line
824 * int gline get a line from the LST file
825 * to translate for the RST file
826 * char rb[] read listing file text line
827 * char *rp pointer to listing file text line
828 * FILE *rfp The file handle to the current
830 * FILE *tfp The file handle to the current
831 * LST file being scanned
835 * int fclose() c_library
836 * int fgets() c_library
837 * int fprintf() c_library
838 * int sprintf() c_library
839 * char * strncpy() c_library
842 * Lines of the LST file are copied to the RST file
843 * with updated data values and code addresses.
855 * Exit if listing file is not open
857 loop: if (tfp == NULL)
861 * Get next LST text line
865 * Clear text line buffer
867 for (i=0,rp=rb; i<sizeof(rb); i++) {
872 * Get next LST text line
874 if (fgets(rb, sizeof(rb), tfp) == NULL) {
883 * Check for a listing line number if required
886 if (!dgt(RAD10, &rb[30], 1)) {
887 fprintf(rfp, "%s", rb);
905 rp = &rb[8 + (3 * gcntr)];
908 * Number must be of proper radix
910 if (!dgt(RAD16, rp, 2)) {
911 fprintf(rfp, "%s", rb);
916 * Output new data value, overwrite relocation codes
918 sprintf(str, " %02X", v);
919 strncpy(rp-1, str, 3);
924 * Output relocated code address
927 if (dgt(RAD16, &rb[3], 4)) {
928 sprintf(str, "%04X", pc);
929 strncpy(&rb[3], str, 4);
933 * Output text line when updates finished
936 fprintf(rfp, "%s", rb);
951 rp = &rb[9 + (3 * gcntr)];
954 * Number must be of proper radix
956 if (!dgt(RAD10, rp, 3)) {
957 fprintf(rfp, "%s", rb);
962 * Output new data value, overwrite relocation codes
964 sprintf(str, " %03d", v);
965 strncpy(rp-1, str, 4);
970 * Output relocated code address
973 if (dgt(RAD10, &rb[3], 5)) {
974 sprintf(str, "%05d", pc);
975 strncpy(&rb[3], str, 5);
979 * Output text line when updates finished
982 fprintf(rfp, "%s", rb);
997 rp = &rb[10 + (3 * gcntr)];
1000 * Number must be of proper radix
1002 if (!dgt(RAD8, rp, 3)) {
1003 fprintf(rfp, "%s", rb);
1008 * Output new data value, overwrite relocation codes
1010 sprintf(str, " %03o", v);
1011 strncpy(rp-1, str, 4);
1016 * Output relocated code address
1019 if (dgt(RAD8, &rb[3], 6)) {
1020 sprintf(str, "%06o", pc);
1021 strncpy(&rb[3], str, 6);
1025 * Output text line when updates finished
1028 fprintf(rfp, "%s", rb);
1035 /*)Function int dgt(rdx,str,n)
1037 * int rdx radix bit code
1038 * char *str pointer to the test string
1039 * int n number of characters to check
1041 * The function dgt() verifies that the string under test
1042 * is of the specified radix.
1045 * int i loop counter
1048 * ctype[] array of character types
1064 for (i=0; i<n; i++) {
1065 if ((ctype[(int)*str++] & rdx) == 0)