Locale changes from Bruno Haible <haible@clisp.cons.org>.
[external/binutils.git] / gas / listing.c
1 /* listing.c - mainting assembly listings
2    Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3    2001
4    Free Software Foundation, Inc.
5
6 This file is part of GAS, the GNU Assembler.
7
8 GAS is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2, or (at your option)
11 any later version.
12
13 GAS is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with GAS; see the file COPYING.  If not, write to the Free
20 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21 02111-1307, USA.  */
22
23 /*
24  Contributed by Steve Chamberlain <sac@cygnus.com>
25
26  A listing page looks like:
27
28  LISTING_HEADER  sourcefilename pagenumber
29  TITLE LINE
30  SUBTITLE LINE
31  linenumber address data  source
32  linenumber address data  source
33  linenumber address data  source
34  linenumber address data  source
35
36  If not overridden, the listing commands are:
37
38  .title  "stuff"
39         Put "stuff" onto the title line
40  .sbttl  "stuff"
41         Put stuff onto the subtitle line
42
43   If these commands come within 10 lines of the top of the page, they
44   will affect the page they are on, as well as any subsequent page
45
46  .eject
47         Thow a page
48  .list
49         Increment the enable listing counter
50  .nolist
51         Decrement the enable listing counter
52
53  .psize Y[,X]
54         Set the paper size to X wide and Y high. Setting a psize Y of
55         zero will suppress form feeds except where demanded by .eject
56
57  If the counter goes below zero, listing is suppressed.
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 "safe-ctype.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   struct file_info_struct * next;
124   char *                    filename;
125   long                      pos;
126   unsigned int              linenum;
127   int                       at_end;
128 } file_info_type;
129
130 /* This structure rememebrs which line from which file goes into which
131    frag.  */
132 struct list_info_struct {
133   /* Frag which this line of source is nearest to.  */
134   fragS *frag;
135
136   /* The actual line in the source file.  */
137   unsigned int line;
138   /* Pointer to the file info struct for the file which this line
139      belongs to.  */
140   file_info_type *file;
141
142   /* The expanded text of any macro that may have been executing.  */
143   char *line_contents;
144
145   /* Next in list.  */
146   struct list_info_struct *next;
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   /* High level language source line.  */
152   unsigned int hll_line;
153
154   /* Pointer to any error message associated with this line.  */
155   char *message;
156
157   enum {
158     EDICT_NONE,
159     EDICT_SBTTL,
160     EDICT_TITLE,
161     EDICT_NOLIST,
162     EDICT_LIST,
163     EDICT_NOLIST_NEXT,
164     EDICT_EJECT
165   } edict;
166   char *edict_arg;
167
168   /* Nonzero if this line is to be omitted because it contains
169      debugging information.  This can become a flags field if we come
170      up with more information to store here.  */
171   int debugging;
172 };
173
174 typedef struct list_info_struct list_info_type;
175
176 int listing_lhs_width        = LISTING_LHS_WIDTH;
177 int listing_lhs_width_second = LISTING_LHS_WIDTH_SECOND;
178 int listing_lhs_cont_lines   = LISTING_LHS_CONT_LINES;
179 int listing_rhs_width        = LISTING_RHS_WIDTH;
180
181 struct list_info_struct *        listing_tail;
182
183 static file_info_type *          file_info_head;
184 static file_info_type *          last_open_file_info;
185 static FILE *                    last_open_file;
186 static struct list_info_struct * head;
187 static int                       paper_width = 200;
188 static int                       paper_height = 60;
189
190 extern int                       listing;
191
192 /* File to output listings to.  */
193 static FILE *list_file;
194
195 /* This static array is used to keep the text of data to be printed
196    before the start of the line.  */
197
198 #define MAX_BYTES                                                       \
199   (((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width                    \
200    + ((((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second)        \
201       * listing_lhs_cont_lines)                                         \
202    + 20)
203
204 static char *data_buffer;
205
206 /* Prototypes.  */
207 static void listing_message PARAMS ((const char *name, const char *message));
208 static file_info_type *file_info PARAMS ((const char *file_name));
209 static void new_frag PARAMS ((void));
210 static char *buffer_line PARAMS ((file_info_type *file,
211                                   char *line, unsigned int size));
212 static void listing_page PARAMS ((list_info_type *list));
213 static unsigned int calc_hex PARAMS ((list_info_type *list));
214 static void print_lines PARAMS ((list_info_type *, unsigned int,
215                                  char *, unsigned int));
216 static void list_symbol_table PARAMS ((void));
217 static void print_source PARAMS ((file_info_type *current_file,
218                                   list_info_type *list,
219                                   char *buffer,
220                                   unsigned int width));
221 static int debugging_pseudo PARAMS ((list_info_type *, const char *));
222 static void listing_listing PARAMS ((char *name));
223
224 static void
225 listing_message (name, message)
226      const char *name;
227      const char *message;
228 {
229   if (listing_tail != (list_info_type *) NULL)
230     {
231       unsigned int l = strlen (name) + strlen (message) + 1;
232       char *n = (char *) xmalloc (l);
233       strcpy (n, name);
234       strcat (n, message);
235       listing_tail->message = n;
236     }
237 }
238
239 void
240 listing_warning (message)
241      const char *message;
242 {
243   listing_message (_("Warning:"), message);
244 }
245
246 void
247 listing_error (message)
248      const char *message;
249 {
250   listing_message (_("Error:"), message);
251 }
252
253 static file_info_type *
254 file_info (file_name)
255      const char *file_name;
256 {
257   /* Find an entry with this file name.  */
258   file_info_type *p = file_info_head;
259
260   while (p != (file_info_type *) NULL)
261     {
262       if (strcmp (p->filename, file_name) == 0)
263         return p;
264       p = p->next;
265     }
266
267   /* Make new entry.  */
268
269   p = (file_info_type *) xmalloc (sizeof (file_info_type));
270   p->next = file_info_head;
271   file_info_head = p;
272   p->filename = xmalloc ((unsigned long) strlen (file_name) + 1);
273   strcpy (p->filename, file_name);
274   p->pos = 0;
275   p->linenum = 0;
276   p->at_end = 0;
277
278   return p;
279 }
280
281 static void
282 new_frag ()
283 {
284
285   frag_wane (frag_now);
286   frag_new (0);
287
288 }
289
290 void
291 listing_newline (ps)
292      char *ps;
293 {
294   char *file;
295   unsigned int line;
296   static unsigned int last_line = 0xffff;
297   static char *last_file = NULL;
298   list_info_type *new = NULL;
299
300   if (listing == 0)
301     return;
302
303   if (now_seg == absolute_section)
304     return;
305
306 #ifdef OBJ_ELF
307   /* In ELF, anything in a section beginning with .debug or .line is
308      considered to be debugging information.  This includes the
309      statement which switches us into the debugging section, which we
310      can only set after we are already in the debugging section.  */
311   if ((listing & LISTING_NODEBUG) != 0
312       && listing_tail != NULL
313       && ! listing_tail->debugging)
314     {
315       const char *segname;
316
317       segname = segment_name (now_seg);
318       if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
319           || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
320         listing_tail->debugging = 1;
321     }
322 #endif
323
324   as_where (&file, &line);
325   if (ps == NULL)
326     {
327       if (line == last_line
328           && !(last_file && file && strcmp (file, last_file)))
329         return;
330
331       new = (list_info_type *) xmalloc (sizeof (list_info_type));
332
333       /* Detect if we are reading from stdin by examining the file
334          name returned by as_where().
335
336          [FIXME: We rely upon the name in the strcmp below being the
337          same as the one used by input_scrub_new_file(), if that is
338          not true, then this code will fail].
339
340          If we are reading from stdin, then we need to save each input
341          line here (assuming of course that we actually have a line of
342          input to read), so that it can be displayed in the listing
343          that is produced at the end of the assembly.  */
344       if (strcmp (file, _("{standard input}")) == 0
345           && input_line_pointer != NULL)
346         {
347           char *copy;
348           int len;
349           int seen_quote = 0;
350
351           for (copy = input_line_pointer - 1;
352                *copy && (seen_quote
353                          || (! is_end_of_line [(unsigned char) *copy]));
354                copy++)
355             if (*copy == '"' && copy[-1] != '\\')
356               seen_quote = ! seen_quote;
357
358           len = (copy - input_line_pointer) + 2;
359
360           copy = xmalloc (len);
361
362           if (copy != NULL)
363             {
364               char *src = input_line_pointer - 1;
365               char *dest = copy;
366
367               while (--len)
368                 {
369                   unsigned char c = *src++;
370
371                   /* Omit control characters in the listing.  */
372                   if (!ISCNTRL (c))
373                     *dest++ = c;
374                 }
375
376               *dest = 0;
377             }
378
379           new->line_contents = copy;
380         }
381       else
382         new->line_contents = NULL;
383     }
384   else
385     {
386       new = (list_info_type *) xmalloc (sizeof (list_info_type));
387       new->line_contents = ps;
388     }
389
390   last_line = line;
391   last_file = file;
392
393   new_frag ();
394
395   if (listing_tail)
396     listing_tail->next = new;
397   else
398     head = new;
399
400   listing_tail = new;
401
402   new->frag = frag_now;
403   new->line = line;
404   new->file = file_info (file);
405   new->next = (list_info_type *) NULL;
406   new->message = (char *) NULL;
407   new->edict = EDICT_NONE;
408   new->hll_file = (file_info_type *) NULL;
409   new->hll_line = 0;
410   new->debugging = 0;
411
412   new_frag ();
413
414 #ifdef OBJ_ELF
415   /* In ELF, anything in a section beginning with .debug or .line is
416      considered to be debugging information.  */
417   if ((listing & LISTING_NODEBUG) != 0)
418     {
419       const char *segname;
420
421       segname = segment_name (now_seg);
422       if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
423           || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
424         new->debugging = 1;
425     }
426 #endif
427 }
428
429 /* Attach all current frags to the previous line instead of the
430    current line.  This is called by the MIPS backend when it discovers
431    that it needs to add some NOP instructions; the added NOP
432    instructions should go with the instruction that has the delay, not
433    with the new instruction.  */
434
435 void
436 listing_prev_line ()
437 {
438   list_info_type *l;
439   fragS *f;
440
441   if (head == (list_info_type *) NULL
442       || head == listing_tail)
443     return;
444
445   new_frag ();
446
447   for (l = head; l->next != listing_tail; l = l->next)
448     ;
449
450   for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next)
451     if (f->line == listing_tail)
452       f->line = l;
453
454   listing_tail->frag = frag_now;
455   new_frag ();
456 }
457
458 /* This function returns the next source line from the file supplied,
459    truncated to size.  It appends a fake line to the end of each input
460    file to make.  */
461
462 static char *
463 buffer_line (file, line, size)
464      file_info_type *file;
465      char *line;
466      unsigned int size;
467 {
468   unsigned int count = 0;
469   int c;
470
471   char *p = line;
472
473   /* If we couldn't open the file, return an empty line.  */
474   if (file->at_end)
475     return "";
476
477   /* Check the cache and see if we last used this file.  */
478   if (!last_open_file_info || file != last_open_file_info)
479     {
480       if (last_open_file)
481         {
482           last_open_file_info->pos = ftell (last_open_file);
483           fclose (last_open_file);
484         }
485
486       last_open_file_info = file;
487       last_open_file = fopen (file->filename, FOPEN_RT);
488       if (last_open_file == NULL)
489         {
490           file->at_end = 1;
491           return "";
492         }
493
494       /* Seek to where we were last time this file was open.  */
495       if (file->pos)
496         fseek (last_open_file, file->pos, SEEK_SET);
497     }
498
499   c = fgetc (last_open_file);
500
501   /* Leave room for null.  */
502   size -= 1;
503
504   while (c != EOF && c != '\n')
505     {
506       if (count < size)
507         *p++ = c;
508       count++;
509
510       c = fgetc (last_open_file);
511
512     }
513   if (c == EOF)
514     {
515       file->at_end = 1;
516       *p++ = '.';
517       *p++ = '.';
518       *p++ = '.';
519     }
520   file->linenum++;
521   *p++ = 0;
522   return line;
523 }
524
525 static const char *fn;
526
527 static unsigned int eject;      /* Eject pending */
528 static unsigned int page;       /* Current page number */
529 static char *title;             /* Current title */
530 static char *subtitle;          /* Current subtitle */
531 static unsigned int on_page;    /* Number of lines printed on current page */
532
533 static void
534 listing_page (list)
535      list_info_type *list;
536 {
537   /* Grope around, see if we can see a title or subtitle edict coming up
538      soon.  (we look down 10 lines of the page and see if it's there)  */
539   if ((eject || (on_page >= (unsigned int) paper_height))
540       && paper_height != 0)
541     {
542       unsigned int c = 10;
543       int had_title = 0;
544       int had_subtitle = 0;
545
546       page++;
547
548       while (c != 0 && list)
549         {
550           if (list->edict == EDICT_SBTTL && !had_subtitle)
551             {
552               had_subtitle = 1;
553               subtitle = list->edict_arg;
554             }
555           if (list->edict == EDICT_TITLE && !had_title)
556             {
557               had_title = 1;
558               title = list->edict_arg;
559             }
560           list = list->next;
561           c--;
562         }
563
564       if (page > 1)
565         {
566           fprintf (list_file, "\f");
567         }
568
569       fprintf (list_file, "%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
570       fprintf (list_file, "%s\n", title);
571       fprintf (list_file, "%s\n", subtitle);
572       on_page = 3;
573       eject = 0;
574     }
575 }
576
577 static unsigned int
578 calc_hex (list)
579      list_info_type *list;
580 {
581   int data_buffer_size;
582   list_info_type *first = list;
583   unsigned int address = ~(unsigned int) 0;
584   fragS *frag;
585   fragS *frag_ptr;
586   unsigned int octet_in_frag;
587
588   /* Find first frag which says it belongs to this line.  */
589   frag = list->frag;
590   while (frag && frag->line != list)
591     frag = frag->fr_next;
592
593   frag_ptr = frag;
594
595   data_buffer_size = 0;
596
597   /* Dump all the frags which belong to this line.  */
598   while (frag_ptr != (fragS *) NULL && frag_ptr->line == first)
599     {
600       /* Print as many bytes from the fixed part as is sensible.  */
601       octet_in_frag = 0;
602       while ((offsetT) octet_in_frag < frag_ptr->fr_fix
603              && data_buffer_size < MAX_BYTES - 3)
604         {
605           if (address == ~(unsigned int) 0)
606             {
607               address = frag_ptr->fr_address / OCTETS_PER_BYTE;
608             }
609
610           sprintf (data_buffer + data_buffer_size,
611                    "%02X",
612                    (frag_ptr->fr_literal[octet_in_frag]) & 0xff);
613           data_buffer_size += 2;
614           octet_in_frag++;
615         }
616     if (frag_ptr->fr_type == rs_fill)
617       {
618         unsigned int var_rep_max = octet_in_frag;
619         unsigned int var_rep_idx = octet_in_frag;
620
621         /* Print as many bytes from the variable part as is sensible.  */
622         while (((offsetT) octet_in_frag
623                 < (frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset))
624                && data_buffer_size < MAX_BYTES - 3)
625           {
626             if (address == ~(unsigned int) 0)
627               {
628                 address = frag_ptr->fr_address / OCTETS_PER_BYTE;
629               }
630             sprintf (data_buffer + data_buffer_size,
631                      "%02X",
632                      (frag_ptr->fr_literal[var_rep_idx]) & 0xff);
633 #if 0
634             data_buffer[data_buffer_size++] = '*';
635             data_buffer[data_buffer_size++] = '*';
636 #endif
637             data_buffer_size += 2;
638
639             var_rep_idx++;
640             octet_in_frag++;
641
642             if ((offsetT) var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var)
643               var_rep_idx = var_rep_max;
644           }
645       }
646
647       frag_ptr = frag_ptr->fr_next;
648     }
649   data_buffer[data_buffer_size] = '\0';
650   return address;
651 }
652
653 static void
654 print_lines (list, lineno, string, address)
655      list_info_type *list;
656      unsigned int lineno;
657      char *string;
658      unsigned int address;
659 {
660   unsigned int idx;
661   unsigned int nchars;
662   unsigned int lines;
663   unsigned int octet_in_word = 0;
664   char *src = data_buffer;
665   int cur;
666
667   /* Print the stuff on the first line.  */
668   listing_page (list);
669   nchars = (LISTING_WORD_SIZE * 2 + 1) * listing_lhs_width;
670
671   /* Print the hex for the first line.  */
672   if (address == ~(unsigned int) 0)
673     {
674       fprintf (list_file, "% 4d     ", lineno);
675       for (idx = 0; idx < nchars; idx++)
676         fprintf (list_file, " ");
677
678       fprintf (list_file, "\t%s\n", string ? string : "");
679
680       on_page++;
681
682       listing_page (0);
683
684       return;
685     }
686
687   if (had_errors ())
688     fprintf (list_file, "% 4d ???? ", lineno);
689   else
690     fprintf (list_file, "% 4d %04x ", lineno, address);
691
692   /* And the data to go along with it.  */
693   idx = 0;
694   cur = 0;
695   while (src[cur] && idx < nchars)
696     {
697       int offset;
698       offset = cur;
699       fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
700       cur += 2;
701       octet_in_word++;
702
703       if (octet_in_word == LISTING_WORD_SIZE)
704         {
705           fprintf (list_file, " ");
706           idx++;
707           octet_in_word = 0;
708         }
709
710       idx += 2;
711     }
712
713   for (; idx < nchars; idx++)
714     fprintf (list_file, " ");
715
716   fprintf (list_file, "\t%s\n", string ? string : "");
717   on_page++;
718   listing_page (list);
719
720   if (list->message)
721     {
722       fprintf (list_file, "****  %s\n", list->message);
723       listing_page (list);
724       on_page++;
725     }
726
727   for (lines = 0;
728        lines < (unsigned int) listing_lhs_cont_lines
729          && src[cur];
730        lines++)
731     {
732       nchars = ((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second - 1;
733       idx = 0;
734
735       /* Print any more lines of data, but more compactly.  */
736       fprintf (list_file, "% 4d      ", lineno);
737
738       while (src[cur] && idx < nchars)
739         {
740           int offset;
741           offset = cur;
742           fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
743           cur += 2;
744           idx += 2;
745           octet_in_word++;
746
747           if (octet_in_word == LISTING_WORD_SIZE)
748             {
749               fprintf (list_file, " ");
750               idx++;
751               octet_in_word = 0;
752             }
753         }
754
755       fprintf (list_file, "\n");
756       on_page++;
757       listing_page (list);
758     }
759 }
760
761 static void
762 list_symbol_table ()
763 {
764   extern symbolS *symbol_rootP;
765   int got_some = 0;
766
767   symbolS *ptr;
768   eject = 1;
769   listing_page (0);
770
771   for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
772     {
773       if (SEG_NORMAL (S_GET_SEGMENT (ptr))
774           || S_GET_SEGMENT (ptr) == absolute_section)
775         {
776 #ifdef BFD_ASSEMBLER
777           /* Don't report section symbols.  They are not interesting.  */
778           if (symbol_section_p (ptr))
779             continue;
780 #endif
781           if (S_GET_NAME (ptr))
782             {
783               char buf[30], fmt[8];
784               valueT val = S_GET_VALUE (ptr);
785
786               /* @@ Note that this is dependent on the compilation options,
787                  not solely on the target characteristics.  */
788               if (sizeof (val) == 4 && sizeof (int) == 4)
789                 sprintf (buf, "%08lx", (unsigned long) val);
790               else if (sizeof (val) <= sizeof (unsigned long))
791                 {
792                   sprintf (fmt, "%%0%lulx",
793                            (unsigned long) (sizeof (val) * 2));
794                   sprintf (buf, fmt, (unsigned long) val);
795                 }
796 #if defined (BFD64)
797               else if (sizeof (val) > 4)
798                 sprintf_vma (buf, val);
799 #endif
800               else
801                 abort ();
802
803               if (!got_some)
804                 {
805                   fprintf (list_file, "DEFINED SYMBOLS\n");
806                   on_page++;
807                   got_some = 1;
808                 }
809
810               if (symbol_get_frag (ptr) && symbol_get_frag (ptr)->line)
811                 {
812                   fprintf (list_file, "%20s:%-5d  %s:%s %s\n",
813                            symbol_get_frag (ptr)->line->file->filename,
814                            symbol_get_frag (ptr)->line->line,
815                            segment_name (S_GET_SEGMENT (ptr)),
816                            buf, S_GET_NAME (ptr));
817                 }
818               else
819                 {
820                   fprintf (list_file, "%33s:%s %s\n",
821                            segment_name (S_GET_SEGMENT (ptr)),
822                            buf, S_GET_NAME (ptr));
823                 }
824
825               on_page++;
826               listing_page (0);
827             }
828         }
829
830     }
831   if (!got_some)
832     {
833       fprintf (list_file, "NO DEFINED SYMBOLS\n");
834       on_page++;
835     }
836   fprintf (list_file, "\n");
837   on_page++;
838   listing_page (0);
839
840   got_some = 0;
841
842   for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
843     {
844       if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
845         {
846           if (S_GET_SEGMENT (ptr) == undefined_section)
847             {
848               if (!got_some)
849                 {
850                   got_some = 1;
851                   fprintf (list_file, "UNDEFINED SYMBOLS\n");
852                   on_page++;
853                   listing_page (0);
854                 }
855               fprintf (list_file, "%s\n", S_GET_NAME (ptr));
856               on_page++;
857               listing_page (0);
858             }
859         }
860     }
861   if (!got_some)
862     {
863       fprintf (list_file, "NO UNDEFINED SYMBOLS\n");
864       on_page++;
865       listing_page (0);
866     }
867 }
868
869 static void
870 print_source (current_file, list, buffer, width)
871      file_info_type *current_file;
872      list_info_type *list;
873      char *buffer;
874      unsigned int width;
875 {
876   if (!current_file->at_end)
877     {
878       while (current_file->linenum < list->hll_line
879              && !current_file->at_end)
880         {
881           char *p = buffer_line (current_file, buffer, width);
882           fprintf (list_file, "%4u:%-13s **** %s\n", current_file->linenum,
883                    current_file->filename, p);
884           on_page++;
885           listing_page (list);
886         }
887     }
888 }
889
890 /* Sometimes the user doesn't want to be bothered by the debugging
891    records inserted by the compiler, see if the line is suspicious.  */
892
893 static int
894 debugging_pseudo (list, line)
895      list_info_type *list;
896      const char *line;
897 {
898   static int in_debug;
899   int was_debug;
900
901   if (list->debugging)
902     {
903       in_debug = 1;
904       return 1;
905     }
906
907   was_debug = in_debug;
908   in_debug = 0;
909
910   while (ISSPACE (*line))
911     line++;
912
913   if (*line != '.')
914     {
915 #ifdef OBJ_ELF
916       /* The ELF compiler sometimes emits blank lines after switching
917          out of a debugging section.  If the next line drops us back
918          into debugging information, then don't print the blank line.
919          This is a hack for a particular compiler behaviour, not a
920          general case.  */
921       if (was_debug
922           && *line == '\0'
923           && list->next != NULL
924           && list->next->debugging)
925         {
926           in_debug = 1;
927           return 1;
928         }
929 #endif
930
931       return 0;
932     }
933
934   line++;
935
936   if (strncmp (line, "def", 3) == 0)
937     return 1;
938   if (strncmp (line, "val", 3) == 0)
939     return 1;
940   if (strncmp (line, "scl", 3) == 0)
941     return 1;
942   if (strncmp (line, "line", 4) == 0)
943     return 1;
944   if (strncmp (line, "endef", 5) == 0)
945     return 1;
946   if (strncmp (line, "ln", 2) == 0)
947     return 1;
948   if (strncmp (line, "type", 4) == 0)
949     return 1;
950   if (strncmp (line, "size", 4) == 0)
951     return 1;
952   if (strncmp (line, "dim", 3) == 0)
953     return 1;
954   if (strncmp (line, "tag", 3) == 0)
955     return 1;
956
957   if (strncmp (line, "stabs", 5) == 0)
958     return 1;
959   if (strncmp (line, "stabn", 5) == 0)
960     return 1;
961
962   return 0;
963 }
964
965 static void
966 listing_listing (name)
967      char *name ATTRIBUTE_UNUSED;
968 {
969   list_info_type *list = head;
970   file_info_type *current_hll_file = (file_info_type *) NULL;
971   char *message;
972   char *buffer;
973   char *p;
974   int show_listing = 1;
975   unsigned int width;
976
977   buffer = xmalloc (listing_rhs_width);
978   data_buffer = xmalloc (MAX_BYTES);
979   eject = 1;
980   list = head;
981
982   while (list != (list_info_type *) NULL && 0)
983     {
984       if (list->next)
985         list->frag = list->next->frag;
986       list = list->next;
987
988     }
989
990   list = head->next;
991
992   while (list)
993     {
994       unsigned int list_line;
995
996       width = listing_rhs_width > paper_width ? paper_width :
997         listing_rhs_width;
998
999       list_line = list->line;
1000       switch (list->edict)
1001         {
1002         case EDICT_LIST:
1003           /* Skip all lines up to the current.  */
1004           list_line--;
1005           break;
1006         case EDICT_NOLIST:
1007           show_listing--;
1008           break;
1009         case EDICT_NOLIST_NEXT:
1010           if (show_listing == 0)
1011             list_line--;
1012           break;
1013         case EDICT_EJECT:
1014           break;
1015         case EDICT_NONE:
1016           break;
1017         case EDICT_TITLE:
1018           title = list->edict_arg;
1019           break;
1020         case EDICT_SBTTL:
1021           subtitle = list->edict_arg;
1022           break;
1023         default:
1024           abort ();
1025         }
1026
1027       if (show_listing <= 0)
1028         {
1029           while (list->file->linenum < list_line
1030                  && !list->file->at_end)
1031             p = buffer_line (list->file, buffer, width);
1032         }
1033
1034       if (list->edict == EDICT_LIST
1035           || (list->edict == EDICT_NOLIST_NEXT && show_listing == 0))
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 && show_listing == 1)
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, FOPEN_WT);
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