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