Don't crash if a symbol has no name
[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       if (strlen(S_GET_NAME(ptr))) 
584       {
585         printf("%20s:%-5d  %2d:%08x %s \n",
586                ptr->sy_frag->line->file->filename,
587                ptr->sy_frag->line->line,
588                S_GET_SEGMENT(ptr),
589                S_GET_VALUE(ptr),
590                S_GET_NAME(ptr));
591
592         on_page++;
593         listing_page(0);
594       }      
595     }
596
597   }
598   printf("\n");
599   on_page++;
600   listing_page(0);
601   printf("UNDEFINED SYMBOLS\n");
602   on_page++;
603   listing_page(0);
604   
605   for (ptr = symbol_rootP; ptr != (symbolS*)NULL; ptr = symbol_next(ptr))
606   {
607     if (ptr && strlen(S_GET_NAME(ptr)) != 0) 
608     {
609       if (ptr->sy_frag->line == 0) 
610       {
611         printf("%s\n",       S_GET_NAME(ptr));
612         on_page++;
613         listing_page(0);
614       }
615     }
616   }
617 }
618
619 void 
620 DEFUN(print_source,(current_file, list, buffer, width),
621       file_info_type *current_file AND
622       list_info_type *list AND
623       char *buffer AND
624       unsigned int width)
625 {
626   if (current_file->file) {  
627       while (current_file->linenum < list->hll_line)
628       {
629         char*    p = buffer_line(current_file, buffer, width);
630         printf("%4d:%-13s **** %s\n", current_file->linenum,  current_file->filename, p);
631         on_page++;
632         listing_page(list);     
633       }
634     }
635 }
636
637 void 
638 DEFUN(listing_listing,(name),
639       char *name)
640 {
641   list_info_type *list = head;
642   file_info_type *current_hll_file = (file_info_type *)NULL;
643   
644   unsigned  int page= 1;
645   unsigned int prev  = 0;
646   char *message;
647   char *buffer;
648   char *p;
649   unsigned int addr = 0;  
650   int on_page = 0;
651   int show_listing = 1;
652   unsigned int width;
653   
654   buffer = malloc(LISTING_RHS_WIDTH);
655   eject = 1;
656   list = head;
657
658   while (list != (list_info_type *)NULL && 0) 
659   {
660     if (list->next)
661      list->frag = list->next->frag;  
662     list = list->next;
663
664   }
665   
666   list = head->next;
667
668
669   while ( list)
670   {
671     width =  LISTING_RHS_WIDTH > paper_width ?  paper_width :
672      LISTING_RHS_WIDTH;
673     
674      switch (list->edict) {
675        case EDICT_LIST:
676          show_listing++;
677          break;
678        case EDICT_NOLIST:
679          show_listing--;
680          break;
681        case EDICT_EJECT:
682          break;
683        case EDICT_NONE:
684          break;
685        case EDICT_TITLE:
686          title = list->edict_arg;
687          break;
688        case EDICT_SBTTL:
689          subtitle = list->edict_arg;
690          break;
691        default:
692          abort();
693        }
694     
695     if (show_listing > 0) 
696     {
697       /* Scan down the list and print all the stuff which can be done
698          with this line (or lines) */
699       message = 0;
700
701       if (list->hll_file) 
702       {
703         current_hll_file = list->hll_file;
704       }
705
706       if (current_hll_file && list->hll_line && listing & LISTING_HLL)
707       {
708         print_source(current_hll_file, list, buffer, width);
709       }
710    
711       p = buffer_line(list->file, buffer, width);      
712
713       print_lines(list, p,      calc_hex(list));
714
715       if (list->edict == EDICT_EJECT) 
716       {
717         eject = 1;
718       }    
719     }
720     else 
721     {
722          
723       p = buffer_line(list->file, buffer, width);      
724     }
725     
726     list = list->next;
727   }
728   free(buffer);
729 }
730
731 void 
732 DEFUN(listing_print,(name),
733       char *name)
734 {
735   title = "";
736   subtitle = "";  
737   
738   if (listing & LISTING_NOFORM) 
739   {
740     paper_height = 0;
741   }
742   
743   if (listing & LISTING_LISTING) 
744   {
745     listing_listing(name);
746     
747   }
748   if (listing & LISTING_SYMBOLS) 
749   {
750     list_symbol_table();
751   }
752 }  
753
754
755 void
756 DEFUN(listing_file,(name),
757 char *name)
758 {
759   fn = name;  
760 }
761
762 void 
763 DEFUN_VOID(listing_eject)
764 {
765   listing_tail->edict = EDICT_EJECT;  
766 }
767
768 void
769 DEFUN_VOID(listing_flags)
770 {
771   
772 }
773 void
774 DEFUN(listing_list,(on),
775            unsigned int on)
776 {
777   listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST;
778 }
779
780
781 void
782 DEFUN_VOID(listing_psize)
783 {
784   paper_height = get_absolute_expression();
785
786   if (paper_height < 0 || paper_height > 1000) 
787   {
788     paper_height = 0;
789     as_warn("strantge paper height, set to no form");
790   }
791  if (*input_line_pointer == ',') 
792   {
793     input_line_pointer++;
794     paper_width = get_absolute_expression();
795   }
796 }
797
798
799 void
800 DEFUN(listing_title,(depth),
801       unsigned int depth)
802 {
803   char *start;
804   char *title;
805   unsigned int length;
806   
807   SKIP_WHITESPACE();
808   if (*input_line_pointer=='\"') {
809       input_line_pointer++;
810       start = input_line_pointer;
811   
812       while (*input_line_pointer) 
813       {
814         if (*input_line_pointer == '\"') 
815         {
816           length = input_line_pointer - start;
817           title = malloc(length + 1);
818           memcpy(title, start, length);
819           title[length] = 0;
820           listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
821           listing_tail->edict_arg = title;
822           input_line_pointer++;
823           demand_empty_rest_of_line();
824           return;      
825         }
826         else if (*input_line_pointer == '\n') 
827         {
828           as_bad("New line in title");
829           demand_empty_rest_of_line();
830           return;
831         }
832         else 
833         {
834           input_line_pointer++;
835         }
836       }
837     }
838   else 
839   {
840     as_bad("expecting title in quotes");
841   }
842 }
843
844
845
846 void
847 DEFUN(listing_source_line,(line),
848            unsigned int line)
849 {
850   new_frag();
851   listing_tail->hll_line = line;
852   new_frag();
853   
854 }
855
856 void
857 DEFUN(listing_source_file,(file),
858          char *file)
859 {
860   listing_tail->hll_file = file_info(file);
861 }
862
863
864            
865 #else
866
867
868 /* Dummy functions for when compiled without listing enabled */
869
870 void 
871 DEFUN_VOID(listing_flags)
872 {
873   s_ignore();  
874 }
875
876 void DEFUN_VOID(listing_list)
877 {
878   s_ignore();  
879 }
880
881 void DEFUN_VOID(listing_eject)
882 {
883   s_ignore();  
884 }
885 void DEFUN(listing_psize)
886 {
887   s_ignore();
888 }
889
890 void DEFUN(listing_title, (depth),
891 unsigned int depth)
892 {
893   s_ignore();  
894 }
895 void
896 DEFUN(listing_file,(name),
897 char *name)
898 {
899
900 }
901
902 void DEFUN(listing_newline,(name),
903 char *name)
904 {
905   
906 }
907
908 void DEFUN(listing_source_line,(n),
909 unsigned int n)
910 {
911   
912 }
913 void DEFUN(listing_source_file, (n),
914 char *n)
915 {
916   
917 }
918
919
920
921 #endif
922