* as.c: change -l to -a[lsn], to avoid conflict with 68000
[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 files 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 any error message associated with this line */
149   char *message;
150   
151   enum 
152   {
153     EDICT_NONE,
154     EDICT_SBTTL,
155     EDICT_TITLE,
156     EDICT_NOLIST,
157     EDICT_LIST,
158     EDICT_EJECT 
159    } edict;
160   char *edict_arg;
161   
162 } list_info_type;
163
164
165 static struct list_info_struct *head;
166 struct list_info_struct *listing_tail;
167 extern int listing;
168 extern unsigned int  physical_input_line;
169 extern fragS *frag_now;
170
171
172 static int paper_width = 200;
173 static int paper_height = 60;
174
175
176 /* this static array is used to keep the text of data to be printed
177    before the start of the line.
178     It is stored so we can give a bit more info on the next line.  To much, and large
179    initialized arrays will use up lots of paper.
180  */
181
182 static char data_buffer[100];
183 static unsigned int data_buffer_size;
184
185                    
186 static void
187 DEFUN(listing_message,(name, message),
188       char *name AND
189       char *message)
190 {
191   unsigned int l = strlen(name) + strlen(message)+1;
192   char *n =  malloc(l);
193   strcpy(n,name);
194   strcat(n,message);
195   if(listing_tail != (list_info_type *)NULL) 
196   {
197     listing_tail->message = n;
198   }
199   
200 }
201
202
203
204
205 void 
206 DEFUN(listing_warning,(message),
207       char *message)
208 {
209   listing_message("Warning:", message);
210 }
211
212 void 
213 DEFUN(listing_error,(message),
214       char *message)
215 {
216   listing_message("Error:", message);
217 }
218
219
220
221  extern char *file_name;
222 static file_info_type *file_info_head;
223
224 static file_info_type *
225 DEFUN_VOID(file_info)
226 {
227   /* Find an entry with this file name */
228   file_info_type *p = file_info_head;
229   
230   while (p != (file_info_type *)NULL) 
231   {
232     if (strcmp(p->filename, file_name) == 0)
233      return p;
234     p = p->next;  
235   }
236
237   /* Make new entry */
238
239   p = (file_info_type *)xmalloc(sizeof(file_info_type));
240   p->next = file_info_head;
241   file_info_head = p;
242   p->filename = xmalloc(strlen(file_name)+1);
243   strcpy(p->filename, file_name);
244   p->linenum = 0;
245   p->file = fopen(p->filename,"r");
246   return p;
247   
248 }
249
250
251 void 
252 DEFUN(listing_newline,(ps),
253       char *ps)
254 {
255   char *s = ps;
256
257   static unsigned int last_line =0xffff ;  
258
259   
260   list_info_type *new;
261   if (physical_input_line != last_line) 
262   {
263     last_line = physical_input_line;
264     frag_wane(frag_now);
265     frag_new(0);
266     new  = (list_info_type *)malloc(sizeof(list_info_type));
267     new->frag = frag_now;
268     new->line = physical_input_line ;
269     new->file = file_info();
270     
271     if (listing_tail) 
272     {
273       listing_tail->next = new;
274     }
275     else 
276     {
277       head = new;
278     }
279     listing_tail = new;
280     new->next = (list_info_type *)NULL;
281     new->message = (char *)NULL;
282     new->edict = EDICT_NONE;    
283     frag_wane(frag_now);
284     frag_new(0);
285   }  
286 }
287
288
289
290
291 static char *
292 DEFUN(buffer_line,(ptr,line, size),
293       list_info_type *ptr AND
294       char *line AND
295       unsigned int size)
296 {
297   unsigned int count = 0;
298   char *p = line;
299   int c = fgetc(ptr->file->file);
300   size -= 1;                    /* leave room for null */
301   while (c != EOF && c != '\n') 
302   {
303     if (count < size) 
304      *p++ = c;
305     count++;
306     
307     c= fgetc(ptr->file->file);
308   }
309   if (c == EOF) 
310   {
311     rewind(ptr->file->file);
312   }
313   
314   *p++ = 0;
315   return line;
316 }
317
318
319 static char *fn;
320
321 static unsigned int eject;      /* Eject pending */
322 static unsigned int page;       /* Current page number */
323 static char *title;             /* current title */
324 static char *subtitle;          /* current subtitle */
325 static unsigned int on_page;    /* number of lines printed on current page */
326
327
328 static void
329 DEFUN(listing_page,(list),
330     list_info_type *list)
331 {
332   /* Grope around, see if we can see a title or subtitle edict coming up
333      soon  (we look down 10 lines of the page and see if it's there)*/
334   if ((eject || (on_page >= paper_height)) && paper_height != 0) 
335   {
336     unsigned int c = 10;
337     int had_title = 0;
338     int had_subtitle = 0;
339
340     page++;
341   
342     while (c != 0 && list) 
343     {
344       if (list->edict == EDICT_SBTTL && !had_subtitle) 
345       {
346         had_subtitle = 1;
347         subtitle = list->edict_arg;
348       }
349       if (list->edict == EDICT_TITLE && !had_title) 
350       {
351         had_title = 1;
352         title = list->edict_arg;
353       }
354       list = list->next;
355       c--;
356     }    
357       
358
359     if (page > 1) 
360     {
361       printf("\f");
362     }
363   
364     printf("%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
365     printf("%s\n", title);
366     printf("%s\n", subtitle);
367     on_page = 3;
368     eject = 0;
369   }
370 }
371
372
373 static unsigned int 
374 DEFUN(calc_hex,(list),
375       list_info_type *list)
376 {
377   list_info_type *first = list;
378   list_info_type *last = first;
379   unsigned int address = ~0;
380   
381   fragS *frag;
382   fragS *frag_ptr;
383
384   unsigned    int    byte_in_frag = 0;
385   
386   int anything = 0;      
387
388   /* Find first frag which says it belongs to this line */
389   frag = list->frag; 
390   while (frag  && frag->line != list) 
391    frag = frag->fr_next;
392
393   frag_ptr = frag;
394
395   data_buffer_size = 0;
396   
397   /* Dump all the frags which belong to this line */
398   while (frag_ptr != (fragS *)NULL  && frag_ptr->line == first)
399   {
400     /* Print as many bytes from the fixed part as is sensible */
401     while(byte_in_frag < frag_ptr->fr_fix && data_buffer_size < sizeof(data_buffer)-10)
402     {
403       if (address == ~0)
404       {
405         address = frag_ptr->fr_address;
406       }
407              
408       sprintf(data_buffer + data_buffer_size, "%02X",(frag_ptr->fr_literal[byte_in_frag]) & 0xff);
409       data_buffer_size += 2;
410       byte_in_frag++;
411     }
412     /* Print as many bytes from the variable part as is sensible */
413     while (byte_in_frag < frag_ptr->fr_var * frag_ptr->fr_offset 
414            && data_buffer_size < sizeof(data_buffer)-10)
415     {
416       if (address == ~0)
417       {
418         address =  frag_ptr->fr_address;
419       }
420       data_buffer[data_buffer_size++] = '*';
421       data_buffer[data_buffer_size++] = '*';
422       
423       byte_in_frag++;
424     }
425     frag_ptr = frag_ptr->fr_next;
426   }
427   data_buffer[data_buffer_size++] = 0;
428   return address;
429 }
430
431
432
433
434
435
436 static void
437 DEFUN(print_lines,(list, string, address),
438 list_info_type *list AND
439 char *string AND
440 unsigned int address)
441 {
442   unsigned int idx;
443   unsigned int nchars;
444   unsigned int lines;
445   unsigned int byte_in_word =0;
446   char *src = data_buffer;
447   
448   /* Print the stuff on the first line */
449   listing_page(list);
450   nchars = (LISTING_WORD_SIZE*2 +1)  * LISTING_LHS_WIDTH ;
451   /* Print the hex for the first line */
452   if (address == ~0)  
453   {
454     printf("% 4d     ", list->line);
455     for (idx = 0; idx < nchars; idx++)
456      printf(" ");
457     
458     printf("\t%s\n", string ? string : "");
459     on_page++;
460     listing_page(0);
461     
462   }
463   else 
464   {
465     if (had_errors()) 
466     {
467       printf("% 4d ???? ", list->line);
468     }
469     else 
470     {
471     printf("% 4d %04x ", list->line, address);
472   }
473     
474     /* And the data to go along with it */
475     idx = 0;
476     
477     while (*src && idx < nchars)
478     {
479       printf("%c%c", src[0], src[1]);
480       src += 2;
481       byte_in_word++;
482       if (byte_in_word == LISTING_WORD_SIZE)  
483       {
484         printf(" ");
485         idx++;
486         byte_in_word = 0;
487       }
488       idx+=2;
489     }       
490
491     for (;idx < nchars; idx++) 
492      printf(" ");
493   
494     printf("\t%s\n", string ? string : "");
495     on_page++;
496     listing_page(list);  
497     if (list->message) 
498     {
499       printf("****  %s\n",list->message);
500       listing_page(list);
501       on_page++;
502     }
503
504     for (lines = 0;
505          lines < LISTING_LHS_CONT_LINES 
506          && *src;
507          lines++) {
508         nchars = ((LISTING_WORD_SIZE*2) +1)  * LISTING_LHS_WIDTH_SECOND -1;
509         idx = 0;
510         /* Print any more lines of data, but more compactly */
511         printf("% 4d      ", list->line);
512   
513         while (*src && idx < nchars)
514         {
515           printf("%c%c", src[0], src[1]);
516           src+=2;
517           idx+=2;
518           byte_in_word++;
519           if (byte_in_word == LISTING_WORD_SIZE)  
520           {
521             printf(" ");
522             idx++;
523             byte_in_word = 0;
524           }
525         }
526         
527         printf("\n");
528         on_page++;
529         listing_page(list);
530         
531       }
532     
533
534   }
535 }
536
537   
538   
539   
540
541
542 static void
543 DEFUN_VOID(list_symbol_table)
544 {
545   extern symbolS *symbol_rootP;
546   
547   symbolS *ptr ;
548   eject = 1;
549   listing_page(0);
550   printf("DEFINED SYMBOLS\n");
551   on_page++;
552   
553   for (ptr = symbol_rootP; ptr != (symbolS*)NULL; ptr = symbol_next(ptr))
554   {
555     if (ptr->sy_frag->line) 
556     {
557      printf("%20s:%-5d  %2d:%08x %s \n",
558              ptr->sy_frag->line->file->filename,
559              ptr->sy_frag->line->line,
560              S_GET_SEGMENT(ptr),
561              S_GET_VALUE(ptr),
562              S_GET_NAME(ptr));
563       on_page++;
564       listing_page(0);
565       
566     }
567
568   }
569   printf("\n");
570   on_page++;
571   listing_page(0);
572   printf("UNDEFINED SYMBOLS\n");
573   on_page++;
574   listing_page(0);
575   
576   for (ptr = symbol_rootP; ptr != (symbolS*)NULL; ptr = symbol_next(ptr))
577   {
578     if (ptr->sy_frag->line == 0) 
579     {
580       
581       printf("%s\n",         S_GET_NAME(ptr));
582       on_page++;
583       listing_page(0);
584       
585     }
586   }
587 }
588
589 void 
590 DEFUN(listing_listing,(name),
591       char *name)
592 {
593   list_info_type *list = head;
594   unsigned  int page= 1;
595   unsigned int prev  = 0;
596   char *message;
597   char *buffer;
598   char *p;
599   unsigned int addr = 0;  
600   int on_page = 0;
601   int show_listing = 1;
602     
603   buffer = malloc(LISTING_RHS_WIDTH);
604   eject = 1;
605   list = head;
606
607   while (list != (list_info_type *)NULL && 0) 
608   {
609     if (list->next)
610      list->frag = list->next->frag;  
611     list = list->next;
612
613   }
614   
615   list = head->next;
616
617
618   while ( list)
619   {
620     p = buffer_line(list, buffer, LISTING_RHS_WIDTH > paper_width ?
621                     paper_width : LISTING_RHS_WIDTH);
622
623     switch (list->edict) {
624       case EDICT_LIST:
625         show_listing++;
626         break;
627       case EDICT_NOLIST:
628         show_listing--;
629         break;
630       case EDICT_EJECT:
631         break;
632       case EDICT_NONE:
633         break;
634       case EDICT_TITLE:
635         title = list->edict_arg;
636         break;
637       case EDICT_SBTTL:
638         subtitle = list->edict_arg;
639         break;
640       default:
641         abort();
642       }
643     
644     if (show_listing > 0) 
645     {
646       /* Scan down the list and print all the stuff which can be done
647          with this line (or lines) */
648       message = 0;
649
650
651       print_lines(list, p,      calc_hex(list));
652
653       if (list->edict == EDICT_EJECT) 
654       {
655         eject = 1;
656       }    
657     }
658     list = list->next;
659   }
660   free(buffer);
661 }
662
663 void 
664 DEFUN(listing_print,(name),
665       char *name)
666 {
667   title = "";
668   subtitle = "";  
669   
670   if (listing & LISTING_NOFORM) 
671   {
672     paper_height = 0;
673   }
674   
675   if (listing & LISTING_LISTING) 
676   {
677     listing_listing(name);
678     
679   }
680   if (listing & LISTING_SYMBOLS) 
681   {
682     list_symbol_table();
683   }
684 }  
685
686
687 void
688 DEFUN(listing_file,(name),
689 char *name)
690 {
691   fn = name;  
692 }
693
694 void 
695 DEFUN_VOID(listing_eject)
696 {
697   listing_tail->edict = EDICT_EJECT;  
698 }
699
700 void
701 DEFUN_VOID(listing_flags)
702 {
703   
704 }
705 void
706 DEFUN(listing_list,(on),
707            unsigned int on)
708 {
709   listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST;
710 }
711
712
713 void
714 DEFUN_VOID(listing_psize)
715 {
716   paper_height = get_absolute_expression();
717
718   if (paper_height < 0 || paper_height > 1000) 
719   {
720     paper_height = 0;
721     as_warn("strantge paper height, set to no form");
722   }
723  if (*input_line_pointer == ',') 
724   {
725     input_line_pointer++;
726     paper_width = get_absolute_expression();
727   }
728 }
729
730
731 void
732 DEFUN(listing_title,(depth),
733       unsigned int depth)
734 {
735   char *start;
736   char *title;
737   unsigned int length;
738   
739   SKIP_WHITESPACE();
740   if (*input_line_pointer=='\"') {
741       input_line_pointer++;
742       start = input_line_pointer;
743   
744       while (*input_line_pointer) 
745       {
746         if (*input_line_pointer == '\"') 
747         {
748           length = input_line_pointer - start;
749           title = malloc(length + 1);
750           memcpy(title, start, length);
751           title[length] = 0;
752           listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
753           listing_tail->edict_arg = title;
754           input_line_pointer++;
755           demand_empty_rest_of_line();
756           return;      
757         }
758         else if (*input_line_pointer == '\n') 
759         {
760           as_bad("New line in title");
761           demand_empty_rest_of_line();
762           return;
763         }
764         else 
765         {
766           input_line_pointer++;
767         }
768       }
769     }
770   else 
771   {
772     as_bad("expecting title in quotes");
773   }
774 }
775
776
777 #else
778
779
780 /* Dummy functions for when compiled without listing enabled */
781
782 void 
783 DEFUN_VOID(listing_flags)
784 {
785   s_ignore();  
786 }
787
788 void DEFUN_VOID(listing_list)
789 {
790   s_ignore();  
791 }
792
793 void DEFUN_VOID(listing_eject)
794 {
795   s_ignore();  
796 }
797 void DEFUN(listing_psize)
798 {
799   s_ignore();
800 }
801
802 void DEFUN(listing_title, (depth),
803 unsigned int depth)
804 {
805   s_ignore();  
806 }
807 void
808 DEFUN(listing_file,(name),
809 char *name)
810 {
811
812 }
813
814 void DEFUN(listing_newline,(name),
815 char *name)
816 {
817   
818 }
819
820
821 #endif