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