struct / union in initializer, RFE #901.
[sdcc.git] / sdcc / sdas / linksrc / lklist.c
blob51c8d06c3d1cd2c3cef6d6eb69d0b7a36c412c89
1 /* lklist.c */
3 /*
4 * Copyright (C) 1989-2009 Alan R. Baldwin
6 * This program is free software: you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation, either version 3 of the License, or
9 * (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 * Alan R. Baldwin
21 * 721 Berkeley St.
22 * Kent, Ohio 44240
27 * 28-Oct-97 JLH:
28 * - lstarea: show s_id as string rather than array [NCPS]
29 * - lstarea: show a_id as string rather than array [NCPS]
30 * 31-Oct-97 JLH: add NoICE output file genration in lstarea
31 * 02-Apr-98 JLH: add XDATA, DATA, BIT flags to area output
34 #include "aslink.h"
36 /*)Module lklist.c
38 * The module lklist.c contains the functions which
39 * output the linker .map file and produce a relocated
40 * listing .rst file.
42 * lklist.c contains the following functions:
43 * int dgt()
44 * VOID newpag()
45 * VOID slew()
46 * VOID lstarea()
47 * VOID lkulist()
48 * VOID lkalist()
49 * VOID lkglist()
51 * lklist.c contains no local variables.
54 /*)Function VOID newpag()
56 * The function newpag() outputs a page skip, writes the
57 * first page header line, sets the line count to 1, and
58 * increments the page counter.
60 * local variables:
61 * none
63 * global variables:
64 * int lop current line number on page
65 * int page current page number
67 * functions called:
68 * int fprintf() c_library
70 * side effects:
71 * The page and line counters are updated.
74 VOID
75 newpag(FILE *fp)
77 fprintf(fp, "\fASxxxx Linker %s, page %u.\n", VERSION, ++page);
78 lop = 1;
81 /*)Function int dgt(rdx,str,n)
83 * int rdx radix bit code
84 * char *str pointer to the test string
85 * int n number of characters to check
87 * The function dgt() verifies that the string under test
88 * is of the specified radix.
90 * local variables:
91 * int i loop counter
93 * global variables:
94 * ctype[] array of character types
96 * functions called:
97 * none
99 * side effects:
100 * none
104 dgt(int rdx, char *str, int n)
106 int i;
108 for (i=0; i<n; i++) {
109 if ((ctype[*str++ & 0x007F] & rdx) == 0)
110 return(0);
112 return(1);
115 /*)Function VOID slew(xp, yp)
117 * area * xp pointer to an area structure
118 * bank * yp pointer to a bank structure
120 * The function slew() increments the page line counter.
121 * If the number of lines exceeds the maximum number of
122 * lines per page then a page skip and a page header are
123 * output.
125 * local variables:
126 * a_uint ai temporary
127 * a_uint aj temporary
128 * int i loop counter
129 * int n repeat counter
130 * char * frmta temporary format specifier
131 * char * frmtb temporary format specifier
132 * char * ptr pointer to an id string
134 * global variables:
135 * int a_bytes T line address bytes
136 * int a_mask addressing mask
137 * int lop current line number on page
138 * FILE *mfp Map output file handle
139 * int wflag Wide format listing
140 * int xflag Map file radix type flag
142 * functions called:
143 * int fprintf() c_library
144 * VOID newpag() lklist.c
145 * char putc() c_library
147 * side effects:
148 * The page line and the page count may be updated.
151 VOID
152 slew(struct area *xp, struct bank *yp)
154 int i, n;
155 char *frmta, *frmtb, *ptr;
156 a_uint ai, aj;
158 if (lop++ >= NLPP) {
159 newpag(mfp);
160 switch(xflag) {
161 default:
162 case 0: frmta = "Hexadecimal"; break;
163 case 1: frmta = "Octal"; break;
164 case 2: frmta = "Decimal"; break;
166 fprintf(mfp, "%s [%d-Bits]\n", frmta, a_bytes*8);
167 if (*yp->b_id) {
168 fprintf(mfp, "[ Bank == %s ]\n", yp->b_id);
169 lop += 1;
171 fprintf(mfp, "\n");
172 if (wflag) {
173 fprintf(mfp,
174 "Area Addr");
175 fprintf(mfp,
176 " Size Decimal Bytes (Attributes)\n");
177 fprintf(mfp,
178 "-------------------------------- ----");
179 fprintf(mfp,
180 " ---- ------- ----- ------------\n");
181 } else {
182 fprintf(mfp,
183 "Area Addr ");
184 fprintf(mfp,
185 " Size Decimal Bytes (Attributes)\n");
186 fprintf(mfp,
187 "-------------------- ---- ");
188 fprintf(mfp,
189 " ---- ------- ----- ------------\n");
192 ai = xp->a_addr & a_mask;
193 aj = xp->a_size & a_mask;
196 * Output Area Header
198 ptr = &xp->a_id[0];
199 if (wflag) {
200 fprintf(mfp, "%-32.32s", ptr);
201 } else {
202 fprintf(mfp, "%-19.19s", ptr);
204 #ifdef LONGINT
205 switch(a_bytes) {
206 default:
207 case 2:
208 switch(xflag) {
209 default:
210 case 0: frmta = " %04lX %04lX"; break;
211 case 1: frmta = " %06lo %06lo"; break;
212 case 2: frmta = " %05lu %05lu"; break;
214 frmtb = " = %6lu. bytes "; break;
215 case 3:
216 switch(xflag) {
217 default:
218 case 0: frmta = " %06lX %06lX"; break;
219 case 1: frmta = " %08lo %08lo"; break;
220 case 2: frmta = " %08lu %08lu"; break;
222 frmtb = " = %8lu. bytes "; break;
223 case 4:
224 switch(xflag) {
225 default:
226 case 0: frmta = " %08lX %08lX"; break;
227 case 1: frmta = " %011lo %011lo"; break;
228 case 2: frmta = " %010lu %010lu"; break;
230 frmtb = " = %10lu. bytes "; break;
232 #else
233 switch(a_bytes) {
234 default:
235 case 2:
236 switch(xflag) {
237 default:
238 case 0: frmta = " %04X %04X"; break;
239 case 1: frmta = " %06o %06o"; break;
240 case 2: frmta = " %05u %05u"; break;
242 frmtb = " = %6u. bytes "; break;
243 case 3:
244 switch(xflag) {
245 default:
246 case 0: frmta = " %06X %06X"; break;
247 case 1: frmta = " %08o %08o"; break;
248 case 2: frmta = " %08u %08u"; break;
250 frmtb = " = %8u. bytes "; break;
251 case 4:
252 switch(xflag) {
253 default:
254 case 0: frmta = " %08X %08X"; break;
255 case 1: frmta = " %011o %011o"; break;
256 case 2: frmta = " %010u %010u"; break;
258 frmtb = " = %10u. bytes "; break;
260 #endif
261 fprintf(mfp, frmta, ai, aj);
262 fprintf(mfp, frmtb, aj);
264 if (xp->a_flag & A3_ABS) {
265 fprintf(mfp, "(ABS");
266 } else {
267 fprintf(mfp, "(REL");
269 if (xp->a_flag & A3_OVR) {
270 fprintf(mfp, ",OVR");
271 } else {
272 fprintf(mfp, ",CON");
274 if (xp->a_flag & A3_PAG) {
275 fprintf(mfp, ",PAG");
278 /* sdld specific */
279 if (xp->a_flag & A_CODE) {
280 fprintf(mfp, ",CODE");
282 if (xp->a_flag & A_XDATA) {
283 fprintf(mfp, ",XDATA");
285 if (xp->a_flag & A_BIT) {
286 fprintf(mfp, ",BIT");
288 /* end sdld specific */
290 fprintf(mfp, ")\n");
291 if (wflag) {
292 putc('\n', mfp);
293 fprintf(mfp,
294 " Value Global ");
295 fprintf(mfp,
296 " Global Defined In Module\n");
297 fprintf(mfp,
298 " ----- --------------------------------");
299 fprintf(mfp,
300 " ------------------------\n");
301 } else {
302 switch(a_bytes) {
303 default:
304 case 2: frmta = " Value Global ";
305 frmtb = " ----- ------ ";
306 n = 4; break;
307 case 3:
308 case 4: frmta = " Value Global ";
309 frmtb = " ----- ------ ";
310 n = 3; break;
312 putc('\n', mfp);
313 for(i=0;i<n;++i)
314 fprintf(mfp, "%s", frmta);
315 putc('\n', mfp);
316 for(i=0;i<n;++i)
317 fprintf(mfp, "%s", frmtb);
318 putc('\n', mfp);
321 lop += 9;
325 /* sdld specific */
326 /* Used for qsort call in lstsym */
327 static int _cmpSymByAddr(const void *p1, const void *p2)
329 struct sym **s1 = (struct sym **)(p1);
330 struct sym **s2 = (struct sym **)(p2);
331 int delta = ((*s1)->s_addr + (*s1)->s_axp->a_addr) -
332 ((*s2)->s_addr + (*s2)->s_axp->a_addr);
334 /* Sort first by address, then by name. */
335 if (delta)
337 return delta;
339 return strcmp((*s1)->s_id,(*s2)->s_id);
341 /* end sdld specific */
343 /*)Function VOID lstarea(xp, yp)
345 * area * xp pointer to an area structure
346 * bank * yp pointer to a bank structure
348 * The function lstarea() creates the linker map output for
349 * the area specified by pointer xp. The generated output
350 * area header includes the area name, starting address,
351 * size of area, number of words (in decimal), and the
352 * area attributes. The symbols defined in this area are
353 * sorted by ascending address and output four per line
354 * in the selected radix (one per line in wide format).
356 * local variables:
357 * areax * oxp pointer to an area extension structure
358 * int i loop counter
359 * int j bubble sort update status
360 * int n repeat counter
361 * char * frmt temporary format specifier
362 * char * ptr pointer to an id string
363 * int nmsym number of symbols in area
364 * a_uint a0 temporary
365 * a_uint ai temporary
366 * a_uint aj temporary
367 * sym * sp pointer to a symbol structure
368 * sym ** p pointer to an array of
369 * pointers to symbol structures
371 * global variables:
372 * int a_bytes T line address bytes
373 * FILE *mfp Map output file handle
374 * sym *symhash[NHASH] array of pointers to NHASH
375 * linked symbol lists
376 * int wflag Wide format listing
377 * int xflag Map file radix type flag
379 * functions called:
380 * int fprintf() c_library
381 * VOID free() c_library
382 * char * malloc() c_library
383 * char putc() c_library
384 * VOID slew() lklist.c
386 * side effects:
387 * Map output generated.
390 VOID
391 lstarea(struct area *xp, struct bank *yp)
393 struct areax *oxp;
394 int i, j, n;
395 char *frmt, *ptr;
396 int nmsym;
397 a_uint a0, ai, aj;
398 struct sym *sp;
399 struct sym **p;
400 /* sdld specific */
401 int memPage;
402 /* end sdld specific */
405 * Find number of symbols in area
407 nmsym = 0;
408 oxp = xp->a_axp;
409 while (oxp) {
410 for (i=0; i<NHASH; i++) {
411 sp = symhash[i];
412 while (sp != NULL) {
413 if (oxp == sp->s_axp)
414 ++nmsym;
415 sp = sp->s_sp;
418 oxp = oxp->a_axp;
421 if ((nmsym == 0) && (xp->a_size == 0)) {
422 return;
425 lop = NLPP;
426 slew(xp, yp);
428 if (nmsym == 0) {
429 return;
433 * Allocate space for an array of pointers to symbols
434 * and load array.
436 if ( (p = (struct sym **) malloc (nmsym*sizeof(struct sym *))) == NULL) {
437 fprintf(mfp, "Insufficient space to build Map Segment.\n");
438 return;
440 nmsym = 0;
441 oxp = xp->a_axp;
442 while (oxp) {
443 for (i=0; i<NHASH; i++) {
444 sp = symhash[i];
445 while (sp != NULL) {
446 if (oxp == sp->s_axp) {
447 p[nmsym++] = sp;
449 sp = sp->s_sp;
452 oxp = oxp->a_axp;
455 if (is_sdld()) {
457 * Quick Sort of Addresses in Symbol Table Array
459 qsort(p, nmsym, sizeof(struct sym *), _cmpSymByAddr);
460 } else {
462 * Bubble Sort of Addresses in Symbol Table Array
464 j = 1;
465 while (j) {
466 j = 0;
467 sp = p[0];
468 a0 = sp->s_addr + sp->s_axp->a_addr;
469 for (i=1; i<nmsym; ++i) {
470 sp = p[i];
471 ai = sp->s_addr + sp->s_axp->a_addr;
472 if (a0 > ai) {
473 j = 1;
474 p[i] = p[i-1];
475 p[i-1] = sp;
477 a0 = ai;
483 * Repeat Counter
485 switch(a_bytes) {
486 default:
487 case 2: n = 4; break;
488 case 3:
489 case 4: n = 3; break;
493 * Symbol Table Output
495 /* sdld specific */
496 memPage = (xp->a_flag & A_CODE) ? 0x0C : ((xp->a_flag & A_XDATA) ? 0x0D : ((xp->a_flag & A_BIT) ? 0x0B : 0x00));
497 /* end sdld specific */
498 i = 0;
499 while (i < nmsym) {
500 if (wflag) {
501 slew(xp, yp);
502 if (is_sdld()) {
503 switch(a_bytes) {
504 default:
505 case 2: frmt = " "; break;
506 case 3:
507 case 4: frmt = ""; break;
509 if (memPage != 0)
510 fprintf(mfp, "%s%X:", frmt, memPage);
511 else
512 fprintf(mfp, "%s ", frmt);
513 } else {
514 switch(a_bytes) {
515 default:
516 case 2: frmt = " "; break;
517 case 3:
518 case 4: frmt = " "; break;
520 fprintf(mfp, "%s", frmt);
522 } else
523 if ((i % n) == 0) {
524 slew(xp, yp);
525 switch(a_bytes) {
526 default:
527 case 2: frmt = " "; break;
528 case 3:
529 case 4: frmt = " "; break;
531 fprintf(mfp, "%s", frmt);
534 sp = p[i];
535 aj = (sp->s_addr + sp->s_axp->a_addr) & a_mask;
536 #ifdef LONGINT
537 switch(a_bytes) {
538 default:
539 case 2:
540 switch(xflag) {
541 default:
542 case 0: frmt = " %04lX "; break;
543 case 1: frmt = "%06lo "; break;
544 case 2: frmt = " %05lu "; break;
546 break;
547 case 3:
548 switch(xflag) {
549 default:
550 case 0: frmt = " %06lX "; break;
551 case 1: frmt = " %08lo "; break;
552 case 2: frmt = " %08lu "; break;
554 break;
555 case 4:
556 switch(xflag) {
557 default:
558 case 0: frmt = " %08lX "; break;
559 case 1: frmt = "%011lo "; break;
560 case 2: frmt = " %010lu "; break;
562 break;
564 #else
565 switch(a_bytes) {
566 default:
567 case 2:
568 switch(xflag) {
569 default:
570 case 0: frmt = " %04X "; break;
571 case 1: frmt = "%06o "; break;
572 case 2: frmt = " %05u "; break;
574 break;
575 case 3:
576 switch(xflag) {
577 default:
578 case 0: frmt = " %06X "; break;
579 case 1: frmt = " %08o "; break;
580 case 2: frmt = " %08u "; break;
582 break;
583 case 4:
584 switch(xflag) {
585 default:
586 case 0: frmt = " %08X "; break;
587 case 1: frmt = "%011o "; break;
588 case 2: frmt = " %010u "; break;
590 break;
592 #endif
593 fprintf(mfp, frmt, aj);
595 ptr = &sp->s_id[0];
597 #if NOICE
599 * NoICE output of symbol
601 if (jflag) DefineNoICE(ptr, aj, yp);
602 #endif
604 #if SDCDB
606 * SDCDB output of symbol
608 if (yflag) DefineSDCDB(ptr, aj);
609 #endif
611 if (wflag) {
612 fprintf(mfp, "%-32.32s", ptr);
613 i++;
614 if(sp->m_id) {
615 ptr = &sp->m_id[0];
616 fprintf(mfp, " %-.28s", ptr);
618 } else {
619 switch(a_bytes) {
620 default:
621 case 2: frmt = "%-8.8s"; break;
622 case 3:
623 case 4: frmt = "%-9.9s"; break;
625 fprintf(mfp, frmt, ptr);
626 if (++i < nmsym)
627 if (i % n != 0)
628 fprintf(mfp, " | ");
630 if (wflag || (i % n == 0)) {
631 putc('\n', mfp);
634 if (i % n != 0) {
635 putc('\n', mfp);
637 free(p);
640 /*)Function VOID lkulist(i)
642 * int i i # 0 process LST to RST file
643 * i = 0 copy remainder of LST file
644 * to RST file and close files
646 * The function lkulist() creates a relocated listing (.rst)
647 * output file from the ASxxxx assembler listing (.lst)
648 * files. The .lst file's program address and code bytes
649 * are changed to reflect the changes made by ASlink as
650 * the .rel files are combined into a single relocated
651 * output file.
653 * local variables:
654 * a_uint cpc current program counter address in PC increments
655 * int cbytes bytes so far in T line
657 * global variables:
658 * int a_bytes T Line Address Bytes
659 * int hilo byte order
660 * int gline get a line from the LST file
661 * to translate for the RST file
662 * a_uint pc current program counter address in bytes
663 * int pcb bytes per instruction word
664 * char rb[] read listing file text line
665 * FILE *rfp The file handle to the current
666 * output RST file
667 * int rtcnt count of data words
668 * int rtflg[] output the data flag
669 * a_uint rtval[] relocated data
670 * int rterr[] error flag ???
671 * FILE *tfp The file handle to the current
672 * LST file being scanned
674 * functions called:
675 * int fclose() c_library
676 * int fgets() c_library
677 * int fprintf() c_library
678 * VOID lkalist() lklist.c
679 * VOID lkglist() lklist.c
681 * side effects:
682 * A .rst file is created for each available .lst
683 * file associated with a .rel file.
686 VOID
687 lkulist(int i)
689 a_uint cpc;
690 int cbytes;
693 * Exit if listing file is not open
695 if (tfp == NULL)
696 return;
699 * Normal processing of LST to RST
701 if (i) {
703 * Line with only address
705 if (rtcnt == a_bytes) {
706 lkalist(pc);
709 * Line with address and code
711 } else {
712 cpc = pc;
713 cbytes = 0;
714 for (i=a_bytes; i < rtcnt; i++) {
715 if (rtflg[i]) {
716 lkglist(cpc, (int) (rtval[i] & 0xFF), rterr[i]);
717 cbytes += 1;
718 cpc += (cbytes % pcb) ? 0 : 1;
723 * Copy remainder of LST to RST
725 } else {
726 if (gline == 0)
727 fprintf(rfp, "%s", rb);
729 while (fgets(rb, sizeof(rb)-2, tfp) != 0) {
730 fprintf(rfp, "%s", rb);
732 fclose(tfp);
733 tfp = NULL;
734 fclose(rfp);
735 rfp = NULL;
739 /*)Function VOID lkalist(cpc)
741 * int cpc current program counter value
743 * The function lkalist() performs the following functions:
745 * (1) if the value of gline = 0 then the current listing
746 * file line is copied to the relocated listing file output.
748 * (2) the listing file is read line by line and copied to
749 * the relocated listing file until a valid source
750 * line number and a program counter value of the correct
751 * radix is found. The new relocated pc value is substituted
752 * and the line is written to the RST file.
754 * local variables:
755 * int i loop counter
756 * int m character count
757 * int n character index
758 * int r character radix
759 * char * frmt temporary format specifier
760 * char str[] temporary string
762 * global variables:
763 * int a_bytes T Line Address Bytes
764 * a_uint a_mask address masking parameter
765 * int gcntr data byte counter
766 * int gline get a line from the LST file
767 * to translate for the RST file
768 * char rb[] read listing file text line
769 * FILE *rfp The file handle to the current
770 * output RST file
771 * FILE *tfp The file handle to the current
772 * LST file being scanned
774 * functions called:
775 * int dgt() lklist.c
776 * int fclose() c_library
777 * int fgets() c_library
778 * int fprintf() c_library
779 * int sprintf() c_library
780 * char * strncpy() c_library
782 * side effects:
783 * Lines of the LST file are copied to the RST file,
784 * the last line copied has the code address
785 * updated to reflect the program relocation.
788 /* The Output Formats, No Cycle Count
789 | Tabs- | | | | | |
790 11111111112222222222333333333344444-----
791 012345678901234567890123456789012345678901234-----
792 | | | | |
793 ee XXXX xx xx xx xx xx xx LLLLL ************* HEX(16)
794 ee 000000 ooo ooo ooo ooo LLLLL ************* OCTAL(16)
795 ee DDDDD ddd ddd ddd ddd LLLLL ************* DECIMAL(16)
796 XXXX
797 OOOOOO
798 DDDDD
800 | Tabs- | | | | | |
801 11111111112222222222333333333344444-----
802 012345678901234567890123456789012345678901234-----
803 | | | | |
804 ee XXXXXX xx xx xx xx xx xx xx LLLLL ********* HEX(24)
805 ee OO000000 ooo ooo ooo ooo ooo LLLLL ********* OCTAL(24)
806 ee DDDDDDDD ddd ddd ddd ddd ddd LLLLL ********* DECIMAL(24)
807 XXXXXX
808 OOOOOOOO
809 DDDDDDDD
811 | Tabs- | | | | | |
812 11111111112222222222333333333344444-----
813 012345678901234567890123456789012345678901234-----
814 | | | | |
815 ee XXXXXXXX xx xx xx xx xx xx xx LLLLL ********* HEX(32)
816 eeOOOOO000000 ooo ooo ooo ooo ooo LLLLL ********* OCTAL(32)
817 ee DDDDDDDDDD ddd ddd ddd ddd ddd LLLLL ********* DECIMAL(32)
818 XXXXXXXX
819 OOOOOOOOOOO
820 DDDDDDDDDD
823 /* The Output Formats, With Cycle Count [nn]
824 | Tabs- | | | | | |
825 11111111112222222222333333333344444-----
826 012345678901234567890123456789012345678901234-----
827 | | | | |
828 ee XXXX xx xx xx xx xx[nn]LLLLL ************* HEX(16)
829 ee 000000 ooo ooo ooo [nn]LLLLL ************* OCTAL(16)
830 ee DDDDD ddd ddd ddd [nn]LLLLL ************* DECIMAL(16)
831 XXXX
832 OOOOOO
833 DDDDD
835 | Tabs- | | | | | |
836 11111111112222222222333333333344444-----
837 012345678901234567890123456789012345678901234-----
838 | | | | |
839 ee XXXXXX xx xx xx xx xx xx[nn]LLLLL ********* HEX(24)
840 ee OO000000 ooo ooo ooo ooo [nn]LLLLL ********* OCTAL(24)
841 ee DDDDDDDD ddd ddd ddd ddd [nn]LLLLL ********* DECIMAL(24)
842 XXXXXX
843 OOOOOOOO
844 DDDDDDDD
846 | Tabs- | | | | | |
847 11111111112222222222333333333344444-----
848 012345678901234567890123456789012345678901234-----
849 | | | | |
850 ee XXXXXXXX xx xx xx xx xx xx[nn]LLLLL ********* HEX(32)
851 eeOOOOO000000 ooo ooo ooo ooo [nn]LLLLL ********* OCTAL(32)
852 ee DDDDDDDDDD ddd ddd ddd ddd [nn]LLLLL ********* DECIMAL(32)
853 XXXXXXXX
854 OOOOOOOOOOO
855 DDDDDDDDDD
858 VOID
859 lkalist(a_uint cpc)
861 char str[16];
862 char *frmt;
863 int m, n, r;
866 * Truncate (int) to N-Bytes
868 cpc &= a_mask;
871 * Exit if listing file is not open
873 loop: if (tfp == NULL)
874 return;
877 * Copy current LST to RST
879 if (gline == 0) {
880 fprintf(rfp, "%s", rb);
881 gline = 1;
885 * Clear text line buffer
887 memset(rb, 0, sizeof(rb));
890 * Get next LST text line
892 if (fgets(rb, sizeof(rb)-2, tfp) == NULL) {
893 fclose(tfp);
894 tfp = NULL;
895 fclose(rfp);
896 rfp = NULL;
897 return;
901 * Must have an ASxxxx Listing line number
903 switch(a_bytes) {
904 default:
905 case 2: n = 30; break;
906 case 3:
907 case 4: n = 38; break;
909 if (!dgt(RAD10, &rb[n], 1)) {
910 fprintf(rfp, "%s", rb);
911 goto loop;
915 * Must have an address in the expected radix
917 #ifdef LONGINT
918 switch(radix) {
919 default:
920 case 16:
921 r = RAD16;
922 switch(a_bytes) {
923 default:
924 case 2: n = 3; m = 4; frmt = "%04lX"; break;
925 case 3: n = 6; m = 6; frmt = "%06lX"; break;
926 case 4: n = 4; m = 8; frmt = "%08lX"; break;
928 break;
929 case 10:
930 r = RAD10;
931 switch(a_bytes) {
932 default:
933 case 2: n = 4; m = 5; frmt = "%05lu"; break;
934 case 3: n = 5; m = 8; frmt = "%08lu"; break;
935 case 4: n = 3; m = 10; frmt = "%010lu"; break;
937 break;
938 case 8:
939 r = RAD8;
940 switch(a_bytes) {
941 default:
942 case 2: n = 3; m = 6; frmt = "%06lo"; break;
943 case 3: n = 5; m = 8; frmt = "%08lo"; break;
944 case 4: n = 2; m = 11; frmt = "%011lo"; break;
946 break;
948 #else
949 switch(radix) {
950 default:
951 case 16:
952 r = RAD16;
953 switch(a_bytes) {
954 default:
955 case 2: n = 3; m = 4; frmt = "%04X"; break;
956 case 3: n = 6; m = 6; frmt = "%06X"; break;
957 case 4: n = 4; m = 8; frmt = "%08X"; break;
959 break;
960 case 10:
961 r = RAD10;
962 switch(a_bytes) {
963 default:
964 case 2: n = 4; m = 5; frmt = "%05u"; break;
965 case 3: n = 5; m = 8; frmt = "%08u"; break;
966 case 4: n = 3; m = 10; frmt = "%010u"; break;
968 break;
969 case 8:
970 r = RAD8;
971 switch(a_bytes) {
972 default:
973 case 2: n = 3; m = 6; frmt = "%06o"; break;
974 case 3: n = 5; m = 8; frmt = "%08o"; break;
975 case 4: n = 2; m = 11; frmt = "%011o"; break;
977 break;
979 #endif
980 if (!dgt(r, &rb[n], m)) {
981 fprintf(rfp, "%s", rb);
982 goto loop;
984 sprintf(str, frmt, cpc);
985 strncpy(&rb[n], str, m);
988 * Copy updated LST text line to RST
990 fprintf(rfp, "%s", rb);
991 gcntr = 0;
994 /*)Function VOID lkglist(cpc,v,err)
996 * int cpc current program counter value
997 * int v value of byte at this address
998 * int err error flag for this value
1000 * The function lkglist() performs the following functions:
1002 * (1) if the value of gline = 1 then the listing file
1003 * is read line by line and copied to the
1004 * relocated listing file until a valid source
1005 * line number and a program counter value of the correct
1006 * radix is found.
1008 * (2) The new relocated values and code address are
1009 * substituted and the line may be written to the RST file.
1011 * local variables:
1012 * int a string index for first byte
1013 * int i loop counter
1014 * int m character count
1015 * int n character index
1016 * int r character radix
1017 * int s spacing
1018 * int u repeat counter
1019 * char * afrmt temporary format specifier
1020 * char * frmt temporary format specifier
1021 * char str[] temporary string
1023 * global variables:
1024 * int a_bytes T Line Address Bytes
1025 * a_uint a_mask address masking parameter
1026 * int gcntr data byte counter
1027 * set to -1 for a continuation line
1028 * int gline get a line from the LST file
1029 * to translate for the RST file
1030 * char rb[] read listing file text line
1031 * char *rp pointer to listing file text line
1032 * FILE *rfp The file handle to the current
1033 * output RST file
1034 * FILE *tfp The file handle to the current
1035 * LST file being scanned
1036 * char *errmsg3[] array of pointers to error strings
1038 * functions called:
1039 * int dgt() lklist.c
1040 * int fclose() c_library
1041 * int fgets() c_library
1042 * int fprintf() c_library
1043 * int sprintf() c_library
1044 * char * strncpy() c_library
1046 * side effects:
1047 * Lines of the LST file are copied to the RST file
1048 * with updated data values and code addresses.
1051 /* The Output Formats, No Cycle Count
1052 | Tabs- | | | | | |
1053 11111111112222222222333333333344444-----
1054 012345678901234567890123456789012345678901234-----
1055 | | | | |
1056 ee XXXX xx xx xx xx xx xx LLLLL ************* HEX(16)
1057 ee 000000 ooo ooo ooo ooo LLLLL ************* OCTAL(16)
1058 ee DDDDD ddd ddd ddd ddd LLLLL ************* DECIMAL(16)
1059 XXXX
1060 OOOOOO
1061 DDDDD
1063 | Tabs- | | | | | |
1064 11111111112222222222333333333344444-----
1065 012345678901234567890123456789012345678901234-----
1066 | | | | |
1067 ee XXXXXX xx xx xx xx xx xx xx LLLLL ********* HEX(24)
1068 ee OO000000 ooo ooo ooo ooo ooo LLLLL ********* OCTAL(24)
1069 ee DDDDDDDD ddd ddd ddd ddd ddd LLLLL ********* DECIMAL(24)
1070 XXXXXX
1071 OOOOOOOO
1072 DDDDDDDD
1074 | Tabs- | | | | | |
1075 11111111112222222222333333333344444-----
1076 012345678901234567890123456789012345678901234-----
1077 | | | | |
1078 ee XXXXXXXX xx xx xx xx xx xx xx LLLLL ********* HEX(32)
1079 eeOOOOO000000 ooo ooo ooo ooo ooo LLLLL ********* OCTAL(32)
1080 ee DDDDDDDDDD ddd ddd ddd ddd ddd LLLLL ********* DECIMAL(32)
1081 XXXXXXXX
1082 OOOOOOOOOOO
1083 DDDDDDDDDD
1086 /* The Output Formats, With Cycle Count [nn]
1087 | Tabs- | | | | | |
1088 11111111112222222222333333333344444-----
1089 012345678901234567890123456789012345678901234-----
1090 | | | | |
1091 ee XXXX xx xx xx xx xx[nn]LLLLL ************* HEX(16)
1092 ee 000000 ooo ooo ooo [nn]LLLLL ************* OCTAL(16)
1093 ee DDDDD ddd ddd ddd [nn]LLLLL ************* DECIMAL(16)
1094 XXXX
1095 OOOOOO
1096 DDDDD
1098 | Tabs- | | | | | |
1099 11111111112222222222333333333344444-----
1100 012345678901234567890123456789012345678901234-----
1101 | | | | |
1102 ee XXXXXX xx xx xx xx xx xx[nn]LLLLL ********* HEX(24)
1103 ee OO000000 ooo ooo ooo ooo [nn]LLLLL ********* OCTAL(24)
1104 ee DDDDDDDD ddd ddd ddd ddd [nn]LLLLL ********* DECIMAL(24)
1105 XXXXXX
1106 OOOOOOOO
1107 DDDDDDDD
1109 | Tabs- | | | | | |
1110 11111111112222222222333333333344444-----
1111 012345678901234567890123456789012345678901234-----
1112 | | | | |
1113 ee XXXXXXXX xx xx xx xx xx xx[nn]LLLLL ********* HEX(32)
1114 eeOOOOO000000 ooo ooo ooo ooo [nn]LLLLL ********* OCTAL(32)
1115 ee DDDDDDDDDD ddd ddd ddd ddd [nn]LLLLL ********* DECIMAL(32)
1116 XXXXXXXX
1117 OOOOOOOOOOO
1118 DDDDDDDDDD
1121 VOID
1122 lkglist(a_uint cpc, int v, int err)
1124 char str[16];
1125 char *afrmt, *frmt;
1126 int a, n, m, r, s, u;
1129 * Truncate (int) to N-Bytes
1131 cpc &= a_mask;
1134 * Exit if listing file is not open
1136 loop: if (tfp == NULL)
1137 return;
1140 * Get next LST text line
1142 if (gline) {
1144 * Clear text line buffer
1146 memset(rb, 0, sizeof(rb));
1149 * Get next LST text line
1151 if (fgets(rb, sizeof(rb)-2, tfp) == NULL) {
1152 fclose(tfp);
1153 tfp = NULL;
1154 fclose(rfp);
1155 rfp = NULL;
1156 return;
1160 * Check for a listing line number if required
1162 if (gcntr != -1) {
1163 switch(a_bytes) {
1164 default:
1165 case 2: n = 30; break;
1166 case 3:
1167 case 4: n = 38; break;
1169 if (!dgt(RAD10, &rb[n], 1)) {
1170 fprintf(rfp, "%s", rb);
1171 goto loop;
1173 gcntr = 0;
1175 gline = 0;
1179 * Hex Listing
1181 #ifdef LONGINT
1182 switch(radix) {
1183 default:
1184 case 16:
1185 r = RAD16;
1186 switch(a_bytes) {
1187 default:
1188 case 2: a = 8; s = 3; n = 3; m = 4; u = 6; afrmt = "%04lX"; break;
1189 case 3: a = 13; s = 3; n = 6; m = 6; u = 7; afrmt = "%06lX"; break;
1190 case 4: a = 13; s = 3; n = 4; m = 8; u = 7; afrmt = "%08lX"; break;
1192 frmt = " %02X"; break;
1193 case 10:
1194 r = RAD10;
1195 switch(a_bytes) {
1196 default:
1197 case 2: a = 10; s = 4; n = 4; m = 5; u = 4; afrmt = "%05lu"; break;
1198 case 3: a = 14; s = 4; n = 5; m = 8; u = 5; afrmt = "%08lu"; break;
1199 case 4: a = 14; s = 4; n = 3; m = 10; u = 5; afrmt = "%010lu"; break;
1201 frmt = " %03u"; break;
1202 case 8:
1203 r = RAD8;
1204 switch(a_bytes) {
1205 default:
1206 case 2: a = 10; s = 4; n = 3; m = 6; u = 4; afrmt = "%06lo"; break;
1207 case 3: a = 14; s = 4; n = 5; m = 8; u = 5; afrmt = "%08lo"; break;
1208 case 4: a = 14; s = 4; n = 2; m = 11; u = 5; afrmt = "%011lo"; break;
1210 frmt = " %03o"; break;
1212 #else
1213 switch(radix) {
1214 default:
1215 case 16:
1216 r = RAD16;
1217 switch(a_bytes) {
1218 default:
1219 case 2: a = 8; s = 3; n = 3; m = 4; u = 6; afrmt = "%04X"; break;
1220 case 3: a = 13; s = 3; n = 6; m = 6; u = 7; afrmt = "%06X"; break;
1221 case 4: a = 13; s = 3; n = 4; m = 8; u = 7; afrmt = "%08X"; break;
1223 frmt = " %02X"; break;
1224 case 10:
1225 r = RAD10;
1226 switch(a_bytes) {
1227 default:
1228 case 2: a = 10; s = 4; n = 4; m = 5; u = 4; afrmt = "%05u"; break;
1229 case 3: a = 14; s = 4; n = 5; m = 8; u = 5; afrmt = "%08u"; break;
1230 case 4: a = 14; s = 4; n = 3; m = 10; u = 5; afrmt = "%010u"; break;
1232 frmt = " %03u"; break;
1233 case 8:
1234 r = RAD8;
1235 switch(a_bytes) {
1236 default:
1237 case 2: a = 10; s = 4; n = 3; m = 6; u = 4; afrmt = "%06o"; break;
1238 case 3: a = 14; s = 4; n = 5; m = 8; u = 5; afrmt = "%08o"; break;
1239 case 4: a = 14; s = 4; n = 2; m = 11; u = 5; afrmt = "%011o"; break;
1241 frmt = " %03o"; break;
1243 #endif
1245 * Data Byte Pointer
1247 if (gcntr == -1) {
1248 rp = &rb[a];
1249 } else {
1250 rp = &rb[a + (s * gcntr)];
1253 * Number must be of proper radix
1255 if (!dgt(r, rp, s-1)) {
1256 fprintf(rfp, "%s", rb);
1257 gline = 1;
1258 goto loop;
1261 * Output new data value, overwrite relocation codes
1263 sprintf(str, frmt, v);
1264 strncpy(rp-1, str, s);
1265 if (gcntr == -1) {
1266 gcntr = 0;
1269 * Output relocated code address
1271 if (gcntr == 0) {
1272 if (dgt(r, &rb[n], m)) {
1273 sprintf(str, afrmt, cpc);
1274 strncpy(&rb[n], str, m);
1278 * Output an error line if required
1280 if (err) {
1281 switch(ASxxxx_VERSION) {
1282 case 3:
1283 fprintf(rfp, "?ASlink-Warning-%s\n", errmsg3[err]);
1284 break;
1286 default:
1287 break;
1291 * Fix 'u' if [nn], cycles, is specified
1293 if (rb[a + (s*u) - 1] == CYCNT_END) {
1294 u -= 1;
1297 * Output text line when updates finished
1299 if (++gcntr == u) {
1300 fprintf(rfp, "%s", rb);
1301 gline = 1;
1302 gcntr = -1;