* listing.c, config/obj-aout.c: added intermixed
[external/binutils.git] / gas / listing.c
1 /* listing.c - mainting assembly listings
2    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING.  If not, write to
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
19
20 /*
21  Contributed by Steve Chamberlain
22                 sac@cygnus.com
23
24
25  A listing page looks like:
26  
27  LISTING_HEADER  sourcefilename pagenumber
28  TITLE LINE
29  SUBTITLE LINE
30  linenumber address data  source
31  linenumber address data  source
32  linenumber address data  source
33  linenumber address data  source
34
35  If not overridden, the listing commands are:
36
37  .title  "stuff" 
38         Put "stuff" onto the title line 
39  .sbttl  "stuff"
40         Put stuff onto the subtitle line
41
42   If these commands come within 10 lines of the top of the page, they
43   will affect the page they are on, as well as any subsequent page
44
45  .eject
46         Thow a page
47  .list
48         Increment the enable listing counter
49  .nolist
50         Decrement the enable listing counter
51
52  .psize Y[,X]
53         Set the paper size to X wide and Y high. Setting a psize Y of
54         zero will suppress form feeds except where demanded by .eject
55
56  If the counter goes below zero, listing is suppressed. 
57
58
59  Listings are a maintained by read calling various listing_<foo>
60  functions.  What happens most is that the macro NO_LISTING is not
61  defined (from the Makefile), then the macro LISTING_NEWLINE expands
62  into a call to listing_newline.  The call is done from read.c, every
63  time it sees a newline, and -l is on the command line.
64
65  The function listing_newline remembers the frag associated with the
66  newline, and creates a new frag - note that this is wasteful, but not
67  a big deal, since listing slows things down a lot anyway.  The
68  function also rememebers when the filename changes.
69
70  When all the input has finished, and gas has had a chance to settle
71  down, the listing is output. This is done by running down the list of
72  frag/source file records, and opening the files as needed and printing
73  out the bytes and chars associated with them.
74
75  The only things which the architecture can change about the listing
76  are defined in these macros:
77
78  LISTING_HEADER         The name of the architecture
79  LISTING_WORD_SIZE      The make of the number of bytes in a word, this determines
80                         the clumping of the output data. eg a value of
81                         2 makes words look like 1234 5678, whilst 1
82                         would make the same value look like 12 34 56
83                         78
84  LISTING_LHS_WIDTH      Number of words of above size for the lhs
85
86  LISTING_LHS_WIDTH_SECOND   Number of words for the data on the lhs
87                         for the second line
88
89  LISTING_LHS_CONT_LINES Max number of lines to use up for a continutation
90  LISTING_RHS_WIDTH      Number of chars from the input file to print
91                         on a line
92 */
93
94 #include "as.h"
95 #include <obstack.h>
96 #include "input-file.h"
97 #include "targ-cpu.h"
98
99 #ifndef NO_LISTING
100 #ifndef LISTING_HEADER
101 #define LISTING_HEADER "GAS LISTING"
102 #endif
103 #ifndef LISTING_WORD_SIZE
104 #define LISTING_WORD_SIZE 4
105 #endif
106 #ifndef LISTING_LHS_WIDTH
107 #define LISTING_LHS_WIDTH 1
108 #endif
109 #ifndef LISTING_LHS_WIDTH_SECOND
110 #define LISTING_LHS_WIDTH_SECOND 1
111 #endif
112 #ifndef LISTING_RHS_WIDTH
113 #define LISTING_RHS_WIDTH 100
114 #endif
115 #ifndef LISTING_LHS_CONT_LINES 
116 #define LISTING_LHS_CONT_LINES 4
117 #endif
118
119
120
121
122 /* This structure remembers which .s were used */
123 typedef struct file_info_struct 
124 {
125   char *filename;
126   int linenum;
127   FILE *file;
128   struct file_info_struct *next;
129 } file_info_type ;
130
131   
132 /* this structure rememebrs which line from which file goes into which
133    frag */
134 typedef struct list_info_struct
135 {
136   /* Frag which this line of source is nearest to */
137   fragS *frag;
138   /* The actual line in the source file */
139   unsigned int line;
140   /* Pointer to the file info struct for the file which this line
141      belongs to */
142   file_info_type *file;
143
144   /* Next in list */
145   struct list_info_struct *next;
146
147
148   /* Pointer to the file info struct for the high level language
149      source line that belongs here */
150   file_info_type *hll_file;
151   
152   /* High level language source line */
153   unsigned int hll_line;
154   
155
156   /* Pointer to any error message associated with this line */
157   char *message;
158   
159   enum 
160   {
161     EDICT_NONE,
162     EDICT_SBTTL,
163     EDICT_TITLE,
164     EDICT_NOLIST,
165     EDICT_LIST,
166     EDICT_EJECT 
167    } edict;
168   char *edict_arg;
169   
170 } list_info_type;
171
172
173 static struct list_info_struct *head;
174 struct list_info_struct *listing_tail;
175 extern int listing;
176 extern unsigned int  physical_input_line;
177 extern fragS *frag_now;
178
179
180 static int paper_width = 200;
181 static int paper_height = 60;
182
183
184 /* this static array is used to keep the text of data to be printed
185    before the start of the line.
186     It is stored so we can give a bit more info on the next line.  To much, and large
187    initialized arrays will use up lots of paper.
188  */
189
190 static char data_buffer[100];
191 static unsigned int data_buffer_size;
192
193                    
194 static void
195 DEFUN(listing_message,(name, message),
196       char *name AND
197       char *message)
198 {
199   unsigned int l = strlen(name) + strlen(message)+1;
200   char *n =  malloc(l);
201   strcpy(n,name);
202   strcat(n,message);
203   if(listing_tail != (list_info_type *)NULL) 
204   {
205     listing_tail->message = n;
206   }
207   
208 }
209
210
211
212
213 void 
214 DEFUN(listing_warning,(message),
215       char *message)
216 {
217   listing_message("Warning:", message);
218 }
219
220 void 
221 DEFUN(listing_error,(message),
222       char *message)
223 {
224   listing_message("Error:", message);
225 }
226
227
228
229
230 static file_info_type *file_info_head;
231
232 static file_info_type *
233 DEFUN(file_info, (file_name),
234            char *file_name)
235 {
236   /* Find an entry with this file name */
237   file_info_type *p = file_info_head;
238   
239   while (p != (file_info_type *)NULL) 
240   {
241     if (strcmp(p->filename, file_name) == 0)
242      return p;
243     p = p->next;  
244   }
245
246   /* Make new entry */
247
248   p = (file_info_type *)xmalloc(sizeof(file_info_type));
249   p->next = file_info_head;
250   file_info_head = p;
251   p->filename = xmalloc(strlen(file_name)+1);
252   strcpy(p->filename, file_name);
253   p->linenum = 0;
254   p->file = fopen(p->filename,"r");
255   return p;
256   
257 }
258
259
260 static void 
261 DEFUN_VOID(new_frag)
262 {
263   
264     frag_wane(frag_now);
265     frag_new(0);
266
267 }
268
269 void 
270 DEFUN(listing_newline,(ps),
271       char *ps)
272 {
273   char *s = ps;
274   extern char *file_name;
275   static unsigned int last_line =0xffff ;  
276
277   
278   list_info_type *new;
279   if (physical_input_line != last_line) 
280   {
281     last_line = physical_input_line;
282     new_frag();
283     
284     new  = (list_info_type *)malloc(sizeof(list_info_type));
285     new->frag = frag_now;
286     new->line = physical_input_line ;
287     new->file = file_info(file_name);
288     
289     if (listing_tail) 
290     {
291       listing_tail->next = new;
292     }
293     else 
294     {
295       head = new;
296     }
297     listing_tail = new;
298     new->next = (list_info_type *)NULL;
299     new->message = (char *)NULL;
300     new->edict = EDICT_NONE;    
301     new_frag();
302   }  
303 }
304
305
306
307
308 static char *
309 DEFUN(buffer_line,(file, line, size),
310       file_info_type *file AND
311       char *line AND
312       unsigned int size)
313 {
314   unsigned int count = 0;
315   int c;
316   
317   char *p = line;
318   if  (file->file == (FILE*)NULL) 
319   {
320     return "";
321   }
322   
323   c = fgetc(file->file);
324   size -= 1;                    /* leave room for null */
325   while (c != EOF && c != '\n') 
326   {
327     if (count < size) 
328      *p++ = c;
329     count++;
330     
331     c= fgetc(file->file);
332   }
333   if (c == EOF) 
334   {
335     rewind(file->file);
336     file->linenum = 0;
337     
338   }
339   file->linenum++;  
340   *p++ = 0;
341   return line;
342 }
343
344
345 static char *fn;
346
347 static unsigned int eject;      /* Eject pending */
348 static unsigned int page;       /* Current page number */
349 static char *title;             /* current title */
350 static char *subtitle;          /* current subtitle */
351 static unsigned int on_page;    /* number of lines printed on current page */
352
353
354 static void
355 DEFUN(listing_page,(list),
356     list_info_type *list)
357 {
358   /* Grope around, see if we can see a title or subtitle edict coming up
359      soon  (we look down 10 lines of the page and see if it's there)*/
360   if ((eject || (on_page >= paper_height)) && paper_height != 0) 
361   {
362     unsigned int c = 10;
363     int had_title = 0;
364     int had_subtitle = 0;
365
366     page++;
367   
368     while (c != 0 && list) 
369     {
370       if (list->edict == EDICT_SBTTL && !had_subtitle) 
371       {
372         had_subtitle = 1;
373         subtitle = list->edict_arg;
374       }
375       if (list->edict == EDICT_TITLE && !had_title) 
376       {
377         had_title = 1;
378         title = list->edict_arg;
379       }
380       list = list->next;
381       c--;
382     }    
383       
384
385     if (page > 1) 
386     {
387       printf("\f");
388     }
389   
390     printf("%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
391     printf("%s\n", title);
392     printf("%s\n", subtitle);
393     on_page = 3;
394     eject = 0;
395   }
396 }
397
398
399 static unsigned int 
400 DEFUN(calc_hex,(list),
401       list_info_type *list)
402 {
403   list_info_type *first = list;
404   list_info_type *last = first;
405   unsigned int address = ~0;
406   
407   fragS *frag;
408   fragS *frag_ptr;
409
410   unsigned    int    byte_in_frag = 0;
411   
412   int anything = 0;      
413
414   /* Find first frag which says it belongs to this line */
415   frag = list->frag; 
416   while (frag  && frag->line != list) 
417    frag = frag->fr_next;
418
419   frag_ptr = frag;
420
421   data_buffer_size = 0;
422   
423   /* Dump all the frags which belong to this line */
424   while (frag_ptr != (fragS *)NULL  && frag_ptr->line == first)
425   {
426     /* Print as many bytes from the fixed part as is sensible */
427     while(byte_in_frag < frag_ptr->fr_fix && data_buffer_size < sizeof(data_buffer)-10)
428     {
429       if (address == ~0)
430       {
431         address = frag_ptr->fr_address;
432       }
433              
434       sprintf(data_buffer + data_buffer_size, "%02X",(frag_ptr->fr_literal[byte_in_frag]) & 0xff);
435       data_buffer_size += 2;
436       byte_in_frag++;
437     }
438     /* Print as many bytes from the variable part as is sensible */
439     while (byte_in_frag < frag_ptr->fr_var * frag_ptr->fr_offset 
440            && data_buffer_size < sizeof(data_buffer)-10)
441     {
442       if (address == ~0)
443       {
444         address =  frag_ptr->fr_address;
445       }
446       data_buffer[data_buffer_size++] = '*';
447       data_buffer[data_buffer_size++] = '*';
448       
449       byte_in_frag++;
450     }
451     frag_ptr = frag_ptr->fr_next;
452   }
453   data_buffer[data_buffer_size++] = 0;
454   return address;
455 }
456
457
458
459
460
461
462 static void
463 DEFUN(print_lines,(list, string, address),
464 list_info_type *list AND
465 char *string AND
466 unsigned int address)
467 {
468   unsigned int idx;
469   unsigned int nchars;
470   unsigned int lines;
471   unsigned int byte_in_word =0;
472   char *src = data_buffer;
473   
474   /* Print the stuff on the first line */
475   listing_page(list);
476   nchars = (LISTING_WORD_SIZE*2 +1)  * LISTING_LHS_WIDTH ;
477   /* Print the hex for the first line */
478   if (address == ~0)  
479   {
480     printf("% 4d     ", list->line);
481     for (idx = 0; idx < nchars; idx++)
482      printf(" ");
483     
484     printf("\t%s\n", string ? string : "");
485     on_page++;
486     listing_page(0);
487     
488   }
489   else 
490   {
491     if (had_errors()) 
492     {
493       printf("% 4d ???? ", list->line);
494     }
495     else 
496     {
497     printf("% 4d %04x ", list->line, address);
498   }
499     
500     /* And the data to go along with it */
501     idx = 0;
502     
503     while (*src && idx < nchars)
504     {
505       printf("%c%c", src[0], src[1]);
506       src += 2;
507       byte_in_word++;
508       if (byte_in_word == LISTING_WORD_SIZE)  
509       {
510         printf(" ");
511         idx++;
512         byte_in_word = 0;
513       }
514       idx+=2;
515     }       
516
517     for (;idx < nchars; idx++) 
518      printf(" ");
519   
520     printf("\t%s\n", string ? string : "");
521     on_page++;
522     listing_page(list);  
523     if (list->message) 
524     {
525       printf("****  %s\n",list->message);
526       listing_page(list);
527       on_page++;
528     }
529
530     for (lines = 0;
531          lines < LISTING_LHS_CONT_LINES 
532          && *src;
533          lines++) {
534         nchars = ((LISTING_WORD_SIZE*2) +1)  * LISTING_LHS_WIDTH_SECOND -1;
535         idx = 0;
536         /* Print any more lines of data, but more compactly */
537         printf("% 4d      ", list->line);
538   
539         while (*src && idx < nchars)
540         {
541           printf("%c%c", src[0], src[1]);
542           src+=2;
543           idx+=2;
544           byte_in_word++;
545           if (byte_in_word == LISTING_WORD_SIZE)  
546           {
547             printf(" ");
548             idx++;
549             byte_in_word = 0;
550           }
551         }
552         
553         printf("\n");
554         on_page++;
555         listing_page(list);
556         
557       }
558     
559
560   }
561 }
562
563   
564   
565   
566
567
568 static void
569 DEFUN_VOID(list_symbol_table)
570 {
571   extern symbolS *symbol_rootP;
572   
573   symbolS *ptr ;
574   eject = 1;
575   listing_page(0);
576   printf("DEFINED SYMBOLS\n");
577   on_page++;
578   
579   for (ptr = symbol_rootP; ptr != (symbolS*)NULL; ptr = symbol_next(ptr))
580   {
581     if (ptr->sy_frag->line) 
582     {
583      printf("%20s:%-5d  %2d:%08x %s \n",
584              ptr->sy_frag->line->file->filename,
585              ptr->sy_frag->line->line,
586              S_GET_SEGMENT(ptr),
587              S_GET_VALUE(ptr),
588              S_GET_NAME(ptr));
589       on_page++;
590       listing_page(0);
591       
592     }
593
594   }
595   printf("\n");
596   on_page++;
597   listing_page(0);
598   printf("UNDEFINED SYMBOLS\n");
599   on_page++;
600   listing_page(0);
601   
602   for (ptr = symbol_rootP; ptr != (symbolS*)NULL; ptr = symbol_next(ptr))
603   {
604     if (strlen(S_GET_NAME(ptr)) != 0) 
605     {
606       if (ptr->sy_frag->line == 0) 
607       {
608       
609         printf("%s\n",       S_GET_NAME(ptr));
610         on_page++;
611         listing_page(0);
612       }
613     }
614   }
615 }
616
617 void 
618 DEFUN(print_source,(current_file, list, buffer, width),
619       file_info_type *current_file AND
620       list_info_type *list AND
621       char *buffer AND
622       unsigned int width)
623 {
624   if (current_file->file) {  
625       while (current_file->linenum < list->hll_line)
626       {
627         char*    p = buffer_line(current_file, buffer, width);
628         printf("%4d:%-13s **** %s\n", current_file->linenum,  current_file->filename, p);
629         on_page++;
630         listing_page(list);     
631       }
632     }
633 }
634
635 void 
636 DEFUN(listing_listing,(name),
637       char *name)
638 {
639   list_info_type *list = head;
640   file_info_type *current_hll_file = (file_info_type *)NULL;
641   
642   unsigned  int page= 1;
643   unsigned int prev  = 0;
644   char *message;
645   char *buffer;
646   char *p;
647   unsigned int addr = 0;  
648   int on_page = 0;
649   int show_listing = 1;
650   unsigned int width;
651   
652   buffer = malloc(LISTING_RHS_WIDTH);
653   eject = 1;
654   list = head;
655
656   while (list != (list_info_type *)NULL && 0) 
657   {
658     if (list->next)
659      list->frag = list->next->frag;  
660     list = list->next;
661
662   }
663   
664   list = head->next;
665
666
667   while ( list)
668   {
669     width =  LISTING_RHS_WIDTH > paper_width ?  paper_width :
670      LISTING_RHS_WIDTH;
671     
672      switch (list->edict) {
673        case EDICT_LIST:
674          show_listing++;
675          break;
676        case EDICT_NOLIST:
677          show_listing--;
678          break;
679        case EDICT_EJECT:
680          break;
681        case EDICT_NONE:
682          break;
683        case EDICT_TITLE:
684          title = list->edict_arg;
685          break;
686        case EDICT_SBTTL:
687          subtitle = list->edict_arg;
688          break;
689        default:
690          abort();
691        }
692     
693     if (show_listing > 0) 
694     {
695       /* Scan down the list and print all the stuff which can be done
696          with this line (or lines) */
697       message = 0;
698
699       if (list->hll_file) 
700       {
701         current_hll_file = list->hll_file;
702       }
703
704       if (current_hll_file && list->hll_line && listing & LISTING_HLL)
705       {
706         print_source(current_hll_file, list, buffer, width);
707       }
708    
709       p = buffer_line(list->file, buffer, width);      
710
711       print_lines(list, p,      calc_hex(list));
712
713       if (list->edict == EDICT_EJECT) 
714       {
715         eject = 1;
716       }    
717     }
718     else 
719     {
720          
721       p = buffer_line(list->file, buffer, width);      
722     }
723     
724     list = list->next;
725   }
726   free(buffer);
727 }
728
729 void 
730 DEFUN(listing_print,(name),
731       char *name)
732 {
733   title = "";
734   subtitle = "";  
735   
736   if (listing & LISTING_NOFORM) 
737   {
738     paper_height = 0;
739   }
740   
741   if (listing & LISTING_LISTING) 
742   {
743     listing_listing(name);
744     
745   }
746   if (listing & LISTING_SYMBOLS) 
747   {
748     list_symbol_table();
749   }
750 }  
751
752
753 void
754 DEFUN(listing_file,(name),
755 char *name)
756 {
757   fn = name;  
758 }
759
760 void 
761 DEFUN_VOID(listing_eject)
762 {
763   listing_tail->edict = EDICT_EJECT;  
764 }
765
766 void
767 DEFUN_VOID(listing_flags)
768 {
769   
770 }
771 void
772 DEFUN(listing_list,(on),
773            unsigned int on)
774 {
775   listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST;
776 }
777
778
779 void
780 DEFUN_VOID(listing_psize)
781 {
782   paper_height = get_absolute_expression();
783
784   if (paper_height < 0 || paper_height > 1000) 
785   {
786     paper_height = 0;
787     as_warn("strantge paper height, set to no form");
788   }
789  if (*input_line_pointer == ',') 
790   {
791     input_line_pointer++;
792     paper_width = get_absolute_expression();
793   }
794 }
795
796
797 void
798 DEFUN(listing_title,(depth),
799       unsigned int depth)
800 {
801   char *start;
802   char *title;
803   unsigned int length;
804   
805   SKIP_WHITESPACE();
806   if (*input_line_pointer=='\"') {
807       input_line_pointer++;
808       start = input_line_pointer;
809   
810       while (*input_line_pointer) 
811       {
812         if (*input_line_pointer == '\"') 
813         {
814           length = input_line_pointer - start;
815           title = malloc(length + 1);
816           memcpy(title, start, length);
817           title[length] = 0;
818           listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
819           listing_tail->edict_arg = title;
820           input_line_pointer++;
821           demand_empty_rest_of_line();
822           return;      
823         }
824         else if (*input_line_pointer == '\n') 
825         {
826           as_bad("New line in title");
827           demand_empty_rest_of_line();
828           return;
829         }
830         else 
831         {
832           input_line_pointer++;
833         }
834       }
835     }
836   else 
837   {
838     as_bad("expecting title in quotes");
839   }
840 }
841
842
843
844 void
845 DEFUN(listing_source_line,(line),
846            unsigned int line)
847 {
848   new_frag();
849   listing_tail->hll_line = line;
850   new_frag();
851   
852 }
853
854 void
855 DEFUN(listing_source_file,(file),
856          char *file)
857 {
858   listing_tail->hll_file = file_info(file);
859 }
860
861
862            
863 #else
864
865
866 /* Dummy functions for when compiled without listing enabled */
867
868 void 
869 DEFUN_VOID(listing_flags)
870 {
871   s_ignore();  
872 }
873
874 void DEFUN_VOID(listing_list)
875 {
876   s_ignore();  
877 }
878
879 void DEFUN_VOID(listing_eject)
880 {
881   s_ignore();  
882 }
883 void DEFUN(listing_psize)
884 {
885   s_ignore();
886 }
887
888 void DEFUN(listing_title, (depth),
889 unsigned int depth)
890 {
891   s_ignore();  
892 }
893 void
894 DEFUN(listing_file,(name),
895 char *name)
896 {
897
898 }
899
900 void DEFUN(listing_newline,(name),
901 char *name)
902 {
903   
904 }
905
906 void DEFUN(listing_source_line,(n),
907 unsigned int n)
908 {
909   
910 }
911 void DEFUN(listing_source_file, (n),
912 char *n)
913 {
914   
915 }
916
917
918
919 #endif
920