Use headers defined in the C[++] standards:
[fw/sdcc] / as / z80 / aslist.c
1 /* aslist.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 /*
13  * Extensions: P. Felber
14  */
15
16 #include <stdio.h>
17 #include <setjmp.h>
18 #include <string.h>
19 #include <stdlib.h>
20 #if defined(__APPLE__) && defined(__MACH__)
21 #include <sys/types.h>
22 #include <sys/malloc.h>
23 #else
24 #include <malloc.h>
25 #endif
26
27
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 #ifndef MLH_LST
84 VOID
85 list()
86 {
87         register char *wp;
88         register int *wpt;
89         register int nb;
90
91         if (lfp == NULL || lmode == NLIST)
92                 return;
93
94         /*
95          * Get Correct Line Number
96          */
97         if (incfil >= 0) {
98                 line = incline[incfil];
99                 if (line == 0) {
100                         if (incfil > 0) {
101                                 line = incline[incfil-1];
102                         } else {
103                                 line = srcline[cfile];
104                         }
105                 }
106         } else {
107                 line = srcline[cfile];
108         }
109
110         /*
111          * Move to next line.
112          */
113         slew(lfp, pflag);
114
115         /*
116          * Output a maximum of NERR error codes with listing.
117          */
118         while (ep < &eb[NERR])
119                 *ep++ = ' ';
120         fprintf(lfp, "%.2s", eb);
121
122         /*
123          * Source listing only option.
124          */
125         if (lmode == SLIST) {
126                 fprintf(lfp, "%24s%5u %s\n", "", line, ib);
127                 return;
128         }
129 #ifndef SDK
130         if (lmode == ALIST) {
131                 outchk(HUGE,HUGE);
132         }
133 #endif
134
135         /*
136          * HEX output Option.
137          */
138         if (xflag == 0) {               /* HEX */
139                 /*
140                  * Equate only
141                  */
142                 if (lmode == ELIST) {
143                         fprintf(lfp, "%18s%04X", "", laddr);
144                         fprintf(lfp, "  %5u %s\n", line, ib);
145                         return;
146                 }
147
148                 /*
149                  * Address (with allocation)
150                  */
151                 fprintf(lfp, " %04X", laddr);
152                 if (lmode == ALIST || lmode == BLIST) {
153                         fprintf(lfp, "%19s%5u %s\n", "", line, ib);
154 #ifndef SDK
155                         outdot();
156 #endif
157                         return;
158                 }
159                 wp = cb;
160                 wpt = cbt;
161                 nb = (int) (cp - cb);
162
163                 /*
164                  * First line of output for this source line with data.
165                  */
166                 list1(wp, wpt, nb, 1);
167                 fprintf(lfp, " %5u %s\n", line, ib);
168
169                 /*
170                  * Subsequent lines of output if more data.
171                  */
172                 while ((nb -= 6) > 0) {
173                         wp += 6;
174                         wpt += 6;
175                         slew(lfp, 0);
176                         fprintf(lfp, "%7s", "");
177                         list1(wp, wpt, nb, 0);
178                         putc('\n', lfp);
179                 }
180         } else
181         /*
182          * OCTAL output Option.
183          */
184         if (xflag == 1) {               /* OCTAL */
185                 /*
186                  * Equate only
187                  */
188                 if (lmode == ELIST) {
189                         fprintf(lfp, "%16s%06o", "", laddr);
190                         fprintf(lfp, "  %5u %s\n", line, ib);
191                         return;
192                 }
193
194                 /*
195                  * Address (with allocation)
196                  */
197                 fprintf(lfp, " %06o", laddr);
198                 if (lmode == ALIST || lmode == BLIST) {
199                         fprintf(lfp, "%17s%5u %s\n", "", line, ib);
200 #ifndef SDK
201                         outdot();
202 #endif
203                         return;
204                 }
205                 wp = cb;
206                 wpt = cbt;
207                 nb = (int) (cp - cb);
208
209                 /*
210                  * First line of output for this source line with data.
211                  */
212                 list1(wp, wpt, nb, 1);
213                 fprintf(lfp, " %5u %s\n", line, ib);
214
215                 /*
216                  * Subsequent lines of output if more data.
217                  */
218                 while ((nb -= 4) > 0) {
219                         wp += 4;
220                         wpt += 4;
221                         slew(lfp, 0);
222                         fprintf(lfp, "%9s", "");
223                         list1(wp, wpt, nb, 0);
224                         putc('\n', lfp);
225                 }
226         } else
227         /*
228          * DECIMAL output Option.
229          */
230         if (xflag == 2) {               /* DECIMAL */
231                 /*
232                  * Equate only
233                  */
234                 if (lmode == ELIST) {
235                         fprintf(lfp, "%16s%05u", "", laddr);
236                         fprintf(lfp, "   %5u %s\n", line, ib);
237                         return;
238                 }
239
240                 /*
241                  * Address (with allocation)
242                  */
243                 fprintf(lfp, "  %05u", laddr);
244                 if (lmode == ALIST || lmode == BLIST) {
245                         fprintf(lfp, "%17s%5u %s\n", "", line, ib);
246 #ifndef SDK
247                         outdot();
248 #endif
249                         return;
250                 }
251                 wp = cb;
252                 wpt = cbt;
253                 nb = (int) (cp - cb);
254
255                 /*
256                  * First line of output for this source line with data.
257                  */
258                 list1(wp, wpt, nb, 1);
259                 fprintf(lfp, " %5u %s\n", line, ib);
260
261                 /*
262                  * Subsequent lines of output if more data.
263                  */
264                 while ((nb -= 4) > 0) {
265                         wp += 4;
266                         wpt += 4;
267                         slew(lfp, 0);
268                         fprintf(lfp, "%9s", "");
269                         list1(wp, wpt, nb, 0);
270                         putc('\n', lfp);
271                 }
272         }
273 }
274 #else
275 VOID
276 list()
277 {
278         register char *wp;
279         register int *wpt;
280         register nb;
281
282         if (lfp == NULL || lmode == NLIST)
283                 return;
284
285         /*
286          * Get Correct Line Number
287          */
288         if (incfil >= 0) {
289                 line = incline[incfil];
290                 if (line == 0) {
291                         if (incfil > 0) {
292                                 line = incline[incfil-1];
293                         } else {
294                                 line = srcline[cfile];
295                         }
296                 }
297         } else {
298                 line = srcline[cfile];
299         }
300
301         /*
302          * HEX output Option.
303          */
304                 /* Output filename relative_address line_number */
305
306         if (incfil >= 0) {
307                 fprintf(lfp, "%s ", incfn[incfil]);
308         }
309         else {
310                 fprintf(lfp, "%s ", srcfn[cfile]);
311         }
312         fprintf(lfp, "%u %04X\n", line, laddr);
313 #if 0
314                 wp = cb;
315                 wpt = cbt;
316                 nb = (int) (cp - cb);
317
318                 /*
319                  * First line of output for this source line with data.
320                  */
321                 list1(wp, wpt, nb, 1);
322                 fprintf(lfp, " %5u %s\n", line, ib);
323
324                 /*
325                  * Subsequent lines of output if more data.
326                  */
327                 while ((nb -= 6) > 0) {
328                         wp += 6;
329                         wpt += 6;
330                         slew(lfp, 0);
331                         fprintf(lfp, "%7s", "");
332                         list1(wp, wpt, nb, 0);
333                         putc('\n', lfp);
334                 }
335 #endif
336 }
337 #endif /* MLH_LST */
338
339 /*)Function     VOID    list1(wp, wpt, nw, f)
340  *
341  *              int     f               fill blank fields (1)
342  *              int     nb              number of data bytes
343  *              int *   wp              pointer to data bytes
344  *              int *   wpt             pointer to data byte mode
345  *
346  *      local variables:
347  *              int     i               loop counter
348  *
349  *      global variables:
350  *              int     xflag           -x, listing radix flag
351  *
352  *      functions called:
353  *              VOID    list2()         asslist.c
354  *              int     fprintf()       c_library
355  *
356  *      side effects:
357  *              Data formatted and output to listing.
358  */
359
360 VOID
361 list1(wp, wpt, nb, f)
362 register char *wp;
363 register int *wpt, nb, f;
364 {
365         register int i;
366
367         /*
368          * HEX output Option.
369          */
370         if (xflag == 0) {               /* HEX */
371                 /*
372                  * Bound number of words to HEX maximum per line.
373                  */
374                 if (nb > 6)
375                         nb = 6;
376
377                 /*
378                  * Output bytes.
379                  */
380                 for (i=0; i<nb; ++i) {
381                         list2(*wpt++);
382                         fprintf(lfp, "%02X", (*wp++)&0377);
383                 }
384
385                 /*
386                  * Output blanks if required.
387                  */
388                 if (f) {
389                         while (i < 6) {
390                                 fprintf(lfp, "   ");
391                                 ++i;
392                         }
393                 }
394         } else
395         /*
396          * OCTAL output Option.
397          */
398         if (xflag == 1) {               /* OCTAL */
399                 /*
400                  * Bound number of words to OCTAL maximum per line.
401                  */
402                 if (nb > 4)
403                         nb = 4;
404
405                 /*
406                  * Output bytes.
407                  */
408                 for (i=0; i<nb; ++i) {
409                         list2(*wpt++);
410                         fprintf(lfp, "%03o", (*wp++)&0377);
411                 }
412
413                 /*
414                  * Output blanks if required.
415                  */
416                 if (f) {
417                         while (i < 4) {
418                                 fprintf(lfp, "    ");
419                                 ++i;
420                         }
421                 }
422         } else
423         /*
424          * DECIMAL output Option.
425          */
426         if (xflag == 2) {               /* DECIMAL */
427                 /*
428                  * Bound number of words to DECIMAL maximum per line.
429                  */
430                 if (nb > 4)
431                         nb = 4;
432
433                 /*
434                  * Output bytes.
435                  */
436                 for (i=0; i<nb; ++i) {
437                         list2(*wpt++);
438                         fprintf(lfp, "%03u", (*wp++)&0377);
439                 }
440
441                 /*
442                  * Output blanks if required.
443                  */
444                 if (f) {
445                         while (i < 4) {
446                                 fprintf(lfp, "    ");
447                                 ++i;
448                         }
449                 }
450         }
451 }
452
453 /*)Function     VOID    list2(wpt)
454  *
455  *              int *   wpt             pointer to relocation mode
456  *
457  *      The function list2() outputs the selected
458  *      relocation flag as specified by fflag.
459  *
460  *      local variables:
461  *              int     c               relocation flag character
462  *              int     t               relocation mode
463  *
464  *      global variables:
465  *              int     fflag           -f(f), relocations flagged flag
466  *
467  *      functions called:
468  *              int     putc()          c_library
469  *
470  *      side effects:
471  *              Relocation flag output to listing file.
472  */
473
474 VOID
475 list2(t)
476 register int t;
477 {
478         register int c;
479
480         c = ' ';
481
482         /*
483          * Designate a relocatable word by `.
484          */
485         if (fflag == 1) {
486                 if (t & R_RELOC) {
487                         c = '`';
488                 }
489         } else
490         /*
491          * Designate a relocatable word by its mode:
492          *      page0 or paged          *
493          *      unsigned                u (v)
494          *      operand offset          p (q)
495          *      relocatable symbol      r (s)
496          */
497         if (fflag >= 2) {
498                 if (t & R_RELOC) {
499                         if (t & (R_PAG0|R_PAG)) {
500                                 c = '*';
501                         } else if (t & R_USGN) {
502                                 c = 'u';
503                         } else if (t & R_PCR) {
504                                 c = 'p';
505                         } else {
506                                 c = 'r';
507                         }
508                         if (t & R_HIGH) c += 1;
509                 }
510         }
511
512         /*
513          * Output the selected mode.
514          */
515         putc(c, lfp);
516 }
517
518 /*)Function     VOID    slew(fp, flag)
519  *
520  *              FILE *  fp              file handle for listing
521  *              int     flag            enable pagination
522  *
523  *      The function slew() increments the page line count.
524  *      If the page overflows and pagination is enabled:
525  *              1)      put out a page skip,
526  *              2)      a title,
527  *              3)      a subtitle,
528  *              4)      and reset the line count.
529  *
530  *      local variables:
531  *              none
532  *
533  *      global variables:
534  *              char    cpu[]           cpu type string
535  *              int     lop             current line number on page
536  *              int     page            current page number
537  *              char    stb[]           Subtitle string buffer
538  *              char    tb[]            Title string buffer
539  *
540  *      functions called:
541  *              int     fprintf()       c_library
542  *
543  *      side effects:
544  *              Increments page line counter, on overflow
545  *              a new page header is output to the listing file.
546  */
547
548 VOID
549 slew(fp,flag)
550 FILE *fp;
551 int flag;
552 {
553         if ((lop++ >= NLPP) && flag) {
554                 fprintf(fp, "\fASxxxx Assembler %s  (%s), page %u.\n",
555                         VERSION, cpu, ++page);
556                 fprintf(fp, "%s\n", tb);
557                 fprintf(fp, "%s\n\n", stb);
558                 lop = 5;
559         }
560 }
561
562 /*)Function     VOID    lstsym(fp)
563  *
564  *              FILE *  fp              file handle for output
565  *
566  *      The function lstsym() outputs alphabetically
567  *      sorted symbol and area tables.
568  *
569  *      local variables:
570  *              int     c               temporary
571  *              int     i               loop counter
572  *              int     j               temporary
573  *              int     k               temporary
574  *              char *  ptr             pointer to an id string
575  *              int     nmsym           number of symbols
576  *              int     narea           number of areas
577  *              sym *   sp              pointer to symbol structure
578  *              sym **  p               pointer to an array of
579  *                                      pointers to symbol structures
580  *              area *  ap              pointer to an area structure
581  *
582  *      global variables:
583  *              area *  areap           pointer to an area structure
584  *              char    aretbl[]        string "Area Table"
585  *              sym     dot             defined as sym[0]
586  *              char    stb[]           Subtitle string buffer
587  *              sym * symhash[]         array of pointers to NHASH
588  *                                      linked symbol lists
589  *              char    symtbl[]        string "Symbol Table"
590  *              FILE *  tfp             symbol table output file handle
591  *              int     xflag           -x, listing radix flag
592  *
593  *      functions called:
594  *              int     fprintf()       c_library
595  *              int     putc()          c_library
596  *              VOID    slew()          aslist.c
597  *              int     strcmp()        c_library
598  *              char *  strcpy()        c_library
599  *
600  *      side effects:
601  *              Symbol and area tables output.
602  */
603
604 VOID
605 lstsym(fp)
606 FILE *fp;
607 {
608         register int c, i, j, k;
609         register char *ptr;
610         int nmsym, narea;
611         struct sym *sp;
612         struct sym **p;
613         struct area *ap;
614
615         /*
616          * Symbol Table Header
617          */
618         strcpy(stb, &symtbl[0]);
619         lop = NLPP;
620         if (fp == tfp)
621                 page = 0;
622         slew(fp, 1);
623
624         /*
625          * Find number of symbols
626          */
627         nmsym = 0;
628         for (i=0; i<NHASH; i++) {
629                 sp = symhash[i];
630                 while (sp) {
631                         if (sp != &dot)
632                                 ++nmsym;
633                         sp = sp->s_sp;
634                 }
635         }
636         if (nmsym == 0)
637                 goto atable;
638
639         /*
640          * Allocate space for an array of pointers to symbols
641          * and load array.
642          */
643         if ((p = (struct sym **) malloc(sizeof((struct sym *) sp)*nmsym))
644                 == NULL) {
645                 fprintf(fp, "Insufficient space to build Symbol Table.\n");
646                 return;
647         }
648         nmsym = 0;
649         for (i=0; i<NHASH; i++) {
650                 sp = symhash[i];
651                 while (sp) {
652                         if (sp != &dot)
653                                 p[nmsym++] = sp;
654                         sp = sp->s_sp;
655                 }
656         }
657
658         /*
659          * Bubble Sort on Symbol Table Array
660          */
661         j = 1;
662         c = nmsym - 1;
663         while (j) {
664                 j = 0;
665                 for (i=0; i<c; ++i) {
666                         if (strcmp(&p[i]->s_id[0],&p[i+1]->s_id[0]) > 0) {
667                                 j = 1;
668                                 sp = p[i+1];
669                                 p[i+1] = p[i];
670                                 p[i] = sp;
671                         }
672                 }
673         }
674
675         /*
676          * Symbol Table Output
677          */
678         for (i=0; i<nmsym;) {
679                 sp = p[i];
680                 if (sp->s_area) {
681                         j = sp->s_area->a_ref;
682                         if (xflag == 0) {
683                                 fprintf(fp, " %2X ", j);
684                         } else
685                         if (xflag == 1) {
686                                 fprintf(fp, "%3o ", j);
687                         } else
688                         if (xflag == 2) {
689                                 fprintf(fp, "%3u ", j);
690                         }
691                 } else {
692                         fprintf(fp, "    ");
693                 }
694                 ptr = &sp->s_id[0];
695                 while (ptr < &sp->s_id[NCPS]) {
696                         if ((c = *ptr++) != 0) {
697                                 putc(c, fp);
698                         } else {
699                                 putc(' ', fp);
700                         }
701                 }
702                 if (sp->s_flag & S_ASG) {
703                         putc('=', fp);
704                 } else {
705                         putc(' ', fp);
706                 }
707                 if (sp->s_type == S_NEW) {
708                         if (xflag == 0) {
709                                 fprintf(fp, "  **** ");
710                         } else
711                         if (xflag == 1) {
712                                 fprintf(fp, "****** ");
713                         } else
714                         if (xflag == 2) {
715                                 fprintf(fp, " ***** ");
716                         }
717                 } else {
718                         j = sp->s_addr;
719                         if (xflag == 0) {
720                                 fprintf(fp, "  %04X ", j);
721                         } else
722                         if (xflag == 1) {
723                                 fprintf(fp, "%06o ", j);
724                         } else
725                         if (xflag == 2) {
726                                 fprintf(fp, " %05u ", j);
727                         }
728                 }
729                 j = 0;
730                 if (sp->s_flag & S_GBL) {
731                         putc('G', fp);
732                         ++j;
733                 }
734                 if (sp->s_area != NULL) {
735                         putc('R', fp);
736                         ++j;
737                 }
738                 if (sp->s_type == S_NEW) {
739                         putc('X', fp);
740                         ++j;
741                 }
742 #if NCPS-8
743                 putc('\n', fp);
744                 slew(fp, 0);
745                 ++i;
746 #else
747                 if (++i % 3 == 0) {
748                         putc('\n', fp);
749                         slew(fp, pflag);
750                 } else
751                 if (i < nmsym) {
752                         while (j++ < 4)
753                                 putc(' ', fp);
754                         fprintf(fp, "| ");
755                 }
756 #endif
757         }
758         putc('\n', fp);
759
760         /*
761          * Area Table Header
762          */
763
764 atable:
765         strcpy(stb, &aretbl[0]);
766         lop = NLPP;
767         slew(fp, 1);
768
769         /*
770          * Area Table Output
771          */
772         narea = 0;
773         ap = areap;
774         while (ap) {
775                 ++narea;
776                 ap = ap->a_ap;
777         }
778         for (i=0; i<narea; ++i) {
779                 ap = areap;
780                 for (j=i+1; j<narea; ++j)
781                         ap = ap->a_ap;
782                 j = ap->a_ref;
783                 if (xflag == 0) {
784                         fprintf(fp, "  %2X ", j);
785                 } else
786                 if (xflag == 1) {
787                         fprintf(fp, " %3o ", j);
788                 } else
789                 if (xflag == 2) {
790                         fprintf(fp, " %3u ", j);
791                 }
792                 ptr = &ap->a_id[0];
793                 while (ptr < &ap->a_id[NCPS]) {
794                         if ((c = *ptr++) != 0) {
795                                 putc(c, fp);
796                         } else {
797                                 putc(' ', fp);
798                         }
799                 }
800                 j = ap->a_size;
801                 k = ap->a_flag;
802                 if (xflag==0) {
803                         fprintf(fp, "   size %4X   flags %X\n", j, k);
804                 } else
805                 if (xflag==1) {
806                         fprintf(fp, "   size %6o   flags %o\n", j, k);
807                 } else
808                 if (xflag==2) {
809                         fprintf(fp, "   size %5u   flags %u\n", j, k);
810                 }
811         }               
812 }