* Added sfr space
[fw/sdcc] / as / mcs51 / 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  * 28-Oct-97 JLH: 
12  *           - lstarea: show s_id as string rather than array [NCPS]
13  *           - lstarea: show a_id as string rather than array [NCPS]
14  * 31-Oct-97 JLH: add NoICE output file genration in lstarea
15  * 02-Apr-98 JLH: add XDATA, DATA, BIT flags to area output
16  */
17
18 #include <stdio.h>
19 #include <string.h>
20 #include <alloc.h>
21 #include "aslink.h"
22
23 /*)Module       lklist.c
24  *
25  *      The module lklist.c contains the functions which
26  *      output the linker .map file and produce a relocated
27  *      listing .rst file.
28  *
29  *      lklist.c contains the following functions:
30  *              int     dgt()
31  *              VOID    lstarea()
32  *              VOID    lkulist()
33  *              VOID    lkalist()
34  *              VOID    lkglist()
35  *              VOID    newpag()
36  *              VOID    slew()
37  *
38  *      lklist.c contains no local variables.
39  */
40
41 /*)Function     VOID    slew(fp)
42  *
43  *              FILE *  fp              output file handle
44  *
45  *      The function slew() increments the page line counter.
46  *      If the number of lines exceeds the maximum number of
47  *      lines per page then a page skip and a page header are
48  *      output.
49  *
50  *      local variables:
51  *              int     i               loop counter
52  *
53  *      global variables:
54  *              int     lop             current line number on page
55  *              int     xflag           Map file radix type flag
56  *
57  *      functions called:
58  *              int     fprintf()       c_library
59  *              VOID    newpag()        lklist.c
60  *
61  *      side effects:
62  *              The page line and the page count may be updated.
63  */
64
65 VOID
66 slew(fp)
67 FILE *fp;
68 {
69         register int i;
70
71         if (lop++ >= NLPP) {
72                 newpag(fp);
73                 if (xflag == 0) {
74                         fprintf(fp, "Hexadecimal\n\n");
75                 } else
76                 if (xflag == 1) {
77                         fprintf(fp, "Octal\n\n");
78                 } else
79                 if (xflag == 2) {
80                         fprintf(fp, "Decimal\n\n");
81                 }
82                 fprintf(fp, "Area       Addr   Size");
83                 fprintf(fp, "   Decimal Bytes (Attributes)\n");
84                 for(i=0;i<4;++i)
85                         fprintf(fp, "      Value--Global");
86                 fprintf(fp, "\n\n");
87                 lop += 6;
88         }
89 }
90
91 /*)Function     VOID    newpag()
92  *
93  *      The function newpag() outputs a page skip, writes the
94  *      first page header line, sets the line count to 1, and
95  *      increments the page counter.
96  *
97  *      local variables:
98  *              none
99  *
100  *      global variables:
101  *              int     lop             current line number on page
102  *              int     page            current page number
103  *
104  *      functions called:
105  *              int     fprintf()       c_library
106  *
107  *      side effects:
108  *              The page and line counters are updated.
109  */
110
111 VOID
112 newpag(fp)
113 FILE *fp;
114 {
115         fprintf(fp, "\fASxxxx Linker %s,  page %u.\n", VERSION, ++page);
116         lop = 1;
117 }
118
119 #if     NCPS-8
120
121 /* NCPS != 8 */
122 /*)Function     VOID    lstarea(xp)
123  *
124  *              area *  xp              pointer to an area structure
125  *
126  *      The function lstarea() creates the linker map output for
127  *      the area specified by pointer xp.  The generated output
128  *      area header includes the area name, starting address,
129  *      size of area, number of words (in decimal), and the
130  *      area attributes.  The symbols defined in this area are
131  *      sorted by ascending address and output one per line
132  *      in the selected radix.
133  *
134  *      local variables:
135  *              areax * oxp             pointer to an area extension structure
136  *              int     c               character value
137  *              int     i               loop counter
138  *              int     j               bubble sort update status
139  *              char *  ptr             pointer to an id string
140  *              int     nmsym           number of symbols in area
141  *              addr_t  a0              temporary
142  *              addr_t  ai              temporary
143  *              addr_t  aj              temporary
144  *              sym *   sp              pointer to a symbol structure
145  *              sym **  p               pointer to an array of
146  *                                      pointers to symbol structures
147  *
148  *      global variables:
149  *              FILE    *mfp            Map output file handle
150  *              sym *symhash[NHASH]     array of pointers to NHASH
151  *                                      linked symbol lists
152  *              int     xflag           Map file radix type flag
153  *
154  *      functions called:
155  *              int     fprintf()       c_library
156  *              VOID    free()          c_library
157  *              char *  malloc()        c_library
158  *              char    putc()          c_library
159  *              VOID    slew()          lklist.c
160  *
161  *      side effects:
162  *              Map output generated.
163  */
164
165 VOID
166 lstarea(xp)
167 struct area *xp;
168 {
169         register struct areax *oxp;
170         register int i, j;
171         register char *ptr;
172         int nmsym;
173         addr_t a0, ai, aj;
174         struct sym *sp;
175         struct sym **p;
176         int memPage;
177
178         putc('\n', mfp);
179         if (xflag == 0) {
180                 fprintf(mfp, "Hexadecimal\n\n");
181         } else
182         if (xflag == 1) {
183                 fprintf(mfp, "Octal\n\n");
184         } else
185         if (xflag == 2) {
186                 fprintf(mfp, "Decimal\n\n");
187         }
188         fprintf(mfp, "Area                               ");
189         fprintf(mfp, "Addr   Size   Decimal Bytes (Attributes)\n");
190         fprintf(mfp, "--------------------------------   ");
191         fprintf(mfp, "----   ----   ------- ----- ------------\n");
192         /*
193          * Output Area Header
194          */
195         ptr = &xp->a_id[0];
196         fprintf(mfp, "%-32s", ptr );    /* JLH: width matches --- above */
197         ai = xp->a_addr;
198         aj = xp->a_size;
199         if (xflag == 0) {
200                 fprintf(mfp, "   %04X   %04X", ai, aj);
201         } else
202         if (xflag == 1) {
203                 fprintf(mfp, " %06o %06o", ai, aj);
204         } else
205         if (xflag == 2) {
206                 fprintf(mfp, "  %05u  %05u", ai, aj);
207         }
208         fprintf(mfp, " = %6u. bytes ", aj);
209         if (xp->a_flag & A_ABS) {
210                 fprintf(mfp, "(ABS");
211         } else {
212                 fprintf(mfp, "(REL");
213         }
214         if (xp->a_flag & A_OVR) {
215                 fprintf(mfp, ",OVR");
216         } else {
217                 fprintf(mfp, ",CON");
218         }
219         if (xp->a_flag & A_PAG) {
220                 fprintf(mfp, ",PAG");
221         }
222
223         memPage = 0x00;
224         if (xp->a_flag & A_CODE) {
225                 fprintf(mfp, ",CODE");
226                 memPage = 0x0C;
227         }
228         if (xp->a_flag & A_XDATA) {
229                 fprintf(mfp, ",XDATA");
230                 memPage = 0x0D;
231         }
232         if (xp->a_flag & A_BIT) {
233                 fprintf(mfp, ",BIT");
234                 memPage = 0x0B;
235         }
236         fprintf(mfp, ")");
237         if (xp->a_flag & A_PAG) {
238                 ai = (ai & 0xFF);
239                 aj = (aj > 256);
240                 if (ai || aj) { fprintf(mfp, "  "); }
241                 if (ai)      { fprintf(mfp, " Boundary"); }
242                 if (ai & aj)  { fprintf(mfp, " /"); }
243                 if (aj)      { fprintf(mfp, " Length"); }
244                 if (ai || aj) { fprintf(mfp, " Error"); }
245         }
246
247         /*
248          * Find number of symbols in area
249          */
250         nmsym = 0;
251         oxp = xp->a_axp;
252         while (oxp) {
253                 for (i=0; i<NHASH; i++) {
254                         sp = symhash[i];
255                         while (sp != NULL) {
256                                 if (oxp == sp->s_axp)
257                                         ++nmsym;
258                                 sp = sp->s_sp;
259                         }
260                 }
261                 oxp = oxp->a_axp;
262         }
263         if (nmsym == 0) {
264                 putc('\n', mfp);
265                 return;
266         }
267
268         /*
269          * Allocate space for an array of pointers to symbols
270          * and load array.
271          */
272         if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
273                 == NULL) {
274                 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
275                 return;
276         }
277         nmsym = 0;
278         oxp = xp->a_axp;
279         while (oxp) {
280                 for (i=0; i<NHASH; i++) {
281                         sp = symhash[i];
282                         while (sp != NULL) {
283                                 if (oxp == sp->s_axp) {
284                                         p[nmsym++] = sp;
285                                 }
286                                 sp = sp->s_sp;
287                         }
288                 }
289                 oxp = oxp->a_axp;
290         }
291
292         /*
293          * Bubble Sort of Addresses in Symbol Table Array
294          */
295         j = 1;
296         while (j) {
297                 j = 0;
298                 sp = p[0];
299                 a0 = sp->s_addr + sp->s_axp->a_addr;
300                 for (i=1; i<nmsym; ++i) {
301                         sp = p[i];
302                         ai = sp->s_addr + sp->s_axp->a_addr;
303                         if (a0 > ai) {
304                                 j = 1;
305                                 p[i] = p[i-1];
306                                 p[i-1] = sp;
307                         }
308                         a0 = ai;
309                 }
310         }
311
312         /*
313          * Symbol Table Output
314          */
315
316         i = 0;
317         fprintf(mfp, "\n\n");
318         fprintf(mfp, "      Value  Global\n");
319         fprintf(mfp, "   --------  --------------------------------");
320         while (i < nmsym) {
321                 fprintf(mfp, "\n");
322                 if (memPage != 0) 
323                         fprintf(mfp, "  %02X:", memPage);
324                 else
325                         fprintf(mfp, "     ");
326
327                 sp = p[i];
328                 aj = sp->s_addr + sp->s_axp->a_addr;
329                 if (xflag == 0) {
330                         fprintf(mfp, "%04X    ", aj);
331                 } else
332                 if (xflag == 1) {
333                         fprintf(mfp, "%06o  ", aj);
334                 } else
335                 if (xflag == 2) {
336                         fprintf(mfp, "%05u   ", aj);
337                 }
338                 ptr = &sp->s_id[0];
339                 fprintf(mfp, "%s", ptr );
340                 
341                 /* if cdb flag set the output cdb Information 
342                    and the symbol has a '$' sign in it then */
343                 if (dflag &&
344                     strchr(ptr,'$'))
345                     fprintf(dfp,"L:%s:%X\n",ptr,aj);
346                 /* NoICE output of symbol */
347                 if (jflag) DefineNoICE( ptr, aj, memPage );
348
349                 i++;
350         }
351         putc('\n', mfp);
352         free(p);
353 }
354
355 #else
356
357 /* NCPS == 8 */
358 /*)Function     VOID    lstarea(xp)
359  *
360  *              area *  xp              pointer to an area structure
361  *
362  *      The function lstarea() creates the linker map output for
363  *      the area specified by pointer xp.  The generated output
364  *      area header includes the area name, starting address,
365  *      size of area, number of words (in decimal), and the
366  *      area attributes.  The symbols defined in this area are
367  *      sorted by ascending address and output four per line
368  *      in the selected radix.
369  *
370  *      local variables:
371  *              areax * oxp             pointer to an area extension structure
372  *              int     c               character value
373  *              int     i               loop counter
374  *              int     j               bubble sort update status
375  *              char *  ptr             pointer to an id string
376  *              int     nmsym           number of symbols in area
377  *              addr_t  a0              temporary
378  *              addr_t  ai              temporary
379  *              addr_t  aj              temporary
380  *              sym *   sp              pointer to a symbol structure
381  *              sym **  p               pointer to an array of
382  *                                      pointers to symbol structures
383  *
384  *      global variables:
385  *              FILE    *mfp            Map output file handle
386  *              sym *symhash[NHASH]     array of pointers to NHASH
387  *                                      linked symbol lists
388  *              int     xflag           Map file radix type flag
389  *
390  *      functions called:
391  *              int     fprintf()       c_library
392  *              VOID    free()          c_library
393  *              char *  malloc()        c_library
394  *              char    putc()          c_library
395  *              VOID    slew()          lklist.c
396  *
397  *      side effects:
398  *              Map output generated.
399  */
400
401 VOID
402 lstarea(xp)
403 struct area *xp;
404 {
405         register struct areax *oxp;
406         register c, i, j;
407         register char *ptr;
408         int nmsym;
409         addr_t a0, ai, aj;
410         struct sym *sp;
411         struct sym **p;
412         int page;
413
414         putc('\n', mfp);
415         slew(mfp);
416         /*
417          * Output Area Header
418          */
419         ptr = &xp->a_id[0];
420         while (ptr < &xp->a_id[NCPS]) {
421                 if ((c = *ptr++) != 0) {
422                         putc(c, mfp);
423                 } else {
424                         putc(' ', mfp);
425                 }
426         }
427         ai = xp->a_addr;
428         aj = xp->a_size;
429         if (xflag == 0) {
430                 fprintf(mfp, "   %04X   %04X", ai, aj);
431         } else
432         if (xflag == 1) {
433                 fprintf(mfp, " %06o %06o", ai, aj);
434         } else
435         if (xflag == 2) {
436                 fprintf(mfp, "  %05u  %05u", ai, aj);
437         }
438         fprintf(mfp, " = %6u. bytes ", aj);
439         if (xp->a_flag & A_ABS) {
440                 fprintf(mfp, "(ABS");
441         } else {
442                 fprintf(mfp, "(REL");
443         }
444         if (xp->a_flag & A_OVR) {
445                 fprintf(mfp, ",OVR");
446         } else {
447                 fprintf(mfp, ",CON");
448         }
449         if (xp->a_flag & A_PAG) {
450                 fprintf(mfp, ",PAG");
451         }
452
453         page = 0x00;
454         if (xp->a_flag & A_CODE) {
455                 fprintf(mfp, ",CODE");
456                 memPage = 0x0C;
457         }
458         if (xp->a_flag & A_XDATA) {
459                 fprintf(mfp, ",XDATA");
460                 memPage = 0x0D;
461         }
462         if (xp->a_flag & A_BIT) {
463                 fprintf(mfp, ",BIT");
464                 memPage = 0x0B;
465         }
466         fprintf(mfp, ")");
467         if (xp->a_flag & A_PAG) {
468                 ai = (ai & 0xFF);
469                 aj = (aj > 256);
470                 if (ai || aj) { fprintf(mfp, "  "); }
471                 if (ai)      { fprintf(mfp, " Boundary"); }
472                 if (ai & aj)  { fprintf(mfp, " /"); }
473                 if (aj)      { fprintf(mfp, " Length"); }
474                 if (ai || aj) { fprintf(mfp, " Error"); }
475         }
476
477         /*
478          * Find number of symbols in area
479          */
480         nmsym = 0;
481         oxp = xp->a_axp;
482         while (oxp) {
483                 for (i=0; i<NHASH; i++) {
484                         sp = symhash[i];
485                         while (sp != NULL) {
486                                 if (oxp == sp->s_axp)
487                                         ++nmsym;
488                                 sp = sp->s_sp;
489                         }
490                 }
491                 oxp = oxp->a_axp;
492         }
493         if (nmsym == 0) {
494                 putc('\n', mfp);
495                 slew(mfp);
496                 return;
497         }
498
499         /*
500          * Allocate space for an array of pointers to symbols
501          * and load array.
502          */
503         if ( (p = (struct sym **) malloc(nmsym*sizeof(struct sym *)))
504                 == NULL) {
505                 fprintf(mfp, "\nInsufficient space to build Map Segment.\n");
506                 slew(mfp);
507                 return;
508         }
509         nmsym = 0;
510         oxp = xp->a_axp;
511         while (oxp) {
512                 for (i=0; i<NHASH; i++) {
513                         sp = symhash[i];
514                         while (sp != NULL) {
515                                 if (oxp == sp->s_axp) {
516                                         p[nmsym++] = sp;
517                                 }
518                                 sp = sp->s_sp;
519                         }
520                 }
521                 oxp = oxp->a_axp;
522         }
523
524         /*
525          * Bubble Sort of Addresses in Symbol Table Array
526          */
527         j = 1;
528         while (j) {
529                 j = 0;
530                 sp = p[0];
531                 a0 = sp->s_addr + sp->s_axp->a_addr;
532                 for (i=1; i<nmsym; ++i) {
533                         sp = p[i];
534                         ai = sp->s_addr + sp->s_axp->a_addr;
535                         if (a0 > ai) {
536                                 j = 1;
537                                 p[i] = p[i-1];
538                                 p[i-1] = sp;
539                         }
540                         a0 = ai;
541                 }
542         }
543
544         /*
545          * Symbol Table Output
546          */
547         i = 0;
548         while (i < nmsym) {
549                 fprintf(mfp, "\n");
550                 slew(mfp);
551                 fprintf(mfp, "     ");
552                 sp = p[i];
553                 aj = sp->s_addr + sp->s_axp->a_addr;
554                 if (xflag == 0) {
555                         fprintf(mfp, "  %04X  ", aj);
556                 } else
557                 if (xflag == 1) {
558                         fprintf(mfp, "%06o  ", aj);
559                 } else
560                 if (xflag == 2) {
561                         fprintf(mfp, " %05u  ", aj);
562                 }
563                 ptr = &sp->s_id[0];
564                 fprintf(mfp, "%s", ptr );
565
566                 /* NoICE output of symbol */
567                 if (jflag) DefineNoICE( ptr, aj, memPage );
568         }
569         putc('\n', mfp);
570         free(p);
571         slew(mfp);
572 }
573 #endif
574
575 /*)Function     VOID    lkulist(i)
576  *
577  *              int     i       i # 0   process LST to RST file
578  *                              i = 0   copy remainder of LST file
579  *                                      to RST file and close files
580  *
581  *      The function lkulist() creates a relocated listing (.rst)
582  *      output file from the ASxxxx assembler listing (.lst)
583  *      files.  The .lst file's program address and code bytes
584  *      are changed to reflect the changes made by ASlink as
585  *      the .rel files are combined into a single relocated
586  *      output file.
587  *
588  *      local variables:
589  *              addr_t  pc              current program counter address
590  *
591  *      global variables:
592  *              int     hilo            byte order
593  *              int     gline           get a line from the LST file
594  *                                      to translate for the RST file
595  *              char    rb[]            read listing file text line
596  *              FILE    *rfp            The file handle to the current
597  *                                      output RST file
598  *              int     rtcnt           count of data words
599  *              int     rtflg[]         output the data flag
600  *              addr_t  rtval[]         relocated data
601  *              FILE    *tfp            The file handle to the current
602  *                                      LST file being scanned
603  *
604  *      functions called:
605  *              int     fclose()        c_library
606  *              int     fgets()         c_library
607  *              int     fprintf()       c_library
608  *              VOID    lkalist()       lklist.c
609  *              VOID    lkglist()       lklist.c
610  *
611  *      side effects:
612  *              A .rst file is created for each available .lst
613  *              file associated with a .rel file.
614  */
615
616 VOID
617 lkulist(i)
618 int i;
619 {
620         addr_t pc;
621
622         /*
623          * Exit if listing file is not open
624          */
625         if (tfp == NULL)
626                 return;
627
628         /*
629          * Normal processing of LST to RST
630          */
631         if (i) {
632                 /*
633                  * Evaluate current code address
634                  */
635                 if (hilo == 0) {
636                         pc = ((rtval[1] & 0xFF) << 8) + (rtval[0] & 0xFF);
637                 } else {
638                         pc = ((rtval[0] & 0xFF) << 8) + (rtval[1] & 0xFF);
639                 }
640
641                 /*
642                  * Line with only address
643                  */
644                 if (rtcnt == 2) {
645                         lkalist(pc);
646
647                 /*
648                  * Line with address and code
649                  */
650                 } else {
651                         for (i=2; i < rtcnt; i++) {
652                                 if (rtflg[i]) {
653                                         lkglist(pc++, rtval[i] & 0xFF);
654                                 }
655                         }
656                 }
657
658         /*
659          * Copy remainder of LST to RST
660          */
661         } else {
662                 if (gline == 0)
663                         fprintf(rfp, "%s", rb);
664
665                 while (fgets(rb, sizeof(rb), tfp) != 0) {
666                         fprintf(rfp, "%s", rb);
667                 }
668                 fclose(tfp);
669                 tfp = NULL;
670                 fclose(rfp);
671                 rfp = NULL;
672         }
673 }
674
675 /*)Function     VOID    lkalist(pc)
676  *
677  *              int     pc              current program counter value
678  *
679  *      The function lkalist() performs the following functions:
680  *
681  *      (1)     if the value of gline = 0 then the current listing
682  *              file line is copied to the relocated listing file output.
683  *
684  *      (2)     the listing file is read line by line and copied to
685  *              the relocated listing file until a valid source
686  *              line number and a program counter value of the correct
687  *              radix is found.  The new relocated pc value is substituted
688  *              and the line is written to the RST file.
689  *
690  *      local variables:
691  *              int     i               loop counter
692  *              char    str[]           temporary string
693  *
694  *      global variables:
695  *              int     gcntr           data byte counter
696  *              int     gline           get a line from the LST file
697  *                                      to translate for the RST file
698  *              char    rb[]            read listing file text line
699  *              char    *rp             pointer to listing file text line
700  *              FILE    *rfp            The file handle to the current
701  *                                      output RST file
702  *              FILE    *tfp            The file handle to the current
703  *                                      LST file being scanned
704  *
705  *      functions called:
706  *              int     dgt()           lklist.c
707  *              int     fclose()        c_library
708  *              int     fgets()         c_library
709  *              int     fprintf()       c_library
710  *              int     sprintf()       c_library
711  *              char *  strncpy()       c_library
712  *
713  *      side effects:
714  *              Lines of the LST file are copied to the RST file,
715  *              the last line copied has the code address
716  *              updated to reflect the program relocation.
717  */
718
719 VOID
720 lkalist(pc)
721 addr_t pc;
722 {
723         char str[8];
724         int i;
725
726         /*
727          * Exit if listing file is not open
728          */
729 loop:   if (tfp == NULL)
730                 return;
731
732         /*
733          * Copy current LST to RST
734          */
735         if (gline == 0) {
736                 fprintf(rfp, "%s", rb);
737                 gline = 1;
738         }
739
740         /*
741          * Clear text line buffer
742          */
743         for (i=0,rp=rb; i<sizeof(rb); i++) {
744                 *rp++ = 0;
745         }
746
747         /*
748          * Get next LST text line
749          */
750         if (fgets(rb, sizeof(rb), tfp) == NULL) {
751                 fclose(tfp);
752                 tfp = NULL;
753                 fclose(rfp);
754                 rfp = NULL;
755                 return;
756         }
757
758         /*
759          * Must have an ASxxxx Listing line number
760          */
761         if (!dgt(RAD10, &rb[30], 1)) {
762                 fprintf(rfp, "%s", rb);
763                 goto loop;
764         }
765
766         /*
767          * Must have an address in the expected radix
768          */
769         if (radix == 16) {
770                 if (!dgt(RAD16, &rb[3], 4)) {
771                         fprintf(rfp, "%s", rb);
772                         goto loop;
773                 }
774                 sprintf(str, "%04X", pc);
775                 strncpy(&rb[3], str, 4);
776         } else
777         if (radix == 10) {
778                 if (!dgt(RAD10, &rb[3], 5)) {
779                         fprintf(rfp, "%s", rb);
780                         goto loop;
781                 }
782                 sprintf(str, "%05d", pc);
783                 strncpy(&rb[3], str, 5);
784         } else
785         if (radix == 8) {
786                 if (!dgt(RAD8, &rb[3], 6)) {
787                         fprintf(rfp, "%s", rb);
788                         goto loop;
789                 }
790                 sprintf(str, "%06o", pc);
791                 strncpy(&rb[3], str, 6);
792         }
793
794         /*
795          * Copy updated LST text line to RST
796          */
797         fprintf(rfp, "%s", rb);
798         gcntr = 0;
799 }
800
801 /*)Function     VOID    lkglist(pc,v)
802  *
803  *              int     pc              current program counter value
804  *              int     v               value of byte at this address
805  *
806  *      The function lkglist() performs the following functions:
807  *
808  *      (1)     if the value of gline = 1 then the listing file
809  *              is read line by line and copied to the
810  *              relocated listing file until a valid source
811  *              line number and a program counter value of the correct
812  *              radix is found.
813  *
814  *      (2)     The new relocated values and code address are
815  *              substituted and the line may be written to the RST file.
816  *
817  *      local variables:
818  *              int     i               loop counter
819  *              char    str[]           temporary string
820  *
821  *      global variables:
822  *              int     gcntr           data byte counter
823  *                                      set to -1 for a continuation line
824  *              int     gline           get a line from the LST file
825  *                                      to translate for the RST file
826  *              char    rb[]            read listing file text line
827  *              char    *rp             pointer to listing file text line
828  *              FILE    *rfp            The file handle to the current
829  *                                      output RST file
830  *              FILE    *tfp            The file handle to the current
831  *                                      LST file being scanned
832  *
833  *      functions called:
834  *              int     dgt()           lklist.c
835  *              int     fclose()        c_library
836  *              int     fgets()         c_library
837  *              int     fprintf()       c_library
838  *              int     sprintf()       c_library
839  *              char *  strncpy()       c_library
840  *
841  *      side effects:
842  *              Lines of the LST file are copied to the RST file
843  *              with updated data values and code addresses.
844  */
845
846 VOID
847 lkglist(pc,v)
848 addr_t pc;
849 int v;
850 {
851         char str[8];
852         int i;
853
854         /*
855          * Exit if listing file is not open
856          */
857 loop:   if (tfp == NULL)
858                 return;
859
860         /*
861          * Get next LST text line
862          */
863         if (gline) {
864                 /*
865                  * Clear text line buffer
866                  */
867                 for (i=0,rp=rb; i<sizeof(rb); i++) {
868                         *rp++ = 0;
869                 }
870
871                 /*
872                  * Get next LST text line
873                  */
874                 if (fgets(rb, sizeof(rb), tfp) == NULL) {
875                         fclose(tfp);
876                         tfp = NULL;
877                         fclose(rfp);
878                         rfp = NULL;
879                         return;
880                 }
881
882                 /*
883                  * Check for a listing line number if required
884                  */
885                 if (gcntr != -1) {
886                         if (!dgt(RAD10, &rb[30], 1)) {
887                                 fprintf(rfp, "%s", rb);
888                                 goto loop;
889                         }
890                         gcntr = 0;
891                 }
892                 gline = 0;
893         }
894
895         /*
896          * Hex Listing
897          */
898         if (radix == 16) {
899                 /*
900                  * Data Byte Pointer
901                  */
902                 if (gcntr == -1) {
903                         rp = &rb[8];
904                 } else {
905                         rp = &rb[8 + (3 * gcntr)];
906                 }
907                 /*
908                  * Number must be of proper radix
909                  */
910                 if (!dgt(RAD16, rp, 2)) {
911                         fprintf(rfp, "%s", rb);
912                         gline = 1;
913                         goto loop;
914                 }
915                 /*
916                  * Output new data value, overwrite relocation codes
917                  */
918                 sprintf(str, " %02X", v);
919                 strncpy(rp-1, str, 3);
920                 if (gcntr == -1) {
921                         gcntr = 0;
922                 }
923                 /*
924                  * Output relocated code address
925                  */
926                 if (gcntr == 0) {
927                         if (dgt(RAD16, &rb[3], 4)) {
928                                 sprintf(str, "%04X", pc);
929                                 strncpy(&rb[3], str, 4);
930                         }
931                 }
932                 /*
933                  * Output text line when updates finished
934                  */
935                 if (++gcntr == 6) {
936                         fprintf(rfp, "%s", rb);
937                         gline = 1;
938                         gcntr = -1;
939                 }
940         } else
941         /*
942          * Decimal Listing
943          */
944         if (radix == 10) {
945                 /*
946                  * Data Byte Pointer
947                  */
948                 if (gcntr == -1) {
949                         rp = &rb[9];
950                 } else {
951                         rp = &rb[9 + (3 * gcntr)];
952                 }
953                 /*
954                  * Number must be of proper radix
955                  */
956                 if (!dgt(RAD10, rp, 3)) {
957                         fprintf(rfp, "%s", rb);
958                         gline = 1;
959                         goto loop;
960                 }
961                 /*
962                  * Output new data value, overwrite relocation codes
963                  */
964                 sprintf(str, " %03d", v);
965                 strncpy(rp-1, str, 4);
966                 if (gcntr == -1) {
967                         gcntr = 0;
968                 }
969                 /*
970                  * Output relocated code address
971                  */
972                 if (gcntr == 0) {
973                         if (dgt(RAD10, &rb[3], 5)) {
974                                 sprintf(str, "%05d", pc);
975                                 strncpy(&rb[3], str, 5);
976                         }
977                 }
978                 /*
979                  * Output text line when updates finished
980                  */
981                 if (++gcntr == 4) {
982                         fprintf(rfp, "%s", rb);
983                         gline = 1;
984                         gcntr = -1;
985                 }
986         } else
987         /*
988          * Octal Listing
989          */
990         if (radix == 8) {
991                 /*
992                  * Data Byte Pointer
993                  */
994                 if (gcntr == -1) {
995                         rp = &rb[10];
996                 } else {
997                         rp = &rb[10 + (3 * gcntr)];
998                 }
999                 /*
1000                  * Number must be of proper radix
1001                  */
1002                 if (!dgt(RAD8, rp, 3)) {
1003                         fprintf(rfp, "%s", rb);
1004                         gline = 1;
1005                         goto loop;
1006                 }
1007                 /*
1008                  * Output new data value, overwrite relocation codes
1009                  */
1010                 sprintf(str, " %03o", v);
1011                 strncpy(rp-1, str, 4);
1012                 if (gcntr == -1) {
1013                         gcntr = 0;
1014                 }
1015                 /*
1016                  * Output relocated code address
1017                  */
1018                 if (gcntr == 0) {
1019                         if (dgt(RAD8, &rb[3], 6)) {
1020                                 sprintf(str, "%06o", pc);
1021                                 strncpy(&rb[3], str, 6);
1022                         }
1023                 }
1024                 /*
1025                  * Output text line when updates finished
1026                  */
1027                 if (++gcntr == 4) {
1028                         fprintf(rfp, "%s", rb);
1029                         gline = 1;
1030                         gcntr = -1;
1031                 }
1032         }
1033 }
1034
1035 /*)Function     int     dgt(rdx,str,n)
1036  *
1037  *              int     rdx             radix bit code
1038  *              char    *str            pointer to the test string
1039  *              int     n               number of characters to check
1040  *
1041  *      The function dgt() verifies that the string under test
1042  *      is of the specified radix.
1043  *
1044  *      local variables:
1045  *              int     i               loop counter
1046  *
1047  *      global variables:
1048  *              ctype[]                 array of character types
1049  *
1050  *      functions called:
1051  *              none
1052  *
1053  *      side effects:
1054  *              none
1055  */
1056
1057 int
1058 dgt(rdx, str, n)
1059 int rdx, n;
1060 char *str;
1061 {
1062         int i;
1063
1064         for (i=0; i<n; i++) {
1065                 if ((ctype[(int)*str++] & rdx) == 0)
1066                         return(0);
1067         }
1068         return(1);
1069 }