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