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