/* lklist.c */ /* * Copyright (C) 1989-2009 Alan R. Baldwin * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . * * * Alan R. Baldwin * 721 Berkeley St. * Kent, Ohio 44240 * */ /* * 28-Oct-97 JLH: * - lstarea: show s_id as string rather than array [NCPS] * - lstarea: show a_id as string rather than array [NCPS] * 31-Oct-97 JLH: add NoICE output file genration in lstarea * 02-Apr-98 JLH: add XDATA, DATA, BIT flags to area output */ #include "aslink.h" /*)Module lklist.c * * The module lklist.c contains the functions which * output the linker .map file and produce a relocated * listing .rst file. * * lklist.c contains the following functions: * int dgt() * VOID newpag() * VOID slew() * VOID lstarea() * VOID lkulist() * VOID lkalist() * VOID lkglist() * * lklist.c contains no local variables. */ /*)Function VOID newpag() * * The function newpag() outputs a page skip, writes the * first page header line, sets the line count to 1, and * increments the page counter. * * local variables: * none * * global variables: * int lop current line number on page * int page current page number * * functions called: * int fprintf() c_library * * side effects: * The page and line counters are updated. */ VOID newpag(FILE *fp) { fprintf(fp, "\fASxxxx Linker %s, page %u.\n", VERSION, ++page); lop = 1; } /*)Function int dgt(rdx,str,n) * * int rdx radix bit code * char *str pointer to the test string * int n number of characters to check * * The function dgt() verifies that the string under test * is of the specified radix. * * local variables: * int i loop counter * * global variables: * ctype[] array of character types * * functions called: * none * * side effects: * none */ int dgt(int rdx, char *str, int n) { int i; for (i=0; i= NLPP) { newpag(mfp); switch(xflag) { default: case 0: frmta = "Hexadecimal"; break; case 1: frmta = "Octal"; break; case 2: frmta = "Decimal"; break; } fprintf(mfp, "%s [%d-Bits]\n", frmta, a_bytes*8); if (*yp->b_id) { fprintf(mfp, "[ Bank == %s ]\n", yp->b_id); lop += 1; } fprintf(mfp, "\n"); if (wflag) { fprintf(mfp, "Area Addr"); fprintf(mfp, " Size Decimal Bytes (Attributes)\n"); fprintf(mfp, "-------------------------------- ----"); fprintf(mfp, " ---- ------- ----- ------------\n"); } else { fprintf(mfp, "Area Addr "); fprintf(mfp, " Size Decimal Bytes (Attributes)\n"); fprintf(mfp, "-------------------- ---- "); fprintf(mfp, " ---- ------- ----- ------------\n"); } ai = xp->a_addr & a_mask; aj = xp->a_size & a_mask; /* * Output Area Header */ ptr = &xp->a_id[0]; if (wflag) { fprintf(mfp, "%-32.32s", ptr); } else { fprintf(mfp, "%-19.19s", ptr); } #ifdef LONGINT switch(a_bytes) { default: case 2: switch(xflag) { default: case 0: frmta = " %04lX %04lX"; break; case 1: frmta = " %06lo %06lo"; break; case 2: frmta = " %05lu %05lu"; break; } frmtb = " = %6lu. bytes "; break; case 3: switch(xflag) { default: case 0: frmta = " %06lX %06lX"; break; case 1: frmta = " %08lo %08lo"; break; case 2: frmta = " %08lu %08lu"; break; } frmtb = " = %8lu. bytes "; break; case 4: switch(xflag) { default: case 0: frmta = " %08lX %08lX"; break; case 1: frmta = " %011lo %011lo"; break; case 2: frmta = " %010lu %010lu"; break; } frmtb = " = %10lu. bytes "; break; } #else switch(a_bytes) { default: case 2: switch(xflag) { default: case 0: frmta = " %04X %04X"; break; case 1: frmta = " %06o %06o"; break; case 2: frmta = " %05u %05u"; break; } frmtb = " = %6u. bytes "; break; case 3: switch(xflag) { default: case 0: frmta = " %06X %06X"; break; case 1: frmta = " %08o %08o"; break; case 2: frmta = " %08u %08u"; break; } frmtb = " = %8u. bytes "; break; case 4: switch(xflag) { default: case 0: frmta = " %08X %08X"; break; case 1: frmta = " %011o %011o"; break; case 2: frmta = " %010u %010u"; break; } frmtb = " = %10u. bytes "; break; } #endif fprintf(mfp, frmta, ai, aj); fprintf(mfp, frmtb, aj); if (xp->a_flag & A3_ABS) { fprintf(mfp, "(ABS"); } else { fprintf(mfp, "(REL"); } if (xp->a_flag & A3_OVR) { fprintf(mfp, ",OVR"); } else { fprintf(mfp, ",CON"); } if (xp->a_flag & A3_PAG) { fprintf(mfp, ",PAG"); } /* sdld specific */ if (xp->a_flag & A_CODE) { fprintf(mfp, ",CODE"); } if (xp->a_flag & A_XDATA) { fprintf(mfp, ",XDATA"); } if (xp->a_flag & A_BIT) { fprintf(mfp, ",BIT"); } /* end sdld specific */ fprintf(mfp, ")\n"); if (wflag) { putc('\n', mfp); fprintf(mfp, " Value Global "); fprintf(mfp, " Global Defined In Module\n"); fprintf(mfp, " ----- --------------------------------"); fprintf(mfp, " ------------------------\n"); } else { switch(a_bytes) { default: case 2: frmta = " Value Global "; frmtb = " ----- ------ "; n = 4; break; case 3: case 4: frmta = " Value Global "; frmtb = " ----- ------ "; n = 3; break; } putc('\n', mfp); for(i=0;is_addr + (*s1)->s_axp->a_addr) - ((*s2)->s_addr + (*s2)->s_axp->a_addr); /* Sort first by address, then by name. */ if (delta) { return delta; } return strcmp((*s1)->s_id,(*s2)->s_id); } /* end sdld specific */ /*)Function VOID lstarea(xp, yp) * * area * xp pointer to an area structure * bank * yp pointer to a bank structure * * The function lstarea() creates the linker map output for * the area specified by pointer xp. The generated output * area header includes the area name, starting address, * size of area, number of words (in decimal), and the * area attributes. The symbols defined in this area are * sorted by ascending address and output four per line * in the selected radix (one per line in wide format). * * local variables: * areax * oxp pointer to an area extension structure * int i loop counter * int j bubble sort update status * int n repeat counter * char * frmt temporary format specifier * char * ptr pointer to an id string * int nmsym number of symbols in area * a_uint a0 temporary * a_uint ai temporary * a_uint aj temporary * sym * sp pointer to a symbol structure * sym ** p pointer to an array of * pointers to symbol structures * * global variables: * int a_bytes T line address bytes * FILE *mfp Map output file handle * sym *symhash[NHASH] array of pointers to NHASH * linked symbol lists * int wflag Wide format listing * int xflag Map file radix type flag * * functions called: * int fprintf() c_library * VOID free() c_library * char * malloc() c_library * char putc() c_library * VOID slew() lklist.c * * side effects: * Map output generated. */ VOID lstarea(struct area *xp, struct bank *yp) { struct areax *oxp; int i, j, n; char *frmt, *ptr; int nmsym; a_uint a0, ai, aj; struct sym *sp; struct sym **p; /* sdld specific */ int memPage; /* end sdld specific */ /* * Find number of symbols in area */ nmsym = 0; oxp = xp->a_axp; while (oxp) { for (i=0; is_axp) ++nmsym; sp = sp->s_sp; } } oxp = oxp->a_axp; } if ((nmsym == 0) && (xp->a_size == 0)) { return; } lop = NLPP; slew(xp, yp); if (nmsym == 0) { return; } /* * Allocate space for an array of pointers to symbols * and load array. */ if ( (p = (struct sym **) malloc (nmsym*sizeof(struct sym *))) == NULL) { fprintf(mfp, "Insufficient space to build Map Segment.\n"); return; } nmsym = 0; oxp = xp->a_axp; while (oxp) { for (i=0; is_axp) { p[nmsym++] = sp; } sp = sp->s_sp; } } oxp = oxp->a_axp; } if (is_sdld()) { /* * Quick Sort of Addresses in Symbol Table Array */ qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr); } else { /* * Bubble Sort of Addresses in Symbol Table Array */ j = 1; while (j) { j = 0; sp = p[0]; a0 = sp->s_addr + sp->s_axp->a_addr; for (i=1; is_addr + sp->s_axp->a_addr; if (a0 > ai) { j = 1; p[i] = p[i-1]; p[i-1] = sp; } a0 = ai; } } } /* * Repeat Counter */ switch(a_bytes) { default: case 2: n = 4; break; case 3: case 4: n = 3; break; } /* * Symbol Table Output */ /* sdld specific */ memPage = (xp->a_flag & A_CODE) ? 0x0C : ((xp->a_flag & A_XDATA) ? 0x0D : ((xp->a_flag & A_BIT) ? 0x0B : 0x00)); /* end sdld specific */ i = 0; while (i < nmsym) { if (wflag) { slew(xp, yp); if (is_sdld()) { switch(a_bytes) { default: case 2: frmt = " "; break; case 3: case 4: frmt = ""; break; } if (memPage != 0) fprintf(mfp, "%s%X:", frmt, memPage); else fprintf(mfp, "%s ", frmt); } else { switch(a_bytes) { default: case 2: frmt = " "; break; case 3: case 4: frmt = " "; break; } fprintf(mfp, "%s", frmt); } } else if ((i % n) == 0) { slew(xp, yp); switch(a_bytes) { default: case 2: frmt = " "; break; case 3: case 4: frmt = " "; break; } fprintf(mfp, "%s", frmt); } sp = p[i]; aj = (sp->s_addr + sp->s_axp->a_addr) & a_mask; #ifdef LONGINT switch(a_bytes) { default: case 2: switch(xflag) { default: case 0: frmt = " %04lX "; break; case 1: frmt = "%06lo "; break; case 2: frmt = " %05lu "; break; } break; case 3: switch(xflag) { default: case 0: frmt = " %06lX "; break; case 1: frmt = " %08lo "; break; case 2: frmt = " %08lu "; break; } break; case 4: switch(xflag) { default: case 0: frmt = " %08lX "; break; case 1: frmt = "%011lo "; break; case 2: frmt = " %010lu "; break; } break; } #else switch(a_bytes) { default: case 2: switch(xflag) { default: case 0: frmt = " %04X "; break; case 1: frmt = "%06o "; break; case 2: frmt = " %05u "; break; } break; case 3: switch(xflag) { default: case 0: frmt = " %06X "; break; case 1: frmt = " %08o "; break; case 2: frmt = " %08u "; break; } break; case 4: switch(xflag) { default: case 0: frmt = " %08X "; break; case 1: frmt = "%011o "; break; case 2: frmt = " %010u "; break; } break; } #endif fprintf(mfp, frmt, aj); ptr = &sp->s_id[0]; #if NOICE /* * NoICE output of symbol */ if (jflag) DefineNoICE(ptr, aj, yp); #endif #if SDCDB /* * SDCDB output of symbol */ if (yflag) DefineSDCDB(ptr, aj); #endif if (wflag) { fprintf(mfp, "%-32.32s", ptr); i++; ptr = &sp->m_id[0]; if(ptr) { fprintf(mfp, " %-.28s", ptr); } } else { switch(a_bytes) { default: case 2: frmt = "%-8.8s"; break; case 3: case 4: frmt = "%-9.9s"; break; } fprintf(mfp, frmt, ptr); if (++i < nmsym) if (i % n != 0) fprintf(mfp, " | "); } if (wflag || (i % n == 0)) { putc('\n', mfp); } } if (i % n != 0) { putc('\n', mfp); } free(p); } /*)Function VOID lkulist(i) * * int i i # 0 process LST to RST file * i = 0 copy remainder of LST file * to RST file and close files * * The function lkulist() creates a relocated listing (.rst) * output file from the ASxxxx assembler listing (.lst) * files. The .lst file's program address and code bytes * are changed to reflect the changes made by ASlink as * the .rel files are combined into a single relocated * output file. * * local variables: * a_uint cpc current program counter address in PC increments * int cbytes bytes so far in T line * * global variables: * int a_bytes T Line Address Bytes * int hilo byte order * int gline get a line from the LST file * to translate for the RST file * a_uint pc current program counter address in bytes * int pcb bytes per instruction word * char rb[] read listing file text line * FILE *rfp The file handle to the current * output RST file * int rtcnt count of data words * int rtflg[] output the data flag * a_uint rtval[] relocated data * int rterr[] error flag ??? * FILE *tfp The file handle to the current * LST file being scanned * * functions called: * int fclose() c_library * int fgets() c_library * int fprintf() c_library * VOID lkalist() lklist.c * VOID lkglist() lklist.c * * side effects: * A .rst file is created for each available .lst * file associated with a .rel file. */ VOID lkulist(int i) { a_uint cpc; int cbytes; /* * Exit if listing file is not open */ if (tfp == NULL) return; /* * Normal processing of LST to RST */ if (i) { /* * Line with only address */ if (rtcnt == a_bytes) { lkalist(pc); /* * Line with address and code */ } else { cpc = pc; cbytes = 0; for (i=a_bytes; i < rtcnt; i++) { if (rtflg[i]) { lkglist(cpc, (int) (rtval[i] & 0xFF), rterr[i]); cbytes += 1; cpc += (cbytes % pcb) ? 0 : 1; } } } /* * Copy remainder of LST to RST */ } else { if (gline == 0) fprintf(rfp, "%s", rb); while (fgets(rb, sizeof(rb)-2, tfp) != 0) { fprintf(rfp, "%s", rb); } fclose(tfp); tfp = NULL; fclose(rfp); rfp = NULL; } } /*)Function VOID lkalist(cpc) * * int cpc current program counter value * * The function lkalist() performs the following functions: * * (1) if the value of gline = 0 then the current listing * file line is copied to the relocated listing file output. * * (2) the listing file is read line by line and copied to * the relocated listing file until a valid source * line number and a program counter value of the correct * radix is found. The new relocated pc value is substituted * and the line is written to the RST file. * * local variables: * int i loop counter * int m character count * int n character index * int r character radix * char * frmt temporary format specifier * char str[] temporary string * * global variables: * int a_bytes T Line Address Bytes * a_uint a_mask address masking parameter * int gcntr data byte counter * int gline get a line from the LST file * to translate for the RST file * char rb[] read listing file text line * FILE *rfp The file handle to the current * output RST file * FILE *tfp The file handle to the current * LST file being scanned * * functions called: * int dgt() lklist.c * int fclose() c_library * int fgets() c_library * int fprintf() c_library * int sprintf() c_library * char * strncpy() c_library * * side effects: * Lines of the LST file are copied to the RST file, * the last line copied has the code address * updated to reflect the program relocation. */ /* The Output Formats, No Cycle Count | Tabs- | | | | | | 11111111112222222222333333333344444----- 012345678901234567890123456789012345678901234----- | | | | | ee XXXX xx xx xx xx xx xx LLLLL ************* HEX(16) ee 000000 ooo ooo ooo ooo LLLLL ************* OCTAL(16) ee DDDDD ddd ddd ddd ddd LLLLL ************* DECIMAL(16) XXXX OOOOOO DDDDD | Tabs- | | | | | | 11111111112222222222333333333344444----- 012345678901234567890123456789012345678901234----- | | | | | ee XXXXXX xx xx xx xx xx xx xx LLLLL ********* HEX(24) ee OO000000 ooo ooo ooo ooo ooo LLLLL ********* OCTAL(24) ee DDDDDDDD ddd ddd ddd ddd ddd LLLLL ********* DECIMAL(24) XXXXXX OOOOOOOO DDDDDDDD | Tabs- | | | | | | 11111111112222222222333333333344444----- 012345678901234567890123456789012345678901234----- | | | | | ee XXXXXXXX xx xx xx xx xx xx xx LLLLL ********* HEX(32) eeOOOOO000000 ooo ooo ooo ooo ooo LLLLL ********* OCTAL(32) ee DDDDDDDDDD ddd ddd ddd ddd ddd LLLLL ********* DECIMAL(32) XXXXXXXX OOOOOOOOOOO DDDDDDDDDD */ /* The Output Formats, With Cycle Count [nn] | Tabs- | | | | | | 11111111112222222222333333333344444----- 012345678901234567890123456789012345678901234----- | | | | | ee XXXX xx xx xx xx xx[nn]LLLLL ************* HEX(16) ee 000000 ooo ooo ooo [nn]LLLLL ************* OCTAL(16) ee DDDDD ddd ddd ddd [nn]LLLLL ************* DECIMAL(16) XXXX OOOOOO DDDDD | Tabs- | | | | | | 11111111112222222222333333333344444----- 012345678901234567890123456789012345678901234----- | | | | | ee XXXXXX xx xx xx xx xx xx[nn]LLLLL ********* HEX(24) ee OO000000 ooo ooo ooo ooo [nn]LLLLL ********* OCTAL(24) ee DDDDDDDD ddd ddd ddd ddd [nn]LLLLL ********* DECIMAL(24) XXXXXX OOOOOOOO DDDDDDDD | Tabs- | | | | | | 11111111112222222222333333333344444----- 012345678901234567890123456789012345678901234----- | | | | | ee XXXXXXXX xx xx xx xx xx xx[nn]LLLLL ********* HEX(32) eeOOOOO000000 ooo ooo ooo ooo [nn]LLLLL ********* OCTAL(32) ee DDDDDDDDDD ddd ddd ddd ddd [nn]LLLLL ********* DECIMAL(32) XXXXXXXX OOOOOOOOOOO DDDDDDDDDD */ VOID lkalist(a_uint cpc) { char str[16]; char *frmt; int m, n, r; /* * Truncate (int) to N-Bytes */ cpc &= a_mask; /* * Exit if listing file is not open */ loop: if (tfp == NULL) return; /* * Copy current LST to RST */ if (gline == 0) { fprintf(rfp, "%s", rb); gline = 1; } /* * Clear text line buffer */ memset(rb, 0, sizeof(rb)); /* * Get next LST text line */ if (fgets(rb, sizeof(rb)-2, tfp) == NULL) { fclose(tfp); tfp = NULL; fclose(rfp); rfp = NULL; return; } /* * Must have an ASxxxx Listing line number */ switch(a_bytes) { default: case 2: n = 30; break; case 3: case 4: n = 38; break; } if (!dgt(RAD10, &rb[n], 1)) { fprintf(rfp, "%s", rb); goto loop; } /* * Must have an address in the expected radix */ #ifdef LONGINT switch(radix) { default: case 16: r = RAD16; switch(a_bytes) { default: case 2: n = 3; m = 4; frmt = "%04lX"; break; case 3: n = 6; m = 6; frmt = "%06lX"; break; case 4: n = 4; m = 8; frmt = "%08lX"; break; } break; case 10: r = RAD10; switch(a_bytes) { default: case 2: n = 4; m = 5; frmt = "%05lu"; break; case 3: n = 5; m = 8; frmt = "%08lu"; break; case 4: n = 3; m = 10; frmt = "%010lu"; break; } break; case 8: r = RAD8; switch(a_bytes) { default: case 2: n = 3; m = 6; frmt = "%06lo"; break; case 3: n = 5; m = 8; frmt = "%08lo"; break; case 4: n = 2; m = 11; frmt = "%011lo"; break; } break; } #else switch(radix) { default: case 16: r = RAD16; switch(a_bytes) { default: case 2: n = 3; m = 4; frmt = "%04X"; break; case 3: n = 6; m = 6; frmt = "%06X"; break; case 4: n = 4; m = 8; frmt = "%08X"; break; } break; case 10: r = RAD10; switch(a_bytes) { default: case 2: n = 4; m = 5; frmt = "%05u"; break; case 3: n = 5; m = 8; frmt = "%08u"; break; case 4: n = 3; m = 10; frmt = "%010u"; break; } break; case 8: r = RAD8; switch(a_bytes) { default: case 2: n = 3; m = 6; frmt = "%06o"; break; case 3: n = 5; m = 8; frmt = "%08o"; break; case 4: n = 2; m = 11; frmt = "%011o"; break; } break; } #endif if (!dgt(r, &rb[n], m)) { fprintf(rfp, "%s", rb); goto loop; } sprintf(str, frmt, cpc); strncpy(&rb[n], str, m); /* * Copy updated LST text line to RST */ fprintf(rfp, "%s", rb); gcntr = 0; } /*)Function VOID lkglist(cpc,v,err) * * int cpc current program counter value * int v value of byte at this address * int err error flag for this value * * The function lkglist() performs the following functions: * * (1) if the value of gline = 1 then the listing file * is read line by line and copied to the * relocated listing file until a valid source * line number and a program counter value of the correct * radix is found. * * (2) The new relocated values and code address are * substituted and the line may be written to the RST file. * * local variables: * int a string index for first byte * int i loop counter * int m character count * int n character index * int r character radix * int s spacing * int u repeat counter * char * afrmt temporary format specifier * char * frmt temporary format specifier * char str[] temporary string * * global variables: * int a_bytes T Line Address Bytes * a_uint a_mask address masking parameter * int gcntr data byte counter * set to -1 for a continuation line * int gline get a line from the LST file * to translate for the RST file * char rb[] read listing file text line * char *rp pointer to listing file text line * FILE *rfp The file handle to the current * output RST file * FILE *tfp The file handle to the current * LST file being scanned * char *errmsg3[] array of pointers to error strings * * functions called: * int dgt() lklist.c * int fclose() c_library * int fgets() c_library * int fprintf() c_library * int sprintf() c_library * char * strncpy() c_library * * side effects: * Lines of the LST file are copied to the RST file * with updated data values and code addresses. */ /* The Output Formats, No Cycle Count | Tabs- | | | | | | 11111111112222222222333333333344444----- 012345678901234567890123456789012345678901234----- | | | | | ee XXXX xx xx xx xx xx xx LLLLL ************* HEX(16) ee 000000 ooo ooo ooo ooo LLLLL ************* OCTAL(16) ee DDDDD ddd ddd ddd ddd LLLLL ************* DECIMAL(16) XXXX OOOOOO DDDDD | Tabs- | | | | | | 11111111112222222222333333333344444----- 012345678901234567890123456789012345678901234----- | | | | | ee XXXXXX xx xx xx xx xx xx xx LLLLL ********* HEX(24) ee OO000000 ooo ooo ooo ooo ooo LLLLL ********* OCTAL(24) ee DDDDDDDD ddd ddd ddd ddd ddd LLLLL ********* DECIMAL(24) XXXXXX OOOOOOOO DDDDDDDD | Tabs- | | | | | | 11111111112222222222333333333344444----- 012345678901234567890123456789012345678901234----- | | | | | ee XXXXXXXX xx xx xx xx xx xx xx LLLLL ********* HEX(32) eeOOOOO000000 ooo ooo ooo ooo ooo LLLLL ********* OCTAL(32) ee DDDDDDDDDD ddd ddd ddd ddd ddd LLLLL ********* DECIMAL(32) XXXXXXXX OOOOOOOOOOO DDDDDDDDDD */ /* The Output Formats, With Cycle Count [nn] | Tabs- | | | | | | 11111111112222222222333333333344444----- 012345678901234567890123456789012345678901234----- | | | | | ee XXXX xx xx xx xx xx[nn]LLLLL ************* HEX(16) ee 000000 ooo ooo ooo [nn]LLLLL ************* OCTAL(16) ee DDDDD ddd ddd ddd [nn]LLLLL ************* DECIMAL(16) XXXX OOOOOO DDDDD | Tabs- | | | | | | 11111111112222222222333333333344444----- 012345678901234567890123456789012345678901234----- | | | | | ee XXXXXX xx xx xx xx xx xx[nn]LLLLL ********* HEX(24) ee OO000000 ooo ooo ooo ooo [nn]LLLLL ********* OCTAL(24) ee DDDDDDDD ddd ddd ddd ddd [nn]LLLLL ********* DECIMAL(24) XXXXXX OOOOOOOO DDDDDDDD | Tabs- | | | | | | 11111111112222222222333333333344444----- 012345678901234567890123456789012345678901234----- | | | | | ee XXXXXXXX xx xx xx xx xx xx[nn]LLLLL ********* HEX(32) eeOOOOO000000 ooo ooo ooo ooo [nn]LLLLL ********* OCTAL(32) ee DDDDDDDDDD ddd ddd ddd ddd [nn]LLLLL ********* DECIMAL(32) XXXXXXXX OOOOOOOOOOO DDDDDDDDDD */ VOID lkglist(a_uint cpc, int v, int err) { char str[16]; char *afrmt, *frmt; int a, n, m, r, s, u; /* * Truncate (int) to N-Bytes */ cpc &= a_mask; /* * Exit if listing file is not open */ loop: if (tfp == NULL) return; /* * Get next LST text line */ if (gline) { /* * Clear text line buffer */ memset(rb, 0, sizeof(rb)); /* * Get next LST text line */ if (fgets(rb, sizeof(rb)-2, tfp) == NULL) { fclose(tfp); tfp = NULL; fclose(rfp); rfp = NULL; return; } /* * Check for a listing line number if required */ if (gcntr != -1) { switch(a_bytes) { default: case 2: n = 30; break; case 3: case 4: n = 38; break; } if (!dgt(RAD10, &rb[n], 1)) { fprintf(rfp, "%s", rb); goto loop; } gcntr = 0; } gline = 0; } /* * Hex Listing */ #ifdef LONGINT switch(radix) { default: case 16: r = RAD16; switch(a_bytes) { default: case 2: a = 8; s = 3; n = 3; m = 4; u = 6; afrmt = "%04lX"; break; case 3: a = 13; s = 3; n = 6; m = 6; u = 7; afrmt = "%06lX"; break; case 4: a = 13; s = 3; n = 4; m = 8; u = 7; afrmt = "%08lX"; break; } frmt = " %02X"; break; case 10: r = RAD10; switch(a_bytes) { default: case 2: a = 10; s = 4; n = 4; m = 5; u = 4; afrmt = "%05lu"; break; case 3: a = 14; s = 4; n = 5; m = 8; u = 5; afrmt = "%08lu"; break; case 4: a = 14; s = 4; n = 3; m = 10; u = 5; afrmt = "%010lu"; break; } frmt = " %03u"; break; case 8: r = RAD8; switch(a_bytes) { default: case 2: a = 10; s = 4; n = 3; m = 6; u = 4; afrmt = "%06lo"; break; case 3: a = 14; s = 4; n = 5; m = 8; u = 5; afrmt = "%08lo"; break; case 4: a = 14; s = 4; n = 2; m = 11; u = 5; afrmt = "%011lo"; break; } frmt = " %03o"; break; } #else switch(radix) { default: case 16: r = RAD16; switch(a_bytes) { default: case 2: a = 8; s = 3; n = 3; m = 4; u = 6; afrmt = "%04X"; break; case 3: a = 13; s = 3; n = 6; m = 6; u = 7; afrmt = "%06X"; break; case 4: a = 13; s = 3; n = 4; m = 8; u = 7; afrmt = "%08X"; break; } frmt = " %02X"; break; case 10: r = RAD10; switch(a_bytes) { default: case 2: a = 10; s = 4; n = 4; m = 5; u = 4; afrmt = "%05u"; break; case 3: a = 14; s = 4; n = 5; m = 8; u = 5; afrmt = "%08u"; break; case 4: a = 14; s = 4; n = 3; m = 10; u = 5; afrmt = "%010u"; break; } frmt = " %03u"; break; case 8: r = RAD8; switch(a_bytes) { default: case 2: a = 10; s = 4; n = 3; m = 6; u = 4; afrmt = "%06o"; break; case 3: a = 14; s = 4; n = 5; m = 8; u = 5; afrmt = "%08o"; break; case 4: a = 14; s = 4; n = 2; m = 11; u = 5; afrmt = "%011o"; break; } frmt = " %03o"; break; } #endif /* * Data Byte Pointer */ if (gcntr == -1) { rp = &rb[a]; } else { rp = &rb[a + (s * gcntr)]; } /* * Number must be of proper radix */ if (!dgt(r, rp, s-1)) { fprintf(rfp, "%s", rb); gline = 1; goto loop; } /* * Output new data value, overwrite relocation codes */ sprintf(str, frmt, v); strncpy(rp-1, str, s); if (gcntr == -1) { gcntr = 0; } /* * Output relocated code address */ if (gcntr == 0) { if (dgt(r, &rb[n], m)) { sprintf(str, afrmt, cpc); strncpy(&rb[n], str, m); } } /* * Output an error line if required */ if (err) { switch(ASxxxx_VERSION) { case 3: fprintf(rfp, "?ASlink-Warning-%s\n", errmsg3[err]); break; default: break; } } /* * Fix 'u' if [nn], cycles, is specified */ if (rb[a + (s*u) - 1] == CYCNT_END) { u -= 1; } /* * Output text line when updates finished */ if (++gcntr == u) { fprintf(rfp, "%s", rb); gline = 1; gcntr = -1; } }