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