listing.c revision 104834
133965Sjdp/* listing.c - mainting assembly listings
277298Sobrien   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3104834Sobrien   2001, 2002
438889Sjdp   Free Software Foundation, Inc.
533965Sjdp
633965SjdpThis file is part of GAS, the GNU Assembler.
733965Sjdp
833965SjdpGAS is free software; you can redistribute it and/or modify
933965Sjdpit under the terms of the GNU General Public License as published by
1033965Sjdpthe Free Software Foundation; either version 2, or (at your option)
1133965Sjdpany later version.
1233965Sjdp
1333965SjdpGAS is distributed in the hope that it will be useful,
1433965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of
1533965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1633965SjdpGNU General Public License for more details.
1733965Sjdp
1833965SjdpYou should have received a copy of the GNU General Public License
1933965Sjdpalong with GAS; see the file COPYING.  If not, write to the Free
2033965SjdpSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA
2177298Sobrien02111-1307, USA.  */
2233965Sjdp
2333965Sjdp/*
2477298Sobrien Contributed by Steve Chamberlain <sac@cygnus.com>
2533965Sjdp
2633965Sjdp A listing page looks like:
2733965Sjdp
2833965Sjdp LISTING_HEADER  sourcefilename pagenumber
2933965Sjdp TITLE LINE
3033965Sjdp SUBTITLE LINE
3133965Sjdp linenumber address data  source
3233965Sjdp linenumber address data  source
3333965Sjdp linenumber address data  source
3433965Sjdp linenumber address data  source
3533965Sjdp
3633965Sjdp If not overridden, the listing commands are:
3733965Sjdp
3833965Sjdp .title  "stuff"
3933965Sjdp 	Put "stuff" onto the title line
4033965Sjdp .sbttl  "stuff"
4133965Sjdp        Put stuff onto the subtitle line
4233965Sjdp
4333965Sjdp  If these commands come within 10 lines of the top of the page, they
4433965Sjdp  will affect the page they are on, as well as any subsequent page
4533965Sjdp
4633965Sjdp .eject
4733965Sjdp 	Thow a page
4833965Sjdp .list
4933965Sjdp 	Increment the enable listing counter
5033965Sjdp .nolist
5133965Sjdp 	Decrement the enable listing counter
5233965Sjdp
5333965Sjdp .psize Y[,X]
5433965Sjdp 	Set the paper size to X wide and Y high. Setting a psize Y of
5533965Sjdp	zero will suppress form feeds except where demanded by .eject
5633965Sjdp
5733965Sjdp If the counter goes below zero, listing is suppressed.
5833965Sjdp
5933965Sjdp Listings are a maintained by read calling various listing_<foo>
6033965Sjdp functions.  What happens most is that the macro NO_LISTING is not
6133965Sjdp defined (from the Makefile), then the macro LISTING_NEWLINE expands
6233965Sjdp into a call to listing_newline.  The call is done from read.c, every
6333965Sjdp time it sees a newline, and -l is on the command line.
6433965Sjdp
6533965Sjdp The function listing_newline remembers the frag associated with the
6633965Sjdp newline, and creates a new frag - note that this is wasteful, but not
6733965Sjdp a big deal, since listing slows things down a lot anyway.  The
6833965Sjdp function also rememebers when the filename changes.
6933965Sjdp
7033965Sjdp When all the input has finished, and gas has had a chance to settle
7133965Sjdp down, the listing is output. This is done by running down the list of
7233965Sjdp frag/source file records, and opening the files as needed and printing
7333965Sjdp out the bytes and chars associated with them.
7433965Sjdp
7533965Sjdp The only things which the architecture can change about the listing
7633965Sjdp are defined in these macros:
7733965Sjdp
7833965Sjdp LISTING_HEADER		The name of the architecture
7933965Sjdp LISTING_WORD_SIZE      The make of the number of bytes in a word, this determines
8033965Sjdp 			the clumping of the output data. eg a value of
8133965Sjdp			2 makes words look like 1234 5678, whilst 1
8233965Sjdp			would make the same value look like 12 34 56
8333965Sjdp			78
8433965Sjdp LISTING_LHS_WIDTH      Number of words of above size for the lhs
8533965Sjdp
8633965Sjdp LISTING_LHS_WIDTH_SECOND   Number of words for the data on the lhs
8733965Sjdp 			for the second line
8833965Sjdp
8933965Sjdp LISTING_LHS_CONT_LINES	Max number of lines to use up for a continutation
9033965Sjdp LISTING_RHS_WIDTH      Number of chars from the input file to print
9133965Sjdp                        on a line
9233965Sjdp*/
9333965Sjdp
9433965Sjdp#include "as.h"
95104834Sobrien#include "obstack.h"
9689857Sobrien#include "safe-ctype.h"
9733965Sjdp#include "input-file.h"
9833965Sjdp#include "subsegs.h"
9933965Sjdp
10033965Sjdp#ifndef NO_LISTING
10138889Sjdp
10233965Sjdp#ifndef LISTING_HEADER
10333965Sjdp#define LISTING_HEADER "GAS LISTING"
10433965Sjdp#endif
10533965Sjdp#ifndef LISTING_WORD_SIZE
10633965Sjdp#define LISTING_WORD_SIZE 4
10733965Sjdp#endif
10833965Sjdp#ifndef LISTING_LHS_WIDTH
10960484Sobrien#define LISTING_LHS_WIDTH ((LISTING_WORD_SIZE) > 4 ? 1 : 4 / (LISTING_WORD_SIZE))
11033965Sjdp#endif
11133965Sjdp#ifndef LISTING_LHS_WIDTH_SECOND
11260484Sobrien#define LISTING_LHS_WIDTH_SECOND LISTING_LHS_WIDTH
11333965Sjdp#endif
11433965Sjdp#ifndef LISTING_RHS_WIDTH
11533965Sjdp#define LISTING_RHS_WIDTH 100
11633965Sjdp#endif
11733965Sjdp#ifndef LISTING_LHS_CONT_LINES
11833965Sjdp#define LISTING_LHS_CONT_LINES 4
11933965Sjdp#endif
12033965Sjdp
12177298Sobrien/* This structure remembers which .s were used.  */
12277298Sobrientypedef struct file_info_struct {
12360484Sobrien  struct file_info_struct * next;
12460484Sobrien  char *                    filename;
12560484Sobrien  long                      pos;
12660484Sobrien  unsigned int              linenum;
12760484Sobrien  int                       at_end;
12877298Sobrien} file_info_type;
12933965Sjdp
13060484Sobrien/* This structure rememebrs which line from which file goes into which
13177298Sobrien   frag.  */
13277298Sobrienstruct list_info_struct {
13377298Sobrien  /* Frag which this line of source is nearest to.  */
13477298Sobrien  fragS *frag;
13538889Sjdp
13677298Sobrien  /* The actual line in the source file.  */
13733965Sjdp  unsigned int line;
13833965Sjdp  /* Pointer to the file info struct for the file which this line
13977298Sobrien     belongs to.  */
14077298Sobrien  file_info_type *file;
14133965Sjdp
14238889Sjdp  /* The expanded text of any macro that may have been executing.  */
14377298Sobrien  char *line_contents;
14438889Sjdp
14577298Sobrien  /* Next in list.  */
14677298Sobrien  struct list_info_struct *next;
14733965Sjdp
14833965Sjdp  /* Pointer to the file info struct for the high level language
14977298Sobrien     source line that belongs here.  */
15077298Sobrien  file_info_type *hll_file;
15177298Sobrien  /* High level language source line.  */
15238889Sjdp  unsigned int hll_line;
15333965Sjdp
15477298Sobrien  /* Pointer to any error message associated with this line.  */
15577298Sobrien  char *message;
15633965Sjdp
15777298Sobrien  enum {
15877298Sobrien    EDICT_NONE,
15977298Sobrien    EDICT_SBTTL,
16077298Sobrien    EDICT_TITLE,
16177298Sobrien    EDICT_NOLIST,
16277298Sobrien    EDICT_LIST,
16377298Sobrien    EDICT_NOLIST_NEXT,
16477298Sobrien    EDICT_EJECT
16577298Sobrien  } edict;
16677298Sobrien  char *edict_arg;
16733965Sjdp
16838889Sjdp  /* Nonzero if this line is to be omitted because it contains
16938889Sjdp     debugging information.  This can become a flags field if we come
17038889Sjdp     up with more information to store here.  */
17138889Sjdp  int debugging;
17238889Sjdp};
17333965Sjdp
17438889Sjdptypedef struct list_info_struct list_info_type;
17533965Sjdp
17660484Sobrienint listing_lhs_width        = LISTING_LHS_WIDTH;
17760484Sobrienint listing_lhs_width_second = LISTING_LHS_WIDTH_SECOND;
17860484Sobrienint listing_lhs_cont_lines   = LISTING_LHS_CONT_LINES;
17960484Sobrienint listing_rhs_width        = LISTING_RHS_WIDTH;
18033965Sjdp
18160484Sobrienstruct list_info_struct *        listing_tail;
18260484Sobrien
18360484Sobrienstatic file_info_type *          file_info_head;
18460484Sobrienstatic file_info_type *          last_open_file_info;
18560484Sobrienstatic FILE *                    last_open_file;
18660484Sobrienstatic struct list_info_struct * head;
18760484Sobrienstatic int                       paper_width = 200;
18860484Sobrienstatic int                       paper_height = 60;
18960484Sobrien
19060484Sobrienextern int                       listing;
19160484Sobrien
19233965Sjdp/* File to output listings to.  */
19377298Sobrienstatic FILE *list_file;
19433965Sjdp
19538889Sjdp/* This static array is used to keep the text of data to be printed
19638889Sjdp   before the start of the line.  */
19733965Sjdp
19838889Sjdp#define MAX_BYTES							\
19938889Sjdp  (((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width			\
20038889Sjdp   + ((((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second)	\
20138889Sjdp      * listing_lhs_cont_lines)						\
20238889Sjdp   + 20)
20333965Sjdp
20477298Sobrienstatic char *data_buffer;
20533965Sjdp
20633965Sjdp/* Prototypes.  */
20733965Sjdpstatic void listing_message PARAMS ((const char *name, const char *message));
20877298Sobrienstatic file_info_type *file_info PARAMS ((const char *file_name));
20933965Sjdpstatic void new_frag PARAMS ((void));
21077298Sobrienstatic char *buffer_line PARAMS ((file_info_type *file,
21133965Sjdp				  char *line, unsigned int size));
21233965Sjdpstatic void listing_page PARAMS ((list_info_type *list));
21333965Sjdpstatic unsigned int calc_hex PARAMS ((list_info_type *list));
21433965Sjdpstatic void print_lines PARAMS ((list_info_type *, unsigned int,
21533965Sjdp				 char *, unsigned int));
21633965Sjdpstatic void list_symbol_table PARAMS ((void));
21733965Sjdpstatic void print_source PARAMS ((file_info_type *current_file,
21833965Sjdp				  list_info_type *list,
21933965Sjdp				  char *buffer,
22033965Sjdp				  unsigned int width));
22138889Sjdpstatic int debugging_pseudo PARAMS ((list_info_type *, const char *));
22233965Sjdpstatic void listing_listing PARAMS ((char *name));
22333965Sjdp
22433965Sjdpstatic void
22533965Sjdplisting_message (name, message)
22633965Sjdp     const char *name;
22733965Sjdp     const char *message;
22833965Sjdp{
22933965Sjdp  if (listing_tail != (list_info_type *) NULL)
23033965Sjdp    {
23177298Sobrien      unsigned int l = strlen (name) + strlen (message) + 1;
23277298Sobrien      char *n = (char *) xmalloc (l);
23377298Sobrien      strcpy (n, name);
23477298Sobrien      strcat (n, message);
23533965Sjdp      listing_tail->message = n;
23633965Sjdp    }
23733965Sjdp}
23833965Sjdp
23933965Sjdpvoid
24033965Sjdplisting_warning (message)
24133965Sjdp     const char *message;
24233965Sjdp{
24360484Sobrien  listing_message (_("Warning:"), message);
24433965Sjdp}
24533965Sjdp
24633965Sjdpvoid
24733965Sjdplisting_error (message)
24833965Sjdp     const char *message;
24933965Sjdp{
25060484Sobrien  listing_message (_("Error:"), message);
25133965Sjdp}
25233965Sjdp
25333965Sjdpstatic file_info_type *
25433965Sjdpfile_info (file_name)
25533965Sjdp     const char *file_name;
25633965Sjdp{
25777298Sobrien  /* Find an entry with this file name.  */
25833965Sjdp  file_info_type *p = file_info_head;
25933965Sjdp
26033965Sjdp  while (p != (file_info_type *) NULL)
26133965Sjdp    {
26233965Sjdp      if (strcmp (p->filename, file_name) == 0)
26333965Sjdp	return p;
26433965Sjdp      p = p->next;
26533965Sjdp    }
26633965Sjdp
26777298Sobrien  /* Make new entry.  */
26833965Sjdp
26933965Sjdp  p = (file_info_type *) xmalloc (sizeof (file_info_type));
27033965Sjdp  p->next = file_info_head;
27133965Sjdp  file_info_head = p;
272104834Sobrien  p->filename = xstrdup (file_name);
27338889Sjdp  p->pos = 0;
27433965Sjdp  p->linenum = 0;
27533965Sjdp  p->at_end = 0;
27633965Sjdp
27733965Sjdp  return p;
27833965Sjdp}
27933965Sjdp
28033965Sjdpstatic void
28133965Sjdpnew_frag ()
28233965Sjdp{
28333965Sjdp
28433965Sjdp  frag_wane (frag_now);
28533965Sjdp  frag_new (0);
28633965Sjdp
28733965Sjdp}
28833965Sjdp
28933965Sjdpvoid
29033965Sjdplisting_newline (ps)
29133965Sjdp     char *ps;
29233965Sjdp{
29333965Sjdp  char *file;
29433965Sjdp  unsigned int line;
29533965Sjdp  static unsigned int last_line = 0xffff;
29633965Sjdp  static char *last_file = NULL;
29738889Sjdp  list_info_type *new = NULL;
29833965Sjdp
29933965Sjdp  if (listing == 0)
30033965Sjdp    return;
30133965Sjdp
30233965Sjdp  if (now_seg == absolute_section)
30333965Sjdp    return;
30433965Sjdp
30538889Sjdp#ifdef OBJ_ELF
30638889Sjdp  /* In ELF, anything in a section beginning with .debug or .line is
30738889Sjdp     considered to be debugging information.  This includes the
30838889Sjdp     statement which switches us into the debugging section, which we
30938889Sjdp     can only set after we are already in the debugging section.  */
31038889Sjdp  if ((listing & LISTING_NODEBUG) != 0
31138889Sjdp      && listing_tail != NULL
31238889Sjdp      && ! listing_tail->debugging)
31338889Sjdp    {
31438889Sjdp      const char *segname;
31538889Sjdp
31638889Sjdp      segname = segment_name (now_seg);
31738889Sjdp      if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
31838889Sjdp	  || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
31938889Sjdp	listing_tail->debugging = 1;
32038889Sjdp    }
32138889Sjdp#endif
32238889Sjdp
32333965Sjdp  as_where (&file, &line);
32438889Sjdp  if (ps == NULL)
32533965Sjdp    {
32677298Sobrien      if (line == last_line
32777298Sobrien	  && !(last_file && file && strcmp (file, last_file)))
32838889Sjdp	return;
32933965Sjdp
33033965Sjdp      new = (list_info_type *) xmalloc (sizeof (list_info_type));
33160484Sobrien
33260484Sobrien      /* Detect if we are reading from stdin by examining the file
33360484Sobrien	 name returned by as_where().
33460484Sobrien
33560484Sobrien	 [FIXME: We rely upon the name in the strcmp below being the
33660484Sobrien	 same as the one used by input_scrub_new_file(), if that is
33760484Sobrien	 not true, then this code will fail].
33860484Sobrien
33977298Sobrien	 If we are reading from stdin, then we need to save each input
34077298Sobrien	 line here (assuming of course that we actually have a line of
34177298Sobrien	 input to read), so that it can be displayed in the listing
34277298Sobrien	 that is produced at the end of the assembly.  */
34360484Sobrien      if (strcmp (file, _("{standard input}")) == 0
34460484Sobrien	  && input_line_pointer != NULL)
34560484Sobrien	{
34677298Sobrien	  char *copy;
34760484Sobrien	  int len;
34860484Sobrien	  int seen_quote = 0;
34960484Sobrien
35060484Sobrien	  for (copy = input_line_pointer - 1;
35177298Sobrien	       *copy && (seen_quote
35277298Sobrien			 || (! is_end_of_line [(unsigned char) *copy]));
35377298Sobrien	       copy++)
35477298Sobrien	    if (*copy == '"' && copy[-1] != '\\')
35560484Sobrien	      seen_quote = ! seen_quote;
35660484Sobrien
35760484Sobrien	  len = (copy - input_line_pointer) + 2;
35860484Sobrien
35960484Sobrien	  copy = xmalloc (len);
36060484Sobrien
36160484Sobrien	  if (copy != NULL)
36260484Sobrien	    {
36377298Sobrien	      char *src = input_line_pointer - 1;
36477298Sobrien	      char *dest = copy;
36577298Sobrien
36660484Sobrien	      while (--len)
36760484Sobrien		{
36877298Sobrien		  unsigned char c = *src++;
36960484Sobrien
37060484Sobrien		  /* Omit control characters in the listing.  */
37189857Sobrien		  if (!ISCNTRL (c))
37277298Sobrien		    *dest++ = c;
37360484Sobrien		}
37477298Sobrien
37560484Sobrien	      *dest = 0;
37660484Sobrien	    }
37777298Sobrien
37860484Sobrien	  new->line_contents = copy;
37960484Sobrien	}
38060484Sobrien      else
38160484Sobrien	new->line_contents = NULL;
38238889Sjdp    }
38338889Sjdp  else
38438889Sjdp    {
38538889Sjdp      new = (list_info_type *) xmalloc (sizeof (list_info_type));
38638889Sjdp      new->line_contents = ps;
38738889Sjdp    }
38833965Sjdp
38938889Sjdp  last_line = line;
39038889Sjdp  last_file = file;
39177298Sobrien
39238889Sjdp  new_frag ();
39338889Sjdp
39438889Sjdp  if (listing_tail)
39560484Sobrien    listing_tail->next = new;
39638889Sjdp  else
39760484Sobrien    head = new;
39877298Sobrien
39938889Sjdp  listing_tail = new;
40038889Sjdp
40138889Sjdp  new->frag = frag_now;
40238889Sjdp  new->line = line;
40338889Sjdp  new->file = file_info (file);
40438889Sjdp  new->next = (list_info_type *) NULL;
40538889Sjdp  new->message = (char *) NULL;
40638889Sjdp  new->edict = EDICT_NONE;
40738889Sjdp  new->hll_file = (file_info_type *) NULL;
40838889Sjdp  new->hll_line = 0;
40938889Sjdp  new->debugging = 0;
41077298Sobrien
41138889Sjdp  new_frag ();
41238889Sjdp
41338889Sjdp#ifdef OBJ_ELF
41438889Sjdp  /* In ELF, anything in a section beginning with .debug or .line is
41538889Sjdp     considered to be debugging information.  */
41638889Sjdp  if ((listing & LISTING_NODEBUG) != 0)
41738889Sjdp    {
41838889Sjdp      const char *segname;
41938889Sjdp
42038889Sjdp      segname = segment_name (now_seg);
42138889Sjdp      if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
42238889Sjdp	  || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
42338889Sjdp	new->debugging = 1;
42438889Sjdp    }
42538889Sjdp#endif
42633965Sjdp}
42733965Sjdp
42833965Sjdp/* Attach all current frags to the previous line instead of the
42933965Sjdp   current line.  This is called by the MIPS backend when it discovers
43033965Sjdp   that it needs to add some NOP instructions; the added NOP
43133965Sjdp   instructions should go with the instruction that has the delay, not
43233965Sjdp   with the new instruction.  */
43333965Sjdp
43433965Sjdpvoid
43533965Sjdplisting_prev_line ()
43633965Sjdp{
43733965Sjdp  list_info_type *l;
43833965Sjdp  fragS *f;
43933965Sjdp
44033965Sjdp  if (head == (list_info_type *) NULL
44133965Sjdp      || head == listing_tail)
44233965Sjdp    return;
44333965Sjdp
44433965Sjdp  new_frag ();
44533965Sjdp
44633965Sjdp  for (l = head; l->next != listing_tail; l = l->next)
44733965Sjdp    ;
44833965Sjdp
44933965Sjdp  for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next)
45033965Sjdp    if (f->line == listing_tail)
45133965Sjdp      f->line = l;
45233965Sjdp
45333965Sjdp  listing_tail->frag = frag_now;
45433965Sjdp  new_frag ();
45533965Sjdp}
45633965Sjdp
45777298Sobrien/* This function returns the next source line from the file supplied,
45877298Sobrien   truncated to size.  It appends a fake line to the end of each input
45977298Sobrien   file to make.  */
46033965Sjdp
46133965Sjdpstatic char *
46233965Sjdpbuffer_line (file, line, size)
46377298Sobrien     file_info_type *file;
46433965Sjdp     char *line;
46533965Sjdp     unsigned int size;
46633965Sjdp{
46733965Sjdp  unsigned int count = 0;
46833965Sjdp  int c;
46933965Sjdp
47033965Sjdp  char *p = line;
47133965Sjdp
47277298Sobrien  /* If we couldn't open the file, return an empty line.  */
47338889Sjdp  if (file->at_end)
47438889Sjdp    return "";
47538889Sjdp
47638889Sjdp  /* Check the cache and see if we last used this file.  */
47738889Sjdp  if (!last_open_file_info || file != last_open_file_info)
47833965Sjdp    {
47938889Sjdp      if (last_open_file)
48038889Sjdp	{
48138889Sjdp	  last_open_file_info->pos = ftell (last_open_file);
48238889Sjdp	  fclose (last_open_file);
48338889Sjdp	}
48438889Sjdp
48538889Sjdp      last_open_file_info = file;
48689857Sobrien      last_open_file = fopen (file->filename, FOPEN_RT);
48738889Sjdp      if (last_open_file == NULL)
48838889Sjdp	{
48938889Sjdp	  file->at_end = 1;
49038889Sjdp	  return "";
49138889Sjdp	}
49277298Sobrien
49338889Sjdp      /* Seek to where we were last time this file was open.  */
49438889Sjdp      if (file->pos)
49577298Sobrien	fseek (last_open_file, file->pos, SEEK_SET);
49633965Sjdp    }
49733965Sjdp
49838889Sjdp  c = fgetc (last_open_file);
49933965Sjdp
50077298Sobrien  /* Leave room for null.  */
50177298Sobrien  size -= 1;
50233965Sjdp
50333965Sjdp  while (c != EOF && c != '\n')
50433965Sjdp    {
50533965Sjdp      if (count < size)
50633965Sjdp	*p++ = c;
50733965Sjdp      count++;
50833965Sjdp
50938889Sjdp      c = fgetc (last_open_file);
51033965Sjdp
51133965Sjdp    }
51233965Sjdp  if (c == EOF)
51333965Sjdp    {
51433965Sjdp      file->at_end = 1;
51589857Sobrien      if (count + 2 < size)
51689857Sobrien	{
51789857Sobrien	  *p++ = '.';
51889857Sobrien	  *p++ = '.';
51989857Sobrien	  *p++ = '.';
52089857Sobrien	}
52133965Sjdp    }
52233965Sjdp  file->linenum++;
52333965Sjdp  *p++ = 0;
52433965Sjdp  return line;
52533965Sjdp}
52633965Sjdp
52733965Sjdpstatic const char *fn;
52833965Sjdp
52933965Sjdpstatic unsigned int eject;	/* Eject pending */
53033965Sjdpstatic unsigned int page;	/* Current page number */
53177298Sobrienstatic char *title;		/* Current title */
53277298Sobrienstatic char *subtitle;		/* Current subtitle */
53377298Sobrienstatic unsigned int on_page;	/* Number of lines printed on current page */
53433965Sjdp
53533965Sjdpstatic void
53633965Sjdplisting_page (list)
53733965Sjdp     list_info_type *list;
53833965Sjdp{
53933965Sjdp  /* Grope around, see if we can see a title or subtitle edict coming up
54077298Sobrien     soon.  (we look down 10 lines of the page and see if it's there)  */
54177298Sobrien  if ((eject || (on_page >= (unsigned int) paper_height))
54277298Sobrien      && paper_height != 0)
54333965Sjdp    {
54433965Sjdp      unsigned int c = 10;
54533965Sjdp      int had_title = 0;
54633965Sjdp      int had_subtitle = 0;
54733965Sjdp
54833965Sjdp      page++;
54933965Sjdp
55033965Sjdp      while (c != 0 && list)
55133965Sjdp	{
55233965Sjdp	  if (list->edict == EDICT_SBTTL && !had_subtitle)
55333965Sjdp	    {
55433965Sjdp	      had_subtitle = 1;
55533965Sjdp	      subtitle = list->edict_arg;
55633965Sjdp	    }
55733965Sjdp	  if (list->edict == EDICT_TITLE && !had_title)
55833965Sjdp	    {
55933965Sjdp	      had_title = 1;
56033965Sjdp	      title = list->edict_arg;
56133965Sjdp	    }
56233965Sjdp	  list = list->next;
56333965Sjdp	  c--;
56433965Sjdp	}
56533965Sjdp
56633965Sjdp      if (page > 1)
56733965Sjdp	{
56833965Sjdp	  fprintf (list_file, "\f");
56933965Sjdp	}
57033965Sjdp
57133965Sjdp      fprintf (list_file, "%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
57233965Sjdp      fprintf (list_file, "%s\n", title);
57333965Sjdp      fprintf (list_file, "%s\n", subtitle);
57433965Sjdp      on_page = 3;
57533965Sjdp      eject = 0;
57633965Sjdp    }
57733965Sjdp}
57833965Sjdp
57933965Sjdpstatic unsigned int
58033965Sjdpcalc_hex (list)
58177298Sobrien     list_info_type *list;
58233965Sjdp{
58338889Sjdp  int data_buffer_size;
58433965Sjdp  list_info_type *first = list;
58577298Sobrien  unsigned int address = ~(unsigned int) 0;
58633965Sjdp  fragS *frag;
58733965Sjdp  fragS *frag_ptr;
58860484Sobrien  unsigned int octet_in_frag;
58933965Sjdp
59077298Sobrien  /* Find first frag which says it belongs to this line.  */
59133965Sjdp  frag = list->frag;
59233965Sjdp  while (frag && frag->line != list)
59333965Sjdp    frag = frag->fr_next;
59433965Sjdp
59533965Sjdp  frag_ptr = frag;
59633965Sjdp
59733965Sjdp  data_buffer_size = 0;
59833965Sjdp
59977298Sobrien  /* Dump all the frags which belong to this line.  */
60033965Sjdp  while (frag_ptr != (fragS *) NULL && frag_ptr->line == first)
60133965Sjdp    {
60277298Sobrien      /* Print as many bytes from the fixed part as is sensible.  */
60360484Sobrien      octet_in_frag = 0;
60460484Sobrien      while ((offsetT) octet_in_frag < frag_ptr->fr_fix
60538889Sjdp	     && data_buffer_size < MAX_BYTES - 3)
60633965Sjdp	{
60777298Sobrien	  if (address == ~(unsigned int) 0)
60833965Sjdp	    {
60960484Sobrien	      address = frag_ptr->fr_address / OCTETS_PER_BYTE;
61033965Sjdp	    }
61133965Sjdp
61233965Sjdp	  sprintf (data_buffer + data_buffer_size,
61333965Sjdp		   "%02X",
61460484Sobrien		   (frag_ptr->fr_literal[octet_in_frag]) & 0xff);
61533965Sjdp	  data_buffer_size += 2;
61660484Sobrien	  octet_in_frag++;
61733965Sjdp	}
618104834Sobrien      if (frag_ptr->fr_type == rs_fill)
619104834Sobrien	{
620104834Sobrien	  unsigned int var_rep_max = octet_in_frag;
621104834Sobrien	  unsigned int var_rep_idx = octet_in_frag;
62233965Sjdp
623104834Sobrien	  /* Print as many bytes from the variable part as is sensible.  */
624104834Sobrien	  while (((offsetT) octet_in_frag
625104834Sobrien		  < (frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset))
626104834Sobrien		 && data_buffer_size < MAX_BYTES - 3)
627104834Sobrien	    {
628104834Sobrien	      if (address == ~(unsigned int) 0)
629104834Sobrien		{
630104834Sobrien		  address = frag_ptr->fr_address / OCTETS_PER_BYTE;
631104834Sobrien		}
632104834Sobrien	      sprintf (data_buffer + data_buffer_size,
633104834Sobrien		       "%02X",
634104834Sobrien		       (frag_ptr->fr_literal[var_rep_idx]) & 0xff);
63533965Sjdp#if 0
636104834Sobrien	      data_buffer[data_buffer_size++] = '*';
637104834Sobrien	      data_buffer[data_buffer_size++] = '*';
63833965Sjdp#endif
639104834Sobrien	      data_buffer_size += 2;
64033965Sjdp
641104834Sobrien	      var_rep_idx++;
642104834Sobrien	      octet_in_frag++;
64333965Sjdp
644104834Sobrien	      if ((offsetT) var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var)
645104834Sobrien		var_rep_idx = var_rep_max;
646104834Sobrien	    }
647104834Sobrien	}
64833965Sjdp
64933965Sjdp      frag_ptr = frag_ptr->fr_next;
65033965Sjdp    }
65138889Sjdp  data_buffer[data_buffer_size] = '\0';
65233965Sjdp  return address;
65333965Sjdp}
65433965Sjdp
65533965Sjdpstatic void
65633965Sjdpprint_lines (list, lineno, string, address)
65733965Sjdp     list_info_type *list;
65833965Sjdp     unsigned int lineno;
65933965Sjdp     char *string;
66033965Sjdp     unsigned int address;
66133965Sjdp{
66233965Sjdp  unsigned int idx;
66333965Sjdp  unsigned int nchars;
66433965Sjdp  unsigned int lines;
66560484Sobrien  unsigned int octet_in_word = 0;
66633965Sjdp  char *src = data_buffer;
66760484Sobrien  int cur;
66833965Sjdp
66977298Sobrien  /* Print the stuff on the first line.  */
67033965Sjdp  listing_page (list);
67138889Sjdp  nchars = (LISTING_WORD_SIZE * 2 + 1) * listing_lhs_width;
67277298Sobrien
67377298Sobrien  /* Print the hex for the first line.  */
67477298Sobrien  if (address == ~(unsigned int) 0)
67533965Sjdp    {
67633965Sjdp      fprintf (list_file, "% 4d     ", lineno);
67733965Sjdp      for (idx = 0; idx < nchars; idx++)
67833965Sjdp	fprintf (list_file, " ");
67933965Sjdp
68033965Sjdp      fprintf (list_file, "\t%s\n", string ? string : "");
68177298Sobrien
68277298Sobrien      on_page++;
68377298Sobrien
68433965Sjdp      listing_page (0);
68533965Sjdp
68660484Sobrien      return;
68733965Sjdp    }
68860484Sobrien
68960484Sobrien  if (had_errors ())
69060484Sobrien    fprintf (list_file, "% 4d ???? ", lineno);
69133965Sjdp  else
69260484Sobrien    fprintf (list_file, "% 4d %04x ", lineno, address);
69360484Sobrien
69477298Sobrien  /* And the data to go along with it.  */
69560484Sobrien  idx = 0;
69660484Sobrien  cur = 0;
69760484Sobrien  while (src[cur] && idx < nchars)
69833965Sjdp    {
69960484Sobrien      int offset;
70060484Sobrien      offset = cur;
70177298Sobrien      fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
70260484Sobrien      cur += 2;
70360484Sobrien      octet_in_word++;
70477298Sobrien
70560484Sobrien      if (octet_in_word == LISTING_WORD_SIZE)
70633965Sjdp	{
70760484Sobrien	  fprintf (list_file, " ");
70860484Sobrien	  idx++;
70960484Sobrien	  octet_in_word = 0;
71033965Sjdp	}
71177298Sobrien
71260484Sobrien      idx += 2;
71360484Sobrien    }
71477298Sobrien
71560484Sobrien  for (; idx < nchars; idx++)
71660484Sobrien    fprintf (list_file, " ");
71777298Sobrien
71860484Sobrien  fprintf (list_file, "\t%s\n", string ? string : "");
71960484Sobrien  on_page++;
72060484Sobrien  listing_page (list);
72177298Sobrien
72260484Sobrien  if (list->message)
72360484Sobrien    {
72460484Sobrien      fprintf (list_file, "****  %s\n", list->message);
72560484Sobrien      listing_page (list);
72660484Sobrien      on_page++;
72760484Sobrien    }
72877298Sobrien
72960484Sobrien  for (lines = 0;
73060484Sobrien       lines < (unsigned int) listing_lhs_cont_lines
73160484Sobrien	 && src[cur];
73277298Sobrien       lines++)
73360484Sobrien    {
73477298Sobrien      nchars = ((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second - 1;
73533965Sjdp      idx = 0;
73677298Sobrien
73777298Sobrien      /* Print any more lines of data, but more compactly.  */
73860484Sobrien      fprintf (list_file, "% 4d      ", lineno);
73977298Sobrien
74060484Sobrien      while (src[cur] && idx < nchars)
74133965Sjdp	{
74277298Sobrien	  int offset;
74377298Sobrien	  offset = cur;
74477298Sobrien	  fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
74560484Sobrien	  cur += 2;
74660484Sobrien	  idx += 2;
74760484Sobrien	  octet_in_word++;
74877298Sobrien
74960484Sobrien	  if (octet_in_word == LISTING_WORD_SIZE)
75033965Sjdp	    {
75133965Sjdp	      fprintf (list_file, " ");
75233965Sjdp	      idx++;
75360484Sobrien	      octet_in_word = 0;
75433965Sjdp	    }
75533965Sjdp	}
75677298Sobrien
75760484Sobrien      fprintf (list_file, "\n");
75877298Sobrien      on_page++;
75933965Sjdp      listing_page (list);
76033965Sjdp    }
76133965Sjdp}
76233965Sjdp
76333965Sjdpstatic void
76433965Sjdplist_symbol_table ()
76533965Sjdp{
76633965Sjdp  extern symbolS *symbol_rootP;
76733965Sjdp  int got_some = 0;
76833965Sjdp
76933965Sjdp  symbolS *ptr;
77033965Sjdp  eject = 1;
77133965Sjdp  listing_page (0);
77233965Sjdp
77333965Sjdp  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
77433965Sjdp    {
77538889Sjdp      if (SEG_NORMAL (S_GET_SEGMENT (ptr))
77638889Sjdp	  || S_GET_SEGMENT (ptr) == absolute_section)
77733965Sjdp	{
77838889Sjdp#ifdef BFD_ASSEMBLER
77938889Sjdp	  /* Don't report section symbols.  They are not interesting.  */
78060484Sobrien	  if (symbol_section_p (ptr))
78138889Sjdp	    continue;
78238889Sjdp#endif
78333965Sjdp	  if (S_GET_NAME (ptr))
78433965Sjdp	    {
78533965Sjdp	      char buf[30], fmt[8];
78633965Sjdp	      valueT val = S_GET_VALUE (ptr);
78733965Sjdp
78833965Sjdp	      /* @@ Note that this is dependent on the compilation options,
78933965Sjdp		 not solely on the target characteristics.  */
79033965Sjdp	      if (sizeof (val) == 4 && sizeof (int) == 4)
79133965Sjdp		sprintf (buf, "%08lx", (unsigned long) val);
79233965Sjdp	      else if (sizeof (val) <= sizeof (unsigned long))
79333965Sjdp		{
79433965Sjdp		  sprintf (fmt, "%%0%lulx",
79533965Sjdp			   (unsigned long) (sizeof (val) * 2));
79633965Sjdp		  sprintf (buf, fmt, (unsigned long) val);
79733965Sjdp		}
79833965Sjdp#if defined (BFD64)
79933965Sjdp	      else if (sizeof (val) > 4)
80033965Sjdp		sprintf_vma (buf, val);
80133965Sjdp#endif
80233965Sjdp	      else
80333965Sjdp		abort ();
80433965Sjdp
80533965Sjdp	      if (!got_some)
80633965Sjdp		{
80733965Sjdp		  fprintf (list_file, "DEFINED SYMBOLS\n");
80833965Sjdp		  on_page++;
80933965Sjdp		  got_some = 1;
81033965Sjdp		}
81133965Sjdp
81260484Sobrien	      if (symbol_get_frag (ptr) && symbol_get_frag (ptr)->line)
81338889Sjdp		{
81438889Sjdp		  fprintf (list_file, "%20s:%-5d  %s:%s %s\n",
81560484Sobrien			   symbol_get_frag (ptr)->line->file->filename,
81660484Sobrien			   symbol_get_frag (ptr)->line->line,
81738889Sjdp			   segment_name (S_GET_SEGMENT (ptr)),
81838889Sjdp			   buf, S_GET_NAME (ptr));
81938889Sjdp		}
82038889Sjdp	      else
82138889Sjdp		{
82238889Sjdp		  fprintf (list_file, "%33s:%s %s\n",
82338889Sjdp			   segment_name (S_GET_SEGMENT (ptr)),
82438889Sjdp			   buf, S_GET_NAME (ptr));
82538889Sjdp		}
82633965Sjdp
82777298Sobrien	      on_page++;
82833965Sjdp	      listing_page (0);
82933965Sjdp	    }
83033965Sjdp	}
83133965Sjdp
83233965Sjdp    }
83333965Sjdp  if (!got_some)
83433965Sjdp    {
83533965Sjdp      fprintf (list_file, "NO DEFINED SYMBOLS\n");
83633965Sjdp      on_page++;
83733965Sjdp    }
83833965Sjdp  fprintf (list_file, "\n");
83933965Sjdp  on_page++;
84033965Sjdp  listing_page (0);
84133965Sjdp
84233965Sjdp  got_some = 0;
84333965Sjdp
84433965Sjdp  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
84533965Sjdp    {
84633965Sjdp      if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
84733965Sjdp	{
84838889Sjdp	  if (S_GET_SEGMENT (ptr) == undefined_section)
84933965Sjdp	    {
85033965Sjdp	      if (!got_some)
85133965Sjdp		{
85233965Sjdp		  got_some = 1;
85333965Sjdp		  fprintf (list_file, "UNDEFINED SYMBOLS\n");
85433965Sjdp		  on_page++;
85533965Sjdp		  listing_page (0);
85633965Sjdp		}
85733965Sjdp	      fprintf (list_file, "%s\n", S_GET_NAME (ptr));
85833965Sjdp	      on_page++;
85933965Sjdp	      listing_page (0);
86033965Sjdp	    }
86133965Sjdp	}
86233965Sjdp    }
86333965Sjdp  if (!got_some)
86433965Sjdp    {
86533965Sjdp      fprintf (list_file, "NO UNDEFINED SYMBOLS\n");
86633965Sjdp      on_page++;
86733965Sjdp      listing_page (0);
86833965Sjdp    }
86933965Sjdp}
87033965Sjdp
87133965Sjdpstatic void
87233965Sjdpprint_source (current_file, list, buffer, width)
87333965Sjdp     file_info_type *current_file;
87433965Sjdp     list_info_type *list;
87533965Sjdp     char *buffer;
87633965Sjdp     unsigned int width;
87733965Sjdp{
87838889Sjdp  if (!current_file->at_end)
87933965Sjdp    {
88033965Sjdp      while (current_file->linenum < list->hll_line
88133965Sjdp	     && !current_file->at_end)
88233965Sjdp	{
88333965Sjdp	  char *p = buffer_line (current_file, buffer, width);
88438889Sjdp	  fprintf (list_file, "%4u:%-13s **** %s\n", current_file->linenum,
88533965Sjdp		   current_file->filename, p);
88633965Sjdp	  on_page++;
88733965Sjdp	  listing_page (list);
88833965Sjdp	}
88933965Sjdp    }
89033965Sjdp}
89133965Sjdp
89233965Sjdp/* Sometimes the user doesn't want to be bothered by the debugging
89338889Sjdp   records inserted by the compiler, see if the line is suspicious.  */
89433965Sjdp
89533965Sjdpstatic int
89638889Sjdpdebugging_pseudo (list, line)
89738889Sjdp     list_info_type *list;
89838889Sjdp     const char *line;
89933965Sjdp{
90038889Sjdp  static int in_debug;
90138889Sjdp  int was_debug;
90238889Sjdp
90338889Sjdp  if (list->debugging)
90438889Sjdp    {
90538889Sjdp      in_debug = 1;
90638889Sjdp      return 1;
90738889Sjdp    }
90838889Sjdp
90938889Sjdp  was_debug = in_debug;
91038889Sjdp  in_debug = 0;
91138889Sjdp
91289857Sobrien  while (ISSPACE (*line))
91333965Sjdp    line++;
91433965Sjdp
91533965Sjdp  if (*line != '.')
91638889Sjdp    {
91738889Sjdp#ifdef OBJ_ELF
91838889Sjdp      /* The ELF compiler sometimes emits blank lines after switching
91938889Sjdp         out of a debugging section.  If the next line drops us back
92038889Sjdp         into debugging information, then don't print the blank line.
92138889Sjdp         This is a hack for a particular compiler behaviour, not a
92238889Sjdp         general case.  */
92338889Sjdp      if (was_debug
92438889Sjdp	  && *line == '\0'
92538889Sjdp	  && list->next != NULL
92638889Sjdp	  && list->next->debugging)
92738889Sjdp	{
92838889Sjdp	  in_debug = 1;
92938889Sjdp	  return 1;
93038889Sjdp	}
93138889Sjdp#endif
93233965Sjdp
93338889Sjdp      return 0;
93438889Sjdp    }
93538889Sjdp
93633965Sjdp  line++;
93733965Sjdp
93833965Sjdp  if (strncmp (line, "def", 3) == 0)
93933965Sjdp    return 1;
94033965Sjdp  if (strncmp (line, "val", 3) == 0)
94133965Sjdp    return 1;
94233965Sjdp  if (strncmp (line, "scl", 3) == 0)
94333965Sjdp    return 1;
94433965Sjdp  if (strncmp (line, "line", 4) == 0)
94533965Sjdp    return 1;
94633965Sjdp  if (strncmp (line, "endef", 5) == 0)
94733965Sjdp    return 1;
94833965Sjdp  if (strncmp (line, "ln", 2) == 0)
94933965Sjdp    return 1;
95033965Sjdp  if (strncmp (line, "type", 4) == 0)
95133965Sjdp    return 1;
95233965Sjdp  if (strncmp (line, "size", 4) == 0)
95333965Sjdp    return 1;
95433965Sjdp  if (strncmp (line, "dim", 3) == 0)
95533965Sjdp    return 1;
95633965Sjdp  if (strncmp (line, "tag", 3) == 0)
95733965Sjdp    return 1;
95833965Sjdp
95933965Sjdp  if (strncmp (line, "stabs", 5) == 0)
96033965Sjdp    return 1;
96133965Sjdp  if (strncmp (line, "stabn", 5) == 0)
96233965Sjdp    return 1;
96333965Sjdp
96433965Sjdp  return 0;
96533965Sjdp}
96633965Sjdp
96733965Sjdpstatic void
96833965Sjdplisting_listing (name)
96960484Sobrien     char *name ATTRIBUTE_UNUSED;
97033965Sjdp{
97133965Sjdp  list_info_type *list = head;
97233965Sjdp  file_info_type *current_hll_file = (file_info_type *) NULL;
97333965Sjdp  char *message;
97433965Sjdp  char *buffer;
97533965Sjdp  char *p;
97633965Sjdp  int show_listing = 1;
97733965Sjdp  unsigned int width;
97833965Sjdp
97938889Sjdp  buffer = xmalloc (listing_rhs_width);
98038889Sjdp  data_buffer = xmalloc (MAX_BYTES);
98133965Sjdp  eject = 1;
98233965Sjdp  list = head;
98333965Sjdp
98433965Sjdp  while (list != (list_info_type *) NULL && 0)
98533965Sjdp    {
98633965Sjdp      if (list->next)
98733965Sjdp	list->frag = list->next->frag;
98833965Sjdp      list = list->next;
98933965Sjdp
99033965Sjdp    }
99133965Sjdp
99233965Sjdp  list = head->next;
99333965Sjdp
99433965Sjdp  while (list)
99533965Sjdp    {
99660484Sobrien      unsigned int list_line;
99760484Sobrien
99838889Sjdp      width = listing_rhs_width > paper_width ? paper_width :
99938889Sjdp	listing_rhs_width;
100033965Sjdp
100160484Sobrien      list_line = list->line;
100233965Sjdp      switch (list->edict)
100333965Sjdp	{
100433965Sjdp	case EDICT_LIST:
100560484Sobrien	  /* Skip all lines up to the current.  */
100660484Sobrien	  list_line--;
100733965Sjdp	  break;
100833965Sjdp	case EDICT_NOLIST:
100933965Sjdp	  show_listing--;
101033965Sjdp	  break;
101133965Sjdp	case EDICT_NOLIST_NEXT:
101277298Sobrien	  if (show_listing == 0)
101377298Sobrien	    list_line--;
101433965Sjdp	  break;
101533965Sjdp	case EDICT_EJECT:
101633965Sjdp	  break;
101733965Sjdp	case EDICT_NONE:
101833965Sjdp	  break;
101933965Sjdp	case EDICT_TITLE:
102033965Sjdp	  title = list->edict_arg;
102133965Sjdp	  break;
102233965Sjdp	case EDICT_SBTTL:
102333965Sjdp	  subtitle = list->edict_arg;
102433965Sjdp	  break;
102533965Sjdp	default:
102633965Sjdp	  abort ();
102733965Sjdp	}
102833965Sjdp
102960484Sobrien      if (show_listing <= 0)
103060484Sobrien	{
103160484Sobrien	  while (list->file->linenum < list_line
103260484Sobrien		 && !list->file->at_end)
103360484Sobrien	    p = buffer_line (list->file, buffer, width);
103460484Sobrien	}
103560484Sobrien
103677298Sobrien      if (list->edict == EDICT_LIST
103777298Sobrien	  || (list->edict == EDICT_NOLIST_NEXT && show_listing == 0))
103860484Sobrien	{
103960484Sobrien	  /* Enable listing for the single line that caused the enable.  */
104060484Sobrien	  list_line++;
104160484Sobrien	  show_listing++;
104260484Sobrien	}
104360484Sobrien
104433965Sjdp      if (show_listing > 0)
104533965Sjdp	{
104633965Sjdp	  /* Scan down the list and print all the stuff which can be done
104733965Sjdp	     with this line (or lines).  */
104833965Sjdp	  message = 0;
104933965Sjdp
105033965Sjdp	  if (list->hll_file)
105133965Sjdp	    {
105233965Sjdp	      current_hll_file = list->hll_file;
105333965Sjdp	    }
105433965Sjdp
105538889Sjdp	  if (current_hll_file && list->hll_line && (listing & LISTING_HLL))
105633965Sjdp	    {
105733965Sjdp	      print_source (current_hll_file, list, buffer, width);
105833965Sjdp	    }
105933965Sjdp
106038889Sjdp	  if (list->line_contents)
106133965Sjdp	    {
106238889Sjdp	      if (!((listing & LISTING_NODEBUG)
106338889Sjdp		    && debugging_pseudo (list, list->line_contents)))
106438889Sjdp		{
1065104834Sobrien		  print_lines (list,
106660484Sobrien			       list->file->linenum == 0 ? list->line : list->file->linenum,
106738889Sjdp			       list->line_contents, calc_hex (list));
106838889Sjdp		}
106960484Sobrien	      free (list->line_contents);
107060484Sobrien	      list->line_contents = NULL;
107138889Sjdp	    }
107238889Sjdp	  else
107338889Sjdp	    {
107460484Sobrien	      while (list->file->linenum < list_line
107538889Sjdp		     && !list->file->at_end)
107638889Sjdp		{
107738889Sjdp		  unsigned int address;
107833965Sjdp
107938889Sjdp		  p = buffer_line (list->file, buffer, width);
108033965Sjdp
108160484Sobrien		  if (list->file->linenum < list_line)
108277298Sobrien		    address = ~(unsigned int) 0;
108338889Sjdp		  else
108438889Sjdp		    address = calc_hex (list);
108533965Sjdp
108638889Sjdp		  if (!((listing & LISTING_NODEBUG)
108738889Sjdp			&& debugging_pseudo (list, p)))
108838889Sjdp		    print_lines (list, list->file->linenum, p, address);
108938889Sjdp		}
109033965Sjdp	    }
109133965Sjdp
109233965Sjdp	  if (list->edict == EDICT_EJECT)
109333965Sjdp	    {
109433965Sjdp	      eject = 1;
109533965Sjdp	    }
109633965Sjdp	}
109733965Sjdp
109877298Sobrien      if (list->edict == EDICT_NOLIST_NEXT && show_listing == 1)
109933965Sjdp	--show_listing;
110033965Sjdp
110133965Sjdp      list = list->next;
110233965Sjdp    }
110338889Sjdp
110433965Sjdp  free (buffer);
110538889Sjdp  free (data_buffer);
110638889Sjdp  data_buffer = NULL;
110733965Sjdp}
110833965Sjdp
110933965Sjdpvoid
111033965Sjdplisting_print (name)
111133965Sjdp     char *name;
111233965Sjdp{
111333965Sjdp  int using_stdout;
111477298Sobrien
111533965Sjdp  title = "";
111633965Sjdp  subtitle = "";
111733965Sjdp
111833965Sjdp  if (name == NULL)
111933965Sjdp    {
112033965Sjdp      list_file = stdout;
112133965Sjdp      using_stdout = 1;
112233965Sjdp    }
112333965Sjdp  else
112433965Sjdp    {
112589857Sobrien      list_file = fopen (name, FOPEN_WT);
112633965Sjdp      if (list_file != NULL)
112733965Sjdp	using_stdout = 0;
112833965Sjdp      else
112933965Sjdp	{
113060484Sobrien	  as_perror (_("can't open list file: %s"), name);
113133965Sjdp	  list_file = stdout;
113233965Sjdp	  using_stdout = 1;
113333965Sjdp	}
113433965Sjdp    }
113533965Sjdp
113633965Sjdp  if (listing & LISTING_NOFORM)
113733965Sjdp    {
113833965Sjdp      paper_height = 0;
113933965Sjdp    }
114033965Sjdp
114133965Sjdp  if (listing & LISTING_LISTING)
114233965Sjdp    {
114333965Sjdp      listing_listing (name);
114433965Sjdp    }
114533965Sjdp
114633965Sjdp  if (listing & LISTING_SYMBOLS)
114733965Sjdp    {
114833965Sjdp      list_symbol_table ();
114933965Sjdp    }
115033965Sjdp
115133965Sjdp  if (! using_stdout)
115233965Sjdp    {
115333965Sjdp      if (fclose (list_file) == EOF)
115460484Sobrien	as_perror (_("error closing list file: %s"), name);
115533965Sjdp    }
115633965Sjdp
115738889Sjdp  if (last_open_file)
115833965Sjdp    {
115938889Sjdp      fclose (last_open_file);
116033965Sjdp    }
116133965Sjdp}
116233965Sjdp
116333965Sjdpvoid
116433965Sjdplisting_file (name)
116533965Sjdp     const char *name;
116633965Sjdp{
116733965Sjdp  fn = name;
116833965Sjdp}
116933965Sjdp
117033965Sjdpvoid
117133965Sjdplisting_eject (ignore)
117260484Sobrien     int ignore ATTRIBUTE_UNUSED;
117333965Sjdp{
117433965Sjdp  if (listing)
117533965Sjdp    listing_tail->edict = EDICT_EJECT;
117633965Sjdp}
117733965Sjdp
117833965Sjdpvoid
117933965Sjdplisting_flags (ignore)
118060484Sobrien     int ignore ATTRIBUTE_UNUSED;
118133965Sjdp{
118233965Sjdp  while ((*input_line_pointer++) && (*input_line_pointer != '\n'))
118333965Sjdp    input_line_pointer++;
118433965Sjdp
118533965Sjdp}
118633965Sjdp
118733965Sjdp/* Turn listing on or off.  An argument of 0 means to turn off
118833965Sjdp   listing.  An argument of 1 means to turn on listing.  An argument
118933965Sjdp   of 2 means to turn off listing, but as of the next line; that is,
119033965Sjdp   the current line should be listed, but the next line should not.  */
119133965Sjdp
119233965Sjdpvoid
119333965Sjdplisting_list (on)
119433965Sjdp     int on;
119533965Sjdp{
119633965Sjdp  if (listing)
119733965Sjdp    {
119833965Sjdp      switch (on)
119933965Sjdp	{
120033965Sjdp	case 0:
120133965Sjdp	  if (listing_tail->edict == EDICT_LIST)
120233965Sjdp	    listing_tail->edict = EDICT_NONE;
120333965Sjdp	  else
120433965Sjdp	    listing_tail->edict = EDICT_NOLIST;
120533965Sjdp	  break;
120633965Sjdp	case 1:
120733965Sjdp	  if (listing_tail->edict == EDICT_NOLIST
120833965Sjdp	      || listing_tail->edict == EDICT_NOLIST_NEXT)
120933965Sjdp	    listing_tail->edict = EDICT_NONE;
121033965Sjdp	  else
121133965Sjdp	    listing_tail->edict = EDICT_LIST;
121233965Sjdp	  break;
121333965Sjdp	case 2:
121433965Sjdp	  listing_tail->edict = EDICT_NOLIST_NEXT;
121533965Sjdp	  break;
121633965Sjdp	default:
121733965Sjdp	  abort ();
121833965Sjdp	}
121933965Sjdp    }
122033965Sjdp}
122133965Sjdp
122233965Sjdpvoid
122333965Sjdplisting_psize (width_only)
122433965Sjdp     int width_only;
122533965Sjdp{
122633965Sjdp  if (! width_only)
122733965Sjdp    {
122833965Sjdp      paper_height = get_absolute_expression ();
122933965Sjdp
123033965Sjdp      if (paper_height < 0 || paper_height > 1000)
123133965Sjdp	{
123233965Sjdp	  paper_height = 0;
123360484Sobrien	  as_warn (_("strange paper height, set to no form"));
123433965Sjdp	}
123533965Sjdp
123633965Sjdp      if (*input_line_pointer != ',')
123733965Sjdp	{
123833965Sjdp	  demand_empty_rest_of_line ();
123933965Sjdp	  return;
124033965Sjdp	}
124133965Sjdp
124233965Sjdp      ++input_line_pointer;
124333965Sjdp    }
124433965Sjdp
124533965Sjdp  paper_width = get_absolute_expression ();
124633965Sjdp
124733965Sjdp  demand_empty_rest_of_line ();
124833965Sjdp}
124933965Sjdp
125033965Sjdpvoid
125133965Sjdplisting_nopage (ignore)
125260484Sobrien     int ignore ATTRIBUTE_UNUSED;
125333965Sjdp{
125433965Sjdp  paper_height = 0;
125533965Sjdp}
125633965Sjdp
125733965Sjdpvoid
125833965Sjdplisting_title (depth)
125933965Sjdp     int depth;
126033965Sjdp{
126133965Sjdp  int quoted;
126233965Sjdp  char *start;
126333965Sjdp  char *ttl;
126433965Sjdp  unsigned int length;
126533965Sjdp
126633965Sjdp  SKIP_WHITESPACE ();
126733965Sjdp  if (*input_line_pointer != '\"')
126833965Sjdp    quoted = 0;
126933965Sjdp  else
127033965Sjdp    {
127133965Sjdp      quoted = 1;
127233965Sjdp      ++input_line_pointer;
127333965Sjdp    }
127433965Sjdp
127533965Sjdp  start = input_line_pointer;
127633965Sjdp
127733965Sjdp  while (*input_line_pointer)
127833965Sjdp    {
127933965Sjdp      if (quoted
128033965Sjdp	  ? *input_line_pointer == '\"'
128133965Sjdp	  : is_end_of_line[(unsigned char) *input_line_pointer])
128233965Sjdp	{
128333965Sjdp	  if (listing)
128433965Sjdp	    {
128533965Sjdp	      length = input_line_pointer - start;
128633965Sjdp	      ttl = xmalloc (length + 1);
128733965Sjdp	      memcpy (ttl, start, length);
128833965Sjdp	      ttl[length] = 0;
128933965Sjdp	      listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
129033965Sjdp	      listing_tail->edict_arg = ttl;
129133965Sjdp	    }
129233965Sjdp	  if (quoted)
129333965Sjdp	    input_line_pointer++;
129433965Sjdp	  demand_empty_rest_of_line ();
129533965Sjdp	  return;
129633965Sjdp	}
129733965Sjdp      else if (*input_line_pointer == '\n')
129833965Sjdp	{
129989857Sobrien	  as_bad (_("new line in title"));
130033965Sjdp	  demand_empty_rest_of_line ();
130133965Sjdp	  return;
130233965Sjdp	}
130333965Sjdp      else
130433965Sjdp	{
130533965Sjdp	  input_line_pointer++;
130633965Sjdp	}
130733965Sjdp    }
130833965Sjdp}
130933965Sjdp
131033965Sjdpvoid
131133965Sjdplisting_source_line (line)
131233965Sjdp     unsigned int line;
131333965Sjdp{
131433965Sjdp  if (listing)
131533965Sjdp    {
131633965Sjdp      new_frag ();
131733965Sjdp      listing_tail->hll_line = line;
131833965Sjdp      new_frag ();
131933965Sjdp    }
132033965Sjdp}
132133965Sjdp
132233965Sjdpvoid
132333965Sjdplisting_source_file (file)
132433965Sjdp     const char *file;
132533965Sjdp{
132633965Sjdp  if (listing)
132733965Sjdp    listing_tail->hll_file = file_info (file);
132833965Sjdp}
132933965Sjdp
133033965Sjdp#else
133133965Sjdp
133277298Sobrien/* Dummy functions for when compiled without listing enabled.  */
133333965Sjdp
133433965Sjdpvoid
133533965Sjdplisting_flags (ignore)
133633965Sjdp     int ignore;
133733965Sjdp{
133833965Sjdp  s_ignore (0);
133933965Sjdp}
134033965Sjdp
134177298Sobrienvoid
134233965Sjdplisting_list (on)
134333965Sjdp     int on;
134433965Sjdp{
134533965Sjdp  s_ignore (0);
134633965Sjdp}
134733965Sjdp
134877298Sobrienvoid
134933965Sjdplisting_eject (ignore)
135033965Sjdp     int ignore;
135133965Sjdp{
135233965Sjdp  s_ignore (0);
135333965Sjdp}
135433965Sjdp
135577298Sobrienvoid
135633965Sjdplisting_psize (ignore)
135733965Sjdp     int ignore;
135833965Sjdp{
135933965Sjdp  s_ignore (0);
136033965Sjdp}
136133965Sjdp
136233965Sjdpvoid
136333965Sjdplisting_nopage (ignore)
136433965Sjdp     int ignore;
136533965Sjdp{
136633965Sjdp  s_ignore (0);
136733965Sjdp}
136833965Sjdp
136977298Sobrienvoid
137033965Sjdplisting_title (depth)
137133965Sjdp     int depth;
137233965Sjdp{
137333965Sjdp  s_ignore (0);
137433965Sjdp}
137533965Sjdp
137633965Sjdpvoid
137733965Sjdplisting_file (name)
137833965Sjdp     const char *name;
137933965Sjdp{
138033965Sjdp
138133965Sjdp}
138233965Sjdp
138377298Sobrienvoid
138433965Sjdplisting_newline (name)
138533965Sjdp     char *name;
138633965Sjdp{
138733965Sjdp
138833965Sjdp}
138933965Sjdp
139077298Sobrienvoid
139133965Sjdplisting_source_line (n)
139233965Sjdp     unsigned int n;
139333965Sjdp{
139433965Sjdp
139533965Sjdp}
139677298Sobrien
139777298Sobrienvoid
139833965Sjdplisting_source_file (n)
139933965Sjdp     const char *n;
140033965Sjdp{
140133965Sjdp
140233965Sjdp}
140333965Sjdp
140433965Sjdp#endif
1405