2000-08-31 Kazu Hirata <kazu@hxi.com>
[external/binutils.git] / gas / listing.c
1 /* listing.c - mainting assembly listings
2    Copyright (C) 1991, 92, 93, 94, 95, 96, 97, 98, 99, 2000
3    Free Software Foundation, Inc.
4
5 This file is part of GAS, the GNU Assembler.
6
7 GAS is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
10 any later version.
11
12 GAS is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with GAS; see the file COPYING.  If not, write to the Free
19 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
20 02111-1307, USA.  */
21
22 /*
23  Contributed by Steve Chamberlain <sac@cygnus.com>
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  Listings are a maintained by read calling various listing_<foo>
59  functions.  What happens most is that the macro NO_LISTING is not
60  defined (from the Makefile), then the macro LISTING_NEWLINE expands
61  into a call to listing_newline.  The call is done from read.c, every
62  time it sees a newline, and -l is on the command line.
63
64  The function listing_newline remembers the frag associated with the
65  newline, and creates a new frag - note that this is wasteful, but not
66  a big deal, since listing slows things down a lot anyway.  The
67  function also rememebers when the filename changes.
68
69  When all the input has finished, and gas has had a chance to settle
70  down, the listing is output. This is done by running down the list of
71  frag/source file records, and opening the files as needed and printing
72  out the bytes and chars associated with them.
73
74  The only things which the architecture can change about the listing
75  are defined in these macros:
76
77  LISTING_HEADER         The name of the architecture
78  LISTING_WORD_SIZE      The make of the number of bytes in a word, this determines
79                         the clumping of the output data. eg a value of
80                         2 makes words look like 1234 5678, whilst 1
81                         would make the same value look like 12 34 56
82                         78
83  LISTING_LHS_WIDTH      Number of words of above size for the lhs
84
85  LISTING_LHS_WIDTH_SECOND   Number of words for the data on the lhs
86                         for the second line
87
88  LISTING_LHS_CONT_LINES Max number of lines to use up for a continutation
89  LISTING_RHS_WIDTH      Number of chars from the input file to print
90                         on a line
91 */
92
93 #include <ctype.h>
94
95 #include "as.h"
96 #include <obstack.h>
97 #include "input-file.h"
98 #include "subsegs.h"
99
100 #ifndef NO_LISTING
101
102 #ifndef LISTING_HEADER
103 #define LISTING_HEADER "GAS LISTING"
104 #endif
105 #ifndef LISTING_WORD_SIZE
106 #define LISTING_WORD_SIZE 4
107 #endif
108 #ifndef LISTING_LHS_WIDTH
109 #define LISTING_LHS_WIDTH ((LISTING_WORD_SIZE) > 4 ? 1 : 4 / (LISTING_WORD_SIZE))
110 #endif
111 #ifndef LISTING_LHS_WIDTH_SECOND
112 #define LISTING_LHS_WIDTH_SECOND LISTING_LHS_WIDTH
113 #endif
114 #ifndef LISTING_RHS_WIDTH
115 #define LISTING_RHS_WIDTH 100
116 #endif
117 #ifndef LISTING_LHS_CONT_LINES
118 #define LISTING_LHS_CONT_LINES 4
119 #endif
120
121 /* This structure remembers which .s were used.  */
122 typedef struct file_info_struct
123 {
124   struct file_info_struct * next;
125   char *                    filename;
126   long                      pos;
127   unsigned int              linenum;
128   int                       at_end;
129 }
130 file_info_type;
131
132 /* This structure rememebrs which line from which file goes into which
133    frag.  */
134 struct list_info_struct
135 {
136   /* Frag which this line of source is nearest to.  */
137   fragS *frag;
138
139   /* The actual line in the source file.  */
140   unsigned int line;
141   /* Pointer to the file info struct for the file which this line
142      belongs to.  */
143   file_info_type *file;
144
145   /* The expanded text of any macro that may have been executing.  */
146   char *line_contents;
147
148   /* Next in list.  */
149   struct list_info_struct *next;
150
151   /* Pointer to the file info struct for the high level language
152      source line that belongs here.  */
153   file_info_type *hll_file;
154   /* High level language source line.  */
155   unsigned int hll_line;
156
157   /* Pointer to any error message associated with this line.  */
158   char *message;
159
160   enum
161     {
162       EDICT_NONE,
163       EDICT_SBTTL,
164       EDICT_TITLE,
165       EDICT_NOLIST,
166       EDICT_LIST,
167       EDICT_NOLIST_NEXT,
168       EDICT_EJECT
169     } edict;
170   char *edict_arg;
171
172   /* Nonzero if this line is to be omitted because it contains
173      debugging information.  This can become a flags field if we come
174      up with more information to store here.  */
175   int debugging;
176 };
177
178 typedef struct list_info_struct list_info_type;
179
180 int listing_lhs_width        = LISTING_LHS_WIDTH;
181 int listing_lhs_width_second = LISTING_LHS_WIDTH_SECOND;
182 int listing_lhs_cont_lines   = LISTING_LHS_CONT_LINES;
183 int listing_rhs_width        = LISTING_RHS_WIDTH;
184
185 struct list_info_struct *        listing_tail;
186
187 static file_info_type *          file_info_head;
188 static file_info_type *          last_open_file_info;
189 static FILE *                    last_open_file;
190 static struct list_info_struct * head;
191 static int                       paper_width = 200;
192 static int                       paper_height = 60;
193
194 extern int                       listing;
195
196 /* File to output listings to.  */
197 static FILE * list_file;
198
199 /* This static array is used to keep the text of data to be printed
200    before the start of the line.  */
201
202 #define MAX_BYTES                                                       \
203   (((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width                    \
204    + ((((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second)        \
205       * listing_lhs_cont_lines)                                         \
206    + 20)
207
208 static char *data_buffer;
209
210 /* Prototypes.  */
211 static void listing_message PARAMS ((const char *name, const char *message));
212 static file_info_type * file_info PARAMS ((const char *file_name));
213 static void new_frag PARAMS ((void));
214 static char *buffer_line PARAMS ((file_info_type *file,
215                                   char *line, unsigned int size));
216 static void listing_page PARAMS ((list_info_type *list));
217 static unsigned int calc_hex PARAMS ((list_info_type *list));
218 static void print_lines PARAMS ((list_info_type *, unsigned int,
219                                  char *, unsigned int));
220 static void list_symbol_table PARAMS ((void));
221 static void print_source PARAMS ((file_info_type *current_file,
222                                   list_info_type *list,
223                                   char *buffer,
224                                   unsigned int width));
225 static int debugging_pseudo PARAMS ((list_info_type *, const char *));
226 static void listing_listing PARAMS ((char *name));
227
228 static void
229 listing_message (name, message)
230      const char *name;
231      const char *message;
232 {
233   unsigned int l = strlen (name) + strlen (message) + 1;
234   char *n = (char *) xmalloc (l);
235   strcpy (n, name);
236   strcat (n, message);
237   if (listing_tail != (list_info_type *) NULL)
238     {
239       listing_tail->message = n;
240     }
241 }
242
243 void
244 listing_warning (message)
245      const char *message;
246 {
247   listing_message (_("Warning:"), message);
248 }
249
250 void
251 listing_error (message)
252      const char *message;
253 {
254   listing_message (_("Error:"), message);
255 }
256
257 static file_info_type *
258 file_info (file_name)
259      const char *file_name;
260 {
261   /* Find an entry with this file name.  */
262   file_info_type *p = file_info_head;
263
264   while (p != (file_info_type *) NULL)
265     {
266       if (strcmp (p->filename, file_name) == 0)
267         return p;
268       p = p->next;
269     }
270
271   /* Make new entry.  */
272
273   p = (file_info_type *) xmalloc (sizeof (file_info_type));
274   p->next = file_info_head;
275   file_info_head = p;
276   p->filename = xmalloc ((unsigned long) strlen (file_name) + 1);
277   strcpy (p->filename, file_name);
278   p->pos = 0;
279   p->linenum = 0;
280   p->at_end = 0;
281
282   return p;
283 }
284
285 static void
286 new_frag ()
287 {
288
289   frag_wane (frag_now);
290   frag_new (0);
291
292 }
293
294 void
295 listing_newline (ps)
296      char *ps;
297 {
298   char *file;
299   unsigned int line;
300   static unsigned int last_line = 0xffff;
301   static char *last_file = NULL;
302   list_info_type *new = NULL;
303
304   if (listing == 0)
305     return;
306
307   if (now_seg == absolute_section)
308     return;
309
310 #ifdef OBJ_ELF
311   /* In ELF, anything in a section beginning with .debug or .line is
312      considered to be debugging information.  This includes the
313      statement which switches us into the debugging section, which we
314      can only set after we are already in the debugging section.  */
315   if ((listing & LISTING_NODEBUG) != 0
316       && listing_tail != NULL
317       && ! listing_tail->debugging)
318     {
319       const char *segname;
320
321       segname = segment_name (now_seg);
322       if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
323           || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
324         listing_tail->debugging = 1;
325     }
326 #endif
327
328   as_where (&file, &line);
329   if (ps == NULL)
330     {
331       if (line == last_line
332           && !(last_file && file && strcmp (file, last_file)))
333         return;
334
335       new = (list_info_type *) xmalloc (sizeof (list_info_type));
336
337       /* Detect if we are reading from stdin by examining the file
338          name returned by as_where().
339
340          [FIXME: We rely upon the name in the strcmp below being the
341          same as the one used by input_scrub_new_file(), if that is
342          not true, then this code will fail].
343
344          If we are reading from stdin, then we need to save each input
345          line here (assuming of course that we actually have a line of
346          input to read), so that it can be displayed in the listing
347          that is produced at the end of the assembly.  */
348       if (strcmp (file, _("{standard input}")) == 0
349           && input_line_pointer != NULL)
350         {
351           char *copy;
352           int len;
353           int seen_quote = 0;
354
355           for (copy = input_line_pointer - 1;
356                *copy && (seen_quote
357                          || (! is_end_of_line [(unsigned char) *copy]));
358                copy++)
359             if (*copy == '"' && copy[-1] != '\\')
360               seen_quote = ! seen_quote;
361
362           len = (copy - input_line_pointer) + 2;
363
364           copy = xmalloc (len);
365
366           if (copy != NULL)
367             {
368               char *src = input_line_pointer - 1;
369               char *dest = copy;
370
371               while (--len)
372                 {
373                   unsigned char c = *src++;
374
375                   /* Omit control characters in the listing.  */
376                   if (isascii (c) && ! iscntrl (c))
377                     *dest++ = c;
378                 }
379
380               *dest = 0;
381             }
382
383           new->line_contents = copy;
384         }
385       else
386         new->line_contents = NULL;
387     }
388   else
389     {
390       new = (list_info_type *) xmalloc (sizeof (list_info_type));
391       new->line_contents = ps;
392     }
393
394   last_line = line;
395   last_file = file;
396
397   new_frag ();
398
399   if (listing_tail)
400     listing_tail->next = new;
401   else
402     head = new;
403
404   listing_tail = new;
405
406   new->frag = frag_now;
407   new->line = line;
408   new->file = file_info (file);
409   new->next = (list_info_type *) NULL;
410   new->message = (char *) NULL;
411   new->edict = EDICT_NONE;
412   new->hll_file = (file_info_type *) NULL;
413   new->hll_line = 0;
414   new->debugging = 0;
415
416   new_frag ();
417
418 #ifdef OBJ_ELF
419   /* In ELF, anything in a section beginning with .debug or .line is
420      considered to be debugging information.  */
421   if ((listing & LISTING_NODEBUG) != 0)
422     {
423       const char *segname;
424
425       segname = segment_name (now_seg);
426       if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
427           || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
428         new->debugging = 1;
429     }
430 #endif
431 }
432
433 /* Attach all current frags to the previous line instead of the
434    current line.  This is called by the MIPS backend when it discovers
435    that it needs to add some NOP instructions; the added NOP
436    instructions should go with the instruction that has the delay, not
437    with the new instruction.  */
438
439 void
440 listing_prev_line ()
441 {
442   list_info_type *l;
443   fragS *f;
444
445   if (head == (list_info_type *) NULL
446       || head == listing_tail)
447     return;
448
449   new_frag ();
450
451   for (l = head; l->next != listing_tail; l = l->next)
452     ;
453
454   for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next)
455     if (f->line == listing_tail)
456       f->line = l;
457
458   listing_tail->frag = frag_now;
459   new_frag ();
460 }
461
462 /* This function returns the next source line from the file supplied,
463    truncated to size.  It appends a fake line to the end of each input
464    file to make.  */
465
466 static char *
467 buffer_line (file, line, size)
468      file_info_type *file;
469      char *line;
470      unsigned int size;
471 {
472   unsigned int count = 0;
473   int c;
474
475   char *p = line;
476
477   /* If we couldn't open the file, return an empty line.  */
478   if (file->at_end)
479     return "";
480
481   /* Check the cache and see if we last used this file.  */
482   if (!last_open_file_info || file != last_open_file_info)
483     {
484       if (last_open_file)
485         {
486           last_open_file_info->pos = ftell (last_open_file);
487           fclose (last_open_file);
488         }
489
490       last_open_file_info = file;
491       last_open_file = fopen (file->filename, "r");
492       if (last_open_file == NULL)
493         {
494           file->at_end = 1;
495           return "";
496         }
497
498       /* Seek to where we were last time this file was open.  */
499       if (file->pos)
500         fseek (last_open_file, file->pos, SEEK_SET);
501     }
502
503   c = fgetc (last_open_file);
504
505   /* Leave room for null.  */
506   size -= 1;
507
508   while (c != EOF && c != '\n')
509     {
510       if (count < size)
511         *p++ = c;
512       count++;
513
514       c = fgetc (last_open_file);
515
516     }
517   if (c == EOF)
518     {
519       file->at_end = 1;
520       *p++ = '.';
521       *p++ = '.';
522       *p++ = '.';
523     }
524   file->linenum++;
525   *p++ = 0;
526   return line;
527 }
528
529 static const char *fn;
530
531 static unsigned int eject;      /* Eject pending */
532 static unsigned int page;       /* Current page number */
533 static char *title;             /* Current title */
534 static char *subtitle;          /* Current subtitle */
535 static unsigned int on_page;    /* Number of lines printed on current page */
536
537 static void
538 listing_page (list)
539      list_info_type *list;
540 {
541   /* Grope around, see if we can see a title or subtitle edict coming up
542      soon.  (we look down 10 lines of the page and see if it's there)  */
543   if ((eject || (on_page >= (unsigned int) paper_height))
544       && paper_height != 0)
545     {
546       unsigned int c = 10;
547       int had_title = 0;
548       int had_subtitle = 0;
549
550       page++;
551
552       while (c != 0 && list)
553         {
554           if (list->edict == EDICT_SBTTL && !had_subtitle)
555             {
556               had_subtitle = 1;
557               subtitle = list->edict_arg;
558             }
559           if (list->edict == EDICT_TITLE && !had_title)
560             {
561               had_title = 1;
562               title = list->edict_arg;
563             }
564           list = list->next;
565           c--;
566         }
567
568       if (page > 1)
569         {
570           fprintf (list_file, "\f");
571         }
572
573       fprintf (list_file, "%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
574       fprintf (list_file, "%s\n", title);
575       fprintf (list_file, "%s\n", subtitle);
576       on_page = 3;
577       eject = 0;
578     }
579 }
580
581 static unsigned int
582 calc_hex (list)
583      list_info_type *list;
584 {
585   int data_buffer_size;
586   list_info_type *first = list;
587   unsigned int address = ~(unsigned int) 0;
588   fragS *frag;
589   fragS *frag_ptr;
590   unsigned int octet_in_frag;
591
592   /* Find first frag which says it belongs to this line.  */
593   frag = list->frag;
594   while (frag && frag->line != list)
595     frag = frag->fr_next;
596
597   frag_ptr = frag;
598
599   data_buffer_size = 0;
600
601   /* Dump all the frags which belong to this line.  */
602   while (frag_ptr != (fragS *) NULL && frag_ptr->line == first)
603     {
604       /* Print as many bytes from the fixed part as is sensible.  */
605       octet_in_frag = 0;
606       while ((offsetT) octet_in_frag < frag_ptr->fr_fix
607              && data_buffer_size < MAX_BYTES - 3)
608         {
609           if (address == ~(unsigned int) 0)
610             {
611               address = frag_ptr->fr_address / OCTETS_PER_BYTE;
612             }
613
614           sprintf (data_buffer + data_buffer_size,
615                    "%02X",
616                    (frag_ptr->fr_literal[octet_in_frag]) & 0xff);
617           data_buffer_size += 2;
618           octet_in_frag++;
619         }
620       {
621         unsigned int var_rep_max = octet_in_frag;
622         unsigned int var_rep_idx = octet_in_frag;
623
624         /* Print as many bytes from the variable part as is sensible.  */
625         while (((offsetT) octet_in_frag
626                 < (frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset))
627                && data_buffer_size < MAX_BYTES - 3)
628           {
629             if (address == ~(unsigned int) 0)
630               {
631                 address = frag_ptr->fr_address / OCTETS_PER_BYTE;
632               }
633             sprintf (data_buffer + data_buffer_size,
634                      "%02X",
635                      (frag_ptr->fr_literal[var_rep_idx]) & 0xff);
636 #if 0
637             data_buffer[data_buffer_size++] = '*';
638             data_buffer[data_buffer_size++] = '*';
639 #endif
640             data_buffer_size += 2;
641
642             var_rep_idx++;
643             octet_in_frag++;
644
645             if ((offsetT) var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var)
646               var_rep_idx = var_rep_max;
647           }
648       }
649
650       frag_ptr = frag_ptr->fr_next;
651     }
652   data_buffer[data_buffer_size] = '\0';
653   return address;
654 }
655
656 static void
657 print_lines (list, lineno, string, address)
658      list_info_type *list;
659      unsigned int lineno;
660      char *string;
661      unsigned int address;
662 {
663   unsigned int idx;
664   unsigned int nchars;
665   unsigned int lines;
666   unsigned int octet_in_word = 0;
667   char *src = data_buffer;
668   int cur;
669
670   /* Print the stuff on the first line.  */
671   listing_page (list);
672   nchars = (LISTING_WORD_SIZE * 2 + 1) * listing_lhs_width;
673
674   /* Print the hex for the first line.  */
675   if (address == ~(unsigned int) 0)
676     {
677       fprintf (list_file, "% 4d     ", lineno);
678       for (idx = 0; idx < nchars; idx++)
679         fprintf (list_file, " ");
680
681       fprintf (list_file, "\t%s\n", string ? string : "");
682
683       on_page++;
684
685       listing_page (0);
686
687       return;
688     }
689
690   if (had_errors ())
691     fprintf (list_file, "% 4d ???? ", lineno);
692   else
693     fprintf (list_file, "% 4d %04x ", lineno, address);
694
695   /* And the data to go along with it.  */
696   idx = 0;
697   cur = 0;
698   while (src[cur] && idx < nchars)
699     {
700       int offset;
701       offset = cur;
702       fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
703       cur += 2;
704       octet_in_word++;
705
706       if (octet_in_word == LISTING_WORD_SIZE)
707         {
708           fprintf (list_file, " ");
709           idx++;
710           octet_in_word = 0;
711         }
712
713       idx += 2;
714     }
715
716   for (; idx < nchars; idx++)
717     fprintf (list_file, " ");
718
719   fprintf (list_file, "\t%s\n", string ? string : "");
720   on_page++;
721   listing_page (list);
722
723   if (list->message)
724     {
725       fprintf (list_file, "****  %s\n", list->message);
726       listing_page (list);
727       on_page++;
728     }
729
730   for (lines = 0;
731        lines < (unsigned int) listing_lhs_cont_lines
732          && src[cur];
733        lines++)
734     {
735       nchars = ((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second - 1;
736       idx = 0;
737
738       /* Print any more lines of data, but more compactly.  */
739       fprintf (list_file, "% 4d      ", lineno);
740
741       while (src[cur] && idx < nchars)
742         {
743           int offset;
744           offset = cur;
745           fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
746           cur += 2;
747           idx += 2;
748           octet_in_word++;
749
750           if (octet_in_word == LISTING_WORD_SIZE)
751             {
752               fprintf (list_file, " ");
753               idx++;
754               octet_in_word = 0;
755             }
756         }
757
758       fprintf (list_file, "\n");
759       on_page++;
760       listing_page (list);
761     }
762 }
763
764 static void
765 list_symbol_table ()
766 {
767   extern symbolS *symbol_rootP;
768   int got_some = 0;
769
770   symbolS *ptr;
771   eject = 1;
772   listing_page (0);
773
774   for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
775     {
776       if (SEG_NORMAL (S_GET_SEGMENT (ptr))
777           || S_GET_SEGMENT (ptr) == absolute_section)
778         {
779 #ifdef BFD_ASSEMBLER
780           /* Don't report section symbols.  They are not interesting.  */
781           if (symbol_section_p (ptr))
782             continue;
783 #endif
784           if (S_GET_NAME (ptr))
785             {
786               char buf[30], fmt[8];
787               valueT val = S_GET_VALUE (ptr);
788
789               /* @@ Note that this is dependent on the compilation options,
790                  not solely on the target characteristics.  */
791               if (sizeof (val) == 4 && sizeof (int) == 4)
792                 sprintf (buf, "%08lx", (unsigned long) val);
793               else if (sizeof (val) <= sizeof (unsigned long))
794                 {
795                   sprintf (fmt, "%%0%lulx",
796                            (unsigned long) (sizeof (val) * 2));
797                   sprintf (buf, fmt, (unsigned long) val);
798                 }
799 #if defined (BFD64)
800               else if (sizeof (val) > 4)
801                 sprintf_vma (buf, val);
802 #endif
803               else
804                 abort ();
805
806               if (!got_some)
807                 {
808                   fprintf (list_file, "DEFINED SYMBOLS\n");
809                   on_page++;
810                   got_some = 1;
811                 }
812
813               if (symbol_get_frag (ptr) && symbol_get_frag (ptr)->line)
814                 {
815                   fprintf (list_file, "%20s:%-5d  %s:%s %s\n",
816                            symbol_get_frag (ptr)->line->file->filename,
817                            symbol_get_frag (ptr)->line->line,
818                            segment_name (S_GET_SEGMENT (ptr)),
819                            buf, S_GET_NAME (ptr));
820                 }
821               else
822                 {
823                   fprintf (list_file, "%33s:%s %s\n",
824                            segment_name (S_GET_SEGMENT (ptr)),
825                            buf, S_GET_NAME (ptr));
826                 }
827
828               on_page++;
829               listing_page (0);
830             }
831         }
832
833     }
834   if (!got_some)
835     {
836       fprintf (list_file, "NO DEFINED SYMBOLS\n");
837       on_page++;
838     }
839   fprintf (list_file, "\n");
840   on_page++;
841   listing_page (0);
842
843   got_some = 0;
844
845   for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
846     {
847       if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
848         {
849           if (S_GET_SEGMENT (ptr) == undefined_section)
850             {
851               if (!got_some)
852                 {
853                   got_some = 1;
854                   fprintf (list_file, "UNDEFINED SYMBOLS\n");
855                   on_page++;
856                   listing_page (0);
857                 }
858               fprintf (list_file, "%s\n", S_GET_NAME (ptr));
859               on_page++;
860               listing_page (0);
861             }
862         }
863     }
864   if (!got_some)
865     {
866       fprintf (list_file, "NO UNDEFINED SYMBOLS\n");
867       on_page++;
868       listing_page (0);
869     }
870 }
871
872 static void
873 print_source (current_file, list, buffer, width)
874      file_info_type *current_file;
875      list_info_type *list;
876      char *buffer;
877      unsigned int width;
878 {
879   if (!current_file->at_end)
880     {
881       while (current_file->linenum < list->hll_line
882              && !current_file->at_end)
883         {
884           char *p = buffer_line (current_file, buffer, width);
885           fprintf (list_file, "%4u:%-13s **** %s\n", current_file->linenum,
886                    current_file->filename, p);
887           on_page++;
888           listing_page (list);
889         }
890     }
891 }
892
893 /* Sometimes the user doesn't want to be bothered by the debugging
894    records inserted by the compiler, see if the line is suspicious.  */
895
896 static int
897 debugging_pseudo (list, line)
898      list_info_type *list;
899      const char *line;
900 {
901   static int in_debug;
902   int was_debug;
903
904   if (list->debugging)
905     {
906       in_debug = 1;
907       return 1;
908     }
909
910   was_debug = in_debug;
911   in_debug = 0;
912
913   while (isspace ((unsigned char) *line))
914     line++;
915
916   if (*line != '.')
917     {
918 #ifdef OBJ_ELF
919       /* The ELF compiler sometimes emits blank lines after switching
920          out of a debugging section.  If the next line drops us back
921          into debugging information, then don't print the blank line.
922          This is a hack for a particular compiler behaviour, not a
923          general case.  */
924       if (was_debug
925           && *line == '\0'
926           && list->next != NULL
927           && list->next->debugging)
928         {
929           in_debug = 1;
930           return 1;
931         }
932 #endif
933
934       return 0;
935     }
936
937   line++;
938
939   if (strncmp (line, "def", 3) == 0)
940     return 1;
941   if (strncmp (line, "val", 3) == 0)
942     return 1;
943   if (strncmp (line, "scl", 3) == 0)
944     return 1;
945   if (strncmp (line, "line", 4) == 0)
946     return 1;
947   if (strncmp (line, "endef", 5) == 0)
948     return 1;
949   if (strncmp (line, "ln", 2) == 0)
950     return 1;
951   if (strncmp (line, "type", 4) == 0)
952     return 1;
953   if (strncmp (line, "size", 4) == 0)
954     return 1;
955   if (strncmp (line, "dim", 3) == 0)
956     return 1;
957   if (strncmp (line, "tag", 3) == 0)
958     return 1;
959
960   if (strncmp (line, "stabs", 5) == 0)
961     return 1;
962   if (strncmp (line, "stabn", 5) == 0)
963     return 1;
964
965   return 0;
966 }
967
968 static void
969 listing_listing (name)
970      char *name ATTRIBUTE_UNUSED;
971 {
972   list_info_type *list = head;
973   file_info_type *current_hll_file = (file_info_type *) NULL;
974   char *message;
975   char *buffer;
976   char *p;
977   int show_listing = 1;
978   unsigned int width;
979
980   buffer = xmalloc (listing_rhs_width);
981   data_buffer = xmalloc (MAX_BYTES);
982   eject = 1;
983   list = head;
984
985   while (list != (list_info_type *) NULL && 0)
986     {
987       if (list->next)
988         list->frag = list->next->frag;
989       list = list->next;
990
991     }
992
993   list = head->next;
994
995   while (list)
996     {
997       unsigned int list_line;
998
999       width = listing_rhs_width > paper_width ? paper_width :
1000         listing_rhs_width;
1001
1002       list_line = list->line;
1003       switch (list->edict)
1004         {
1005         case EDICT_LIST:
1006           /* Skip all lines up to the current.  */
1007           list_line--;
1008           break;
1009         case EDICT_NOLIST:
1010           show_listing--;
1011           break;
1012         case EDICT_NOLIST_NEXT:
1013           break;
1014         case EDICT_EJECT:
1015           break;
1016         case EDICT_NONE:
1017           break;
1018         case EDICT_TITLE:
1019           title = list->edict_arg;
1020           break;
1021         case EDICT_SBTTL:
1022           subtitle = list->edict_arg;
1023           break;
1024         default:
1025           abort ();
1026         }
1027
1028       if (show_listing <= 0)
1029         {
1030           while (list->file->linenum < list_line
1031                  && !list->file->at_end)
1032             p = buffer_line (list->file, buffer, width);
1033         }
1034
1035       if (list->edict == EDICT_LIST)
1036         {
1037           /* Enable listing for the single line that caused the enable.  */
1038           list_line++;
1039           show_listing++;
1040         }
1041
1042       if (show_listing > 0)
1043         {
1044           /* Scan down the list and print all the stuff which can be done
1045              with this line (or lines).  */
1046           message = 0;
1047
1048           if (list->hll_file)
1049             {
1050               current_hll_file = list->hll_file;
1051             }
1052
1053           if (current_hll_file && list->hll_line && (listing & LISTING_HLL))
1054             {
1055               print_source (current_hll_file, list, buffer, width);
1056             }
1057
1058           if (list->line_contents)
1059             {
1060               if (!((listing & LISTING_NODEBUG)
1061                     && debugging_pseudo (list, list->line_contents)))
1062                 {
1063                   print_lines (list,
1064                                list->file->linenum == 0 ? list->line : list->file->linenum,
1065                                list->line_contents, calc_hex (list));
1066                 }
1067               free (list->line_contents);
1068               list->line_contents = NULL;
1069             }
1070           else
1071             {
1072               while (list->file->linenum < list_line
1073                      && !list->file->at_end)
1074                 {
1075                   unsigned int address;
1076
1077                   p = buffer_line (list->file, buffer, width);
1078
1079                   if (list->file->linenum < list_line)
1080                     address = ~(unsigned int) 0;
1081                   else
1082                     address = calc_hex (list);
1083
1084                   if (!((listing & LISTING_NODEBUG)
1085                         && debugging_pseudo (list, p)))
1086                     print_lines (list, list->file->linenum, p, address);
1087                 }
1088             }
1089
1090           if (list->edict == EDICT_EJECT)
1091             {
1092               eject = 1;
1093             }
1094         }
1095
1096       if (list->edict == EDICT_NOLIST_NEXT)
1097         --show_listing;
1098
1099       list = list->next;
1100     }
1101
1102   free (buffer);
1103   free (data_buffer);
1104   data_buffer = NULL;
1105 }
1106
1107 void
1108 listing_print (name)
1109      char *name;
1110 {
1111   int using_stdout;
1112
1113   title = "";
1114   subtitle = "";
1115
1116   if (name == NULL)
1117     {
1118       list_file = stdout;
1119       using_stdout = 1;
1120     }
1121   else
1122     {
1123       list_file = fopen (name, "w");
1124       if (list_file != NULL)
1125         using_stdout = 0;
1126       else
1127         {
1128           as_perror (_("can't open list file: %s"), name);
1129           list_file = stdout;
1130           using_stdout = 1;
1131         }
1132     }
1133
1134   if (listing & LISTING_NOFORM)
1135     {
1136       paper_height = 0;
1137     }
1138
1139   if (listing & LISTING_LISTING)
1140     {
1141       listing_listing (name);
1142     }
1143
1144   if (listing & LISTING_SYMBOLS)
1145     {
1146       list_symbol_table ();
1147     }
1148
1149   if (! using_stdout)
1150     {
1151       if (fclose (list_file) == EOF)
1152         as_perror (_("error closing list file: %s"), name);
1153     }
1154
1155   if (last_open_file)
1156     {
1157       fclose (last_open_file);
1158     }
1159 }
1160
1161 void
1162 listing_file (name)
1163      const char *name;
1164 {
1165   fn = name;
1166 }
1167
1168 void
1169 listing_eject (ignore)
1170      int ignore ATTRIBUTE_UNUSED;
1171 {
1172   if (listing)
1173     listing_tail->edict = EDICT_EJECT;
1174 }
1175
1176 void
1177 listing_flags (ignore)
1178      int ignore ATTRIBUTE_UNUSED;
1179 {
1180   while ((*input_line_pointer++) && (*input_line_pointer != '\n'))
1181     input_line_pointer++;
1182
1183 }
1184
1185 /* Turn listing on or off.  An argument of 0 means to turn off
1186    listing.  An argument of 1 means to turn on listing.  An argument
1187    of 2 means to turn off listing, but as of the next line; that is,
1188    the current line should be listed, but the next line should not.  */
1189
1190 void
1191 listing_list (on)
1192      int on;
1193 {
1194   if (listing)
1195     {
1196       switch (on)
1197         {
1198         case 0:
1199           if (listing_tail->edict == EDICT_LIST)
1200             listing_tail->edict = EDICT_NONE;
1201           else
1202             listing_tail->edict = EDICT_NOLIST;
1203           break;
1204         case 1:
1205           if (listing_tail->edict == EDICT_NOLIST
1206               || listing_tail->edict == EDICT_NOLIST_NEXT)
1207             listing_tail->edict = EDICT_NONE;
1208           else
1209             listing_tail->edict = EDICT_LIST;
1210           break;
1211         case 2:
1212           listing_tail->edict = EDICT_NOLIST_NEXT;
1213           break;
1214         default:
1215           abort ();
1216         }
1217     }
1218 }
1219
1220 void
1221 listing_psize (width_only)
1222      int width_only;
1223 {
1224   if (! width_only)
1225     {
1226       paper_height = get_absolute_expression ();
1227
1228       if (paper_height < 0 || paper_height > 1000)
1229         {
1230           paper_height = 0;
1231           as_warn (_("strange paper height, set to no form"));
1232         }
1233
1234       if (*input_line_pointer != ',')
1235         {
1236           demand_empty_rest_of_line ();
1237           return;
1238         }
1239
1240       ++input_line_pointer;
1241     }
1242
1243   paper_width = get_absolute_expression ();
1244
1245   demand_empty_rest_of_line ();
1246 }
1247
1248 void
1249 listing_nopage (ignore)
1250      int ignore ATTRIBUTE_UNUSED;
1251 {
1252   paper_height = 0;
1253 }
1254
1255 void
1256 listing_title (depth)
1257      int depth;
1258 {
1259   int quoted;
1260   char *start;
1261   char *ttl;
1262   unsigned int length;
1263
1264   SKIP_WHITESPACE ();
1265   if (*input_line_pointer != '\"')
1266     quoted = 0;
1267   else
1268     {
1269       quoted = 1;
1270       ++input_line_pointer;
1271     }
1272
1273   start = input_line_pointer;
1274
1275   while (*input_line_pointer)
1276     {
1277       if (quoted
1278           ? *input_line_pointer == '\"'
1279           : is_end_of_line[(unsigned char) *input_line_pointer])
1280         {
1281           if (listing)
1282             {
1283               length = input_line_pointer - start;
1284               ttl = xmalloc (length + 1);
1285               memcpy (ttl, start, length);
1286               ttl[length] = 0;
1287               listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
1288               listing_tail->edict_arg = ttl;
1289             }
1290           if (quoted)
1291             input_line_pointer++;
1292           demand_empty_rest_of_line ();
1293           return;
1294         }
1295       else if (*input_line_pointer == '\n')
1296         {
1297           as_bad (_("New line in title"));
1298           demand_empty_rest_of_line ();
1299           return;
1300         }
1301       else
1302         {
1303           input_line_pointer++;
1304         }
1305     }
1306 }
1307
1308 void
1309 listing_source_line (line)
1310      unsigned int line;
1311 {
1312   if (listing)
1313     {
1314       new_frag ();
1315       listing_tail->hll_line = line;
1316       new_frag ();
1317     }
1318 }
1319
1320 void
1321 listing_source_file (file)
1322      const char *file;
1323 {
1324   if (listing)
1325     listing_tail->hll_file = file_info (file);
1326 }
1327
1328 #else
1329
1330 /* Dummy functions for when compiled without listing enabled.  */
1331
1332 void
1333 listing_flags (ignore)
1334      int ignore;
1335 {
1336   s_ignore (0);
1337 }
1338
1339 void
1340 listing_list (on)
1341      int on;
1342 {
1343   s_ignore (0);
1344 }
1345
1346 void
1347 listing_eject (ignore)
1348      int ignore;
1349 {
1350   s_ignore (0);
1351 }
1352
1353 void
1354 listing_psize (ignore)
1355      int ignore;
1356 {
1357   s_ignore (0);
1358 }
1359
1360 void
1361 listing_nopage (ignore)
1362      int ignore;
1363 {
1364   s_ignore (0);
1365 }
1366
1367 void
1368 listing_title (depth)
1369      int depth;
1370 {
1371   s_ignore (0);
1372 }
1373
1374 void
1375 listing_file (name)
1376      const char *name;
1377 {
1378
1379 }
1380
1381 void
1382 listing_newline (name)
1383      char *name;
1384 {
1385
1386 }
1387
1388 void
1389 listing_source_line (n)
1390      unsigned int n;
1391 {
1392
1393 }
1394
1395 void
1396 listing_source_file (n)
1397      const char *n;
1398 {
1399
1400 }
1401
1402 #endif