* asranlib/asranlib.c, link/lkar.h, link/lkar.c:
[fw/sdcc] / as / hc08 / aslist.c
1 /* aslist.c
2
3    Copyright (C) 1989-1995 Alan R. Baldwin
4    721 Berkeley St., Kent, Ohio 44240
5
6 This program is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 3, or (at your option) any
9 later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program.  If not, see <http://www.gnu.org/licenses/>. */
18
19 /*
20  * 28-Oct-97 JLH: 
21  *           - lstsym: show s_id as string rather than array [NCPS]
22  */
23
24 #include <stdio.h>
25 #include <setjmp.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include "asm.h"
29
30 /*)Module       aslist.c
31  *
32  *      The module aslist.c contains all the functions used
33  *      to generate the assembler list and symbol output files.
34  *
35  *      aslist.c contains the following functions:
36  *              VOID    list()
37  *              VOID    list1()
38  *              VOID    list2()
39  *              VOID    slew()
40  *              VOID    lstsym()
41  *
42  *      The module aslist.c contains no local/static variables
43  */
44
45 /*)Function     VOID    list()
46  *
47  *      The function list() generates the listing output
48  *      which includes the input source, line numbers,
49  *      and generated code.  Numerical output may be selected
50  *      as hexadecimal, decimal, or octal.
51  * 
52  *      local variables:
53  *              int *   wp              pointer to the assembled data bytes
54  *              int *   wpt             pointer to the data byte mode
55  *              int     nb              computed number of assembled bytes
56  *
57  *      global variables:
58  *              int     cb[]            array of assembler output values
59  *              int     cbt[]           array of assembler relocation types
60  *                                      describing the data in cb[]
61  *              int *   cp              pointer to assembler output array cb[]
62  *              int *   cpt             pointer to assembler relocation type
63  *                                      output array cbt[]
64  *              char    eb[]            array of generated error codes
65  *              char *  ep              pointer into error list
66  *                                      array eb[]
67  *              char    ib[]            assembler-source text line
68  *              FILE *  lfp             list output file handle
69  *              int     line            current assembler source line number
70  *              int     lmode           listing mode
71  *              int     xflag           -x, listing radix flag
72  *
73  *      functions called:
74  *              int     fprintf()       c_library
75  *              VOID    list1()         aslist.c
76  *              int     putc()          c_library
77  *              VOID    slew()          asslist.c
78  *
79  *      side effects:
80  *              Listing or symbol output updated.
81  */
82
83 VOID
84 list()
85 {
86         register char *wp;
87         register int *wpt;
88         register int nb;
89
90         if (lfp == NULL || lmode == NLIST)
91                 return;
92
93         /*
94          * Get Correct Line Number
95          */
96         if (incfil >= 0) {
97                 line = incline[incfil];
98                 if (line == 0) {
99                         if (incfil > 0) {
100                                 line = incline[incfil-1];
101                         } else {
102                                 line = srcline[cfile];
103                         }
104                 }
105         } else {
106                 line = srcline[cfile];
107         }
108
109         /*
110          * Move to next line.
111          */
112         slew(lfp, pflag);
113
114         /*
115          * Output a maximum of NERR error codes with listing.
116          */
117         while (ep < &eb[NERR])
118                 *ep++ = ' ';
119         fprintf(lfp, "%.2s", eb);
120
121         /*
122          * Source listing only option.
123          */
124         if (lmode == SLIST) {
125                 fprintf(lfp, "%24s%5u %s\n", "", line, ib);
126                 return;
127         }
128         if (lmode == ALIST) {
129                 outchk(HUGE,HUGE);
130         }
131
132         /*
133          * HEX output Option.
134          */
135         if (xflag == 0) {               /* HEX */
136                 /*
137                  * Equate only
138                  */
139                 if (lmode == ELIST) {
140                         fprintf(lfp, "%18s%04X", "", laddr);
141                         fprintf(lfp, "  %5u %s\n", line, ib);
142                         return;
143                 }
144
145                 /*
146                  * Address (with allocation)
147                  */
148                 fprintf(lfp, " %04X", laddr);
149                 if (lmode == ALIST || lmode == BLIST) {
150                         fprintf(lfp, "%19s%5u %s\n", "", line, ib);
151                         outdot();
152                         return;
153                 }
154                 wp = cb;
155                 wpt = cbt;
156                 nb = (int) (cp - cb);
157
158                 /*
159                  * First line of output for this source line with data.
160                  */
161                 list1(wp, wpt, nb, 1);
162                 fprintf(lfp, " %5u %s\n", line, ib);
163
164                 /*
165                  * Subsequent lines of output if more data.
166                  */
167                 while ((nb -= 6) > 0) {
168                         wp += 6;
169                         wpt += 6;
170                         slew(lfp, 0);
171                         fprintf(lfp, "%7s", "");
172                         list1(wp, wpt, nb, 0);
173                         putc('\n', lfp);
174                 }
175         } else
176         /*
177          * OCTAL output Option.
178          */
179         if (xflag == 1) {               /* OCTAL */
180                 /*
181                  * Equate only
182                  */
183                 if (lmode == ELIST) {
184                         fprintf(lfp, "%16s%06o", "", laddr);
185                         fprintf(lfp, "  %5u %s\n", line, ib);
186                         return;
187                 }
188
189                 /*
190                  * Address (with allocation)
191                  */
192                 fprintf(lfp, " %06o", laddr);
193                 if (lmode == ALIST || lmode == BLIST) {
194                         fprintf(lfp, "%17s%5u %s\n", "", line, ib);
195                         outdot();
196                         return;
197                 }
198                 wp = cb;
199                 wpt = cbt;
200                 nb = (int) (cp - cb);
201
202                 /*
203                  * First line of output for this source line with data.
204                  */
205                 list1(wp, wpt, nb, 1);
206                 fprintf(lfp, " %5u %s\n", line, ib);
207
208                 /*
209                  * Subsequent lines of output if more data.
210                  */
211                 while ((nb -= 4) > 0) {
212                         wp += 4;
213                         wpt += 4;
214                         slew(lfp, 0);
215                         fprintf(lfp, "%9s", "");
216                         list1(wp, wpt, nb, 0);
217                         putc('\n', lfp);
218                 }
219         } else
220         /*
221          * DECIMAL output Option.
222          */
223         if (xflag == 2) {               /* DECIMAL */
224                 /*
225                  * Equate only
226                  */
227                 if (lmode == ELIST) {
228                         fprintf(lfp, "%16s%05u", "", laddr);
229                         fprintf(lfp, "   %5u %s\n", line, ib);
230                         return;
231                 }
232
233                 /*
234                  * Address (with allocation)
235                  */
236                 fprintf(lfp, "  %05u", laddr);
237                 if (lmode == ALIST || lmode == BLIST) {
238                         fprintf(lfp, "%17s%5u %s\n", "", line, ib);
239                         outdot();
240                         return;
241                 }
242                 wp = cb;
243                 wpt = cbt;
244                 nb = (int) (cp - cb);
245
246                 /*
247                  * First line of output for this source line with data.
248                  */
249                 list1(wp, wpt, nb, 1);
250                 fprintf(lfp, " %5u %s\n", line, ib);
251
252                 /*
253                  * Subsequent lines of output if more data.
254                  */
255                 while ((nb -= 4) > 0) {
256                         wp += 4;
257                         wpt += 4;
258                         slew(lfp, 0);
259                         fprintf(lfp, "%9s", "");
260                         list1(wp, wpt, nb, 0);
261                         putc('\n', lfp);
262                 }
263         }
264 }
265
266 /*)Function     VOID    list1(wp, wpt, nw, f)
267  *
268  *              int     f               fill blank fields (1)
269  *              int     nb              number of data bytes
270  *              int *   wp              pointer to data bytes
271  *              int *   wpt             pointer to data byte mode
272  *
273  *      local variables:
274  *              int     i               loop counter
275  *
276  *      global variables:
277  *              int     xflag           -x, listing radix flag
278  *
279  *      functions called:
280  *              VOID    list2()         asslist.c
281  *              int     fprintf()       c_library
282  *
283  *      side effects:
284  *              Data formatted and output to listing.
285  */
286
287 VOID
288 list1(wp, wpt, nb, f)
289 register char *wp;
290 register int *wpt, nb, f;
291 {
292         register int i;
293
294         /*
295          * HEX output Option.
296          */
297         if (xflag == 0) {               /* HEX */
298                 /*
299                  * Bound number of words to HEX maximum per line.
300                  */
301                 if (nb > 6)
302                         nb = 6;
303
304                 /*
305                  * Output bytes.
306                  */
307                 for (i=0; i<nb; ++i) {
308                         list2(*wpt++);
309                         fprintf(lfp, "%02X", (*wp++)&0377);
310                 }
311
312                 /*
313                  * Output blanks if required.
314                  */
315                 if (f) {
316                         while (i < 6) {
317                                 fprintf(lfp, "   ");
318                                 ++i;
319                         }
320                 }
321         } else
322         /*
323          * OCTAL output Option.
324          */
325         if (xflag == 1) {               /* OCTAL */
326                 /*
327                  * Bound number of words to OCTAL maximum per line.
328                  */
329                 if (nb > 4)
330                         nb = 4;
331
332                 /*
333                  * Output bytes.
334                  */
335                 for (i=0; i<nb; ++i) {
336                         list2(*wpt++);
337                         fprintf(lfp, "%03o", (*wp++)&0377);
338                 }
339
340                 /*
341                  * Output blanks if required.
342                  */
343                 if (f) {
344                         while (i < 4) {
345                                 fprintf(lfp, "    ");
346                                 ++i;
347                         }
348                 }
349         } else
350         /*
351          * DECIMAL output Option.
352          */
353         if (xflag == 2) {               /* DECIMAL */
354                 /*
355                  * Bound number of words to DECIMAL maximum per line.
356                  */
357                 if (nb > 4)
358                         nb = 4;
359
360                 /*
361                  * Output bytes.
362                  */
363                 for (i=0; i<nb; ++i) {
364                         list2(*wpt++);
365                         fprintf(lfp, "%03u", (*wp++)&0377);
366                 }
367
368                 /*
369                  * Output blanks if required.
370                  */
371                 if (f) {
372                         while (i < 4) {
373                                 fprintf(lfp, "    ");
374                                 ++i;
375                         }
376                 }
377         }
378 }
379
380 /*)Function     VOID    list2(wpt)
381  *
382  *              int *   wpt             pointer to relocation mode
383  *
384  *      The function list2() outputs the selected
385  *      relocation flag as specified by fflag.
386  *
387  *      local variables:
388  *              int     c               relocation flag character
389  *              int     t               relocation mode
390  *
391  *      global variables:
392  *              int     fflag           -f(f), relocations flagged flag
393  *
394  *      functions called:
395  *              int     putc()          c_library
396  *
397  *      side effects:
398  *              Relocation flag output to listing file.
399  */
400
401 VOID
402 list2(t)
403 register int t;
404 {
405         register int c;
406
407         c = ' ';
408
409         /*
410          * Designate a relocatable word by `.
411          */
412         if (fflag == 1) {
413                 if (t & R_RELOC) {
414                         c = '`';
415                 }
416         } else
417         /*
418          * Designate a relocatable word by its mode:
419          *      page0 or paged          *
420          *      unsigned                u (v)
421          *      operand offset          p (q)
422          *      relocatable symbol      r (s)
423          */
424         if (fflag >= 2) {
425                 if (t & R_RELOC) {
426                         if (t & (R_PAG0|R_PAG)) {
427                                 c = '*';
428                         } else if (t & R_USGN) {
429                                 c = 'u';
430                         } else if (t & R_PCR) {
431                                 c = 'p';
432                         } else {
433                                 c = 'r';
434                         }
435                         if (t & R_HIGH) c += 1;
436                 }
437         }
438
439         /*
440          * Output the selected mode.
441          */
442         putc(c, lfp);
443 }
444
445 /*)Function     VOID    slew(fp, flag)
446  *
447  *              FILE *  fp              file handle for listing
448  *              int     flag            enable pagination
449  *
450  *      The function slew() increments the page line count.
451  *      If the page overflows and pagination is enabled:
452  *              1)      put out a page skip,
453  *              2)      a title,
454  *              3)      a subtitle,
455  *              4)      and reset the line count.
456  *
457  *      local variables:
458  *              none
459  *
460  *      global variables:
461  *              char    cpu[]           cpu type string
462  *              int     lop             current line number on page
463  *              int     page            current page number
464  *              char    stb[]           Subtitle string buffer
465  *              char    tb[]            Title string buffer
466  *
467  *      functions called:
468  *              int     fprintf()       c_library
469  *
470  *      side effects:
471  *              Increments page line counter, on overflow
472  *              a new page header is output to the listing file.
473  */
474
475 VOID
476 slew(fp,flag)
477 FILE *fp;
478 int flag;
479 {
480         if ((lop++ >= NLPP) && flag) {
481                 fprintf(fp, "\fASxxxx Assembler %s  (%s), page %u.\n",
482                         VERSION, cpu, ++page);
483                 fprintf(fp, "%s\n", tb);
484                 fprintf(fp, "%s\n\n", stb);
485                 lop = 5;
486         }
487 }
488
489 /* Used for qsort call in lstsym */
490 static int _cmpSym(const void *p1, const void *p2)
491 {
492     struct sym **s1 = (struct sym **)(p1);
493     struct sym **s2 = (struct sym **)(p2);
494     return strcmp((*s1)->s_id,(*s2)->s_id);
495 }
496
497 /*)Function     VOID    lstsym(fp)
498  *
499  *              FILE *  fp              file handle for output
500  *
501  *      The function lstsym() outputs alphabetically
502  *      sorted symbol and area tables.
503  *
504  *      local variables:
505  *              int     c               temporary
506  *              int     i               loop counter
507  *              int     j               temporary
508  *              int     k               temporary
509  *              char *  ptr             pointer to an id string
510  *              int     nmsym           number of symbols
511  *              int     narea           number of areas
512  *              sym *   sp              pointer to symbol structure
513  *              sym **  p               pointer to an array of
514  *                                      pointers to symbol structures
515  *              area *  ap              pointer to an area structure
516  *
517  *      global variables:
518  *              area *  areap           pointer to an area structure
519  *              char    aretbl[]        string "Area Table"
520  *              sym     dot             defined as sym[0]
521  *              char    stb[]           Subtitle string buffer
522  *              sym * symhash[]         array of pointers to NHASH
523  *                                      linked symbol lists
524  *              char    symtbl[]        string "Symbol Table"
525  *              FILE *  tfp             symbol table output file handle
526  *              int     xflag           -x, listing radix flag
527  *
528  *      functions called:
529  *              int     fprintf()       c_library
530  *              int     putc()          c_library
531  *              VOID    slew()          aslist.c
532  *              int     strcmp()        c_library
533  *              char *  strcpy()        c_library
534  *
535  *      side effects:
536  *              Symbol and area tables output.
537  */
538
539 VOID
540 lstsym(fp)
541 FILE *fp;
542 {
543         register int c, i, j, k;
544         register char *ptr;
545         int nmsym, narea;
546         struct sym *sp;
547         struct sym **p;
548         struct area *ap;
549
550         /*
551          * Symbol Table Header
552          */
553         strcpy(stb, &symtbl[0]);
554         lop = NLPP;
555         if (fp == tfp)
556                 page = 0;
557         slew(fp, 1);
558
559         /*
560          * Find number of symbols
561          */
562         nmsym = 0;
563         for (i=0; i<NHASH; i++) {
564                 sp = symhash[i];
565                 while (sp) {
566                         if (sp != &dot)
567                                 ++nmsym;
568                         sp = sp->s_sp;
569                 }
570         }
571         if (nmsym == 0)
572                 goto atable;
573
574         /*
575          * Allocate space for an array of pointers to symbols
576          * and load array.
577          */
578         if ((p = (struct sym **) malloc(sizeof((struct sym *) sp)*nmsym))
579                 == NULL) {
580                 fprintf(fp, "Insufficient space to build Symbol Table.\n");
581                 return;
582         }
583         nmsym = 0;
584         for (i=0; i<NHASH; i++) {
585                 sp = symhash[i];
586                 while (sp) {
587                         if (sp != &dot)
588                                 p[nmsym++] = sp;
589                         sp = sp->s_sp;
590                 }
591         }
592
593 #if 0
594         /* BUBBLE SORT?? WTF??? */
595         /*
596          * Bubble Sort on Symbol Table Array
597          */
598         j = 1;
599         c = nmsym - 1;
600         while (j) {
601                 j = 0;
602                 for (i=0; i<c; ++i) {
603                         if (strcmp(&p[i]->s_id[0],&p[i+1]->s_id[0]) > 0) {
604                                 j = 1;
605                                 sp = p[i+1];
606                                 p[i+1] = p[i];
607                                 p[i] = sp;
608                         }
609                 }
610         }
611 #else
612
613         qsort(p, nmsym, sizeof(struct sym *), _cmpSym);
614 #endif  
615
616         /*
617          * Symbol Table Output
618          */
619         for (i=0; i<nmsym;) {
620                 sp = p[i];
621                 if (sp->s_area) {
622                         j = sp->s_area->a_ref;
623                         if (xflag == 0) {
624                                 fprintf(fp, " %2X ", j);
625                         } else
626                         if (xflag == 1) {
627                                 fprintf(fp, "%3o ", j);
628                         } else
629                         if (xflag == 2) {
630                                 fprintf(fp, "%3u ", j);
631                         }
632                 } else {
633                         fprintf(fp, "    ");
634                 }
635                 ptr = &sp->s_id[0];
636                 fprintf(fp, "%-60s", ptr );     /* JLH */
637
638                 if (sp->s_flag & S_ASG) {
639                         putc('=', fp);
640                 } else {
641                         putc(' ', fp);
642                 }
643                 if (sp->s_type == S_NEW) {
644                         if (xflag == 0) {
645                                 fprintf(fp, "  **** ");
646                         } else
647                         if (xflag == 1) {
648                                 fprintf(fp, "****** ");
649                         } else
650                         if (xflag == 2) {
651                                 fprintf(fp, " ***** ");
652                         }
653                 } else {
654                         j = sp->s_addr;
655                         if (xflag == 0) {
656                                 fprintf(fp, "  %04X ", j);
657                         } else
658                         if (xflag == 1) {
659                                 fprintf(fp, "%06o ", j);
660                         } else
661                         if (xflag == 2) {
662                                 fprintf(fp, " %05u ", j);
663                         }
664                 }
665                 j = 0;
666                 if (sp->s_flag & S_GBL) {
667                         putc('G', fp);
668                         ++j;
669                 }
670                 if (sp->s_area != NULL) {
671                         putc('R', fp);
672                         ++j;
673                 }
674                 if (sp->s_type == S_NEW) {
675                         putc('X', fp);
676                         ++j;
677                 }
678 #if NCPS-8
679                 putc('\n', fp);
680                 slew(fp, 0);
681                 ++i;
682 #else
683                 if (++i % 3 == 0) {
684                         putc('\n', fp);
685                         slew(fp, pflag);
686                 } else
687                 if (i < nmsym) {
688                         while (j++ < 4)
689                                 putc(' ', fp);
690                         fprintf(fp, "| ");
691                 }
692 #endif
693         }
694         putc('\n', fp);
695
696         /*
697          * Area Table Header
698          */
699
700 atable:
701         strcpy(stb, &aretbl[0]);
702         lop = NLPP;
703         slew(fp, 1);
704
705         /*
706          * Area Table Output
707          */
708         narea = 0;
709         ap = areap;
710         while (ap) {
711                 ++narea;
712                 ap = ap->a_ap;
713         }
714         for (i=0; i<narea; ++i) {
715                 ap = areap;
716                 for (j=i+1; j<narea; ++j)
717                         ap = ap->a_ap;
718                 j = ap->a_ref;
719                 if (xflag == 0) {
720                         fprintf(fp, "  %2X ", j);
721                 } else
722                 if (xflag == 1) {
723                         fprintf(fp, " %3o ", j);
724                 } else
725                 if (xflag == 2) {
726                         fprintf(fp, " %3u ", j);
727                 }
728                 ptr = &ap->a_id[0];
729                 while (ptr < &ap->a_id[NCPS]) {
730                         if ((c = *ptr++) != 0) {
731                                 putc(c, fp);
732                         } else {
733                                 putc(' ', fp);
734                         }
735                 }
736                 j = ap->a_size;
737                 k = ap->a_flag;
738                 if (xflag==0) {
739                         fprintf(fp, "   size %4X   flags %X\n", j, k);
740                 } else
741                 if (xflag==1) {
742                         fprintf(fp, "   size %6o   flags %o\n", j, k);
743                 } else
744                 if (xflag==2) {
745                         fprintf(fp, "   size %5u   flags %u\n", j, k);
746                 }
747         }               
748 }