* as/mcs51/i51mch.c (machine): fixed warning
[fw/sdcc] / link / z80 / lklist.c
1 /* lklist.c */
2
3 /*
4  * (C) Copyright 1989-1995
5  * All Rights Reserved
6  *
7  * Alan R. Baldwin
8  * 721 Berkeley St.
9  * Kent, Ohio  44240
10  */
11
12 #include <stdio.h>
13 #include <string.h>
14 #include <stdlib.h>
15 #include "aslink.h"
16
17 /*)Module       lklist.c
18  *
19  *      The module lklist.c contains the functions which
20  *      output the linker .map file and produce a relocated
21  *      listing .rst file.
22  *
23  *      lklist.c contains the following functions:
24  *              int     dgt()
25  *              VOID    lstarea()
26  *              VOID    lkulist()
27  *              VOID    lkalist()
28  *              VOID    lkglist()
29  *              VOID    newpag()
30  *              VOID    slew()
31  *
32  *      lklist.c contains no local variables.
33  */
34
35 /*)Function     VOID    slew(fp)
36  *
37  *              FILE *  fp              output file handle
38  *
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
42  *      output.
43  *
44  *      local variables:
45  *              int     i               loop counter
46  *
47  *      global variables:
48  *              int     lop             current line number on page
49  *              int     xflag           Map file radix type flag
50  *
51  *      functions called:
52  *              int     fprintf()       c_library
53  *              VOID    newpag()        lklist.c
54  *
55  *      side effects:
56  *              The page line and the page count may be updated.
57  */
58
59 VOID
60 slew(fp)
61 FILE *fp;
62 {
63         register int i;
64
65         if (lop++ >= NLPP) {
66                 newpag(fp);
67                 if (xflag == 0) {
68                         fprintf(fp, "Hexidecimal\n\n");
69                 } else
70                 if (xflag == 1) {
71                         fprintf(fp, "Octal\n\n");
72                 } else
73                 if (xflag == 2) {
74                         fprintf(fp, "Decimal\n\n");
75                 }
76                 fprintf(fp, "Area       Addr   Size");
77                 fprintf(fp, "   Decimal Bytes (Attributes)\n");
78                 for(i=0;i<4;++i)
79                         fprintf(fp, "      Value--Global");
80                 fprintf(fp, "\n\n");
81                 lop += 6;
82         }
83 }
84
85 /*)Function     VOID    newpag()
86  *
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.
90  *
91  *      local variables:
92  *              none
93  *
94  *      global variables:
95  *              int     lop             current line number on page
96  *              int     page            current page number
97  *
98  *      functions called:
99  *              int     fprintf()       c_library
100  *
101  *      side effects:
102  *              The page and line counters are updated.
103  */
104
105 VOID
106 newpag(fp)
107 FILE *fp;
108 {
109         fprintf(fp, "\fASxxxx Linker %s,  page %u.\n", VERSION, ++page);
110         lop = 1;
111 }
112
113 #if     NCPS-8
114
115 /* NCPS != 8 */
116 /*)Function     VOID    lstarea(xp)
117  *
118  *              area *  xp              pointer to an area structure
119  *
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.
127  *
128  *      local variables:
129  *              areax * oxp             pointer to an area extension structure
130  *              int     c               character value
131  *              int     i               loop counter
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
141  *
142  *      global variables:
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
147  *
148  *      functions called:
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
154  *
155  *      side effects:
156  *              Map output generated.
157  */
158
159 #ifndef MLH_MAP
160 VOID
161 lstarea(xp)
162 struct area *xp;
163 {
164 //      register struct area *op;
165         register struct areax *oxp;
166         register c, i, j;
167         register char *ptr;
168         int nmsym;
169         Addr_T a0, ai, aj;
170         struct sym *sp;
171         struct sym **p;
172
173         putc('\n', mfp);
174         if (xflag == 0) {
175                 fprintf(mfp, "Hexidecimal\n\n");
176         } else
177         if (xflag == 1) {
178                 fprintf(mfp, "Octal\n\n");
179         } else
180         if (xflag == 2) {
181                 fprintf(mfp, "Decimal\n\n");
182         }
183         fprintf(mfp, "Area                               ");
184         fprintf(mfp, "Addr   Size   Decimal Bytes (Attributes)\n");
185         fprintf(mfp, "--------------------------------   ");
186         fprintf(mfp, "----   ----   ------- ----- ------------\n");
187         /*
188          * Output Area Header
189          */
190         ptr = &xp->a_id[0];
191         while (ptr < &xp->a_id[NCPS]) {
192                 if ((c = *ptr++) != 0) {
193                         putc(c, mfp);
194                 } else {
195                         putc(' ', mfp);
196                 }
197         }
198         ai = xp->a_addr;
199         aj = xp->a_size;
200         if (xflag == 0) {
201                 fprintf(mfp, "   %04X   %04X", ai, aj);
202         } else
203         if (xflag == 1) {
204                 fprintf(mfp, " %06o %06o", ai, aj);
205         } else
206         if (xflag == 2) {
207                 fprintf(mfp, "  %05u  %05u", ai, aj);
208         }
209         fprintf(mfp, " = %6u. bytes ", aj);
210         if (xp->a_flag & A_ABS) {
211                 fprintf(mfp, "(ABS");
212         } else {
213                 fprintf(mfp, "(REL");
214         }
215         if (xp->a_flag & A_OVR) {
216                 fprintf(mfp, ",OVR");
217         } else {
218                 fprintf(mfp, ",CON");
219         }
220         if (xp->a_flag & A_PAG) {
221                 fprintf(mfp, ",PAG");
222         }
223         fprintf(mfp, ")");
224         if (xp->a_flag & A_PAG) {
225                 ai = (ai & 0xFF);
226                 aj = (aj > 256);
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"); }
232         }
233
234         /*
235          * Find number of symbols in area
236          */
237         nmsym = 0;
238         oxp = xp->a_axp;
239         while (oxp) {
240                 for (i=0; i<NHASH; i++) {
241                         sp = symhash[i];
242                         while (sp != NULL) {
243                                 if (oxp == sp->s_axp)
244                                         ++nmsym;
245                                 sp = sp->s_sp;
246                         }
247                 }
248                 oxp = oxp->a_axp;
249         }
250         if (nmsym == 0) {
251                 putc('\n', mfp);
252                 return;
253         }
254
255         /*
256          * Allocate space for an array of pointers to symbols
257          * and load array.
258          */
259         if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
260                 == NULL) {
261                 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
262                 return;
263         }
264         nmsym = 0;
265         oxp = xp->a_axp;
266         while (oxp) {
267                 for (i=0; i<NHASH; i++) {
268                         sp = symhash[i];
269                         while (sp != NULL) {
270                                 if (oxp == sp->s_axp) {
271                                         p[nmsym++] = sp;
272                                 }
273                                 sp = sp->s_sp;
274                         }
275                 }
276                 oxp = oxp->a_axp;
277         }
278
279         /*
280          * Bubble Sort of Addresses in Symbol Table Array
281          */
282         j = 1;
283         while (j) {
284                 j = 0;
285                 sp = p[0];
286                 a0 = sp->s_addr + sp->s_axp->a_addr;
287                 for (i=1; i<nmsym; ++i) {
288                         sp = p[i];
289                         ai = sp->s_addr + sp->s_axp->a_addr;
290                         if (a0 > ai) {
291                                 j = 1;
292                                 p[i] = p[i-1];
293                                 p[i-1] = sp;
294                         }
295                         a0 = ai;
296                 }
297         }
298
299         /*
300          * Symbol Table Output
301          */
302         i = 0;
303         fprintf(mfp, "\n\n");
304         fprintf(mfp, "      Value  Global\n");
305         fprintf(mfp, "      -----  --------------------------------");
306         while (i < nmsym) {
307                 fprintf(mfp, "\n");
308                 fprintf(mfp, "     ");
309
310                 sp = p[i];
311                 aj = sp->s_addr + sp->s_axp->a_addr;
312                 if (xflag == 0) {
313                         fprintf(mfp, "  %04X  ", aj);
314                 } else
315                 if (xflag == 1) {
316                         fprintf(mfp, "%06o  ", aj);
317                 } else
318                 if (xflag == 2) {
319                         fprintf(mfp, " %05u  ", aj);
320                 }
321                 ptr = &sp->s_id[0];
322                 while (ptr < &sp->s_id[NCPS]) {
323                         if ((c = *ptr++) != 0) {
324                                 putc(c, mfp);
325                         } else {
326                                 putc(' ', mfp);
327                         }
328                 }
329                 i++;
330         }
331         putc('\n', mfp);
332         free(p);
333 }
334 #else
335 VOID lstarea(struct area *xp)
336 {
337         register struct areax *oxp;
338         register int i, j;
339         int nmsym;
340         Addr_T a0, ai = 0, aj = 0;
341         struct sym *sp;
342         struct sym **p;
343
344         /*
345          * Find number of symbols in area
346          */
347         nmsym = 0;
348         oxp = xp->a_axp;
349         while (oxp) {
350                 for (i=0; i<NHASH; i++) {
351                         sp = symhash[i];
352                         while (sp != NULL) {
353                                 if (oxp == sp->s_axp)
354                                         ++nmsym;
355                                 sp = sp->s_sp;
356                         }
357                 }
358                 oxp = oxp->a_axp;
359         }
360
361         /*
362          * Symbol Table Output
363          */
364         if (!((xp->a_size==0)&&(xp->a_addr==0)&&(nmsym==0))) {
365                 fprintf(mfp, "AREA %s\n", xp->a_id );
366                 switch (xflag) {
367                         case 1:
368                                 fprintf(mfp, "\tRADIX OCTAL\n" );
369                                 break;
370                         case 2:
371                                 fprintf(mfp, "\tRADIX DEC\n" );
372                                 break;
373                         default:
374                                 fprintf(mfp, "\tRADIX HEX\n" );
375                                 break;
376                 }
377                 fprintf( mfp,   "\tBASE %04X\n"
378                                 "\tSIZE %04X\n"
379                                 "\tATTRIB "
380                         , xp->a_addr, xp->a_size );
381                 if (xp->a_flag & A_ABS) {
382                         fprintf(mfp, "ABS");
383                 } else {
384                         fprintf(mfp, "REL");
385                 }
386                 if (xp->a_flag & A_OVR) {
387                         fprintf(mfp, " OVR");
388                 } else {
389                         fprintf(mfp, " CON");
390                 }
391                 if (xp->a_flag & A_PAG) {
392                         fprintf(mfp, " PAG");
393                 }
394                 if (xp->a_flag & A_PAG) {
395                         ai = (ai & 0xFF);
396                         aj = (aj > 256);
397                         if (ai || aj) { fprintf(mfp, "  "); }
398                         if (ai)      { fprintf(mfp, " Boundary"); }
399                         if (ai & aj)  { fprintf(mfp, " /"); }
400                         if (aj)      { fprintf(mfp, " Length"); }
401                         if (ai || aj) { fprintf(mfp, " Error"); }
402                 }
403
404                 fprintf( mfp,"\n");
405                 if (nmsym>0) {
406                         /*
407                          * Allocate space for an array of pointers to symbols
408                          * and load array.
409                          */
410                         if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
411                             == NULL) {
412                                 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
413                                 return;
414                         }
415                         nmsym = 0;
416                         oxp = xp->a_axp;
417                         while (oxp) {
418                                 for (i=0; i<NHASH; i++) {
419                                         sp = symhash[i];
420                                         while (sp != NULL) {
421                                                 if (oxp == sp->s_axp) {
422                                                         p[nmsym++] = sp;
423                                                 }
424                                                 sp = sp->s_sp;
425                                         }
426                                 }
427                                 oxp = oxp->a_axp;
428                         }
429
430                         /*
431                          * Bubble Sort of Addresses in Symbol Table Array
432                          */
433                         j = 1;
434                         while (j) {
435                                 j = 0;
436                                 sp = p[0];
437                                 a0 = sp->s_addr + sp->s_axp->a_addr;
438                                 for (i=1; i<nmsym; ++i) {
439                                         sp = p[i];
440                                         ai = sp->s_addr + sp->s_axp->a_addr;
441                                         if (a0 > ai) {
442                                                 j = 1;
443                                                 p[i] = p[i-1];
444                                                 p[i-1] = sp;
445                                         }
446                                         a0 = ai;
447                                 }
448                         }
449
450                         fprintf( mfp, "\tGLOBALS\n");
451                         i = 0;
452                         while (i < nmsym) {
453                                 fprintf(mfp, "\t\t%s\t%04X\n", p[i]->s_id, p[i]->s_addr + p[i]->s_axp->a_addr );
454                                 i++;
455                         }
456                         free(p);
457                 }
458         }
459 }
460 #endif /* MLH_MAP */
461 #else
462
463 /* NCPS == 8 */
464 /*)Function     VOID    lstarea(xp)
465  *
466  *              area *  xp              pointer to an area structure
467  *
468  *      The function lstarea() creates the linker map output for
469  *      the area specified by pointer xp.  The generated output
470  *      area header includes the area name, starting address,
471  *      size of area, number of words (in decimal), and the
472  *      area attributes.  The symbols defined in this area are
473  *      sorted by ascending address and output four per line
474  *      in the selected radix.
475  *
476  *      local variables:
477  *              areax * oxp             pointer to an area extension structure
478  *              int     c               character value
479  *              int     i               loop counter
480  *              int     j               bubble sort update status
481  *              char *  ptr             pointer to an id string
482  *              int     nmsym           number of symbols in area
483  *              Addr_T  a0              temporary
484  *              Addr_T  ai              temporary
485  *              Addr_T  aj              temporary
486  *              sym *   sp              pointer to a symbol structure
487  *              sym **  p               pointer to an array of
488  *                                      pointers to symbol structures
489  *
490  *      global variables:
491  *              FILE    *mfp            Map output file handle
492  *              sym *symhash[NHASH]     array of pointers to NHASH
493  *                                      linked symbol lists
494  *              int     xflag           Map file radix type flag
495  *
496  *      functions called:
497  *              int     fprintf()       c_library
498  *              VOID    free()          c_library
499  *              char *  malloc()        c_library
500  *              char    putc()          c_library
501  *              VOID    slew()          lklist.c
502  *
503  *      side effects:
504  *              Map output generated.
505  */
506
507 VOID
508 lstarea(xp)
509 struct area *xp;
510 {
511         register struct areax *oxp;
512         register c, i, j;
513         register char *ptr;
514         int nmsym;
515         Addr_T a0, ai, aj;
516         struct sym *sp;
517         struct sym **p;
518
519         putc('\n', mfp);
520         slew(mfp);
521         /*
522          * Output Area Header
523          */
524         ptr = &xp->a_id[0];
525         while (ptr < &xp->a_id[NCPS]) {
526                 if ((c = *ptr++) != 0) {
527                         putc(c, mfp);
528                 } else {
529                         putc(' ', mfp);
530                 }
531         }
532         ai = xp->a_addr;
533         aj = xp->a_size;
534         if (xflag == 0) {
535                 fprintf(mfp, "   %04X   %04X", ai, aj);
536         } else
537         if (xflag == 1) {
538                 fprintf(mfp, " %06o %06o", ai, aj);
539         } else
540         if (xflag == 2) {
541                 fprintf(mfp, "  %05u  %05u", ai, aj);
542         }
543         fprintf(mfp, " = %6u. bytes ", aj);
544         if (xp->a_flag & A_ABS) {
545                 fprintf(mfp, "(ABS");
546         } else {
547                 fprintf(mfp, "(REL");
548         }
549         if (xp->a_flag & A_OVR) {
550                 fprintf(mfp, ",OVR");
551         } else {
552                 fprintf(mfp, ",CON");
553         }
554         if (xp->a_flag & A_PAG) {
555                 fprintf(mfp, ",PAG");
556         }
557         fprintf(mfp, ")");
558         if (xp->a_flag & A_PAG) {
559                 ai = (ai & 0xFF);
560                 aj = (aj > 256);
561                 if (ai || aj) { fprintf(mfp, "  "); }
562                 if (ai)      { fprintf(mfp, " Boundary"); }
563                 if (ai & aj)  { fprintf(mfp, " /"); }
564                 if (aj)      { fprintf(mfp, " Length"); }
565                 if (ai || aj) { fprintf(mfp, " Error"); }
566         }
567
568         /*
569          * Find number of symbols in area
570          */
571         nmsym = 0;
572         oxp = xp->a_axp;
573         while (oxp) {
574                 for (i=0; i<NHASH; i++) {
575                         sp = symhash[i];
576                         while (sp != NULL) {
577                                 if (oxp == sp->s_axp)
578                                         ++nmsym;
579                                 sp = sp->s_sp;
580                         }
581                 }
582                 oxp = oxp->a_axp;
583         }
584         if (nmsym == 0) {
585                 putc('\n', mfp);
586                 slew(mfp);
587                 return;
588         }
589
590         /*
591          * Allocate space for an array of pointers to symbols
592          * and load array.
593          */
594         if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
595                 == NULL) {
596                 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
597                 slew(mfp);
598                 return;
599         }
600         nmsym = 0;
601         oxp = xp->a_axp;
602         while (oxp) {
603                 for (i=0; i<NHASH; i++) {
604                         sp = symhash[i];
605                         while (sp != NULL) {
606                                 if (oxp == sp->s_axp) {
607                                         p[nmsym++] = sp;
608                                 }
609                                 sp = sp->s_sp;
610                         }
611                 }
612                 oxp = oxp->a_axp;
613         }
614
615         /*
616          * Bubble Sort of Addresses in Symbol Table Array
617          */
618         j = 1;
619         while (j) {
620                 j = 0;
621                 sp = p[0];
622                 a0 = sp->s_addr + sp->s_axp->a_addr;
623                 for (i=1; i<nmsym; ++i) {
624                         sp = p[i];
625                         ai = sp->s_addr + sp->s_axp->a_addr;
626                         if (a0 > ai) {
627                                 j = 1;
628                                 p[i] = p[i-1];
629                                 p[i-1] = sp;
630                         }
631                         a0 = ai;
632                 }
633         }
634
635         /*
636          * Symbol Table Output
637          */
638         i = 0;
639         while (i < nmsym) {
640                 if (i % 4 == 0) {
641                         fprintf(mfp, "\n");
642                         slew(mfp);
643                         fprintf(mfp, "     ");
644                 }
645                 sp = p[i];
646                 aj = sp->s_addr + sp->s_axp->a_addr;
647                 if (xflag == 0) {
648                         fprintf(mfp, "  %04X  ", aj);
649                 } else
650                 if (xflag == 1) {
651                         fprintf(mfp, "%06o  ", aj);
652                 } else
653                 if (xflag == 2) {
654                         fprintf(mfp, " %05u  ", aj);
655                 }
656                 ptr = &sp->s_id[0];
657                 while (ptr < &sp->s_id[NCPS]) {
658                         if ((c = *ptr++) != 0) {
659                                 putc(c, mfp);
660                         } else {
661                                 putc(' ', mfp);
662                         }
663                 }
664                 if (++i < nmsym)
665                         if (i % 4 != 0)
666                                 fprintf(mfp, " | ");
667         }
668         putc('\n', mfp);
669         free(p);
670         slew(mfp);
671 }
672 #endif
673
674 #ifdef SDK
675 VOID lstareatosym(struct area *xp)
676 {
677         /* Output the current area symbols to a NO$GMB .sym file */
678         register struct areax *oxp;
679         register int i, j;
680         int nmsym;
681         Addr_T a0, ai;
682         struct sym *sp;
683         struct sym **p;
684
685         /*
686          * Find number of symbols in area
687          */
688         nmsym = 0;
689         oxp = xp->a_axp;
690         while (oxp) {
691                 for (i=0; i<NHASH; i++) {
692                         sp = symhash[i];
693                         while (sp != NULL) {
694                                 if (oxp == sp->s_axp)
695                                         ++nmsym;
696                                 sp = sp->s_sp;
697                         }
698                 }
699                 oxp = oxp->a_axp;
700         }
701
702         /*
703          * Symbol Table Output
704          */
705         if (!((xp->a_size==0)&&(xp->a_addr==0)&&(nmsym==0))) {
706                 /* Dont worry about any area information */
707                 fprintf(mfp, "; Area: %s\n", xp->a_id );
708                 if (nmsym>0) {
709                         /*
710                          * Allocate space for an array of pointers to symbols
711                          * and load array.
712                          */
713                         if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
714                             == NULL) {
715                                 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
716                                 return;
717                         }
718                         nmsym = 0;
719                         oxp = xp->a_axp;
720                         while (oxp) {
721                                 for (i=0; i<NHASH; i++) {
722                                         sp = symhash[i];
723                                         while (sp != NULL) {
724                                                 if (oxp == sp->s_axp) {
725                                                         p[nmsym++] = sp;
726                                                 }
727                                                 sp = sp->s_sp;
728                                         }
729                                 }
730                                 oxp = oxp->a_axp;
731                         }
732
733                         /*
734                          * Bubble Sort of Addresses in Symbol Table Array
735                          */
736                         j = 1;
737                         while (j) {
738                                 j = 0;
739                                 sp = p[0];
740                                 a0 = sp->s_addr + sp->s_axp->a_addr;
741                                 for (i=1; i<nmsym; ++i) {
742                                         sp = p[i];
743                                         ai = sp->s_addr + sp->s_axp->a_addr;
744                                         if (a0 > ai) {
745                                                 j = 1;
746                                                 p[i] = p[i-1];
747                                                 p[i-1] = sp;
748                                         }
749                                         a0 = ai;
750                                 }
751                         }
752                         i = 0;
753                         while (i < nmsym) {
754                                 /* no$gmb requires the symbol names to be less than 32 chars long.  Truncate. */
755                                 char name[32];
756                                 strncpy(name, p[i]->s_id, 31);
757                                 name[31] = '\0';
758                                 if ((strncmp("l__", name, 3)!=0)&&(strchr(name,' ')==NULL)) {
759                                         a0=p[i]->s_addr + p[i]->s_axp->a_addr;
760                                         if (a0>0x7FFFU) {
761                                                 /* Not inside the ROM, so treat as being in bank zero */
762                                                 fprintf(mfp, "00:%04X %s\n", a0, name);
763                                         }
764                                         else {
765                                                 fprintf(mfp, "%02X:%04X %s\n", a0/16384, a0, name);
766                                         }
767                                 }
768                                 i++;
769                         }
770                         free(p);
771                 }
772         }
773 }
774 #endif
775
776 /*)Function     VOID    lkulist(i)
777  *
778  *              int     i       i # 0   process LST to RST file
779  *                              i = 0   copy remainder of LST file
780  *                                      to RST file and close files
781  *
782  *      The function lkulist() creates a relocated listing (.rst)
783  *      output file from the ASxxxx assembler listing (.lst)
784  *      files.  The .lst file's program address and code bytes
785  *      are changed to reflect the changes made by ASlink as
786  *      the .rel files are combined into a single relocated
787  *      output file.
788  *
789  *      local variables:
790  *              Addr_T  pc              current program counter address
791  *
792  *      global variables:
793  *              int     hilo            byte order
794  *              int     gline           get a line from the LST file
795  *                                      to translate for the RST file
796  *              char    rb[]            read listing file text line
797  *              FILE    *rfp            The file handle to the current
798  *                                      output RST file
799  *              int     rtcnt           count of data words
800  *              int     rtflg[]         output the data flag
801  *              Addr_T  rtval[]         relocated data
802  *              FILE    *tfp            The file handle to the current
803  *                                      LST file being scanned
804  *
805  *      functions called:
806  *              int     fclose()        c_library
807  *              int     fgets()         c_library
808  *              int     fprintf()       c_library
809  *              VOID    lkalist()       lklist.c
810  *              VOID    lkglist()       lklist.c
811  *
812  *      side effects:
813  *              A .rst file is created for each available .lst
814  *              file associated with a .rel file.
815  */
816
817 VOID
818 lkulist(i)
819 int i;
820 {
821         Addr_T pc;
822
823         /*
824          * Exit if listing file is not open
825          */
826         if (tfp == NULL)
827                 return;
828
829         /*
830          * Normal processing of LST to RST
831          */
832         if (i) {
833                 /*
834                  * Evaluate current code address
835                  */
836                 if (hilo == 0) {
837                         pc = ((rtval[1] & 0xFF) << 8) + (rtval[0] & 0xFF);
838                 } else {
839                         pc = ((rtval[0] & 0xFF) << 8) + (rtval[1] & 0xFF);
840                 }
841
842                 /*
843                  * Line with only address
844                  */
845                 if (rtcnt == 2) {
846                         lkalist(pc);
847
848                 /*
849                  * Line with address and code
850                  */
851                 } else {
852                         for (i=2; i < rtcnt; i++) {
853                                 if (rtflg[i]) {
854                                         lkglist(pc++, rtval[i] & 0xFF);
855                                 }
856                         }
857                 }
858
859         /*
860          * Copy remainder of LST to RST
861          */
862         } else {
863                 if (gline == 0)
864                         fprintf(rfp, rb);
865
866                 while (fgets(rb, sizeof(rb), tfp) != 0) {
867                         fprintf(rfp, rb);
868                 }
869                 fclose(tfp);
870                 tfp = NULL;
871                 fclose(rfp);
872                 rfp = NULL;
873         }
874 }
875
876 /*)Function     VOID    lkalist(pc)
877  *
878  *              int     pc              current program counter value
879  *
880  *      The function lkalist() performs the following functions:
881  *
882  *      (1)     if the value of gline = 0 then the current listing
883  *              file line is copied to the relocated listing file output.
884  *
885  *      (2)     the listing file is read line by line and copied to
886  *              the relocated listing file until a valid source
887  *              line number and a program counter value of the correct
888  *              radix is found.  The new relocated pc value is substituted
889  *              and the line is written to the RST file.
890  *
891  *      local variables:
892  *              int     i               loop counter
893  *              char    str[]           temporary string
894  *
895  *      global variables:
896  *              int     gcntr           data byte counter
897  *              int     gline           get a line from the LST file
898  *                                      to translate for the RST file
899  *              char    rb[]            read listing file text line
900  *              char    *rp             pointer to listing file text line
901  *              FILE    *rfp            The file handle to the current
902  *                                      output RST file
903  *              FILE    *tfp            The file handle to the current
904  *                                      LST file being scanned
905  *
906  *      functions called:
907  *              int     dgt()           lklist.c
908  *              int     fclose()        c_library
909  *              int     fgets()         c_library
910  *              int     fprintf()       c_library
911  *              int     sprintf()       c_library
912  *              char *  strncpy()       c_library
913  *
914  *      side effects:
915  *              Lines of the LST file are copied to the RST file,
916  *              the last line copied has the code address
917  *              updated to reflect the program relocation.
918  */
919
920 VOID
921 lkalist(pc)
922 Addr_T pc;
923 {
924         char str[8];
925         int i;
926
927         /*
928          * Exit if listing file is not open
929          */
930 loop:   if (tfp == NULL)
931                 return;
932
933         /*
934          * Copy current LST to RST
935          */
936         if (gline == 0) {
937                 fprintf(rfp, rb);
938                 gline = 1;
939         }
940
941         /*
942          * Clear text line buffer
943          */
944         for (i=0,rp=rb; i<sizeof(rb); i++) {
945                 *rp++ = 0;
946         }
947
948         /*
949          * Get next LST text line
950          */
951         if (fgets(rb, sizeof(rb), tfp) == NULL) {
952                 fclose(tfp);
953                 tfp = NULL;
954                 fclose(rfp);
955                 rfp = NULL;
956                 return;
957         }
958
959         /*
960          * Must have an ASxxxx Listing line number
961          */
962         if (!dgt(RAD10, &rb[30], 1)) {
963                 fprintf(rfp, rb);
964                 goto loop;
965         }
966
967         /*
968          * Must have an address in the expected radix
969          */
970         if (radix == 16) {
971                 if (!dgt(RAD16, &rb[3], 4)) {
972                         fprintf(rfp, rb);
973                         goto loop;
974                 }
975                 sprintf(str, "%04X", pc);
976                 strncpy(&rb[3], str, 4);
977         } else
978         if (radix == 10) {
979                 if (!dgt(RAD10, &rb[3], 5)) {
980                         fprintf(rfp, rb);
981                         goto loop;
982                 }
983                 sprintf(str, "%05d", pc);
984                 strncpy(&rb[3], str, 5);
985         } else
986         if (radix == 8) {
987                 if (!dgt(RAD8, &rb[3], 6)) {
988                         fprintf(rfp, rb);
989                         goto loop;
990                 }
991                 sprintf(str, "%06o", pc);
992                 strncpy(&rb[3], str, 6);
993         }
994
995         /*
996          * Copy updated LST text line to RST
997          */
998         fprintf(rfp, rb);
999         gcntr = 0;
1000 }
1001
1002 /*)Function     VOID    lkglist(pc,v)
1003  *
1004  *              int     pc              current program counter value
1005  *              int     v               value of byte at this address
1006  *
1007  *      The function lkglist() performs the following functions:
1008  *
1009  *      (1)     if the value of gline = 1 then the listing file
1010  *              is read line by line and copied to the
1011  *              relocated listing file until a valid source
1012  *              line number and a program counter value of the correct
1013  *              radix is found.
1014  *
1015  *      (2)     The new relocated values and code address are
1016  *              substituted and the line may be written to the RST file.
1017  *
1018  *      local variables:
1019  *              int     i               loop counter
1020  *              char    str[]           temporary string
1021  *
1022  *      global variables:
1023  *              int     gcntr           data byte counter
1024  *                                      set to -1 for a continuation line
1025  *              int     gline           get a line from the LST file
1026  *                                      to translate for the RST file
1027  *              char    rb[]            read listing file text line
1028  *              char    *rp             pointer to listing file text line
1029  *              FILE    *rfp            The file handle to the current
1030  *                                      output RST file
1031  *              FILE    *tfp            The file handle to the current
1032  *                                      LST file being scanned
1033  *
1034  *      functions called:
1035  *              int     dgt()           lklist.c
1036  *              int     fclose()        c_library
1037  *              int     fgets()         c_library
1038  *              int     fprintf()       c_library
1039  *              int     sprintf()       c_library
1040  *              char *  strncpy()       c_library
1041  *
1042  *      side effects:
1043  *              Lines of the LST file are copied to the RST file
1044  *              with updated data values and code addresses.
1045  */
1046
1047 VOID
1048 lkglist(pc,v)
1049 Addr_T pc;
1050 int v;
1051 {
1052         char str[8];
1053         int i;
1054
1055         /*
1056          * Exit if listing file is not open
1057          */
1058 loop:   if (tfp == NULL)
1059                 return;
1060
1061         /*
1062          * Get next LST text line
1063          */
1064         if (gline) {
1065                 /*
1066                  * Clear text line buffer
1067                  */
1068                 for (i=0,rp=rb; i<sizeof(rb); i++) {
1069                         *rp++ = 0;
1070                 }
1071
1072                 /*
1073                  * Get next LST text line
1074                  */
1075                 if (fgets(rb, sizeof(rb), tfp) == NULL) {
1076                         fclose(tfp);
1077                         tfp = NULL;
1078                         fclose(rfp);
1079                         rfp = NULL;
1080                         return;
1081                 }
1082
1083                 /*
1084                  * Check for a listing line number if required
1085                  */
1086                 if (gcntr != -1) {
1087                         if (!dgt(RAD10, &rb[30], 1)) {
1088                                 fprintf(rfp, rb);
1089                                 goto loop;
1090                         }
1091                         gcntr = 0;
1092                 }
1093                 gline = 0;
1094         }
1095
1096         /*
1097          * Hex Listing
1098          */
1099         if (radix == 16) {
1100                 /*
1101                  * Data Byte Pointer
1102                  */
1103                 if (gcntr == -1) {
1104                         rp = &rb[8];
1105                 } else {
1106                         rp = &rb[8 + (3 * gcntr)];
1107                 }
1108                 /*
1109                  * Number must be of proper radix
1110                  */
1111                 if (!dgt(RAD16, rp, 2)) {
1112                         fprintf(rfp, rb);
1113                         gline = 1;
1114                         goto loop;
1115                 }
1116                 /*
1117                  * Output new data value, overwrite relocation codes
1118                  */
1119                 sprintf(str, " %02X", v);
1120                 strncpy(rp-1, str, 3);
1121                 if (gcntr == -1) {
1122                         gcntr = 0;
1123                 }
1124                 /*
1125                  * Output relocated code address
1126                  */
1127                 if (gcntr == 0) {
1128                         if (dgt(RAD16, &rb[3], 4)) {
1129                                 sprintf(str, "%04X", pc);
1130                                 strncpy(&rb[3], str, 4);
1131                         }
1132                 }
1133                 /*
1134                  * Output text line when updates finished
1135                  */
1136                 if (++gcntr == 6) {
1137                         fprintf(rfp, rb);
1138                         gline = 1;
1139                         gcntr = -1;
1140                 }
1141         } else
1142         /*
1143          * Decimal Listing
1144          */
1145         if (radix == 10) {
1146                 /*
1147                  * Data Byte Pointer
1148                  */
1149                 if (gcntr == -1) {
1150                         rp = &rb[9];
1151                 } else {
1152                         rp = &rb[9 + (3 * gcntr)];
1153                 }
1154                 /*
1155                  * Number must be of proper radix
1156                  */
1157                 if (!dgt(RAD10, rp, 3)) {
1158                         fprintf(rfp, rb);
1159                         gline = 1;
1160                         goto loop;
1161                 }
1162                 /*
1163                  * Output new data value, overwrite relocation codes
1164                  */
1165                 sprintf(str, " %03d", v);
1166                 strncpy(rp-1, str, 4);
1167                 if (gcntr == -1) {
1168                         gcntr = 0;
1169                 }
1170                 /*
1171                  * Output relocated code address
1172                  */
1173                 if (gcntr == 0) {
1174                         if (dgt(RAD10, &rb[3], 5)) {
1175                                 sprintf(str, "%05d", pc);
1176                                 strncpy(&rb[3], str, 5);
1177                         }
1178                 }
1179                 /*
1180                  * Output text line when updates finished
1181                  */
1182                 if (++gcntr == 4) {
1183                         fprintf(rfp, rb);
1184                         gline = 1;
1185                         gcntr = -1;
1186                 }
1187         } else
1188         /*
1189          * Octal Listing
1190          */
1191         if (radix == 8) {
1192                 /*
1193                  * Data Byte Pointer
1194                  */
1195                 if (gcntr == -1) {
1196                         rp = &rb[10];
1197                 } else {
1198                         rp = &rb[10 + (3 * gcntr)];
1199                 }
1200                 /*
1201                  * Number must be of proper radix
1202                  */
1203                 if (!dgt(RAD8, rp, 3)) {
1204                         fprintf(rfp, rb);
1205                         gline = 1;
1206                         goto loop;
1207                 }
1208                 /*
1209                  * Output new data value, overwrite relocation codes
1210                  */
1211                 sprintf(str, " %03o", v);
1212                 strncpy(rp-1, str, 4);
1213                 if (gcntr == -1) {
1214                         gcntr = 0;
1215                 }
1216                 /*
1217                  * Output relocated code address
1218                  */
1219                 if (gcntr == 0) {
1220                         if (dgt(RAD8, &rb[3], 6)) {
1221                                 sprintf(str, "%06o", pc);
1222                                 strncpy(&rb[3], str, 6);
1223                         }
1224                 }
1225                 /*
1226                  * Output text line when updates finished
1227                  */
1228                 if (++gcntr == 4) {
1229                         fprintf(rfp, rb);
1230                         gline = 1;
1231                         gcntr = -1;
1232                 }
1233         }
1234 }
1235
1236 /*)Function     int     dgt(rdx,str,n)
1237  *
1238  *              int     rdx             radix bit code
1239  *              char    *str            pointer to the test string
1240  *              int     n               number of characters to check
1241  *
1242  *      The function dgt() verifies that the string under test
1243  *      is of the specified radix.
1244  *
1245  *      local variables:
1246  *              int     i               loop counter
1247  *
1248  *      global variables:
1249  *              ctype[]                 array of character types
1250  *
1251  *      functions called:
1252  *              none
1253  *
1254  *      side effects:
1255  *              none
1256  */
1257
1258 int
1259 dgt(rdx, str, n)
1260 int rdx, n;
1261 char *str;
1262 {
1263         int i;
1264
1265         for (i=0; i<n; i++) {
1266                 if ((ctype[(unsigned char)(*str++)] & rdx) == 0)
1267                         return(0);
1268         }
1269         return(1);
1270 }