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