listing.c revision 130561
1130561Sobrien/* listing.c - maintain assembly listings
277298Sobrien   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3130561Sobrien   2001, 2002, 2003
438889Sjdp   Free Software Foundation, Inc.
533965Sjdp
6130561Sobrien   This file is part of GAS, the GNU Assembler.
733965Sjdp
8130561Sobrien   GAS is free software; you can redistribute it and/or modify
9130561Sobrien   it under the terms of the GNU General Public License as published by
10130561Sobrien   the Free Software Foundation; either version 2, or (at your option)
11130561Sobrien   any later version.
1233965Sjdp
13130561Sobrien   GAS is distributed in the hope that it will be useful,
14130561Sobrien   but WITHOUT ANY WARRANTY; without even the implied warranty of
15130561Sobrien   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16130561Sobrien   GNU General Public License for more details.
1733965Sjdp
18130561Sobrien   You should have received a copy of the GNU General Public License
19130561Sobrien   along with GAS; see the file COPYING.  If not, write to the Free
20130561Sobrien   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
21130561Sobrien   02111-1307, USA.  */
2233965Sjdp
23130561Sobrien/* Contributed by Steve Chamberlain <sac@cygnus.com>
2433965Sjdp
2533965Sjdp A listing page looks like:
2633965Sjdp
2733965Sjdp LISTING_HEADER  sourcefilename pagenumber
2833965Sjdp TITLE LINE
2933965Sjdp SUBTITLE LINE
3033965Sjdp linenumber address data  source
3133965Sjdp linenumber address data  source
3233965Sjdp linenumber address data  source
3333965Sjdp linenumber address data  source
3433965Sjdp
3533965Sjdp If not overridden, the listing commands are:
3633965Sjdp
3733965Sjdp .title  "stuff"
3833965Sjdp 	Put "stuff" onto the title line
3933965Sjdp .sbttl  "stuff"
4033965Sjdp        Put stuff onto the subtitle line
4133965Sjdp
4233965Sjdp  If these commands come within 10 lines of the top of the page, they
4333965Sjdp  will affect the page they are on, as well as any subsequent page
4433965Sjdp
4533965Sjdp .eject
4633965Sjdp 	Thow a page
4733965Sjdp .list
4833965Sjdp 	Increment the enable listing counter
4933965Sjdp .nolist
5033965Sjdp 	Decrement the enable listing counter
5133965Sjdp
5233965Sjdp .psize Y[,X]
5333965Sjdp 	Set the paper size to X wide and Y high. Setting a psize Y of
5433965Sjdp	zero will suppress form feeds except where demanded by .eject
5533965Sjdp
5633965Sjdp If the counter goes below zero, listing is suppressed.
5733965Sjdp
5833965Sjdp Listings are a maintained by read calling various listing_<foo>
5933965Sjdp functions.  What happens most is that the macro NO_LISTING is not
6033965Sjdp defined (from the Makefile), then the macro LISTING_NEWLINE expands
6133965Sjdp into a call to listing_newline.  The call is done from read.c, every
6233965Sjdp time it sees a newline, and -l is on the command line.
6333965Sjdp
6433965Sjdp The function listing_newline remembers the frag associated with the
6533965Sjdp newline, and creates a new frag - note that this is wasteful, but not
6633965Sjdp a big deal, since listing slows things down a lot anyway.  The
67130561Sobrien function also remembers when the filename changes.
6833965Sjdp
6933965Sjdp When all the input has finished, and gas has had a chance to settle
7033965Sjdp down, the listing is output. This is done by running down the list of
7133965Sjdp frag/source file records, and opening the files as needed and printing
7233965Sjdp out the bytes and chars associated with them.
7333965Sjdp
7433965Sjdp The only things which the architecture can change about the listing
7533965Sjdp are defined in these macros:
7633965Sjdp
7733965Sjdp LISTING_HEADER		The name of the architecture
7833965Sjdp LISTING_WORD_SIZE      The make of the number of bytes in a word, this determines
7933965Sjdp 			the clumping of the output data. eg a value of
8033965Sjdp			2 makes words look like 1234 5678, whilst 1
8133965Sjdp			would make the same value look like 12 34 56
8233965Sjdp			78
8333965Sjdp LISTING_LHS_WIDTH      Number of words of above size for the lhs
8433965Sjdp
8533965Sjdp LISTING_LHS_WIDTH_SECOND   Number of words for the data on the lhs
8633965Sjdp 			for the second line
8733965Sjdp
88130561Sobrien LISTING_LHS_CONT_LINES	Max number of lines to use up for a continuation
8933965Sjdp LISTING_RHS_WIDTH      Number of chars from the input file to print
90130561Sobrien                        on a line.  */
9133965Sjdp
9233965Sjdp#include "as.h"
93104834Sobrien#include "obstack.h"
9489857Sobrien#include "safe-ctype.h"
9533965Sjdp#include "input-file.h"
9633965Sjdp#include "subsegs.h"
9733965Sjdp
9833965Sjdp#ifndef NO_LISTING
9938889Sjdp
10033965Sjdp#ifndef LISTING_HEADER
10133965Sjdp#define LISTING_HEADER "GAS LISTING"
10233965Sjdp#endif
10333965Sjdp#ifndef LISTING_WORD_SIZE
10433965Sjdp#define LISTING_WORD_SIZE 4
10533965Sjdp#endif
10633965Sjdp#ifndef LISTING_LHS_WIDTH
10760484Sobrien#define LISTING_LHS_WIDTH ((LISTING_WORD_SIZE) > 4 ? 1 : 4 / (LISTING_WORD_SIZE))
10833965Sjdp#endif
10933965Sjdp#ifndef LISTING_LHS_WIDTH_SECOND
11060484Sobrien#define LISTING_LHS_WIDTH_SECOND LISTING_LHS_WIDTH
11133965Sjdp#endif
11233965Sjdp#ifndef LISTING_RHS_WIDTH
11333965Sjdp#define LISTING_RHS_WIDTH 100
11433965Sjdp#endif
11533965Sjdp#ifndef LISTING_LHS_CONT_LINES
11633965Sjdp#define LISTING_LHS_CONT_LINES 4
11733965Sjdp#endif
11833965Sjdp
11977298Sobrien/* This structure remembers which .s were used.  */
120130561Sobrientypedef struct file_info_struct
121130561Sobrien{
12260484Sobrien  struct file_info_struct * next;
12360484Sobrien  char *                    filename;
12460484Sobrien  long                      pos;
12560484Sobrien  unsigned int              linenum;
12660484Sobrien  int                       at_end;
12777298Sobrien} file_info_type;
12833965Sjdp
129130561Sobrien/* This structure remembers which line from which file goes into which
13077298Sobrien   frag.  */
131130561Sobrienstruct list_info_struct
132130561Sobrien{
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;
138130561Sobrien
13933965Sjdp  /* Pointer to the file info struct for the file which this line
14077298Sobrien     belongs to.  */
14177298Sobrien  file_info_type *file;
14233965Sjdp
14338889Sjdp  /* The expanded text of any macro that may have been executing.  */
14477298Sobrien  char *line_contents;
14538889Sjdp
14677298Sobrien  /* Next in list.  */
14777298Sobrien  struct list_info_struct *next;
14833965Sjdp
14933965Sjdp  /* Pointer to the file info struct for the high level language
15077298Sobrien     source line that belongs here.  */
15177298Sobrien  file_info_type *hll_file;
152130561Sobrien
15377298Sobrien  /* High level language source line.  */
15438889Sjdp  unsigned int hll_line;
15533965Sjdp
15677298Sobrien  /* Pointer to any error message associated with this line.  */
15777298Sobrien  char *message;
15833965Sjdp
159130561Sobrien  enum
160130561Sobrien    {
161130561Sobrien      EDICT_NONE,
162130561Sobrien      EDICT_SBTTL,
163130561Sobrien      EDICT_TITLE,
164130561Sobrien      EDICT_NOLIST,
165130561Sobrien      EDICT_LIST,
166130561Sobrien      EDICT_NOLIST_NEXT,
167130561Sobrien      EDICT_EJECT
168130561Sobrien    } edict;
16977298Sobrien  char *edict_arg;
17033965Sjdp
17138889Sjdp  /* Nonzero if this line is to be omitted because it contains
17238889Sjdp     debugging information.  This can become a flags field if we come
17338889Sjdp     up with more information to store here.  */
17438889Sjdp  int debugging;
17538889Sjdp};
17633965Sjdp
17738889Sjdptypedef struct list_info_struct list_info_type;
17833965Sjdp
17960484Sobrienint listing_lhs_width        = LISTING_LHS_WIDTH;
18060484Sobrienint listing_lhs_width_second = LISTING_LHS_WIDTH_SECOND;
18160484Sobrienint listing_lhs_cont_lines   = LISTING_LHS_CONT_LINES;
18260484Sobrienint listing_rhs_width        = LISTING_RHS_WIDTH;
18333965Sjdp
18460484Sobrienstruct list_info_struct *        listing_tail;
18560484Sobrien
18660484Sobrienstatic file_info_type *          file_info_head;
18760484Sobrienstatic file_info_type *          last_open_file_info;
18860484Sobrienstatic FILE *                    last_open_file;
18960484Sobrienstatic struct list_info_struct * head;
19060484Sobrienstatic int                       paper_width = 200;
19160484Sobrienstatic int                       paper_height = 60;
19260484Sobrien
19360484Sobrienextern int                       listing;
19460484Sobrien
19533965Sjdp/* File to output listings to.  */
19677298Sobrienstatic FILE *list_file;
19733965Sjdp
19838889Sjdp/* This static array is used to keep the text of data to be printed
19938889Sjdp   before the start of the line.  */
20033965Sjdp
20138889Sjdp#define MAX_BYTES							\
20238889Sjdp  (((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width			\
20338889Sjdp   + ((((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second)	\
20438889Sjdp      * listing_lhs_cont_lines)						\
20538889Sjdp   + 20)
20633965Sjdp
20777298Sobrienstatic char *data_buffer;
20833965Sjdp
20933965Sjdp/* Prototypes.  */
210130561Sobrienstatic void listing_message (const char *, const char *);
211130561Sobrienstatic file_info_type *file_info (const char *);
212130561Sobrienstatic void new_frag (void);
213130561Sobrienstatic char *buffer_line (file_info_type *, char *, unsigned int);
214130561Sobrienstatic void listing_page (list_info_type *);
215130561Sobrienstatic unsigned int calc_hex (list_info_type *);
216130561Sobrienstatic void print_lines (list_info_type *, unsigned int, char *, unsigned int);
217130561Sobrienstatic void list_symbol_table (void);
218130561Sobrienstatic void print_source (file_info_type *, list_info_type *, char *, unsigned int);
219130561Sobrienstatic int debugging_pseudo (list_info_type *, const char *);
220130561Sobrienstatic void listing_listing (char *);
22133965Sjdp
22233965Sjdpstatic void
223130561Sobrienlisting_message (const char *name, const char *message)
22433965Sjdp{
22533965Sjdp  if (listing_tail != (list_info_type *) NULL)
22633965Sjdp    {
22777298Sobrien      unsigned int l = strlen (name) + strlen (message) + 1;
22877298Sobrien      char *n = (char *) xmalloc (l);
22977298Sobrien      strcpy (n, name);
23077298Sobrien      strcat (n, message);
23133965Sjdp      listing_tail->message = n;
23233965Sjdp    }
23333965Sjdp}
23433965Sjdp
23533965Sjdpvoid
236130561Sobrienlisting_warning (const char *message)
23733965Sjdp{
23860484Sobrien  listing_message (_("Warning:"), message);
23933965Sjdp}
24033965Sjdp
24133965Sjdpvoid
242130561Sobrienlisting_error (const char *message)
24333965Sjdp{
24460484Sobrien  listing_message (_("Error:"), message);
24533965Sjdp}
24633965Sjdp
24733965Sjdpstatic file_info_type *
248130561Sobrienfile_info (const char *file_name)
24933965Sjdp{
25077298Sobrien  /* Find an entry with this file name.  */
25133965Sjdp  file_info_type *p = file_info_head;
25233965Sjdp
25333965Sjdp  while (p != (file_info_type *) NULL)
25433965Sjdp    {
25533965Sjdp      if (strcmp (p->filename, file_name) == 0)
25633965Sjdp	return p;
25733965Sjdp      p = p->next;
25833965Sjdp    }
25933965Sjdp
26077298Sobrien  /* Make new entry.  */
261130561Sobrien  p = xmalloc (sizeof (file_info_type));
26233965Sjdp  p->next = file_info_head;
26333965Sjdp  file_info_head = p;
264104834Sobrien  p->filename = xstrdup (file_name);
26538889Sjdp  p->pos = 0;
26633965Sjdp  p->linenum = 0;
26733965Sjdp  p->at_end = 0;
26833965Sjdp
26933965Sjdp  return p;
27033965Sjdp}
27133965Sjdp
27233965Sjdpstatic void
273130561Sobriennew_frag (void)
27433965Sjdp{
27533965Sjdp  frag_wane (frag_now);
27633965Sjdp  frag_new (0);
27733965Sjdp}
27833965Sjdp
27933965Sjdpvoid
280130561Sobrienlisting_newline (char *ps)
28133965Sjdp{
28233965Sjdp  char *file;
28333965Sjdp  unsigned int line;
28433965Sjdp  static unsigned int last_line = 0xffff;
28533965Sjdp  static char *last_file = NULL;
28638889Sjdp  list_info_type *new = NULL;
28733965Sjdp
28833965Sjdp  if (listing == 0)
28933965Sjdp    return;
29033965Sjdp
29133965Sjdp  if (now_seg == absolute_section)
29233965Sjdp    return;
29333965Sjdp
29438889Sjdp#ifdef OBJ_ELF
29538889Sjdp  /* In ELF, anything in a section beginning with .debug or .line is
29638889Sjdp     considered to be debugging information.  This includes the
29738889Sjdp     statement which switches us into the debugging section, which we
29838889Sjdp     can only set after we are already in the debugging section.  */
29938889Sjdp  if ((listing & LISTING_NODEBUG) != 0
30038889Sjdp      && listing_tail != NULL
30138889Sjdp      && ! listing_tail->debugging)
30238889Sjdp    {
30338889Sjdp      const char *segname;
30438889Sjdp
30538889Sjdp      segname = segment_name (now_seg);
30638889Sjdp      if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
30738889Sjdp	  || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
30838889Sjdp	listing_tail->debugging = 1;
30938889Sjdp    }
31038889Sjdp#endif
31138889Sjdp
31233965Sjdp  as_where (&file, &line);
31338889Sjdp  if (ps == NULL)
31433965Sjdp    {
31577298Sobrien      if (line == last_line
31677298Sobrien	  && !(last_file && file && strcmp (file, last_file)))
31738889Sjdp	return;
31833965Sjdp
31933965Sjdp      new = (list_info_type *) xmalloc (sizeof (list_info_type));
32060484Sobrien
32160484Sobrien      /* Detect if we are reading from stdin by examining the file
32260484Sobrien	 name returned by as_where().
32360484Sobrien
32460484Sobrien	 [FIXME: We rely upon the name in the strcmp below being the
32560484Sobrien	 same as the one used by input_scrub_new_file(), if that is
32660484Sobrien	 not true, then this code will fail].
32760484Sobrien
32877298Sobrien	 If we are reading from stdin, then we need to save each input
32977298Sobrien	 line here (assuming of course that we actually have a line of
33077298Sobrien	 input to read), so that it can be displayed in the listing
33177298Sobrien	 that is produced at the end of the assembly.  */
33260484Sobrien      if (strcmp (file, _("{standard input}")) == 0
33360484Sobrien	  && input_line_pointer != NULL)
33460484Sobrien	{
33577298Sobrien	  char *copy;
33660484Sobrien	  int len;
33760484Sobrien	  int seen_quote = 0;
33860484Sobrien
33960484Sobrien	  for (copy = input_line_pointer - 1;
34077298Sobrien	       *copy && (seen_quote
34177298Sobrien			 || (! is_end_of_line [(unsigned char) *copy]));
34277298Sobrien	       copy++)
34377298Sobrien	    if (*copy == '"' && copy[-1] != '\\')
34460484Sobrien	      seen_quote = ! seen_quote;
34560484Sobrien
34660484Sobrien	  len = (copy - input_line_pointer) + 2;
34760484Sobrien
34860484Sobrien	  copy = xmalloc (len);
34960484Sobrien
35060484Sobrien	  if (copy != NULL)
35160484Sobrien	    {
35277298Sobrien	      char *src = input_line_pointer - 1;
35377298Sobrien	      char *dest = copy;
35477298Sobrien
35560484Sobrien	      while (--len)
35660484Sobrien		{
35777298Sobrien		  unsigned char c = *src++;
35860484Sobrien
35960484Sobrien		  /* Omit control characters in the listing.  */
36089857Sobrien		  if (!ISCNTRL (c))
36177298Sobrien		    *dest++ = c;
36260484Sobrien		}
36377298Sobrien
36460484Sobrien	      *dest = 0;
36560484Sobrien	    }
36677298Sobrien
36760484Sobrien	  new->line_contents = copy;
36860484Sobrien	}
36960484Sobrien      else
37060484Sobrien	new->line_contents = NULL;
37138889Sjdp    }
37238889Sjdp  else
37338889Sjdp    {
374130561Sobrien      new = xmalloc (sizeof (list_info_type));
37538889Sjdp      new->line_contents = ps;
37638889Sjdp    }
37733965Sjdp
37838889Sjdp  last_line = line;
37938889Sjdp  last_file = file;
38077298Sobrien
38138889Sjdp  new_frag ();
38238889Sjdp
38338889Sjdp  if (listing_tail)
38460484Sobrien    listing_tail->next = new;
38538889Sjdp  else
38660484Sobrien    head = new;
38777298Sobrien
38838889Sjdp  listing_tail = new;
38938889Sjdp
39038889Sjdp  new->frag = frag_now;
39138889Sjdp  new->line = line;
39238889Sjdp  new->file = file_info (file);
39338889Sjdp  new->next = (list_info_type *) NULL;
39438889Sjdp  new->message = (char *) NULL;
39538889Sjdp  new->edict = EDICT_NONE;
39638889Sjdp  new->hll_file = (file_info_type *) NULL;
39738889Sjdp  new->hll_line = 0;
39838889Sjdp  new->debugging = 0;
39977298Sobrien
40038889Sjdp  new_frag ();
40138889Sjdp
40238889Sjdp#ifdef OBJ_ELF
40338889Sjdp  /* In ELF, anything in a section beginning with .debug or .line is
40438889Sjdp     considered to be debugging information.  */
40538889Sjdp  if ((listing & LISTING_NODEBUG) != 0)
40638889Sjdp    {
40738889Sjdp      const char *segname;
40838889Sjdp
40938889Sjdp      segname = segment_name (now_seg);
41038889Sjdp      if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
41138889Sjdp	  || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
41238889Sjdp	new->debugging = 1;
41338889Sjdp    }
41438889Sjdp#endif
41533965Sjdp}
41633965Sjdp
41733965Sjdp/* Attach all current frags to the previous line instead of the
41833965Sjdp   current line.  This is called by the MIPS backend when it discovers
41933965Sjdp   that it needs to add some NOP instructions; the added NOP
42033965Sjdp   instructions should go with the instruction that has the delay, not
42133965Sjdp   with the new instruction.  */
42233965Sjdp
42333965Sjdpvoid
424130561Sobrienlisting_prev_line (void)
42533965Sjdp{
42633965Sjdp  list_info_type *l;
42733965Sjdp  fragS *f;
42833965Sjdp
42933965Sjdp  if (head == (list_info_type *) NULL
43033965Sjdp      || head == listing_tail)
43133965Sjdp    return;
43233965Sjdp
43333965Sjdp  new_frag ();
43433965Sjdp
43533965Sjdp  for (l = head; l->next != listing_tail; l = l->next)
43633965Sjdp    ;
43733965Sjdp
43833965Sjdp  for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next)
43933965Sjdp    if (f->line == listing_tail)
44033965Sjdp      f->line = l;
44133965Sjdp
44233965Sjdp  listing_tail->frag = frag_now;
44333965Sjdp  new_frag ();
44433965Sjdp}
44533965Sjdp
44677298Sobrien/* This function returns the next source line from the file supplied,
44777298Sobrien   truncated to size.  It appends a fake line to the end of each input
44877298Sobrien   file to make.  */
44933965Sjdp
45033965Sjdpstatic char *
451130561Sobrienbuffer_line (file_info_type *file, char *line, unsigned int size)
45233965Sjdp{
45333965Sjdp  unsigned int count = 0;
45433965Sjdp  int c;
45533965Sjdp
45633965Sjdp  char *p = line;
45733965Sjdp
45877298Sobrien  /* If we couldn't open the file, return an empty line.  */
45938889Sjdp  if (file->at_end)
46038889Sjdp    return "";
46138889Sjdp
46238889Sjdp  /* Check the cache and see if we last used this file.  */
46338889Sjdp  if (!last_open_file_info || file != last_open_file_info)
46433965Sjdp    {
46538889Sjdp      if (last_open_file)
46638889Sjdp	{
46738889Sjdp	  last_open_file_info->pos = ftell (last_open_file);
46838889Sjdp	  fclose (last_open_file);
46938889Sjdp	}
47038889Sjdp
47138889Sjdp      last_open_file_info = file;
47289857Sobrien      last_open_file = fopen (file->filename, FOPEN_RT);
47338889Sjdp      if (last_open_file == NULL)
47438889Sjdp	{
47538889Sjdp	  file->at_end = 1;
47638889Sjdp	  return "";
47738889Sjdp	}
47877298Sobrien
47938889Sjdp      /* Seek to where we were last time this file was open.  */
48038889Sjdp      if (file->pos)
48177298Sobrien	fseek (last_open_file, file->pos, SEEK_SET);
48233965Sjdp    }
48333965Sjdp
48438889Sjdp  c = fgetc (last_open_file);
48533965Sjdp
48677298Sobrien  /* Leave room for null.  */
48777298Sobrien  size -= 1;
48833965Sjdp
48933965Sjdp  while (c != EOF && c != '\n')
49033965Sjdp    {
49133965Sjdp      if (count < size)
49233965Sjdp	*p++ = c;
49333965Sjdp      count++;
49433965Sjdp
49538889Sjdp      c = fgetc (last_open_file);
49633965Sjdp
49733965Sjdp    }
49833965Sjdp  if (c == EOF)
49933965Sjdp    {
50033965Sjdp      file->at_end = 1;
50189857Sobrien      if (count + 2 < size)
50289857Sobrien	{
50389857Sobrien	  *p++ = '.';
50489857Sobrien	  *p++ = '.';
50589857Sobrien	  *p++ = '.';
50689857Sobrien	}
50733965Sjdp    }
50833965Sjdp  file->linenum++;
50933965Sjdp  *p++ = 0;
51033965Sjdp  return line;
51133965Sjdp}
51233965Sjdp
51333965Sjdpstatic const char *fn;
51433965Sjdp
51533965Sjdpstatic unsigned int eject;	/* Eject pending */
51633965Sjdpstatic unsigned int page;	/* Current page number */
51777298Sobrienstatic char *title;		/* Current title */
51877298Sobrienstatic char *subtitle;		/* Current subtitle */
51977298Sobrienstatic unsigned int on_page;	/* Number of lines printed on current page */
52033965Sjdp
52133965Sjdpstatic void
522130561Sobrienlisting_page (list_info_type *list)
52333965Sjdp{
52433965Sjdp  /* Grope around, see if we can see a title or subtitle edict coming up
52577298Sobrien     soon.  (we look down 10 lines of the page and see if it's there)  */
52677298Sobrien  if ((eject || (on_page >= (unsigned int) paper_height))
52777298Sobrien      && paper_height != 0)
52833965Sjdp    {
52933965Sjdp      unsigned int c = 10;
53033965Sjdp      int had_title = 0;
53133965Sjdp      int had_subtitle = 0;
53233965Sjdp
53333965Sjdp      page++;
53433965Sjdp
53533965Sjdp      while (c != 0 && list)
53633965Sjdp	{
53733965Sjdp	  if (list->edict == EDICT_SBTTL && !had_subtitle)
53833965Sjdp	    {
53933965Sjdp	      had_subtitle = 1;
54033965Sjdp	      subtitle = list->edict_arg;
54133965Sjdp	    }
54233965Sjdp	  if (list->edict == EDICT_TITLE && !had_title)
54333965Sjdp	    {
54433965Sjdp	      had_title = 1;
54533965Sjdp	      title = list->edict_arg;
54633965Sjdp	    }
54733965Sjdp	  list = list->next;
54833965Sjdp	  c--;
54933965Sjdp	}
55033965Sjdp
55133965Sjdp      if (page > 1)
55233965Sjdp	{
55333965Sjdp	  fprintf (list_file, "\f");
55433965Sjdp	}
55533965Sjdp
55633965Sjdp      fprintf (list_file, "%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
55733965Sjdp      fprintf (list_file, "%s\n", title);
55833965Sjdp      fprintf (list_file, "%s\n", subtitle);
55933965Sjdp      on_page = 3;
56033965Sjdp      eject = 0;
56133965Sjdp    }
56233965Sjdp}
56333965Sjdp
56433965Sjdpstatic unsigned int
565130561Sobriencalc_hex (list_info_type *list)
56633965Sjdp{
56738889Sjdp  int data_buffer_size;
56833965Sjdp  list_info_type *first = list;
56977298Sobrien  unsigned int address = ~(unsigned int) 0;
57033965Sjdp  fragS *frag;
57133965Sjdp  fragS *frag_ptr;
57260484Sobrien  unsigned int octet_in_frag;
57333965Sjdp
57477298Sobrien  /* Find first frag which says it belongs to this line.  */
57533965Sjdp  frag = list->frag;
57633965Sjdp  while (frag && frag->line != list)
57733965Sjdp    frag = frag->fr_next;
57833965Sjdp
57933965Sjdp  frag_ptr = frag;
58033965Sjdp
58133965Sjdp  data_buffer_size = 0;
58233965Sjdp
58377298Sobrien  /* Dump all the frags which belong to this line.  */
58433965Sjdp  while (frag_ptr != (fragS *) NULL && frag_ptr->line == first)
58533965Sjdp    {
58677298Sobrien      /* Print as many bytes from the fixed part as is sensible.  */
58760484Sobrien      octet_in_frag = 0;
58860484Sobrien      while ((offsetT) octet_in_frag < frag_ptr->fr_fix
58938889Sjdp	     && data_buffer_size < MAX_BYTES - 3)
59033965Sjdp	{
59177298Sobrien	  if (address == ~(unsigned int) 0)
592130561Sobrien	    address = frag_ptr->fr_address / OCTETS_PER_BYTE;
59333965Sjdp
59433965Sjdp	  sprintf (data_buffer + data_buffer_size,
59533965Sjdp		   "%02X",
59660484Sobrien		   (frag_ptr->fr_literal[octet_in_frag]) & 0xff);
59733965Sjdp	  data_buffer_size += 2;
59860484Sobrien	  octet_in_frag++;
59933965Sjdp	}
600104834Sobrien      if (frag_ptr->fr_type == rs_fill)
601104834Sobrien	{
602104834Sobrien	  unsigned int var_rep_max = octet_in_frag;
603104834Sobrien	  unsigned int var_rep_idx = octet_in_frag;
60433965Sjdp
605104834Sobrien	  /* Print as many bytes from the variable part as is sensible.  */
606104834Sobrien	  while (((offsetT) octet_in_frag
607104834Sobrien		  < (frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset))
608104834Sobrien		 && data_buffer_size < MAX_BYTES - 3)
609104834Sobrien	    {
610104834Sobrien	      if (address == ~(unsigned int) 0)
611130561Sobrien		address = frag_ptr->fr_address / OCTETS_PER_BYTE;
612130561Sobrien
613104834Sobrien	      sprintf (data_buffer + data_buffer_size,
614104834Sobrien		       "%02X",
615104834Sobrien		       (frag_ptr->fr_literal[var_rep_idx]) & 0xff);
61633965Sjdp#if 0
617104834Sobrien	      data_buffer[data_buffer_size++] = '*';
618104834Sobrien	      data_buffer[data_buffer_size++] = '*';
61933965Sjdp#endif
620104834Sobrien	      data_buffer_size += 2;
62133965Sjdp
622104834Sobrien	      var_rep_idx++;
623104834Sobrien	      octet_in_frag++;
62433965Sjdp
625104834Sobrien	      if ((offsetT) var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var)
626104834Sobrien		var_rep_idx = var_rep_max;
627104834Sobrien	    }
628104834Sobrien	}
62933965Sjdp
63033965Sjdp      frag_ptr = frag_ptr->fr_next;
63133965Sjdp    }
63238889Sjdp  data_buffer[data_buffer_size] = '\0';
63333965Sjdp  return address;
63433965Sjdp}
63533965Sjdp
63633965Sjdpstatic void
637130561Sobrienprint_lines (list_info_type *list, unsigned int lineno,
638130561Sobrien	     char *string, unsigned int address)
63933965Sjdp{
64033965Sjdp  unsigned int idx;
64133965Sjdp  unsigned int nchars;
64233965Sjdp  unsigned int lines;
64360484Sobrien  unsigned int octet_in_word = 0;
64433965Sjdp  char *src = data_buffer;
64560484Sobrien  int cur;
64633965Sjdp
64777298Sobrien  /* Print the stuff on the first line.  */
64833965Sjdp  listing_page (list);
64938889Sjdp  nchars = (LISTING_WORD_SIZE * 2 + 1) * listing_lhs_width;
65077298Sobrien
65177298Sobrien  /* Print the hex for the first line.  */
65277298Sobrien  if (address == ~(unsigned int) 0)
65333965Sjdp    {
65433965Sjdp      fprintf (list_file, "% 4d     ", lineno);
65533965Sjdp      for (idx = 0; idx < nchars; idx++)
65633965Sjdp	fprintf (list_file, " ");
65733965Sjdp
65833965Sjdp      fprintf (list_file, "\t%s\n", string ? string : "");
65977298Sobrien
66077298Sobrien      on_page++;
66177298Sobrien
66233965Sjdp      listing_page (0);
66333965Sjdp
66460484Sobrien      return;
66533965Sjdp    }
66660484Sobrien
66760484Sobrien  if (had_errors ())
66860484Sobrien    fprintf (list_file, "% 4d ???? ", lineno);
66933965Sjdp  else
67060484Sobrien    fprintf (list_file, "% 4d %04x ", lineno, address);
67160484Sobrien
67277298Sobrien  /* And the data to go along with it.  */
67360484Sobrien  idx = 0;
67460484Sobrien  cur = 0;
67560484Sobrien  while (src[cur] && idx < nchars)
67633965Sjdp    {
67760484Sobrien      int offset;
67860484Sobrien      offset = cur;
67977298Sobrien      fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
68060484Sobrien      cur += 2;
68160484Sobrien      octet_in_word++;
68277298Sobrien
68360484Sobrien      if (octet_in_word == LISTING_WORD_SIZE)
68433965Sjdp	{
68560484Sobrien	  fprintf (list_file, " ");
68660484Sobrien	  idx++;
68760484Sobrien	  octet_in_word = 0;
68833965Sjdp	}
68977298Sobrien
69060484Sobrien      idx += 2;
69160484Sobrien    }
69277298Sobrien
69360484Sobrien  for (; idx < nchars; idx++)
69460484Sobrien    fprintf (list_file, " ");
69577298Sobrien
69660484Sobrien  fprintf (list_file, "\t%s\n", string ? string : "");
69760484Sobrien  on_page++;
69860484Sobrien  listing_page (list);
69977298Sobrien
70060484Sobrien  if (list->message)
70160484Sobrien    {
70260484Sobrien      fprintf (list_file, "****  %s\n", list->message);
70360484Sobrien      listing_page (list);
70460484Sobrien      on_page++;
70560484Sobrien    }
70677298Sobrien
70760484Sobrien  for (lines = 0;
70860484Sobrien       lines < (unsigned int) listing_lhs_cont_lines
70960484Sobrien	 && src[cur];
71077298Sobrien       lines++)
71160484Sobrien    {
71277298Sobrien      nchars = ((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second - 1;
71333965Sjdp      idx = 0;
71477298Sobrien
71577298Sobrien      /* Print any more lines of data, but more compactly.  */
71660484Sobrien      fprintf (list_file, "% 4d      ", lineno);
71777298Sobrien
71860484Sobrien      while (src[cur] && idx < nchars)
71933965Sjdp	{
72077298Sobrien	  int offset;
72177298Sobrien	  offset = cur;
72277298Sobrien	  fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
72360484Sobrien	  cur += 2;
72460484Sobrien	  idx += 2;
72560484Sobrien	  octet_in_word++;
72677298Sobrien
72760484Sobrien	  if (octet_in_word == LISTING_WORD_SIZE)
72833965Sjdp	    {
72933965Sjdp	      fprintf (list_file, " ");
73033965Sjdp	      idx++;
73160484Sobrien	      octet_in_word = 0;
73233965Sjdp	    }
73333965Sjdp	}
73477298Sobrien
73560484Sobrien      fprintf (list_file, "\n");
73677298Sobrien      on_page++;
73733965Sjdp      listing_page (list);
73833965Sjdp    }
73933965Sjdp}
74033965Sjdp
74133965Sjdpstatic void
742130561Sobrienlist_symbol_table (void)
74333965Sjdp{
74433965Sjdp  extern symbolS *symbol_rootP;
74533965Sjdp  int got_some = 0;
74633965Sjdp
74733965Sjdp  symbolS *ptr;
74833965Sjdp  eject = 1;
74933965Sjdp  listing_page (0);
75033965Sjdp
75133965Sjdp  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
75233965Sjdp    {
75338889Sjdp      if (SEG_NORMAL (S_GET_SEGMENT (ptr))
75438889Sjdp	  || S_GET_SEGMENT (ptr) == absolute_section)
75533965Sjdp	{
75638889Sjdp#ifdef BFD_ASSEMBLER
75738889Sjdp	  /* Don't report section symbols.  They are not interesting.  */
75860484Sobrien	  if (symbol_section_p (ptr))
75938889Sjdp	    continue;
76038889Sjdp#endif
76133965Sjdp	  if (S_GET_NAME (ptr))
76233965Sjdp	    {
76333965Sjdp	      char buf[30], fmt[8];
76433965Sjdp	      valueT val = S_GET_VALUE (ptr);
76533965Sjdp
76633965Sjdp	      /* @@ Note that this is dependent on the compilation options,
76733965Sjdp		 not solely on the target characteristics.  */
76833965Sjdp	      if (sizeof (val) == 4 && sizeof (int) == 4)
76933965Sjdp		sprintf (buf, "%08lx", (unsigned long) val);
77033965Sjdp	      else if (sizeof (val) <= sizeof (unsigned long))
77133965Sjdp		{
77233965Sjdp		  sprintf (fmt, "%%0%lulx",
77333965Sjdp			   (unsigned long) (sizeof (val) * 2));
77433965Sjdp		  sprintf (buf, fmt, (unsigned long) val);
77533965Sjdp		}
77633965Sjdp#if defined (BFD64)
77733965Sjdp	      else if (sizeof (val) > 4)
77833965Sjdp		sprintf_vma (buf, val);
77933965Sjdp#endif
78033965Sjdp	      else
78133965Sjdp		abort ();
78233965Sjdp
78333965Sjdp	      if (!got_some)
78433965Sjdp		{
78533965Sjdp		  fprintf (list_file, "DEFINED SYMBOLS\n");
78633965Sjdp		  on_page++;
78733965Sjdp		  got_some = 1;
78833965Sjdp		}
78933965Sjdp
79060484Sobrien	      if (symbol_get_frag (ptr) && symbol_get_frag (ptr)->line)
79138889Sjdp		{
79238889Sjdp		  fprintf (list_file, "%20s:%-5d  %s:%s %s\n",
79360484Sobrien			   symbol_get_frag (ptr)->line->file->filename,
79460484Sobrien			   symbol_get_frag (ptr)->line->line,
79538889Sjdp			   segment_name (S_GET_SEGMENT (ptr)),
79638889Sjdp			   buf, S_GET_NAME (ptr));
79738889Sjdp		}
79838889Sjdp	      else
79938889Sjdp		{
80038889Sjdp		  fprintf (list_file, "%33s:%s %s\n",
80138889Sjdp			   segment_name (S_GET_SEGMENT (ptr)),
80238889Sjdp			   buf, S_GET_NAME (ptr));
80338889Sjdp		}
80433965Sjdp
80577298Sobrien	      on_page++;
80633965Sjdp	      listing_page (0);
80733965Sjdp	    }
80833965Sjdp	}
80933965Sjdp
81033965Sjdp    }
81133965Sjdp  if (!got_some)
81233965Sjdp    {
81333965Sjdp      fprintf (list_file, "NO DEFINED SYMBOLS\n");
81433965Sjdp      on_page++;
81533965Sjdp    }
81633965Sjdp  fprintf (list_file, "\n");
81733965Sjdp  on_page++;
81833965Sjdp  listing_page (0);
81933965Sjdp
82033965Sjdp  got_some = 0;
82133965Sjdp
82233965Sjdp  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
82333965Sjdp    {
82433965Sjdp      if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
82533965Sjdp	{
82638889Sjdp	  if (S_GET_SEGMENT (ptr) == undefined_section)
82733965Sjdp	    {
82833965Sjdp	      if (!got_some)
82933965Sjdp		{
83033965Sjdp		  got_some = 1;
83133965Sjdp		  fprintf (list_file, "UNDEFINED SYMBOLS\n");
83233965Sjdp		  on_page++;
83333965Sjdp		  listing_page (0);
83433965Sjdp		}
83533965Sjdp	      fprintf (list_file, "%s\n", S_GET_NAME (ptr));
83633965Sjdp	      on_page++;
83733965Sjdp	      listing_page (0);
83833965Sjdp	    }
83933965Sjdp	}
84033965Sjdp    }
84133965Sjdp  if (!got_some)
84233965Sjdp    {
84333965Sjdp      fprintf (list_file, "NO UNDEFINED SYMBOLS\n");
84433965Sjdp      on_page++;
84533965Sjdp      listing_page (0);
84633965Sjdp    }
84733965Sjdp}
84833965Sjdp
84933965Sjdpstatic void
850130561Sobrienprint_source (file_info_type *current_file, list_info_type *list,
851130561Sobrien	      char *buffer, unsigned int width)
85233965Sjdp{
85338889Sjdp  if (!current_file->at_end)
85433965Sjdp    {
85533965Sjdp      while (current_file->linenum < list->hll_line
85633965Sjdp	     && !current_file->at_end)
85733965Sjdp	{
85833965Sjdp	  char *p = buffer_line (current_file, buffer, width);
859130561Sobrien
86038889Sjdp	  fprintf (list_file, "%4u:%-13s **** %s\n", current_file->linenum,
86133965Sjdp		   current_file->filename, p);
86233965Sjdp	  on_page++;
86333965Sjdp	  listing_page (list);
86433965Sjdp	}
86533965Sjdp    }
86633965Sjdp}
86733965Sjdp
86833965Sjdp/* Sometimes the user doesn't want to be bothered by the debugging
86938889Sjdp   records inserted by the compiler, see if the line is suspicious.  */
87033965Sjdp
87133965Sjdpstatic int
872130561Sobriendebugging_pseudo (list_info_type *list, const char *line)
87333965Sjdp{
87438889Sjdp  static int in_debug;
87538889Sjdp  int was_debug;
87638889Sjdp
87738889Sjdp  if (list->debugging)
87838889Sjdp    {
87938889Sjdp      in_debug = 1;
88038889Sjdp      return 1;
88138889Sjdp    }
88238889Sjdp
88338889Sjdp  was_debug = in_debug;
88438889Sjdp  in_debug = 0;
88538889Sjdp
88689857Sobrien  while (ISSPACE (*line))
88733965Sjdp    line++;
88833965Sjdp
88933965Sjdp  if (*line != '.')
89038889Sjdp    {
89138889Sjdp#ifdef OBJ_ELF
89238889Sjdp      /* The ELF compiler sometimes emits blank lines after switching
89338889Sjdp         out of a debugging section.  If the next line drops us back
89438889Sjdp         into debugging information, then don't print the blank line.
89538889Sjdp         This is a hack for a particular compiler behaviour, not a
89638889Sjdp         general case.  */
89738889Sjdp      if (was_debug
89838889Sjdp	  && *line == '\0'
89938889Sjdp	  && list->next != NULL
90038889Sjdp	  && list->next->debugging)
90138889Sjdp	{
90238889Sjdp	  in_debug = 1;
90338889Sjdp	  return 1;
90438889Sjdp	}
90538889Sjdp#endif
90633965Sjdp
90738889Sjdp      return 0;
90838889Sjdp    }
90938889Sjdp
91033965Sjdp  line++;
91133965Sjdp
91233965Sjdp  if (strncmp (line, "def", 3) == 0)
91333965Sjdp    return 1;
91433965Sjdp  if (strncmp (line, "val", 3) == 0)
91533965Sjdp    return 1;
91633965Sjdp  if (strncmp (line, "scl", 3) == 0)
91733965Sjdp    return 1;
91833965Sjdp  if (strncmp (line, "line", 4) == 0)
91933965Sjdp    return 1;
92033965Sjdp  if (strncmp (line, "endef", 5) == 0)
92133965Sjdp    return 1;
92233965Sjdp  if (strncmp (line, "ln", 2) == 0)
92333965Sjdp    return 1;
92433965Sjdp  if (strncmp (line, "type", 4) == 0)
92533965Sjdp    return 1;
92633965Sjdp  if (strncmp (line, "size", 4) == 0)
92733965Sjdp    return 1;
92833965Sjdp  if (strncmp (line, "dim", 3) == 0)
92933965Sjdp    return 1;
93033965Sjdp  if (strncmp (line, "tag", 3) == 0)
93133965Sjdp    return 1;
93233965Sjdp  if (strncmp (line, "stabs", 5) == 0)
93333965Sjdp    return 1;
93433965Sjdp  if (strncmp (line, "stabn", 5) == 0)
93533965Sjdp    return 1;
93633965Sjdp
93733965Sjdp  return 0;
93833965Sjdp}
93933965Sjdp
94033965Sjdpstatic void
941130561Sobrienlisting_listing (char *name ATTRIBUTE_UNUSED)
94233965Sjdp{
94333965Sjdp  list_info_type *list = head;
94433965Sjdp  file_info_type *current_hll_file = (file_info_type *) NULL;
94533965Sjdp  char *message;
94633965Sjdp  char *buffer;
94733965Sjdp  char *p;
94833965Sjdp  int show_listing = 1;
94933965Sjdp  unsigned int width;
95033965Sjdp
95138889Sjdp  buffer = xmalloc (listing_rhs_width);
95238889Sjdp  data_buffer = xmalloc (MAX_BYTES);
95333965Sjdp  eject = 1;
95433965Sjdp  list = head;
95533965Sjdp
95633965Sjdp  while (list != (list_info_type *) NULL && 0)
95733965Sjdp    {
95833965Sjdp      if (list->next)
95933965Sjdp	list->frag = list->next->frag;
96033965Sjdp      list = list->next;
96133965Sjdp    }
96233965Sjdp
96333965Sjdp  list = head->next;
96433965Sjdp
96533965Sjdp  while (list)
96633965Sjdp    {
96760484Sobrien      unsigned int list_line;
96860484Sobrien
96938889Sjdp      width = listing_rhs_width > paper_width ? paper_width :
97038889Sjdp	listing_rhs_width;
97133965Sjdp
97260484Sobrien      list_line = list->line;
97333965Sjdp      switch (list->edict)
97433965Sjdp	{
97533965Sjdp	case EDICT_LIST:
97660484Sobrien	  /* Skip all lines up to the current.  */
97760484Sobrien	  list_line--;
97833965Sjdp	  break;
97933965Sjdp	case EDICT_NOLIST:
98033965Sjdp	  show_listing--;
98133965Sjdp	  break;
98233965Sjdp	case EDICT_NOLIST_NEXT:
98377298Sobrien	  if (show_listing == 0)
98477298Sobrien	    list_line--;
98533965Sjdp	  break;
98633965Sjdp	case EDICT_EJECT:
98733965Sjdp	  break;
98833965Sjdp	case EDICT_NONE:
98933965Sjdp	  break;
99033965Sjdp	case EDICT_TITLE:
99133965Sjdp	  title = list->edict_arg;
99233965Sjdp	  break;
99333965Sjdp	case EDICT_SBTTL:
99433965Sjdp	  subtitle = list->edict_arg;
99533965Sjdp	  break;
99633965Sjdp	default:
99733965Sjdp	  abort ();
99833965Sjdp	}
99933965Sjdp
100060484Sobrien      if (show_listing <= 0)
100160484Sobrien	{
100260484Sobrien	  while (list->file->linenum < list_line
100360484Sobrien		 && !list->file->at_end)
100460484Sobrien	    p = buffer_line (list->file, buffer, width);
100560484Sobrien	}
100660484Sobrien
100777298Sobrien      if (list->edict == EDICT_LIST
100877298Sobrien	  || (list->edict == EDICT_NOLIST_NEXT && show_listing == 0))
100960484Sobrien	{
101060484Sobrien	  /* Enable listing for the single line that caused the enable.  */
101160484Sobrien	  list_line++;
101260484Sobrien	  show_listing++;
101360484Sobrien	}
101460484Sobrien
101533965Sjdp      if (show_listing > 0)
101633965Sjdp	{
101733965Sjdp	  /* Scan down the list and print all the stuff which can be done
101833965Sjdp	     with this line (or lines).  */
101933965Sjdp	  message = 0;
102033965Sjdp
102133965Sjdp	  if (list->hll_file)
1022130561Sobrien	    current_hll_file = list->hll_file;
102333965Sjdp
102438889Sjdp	  if (current_hll_file && list->hll_line && (listing & LISTING_HLL))
1025130561Sobrien	    print_source (current_hll_file, list, buffer, width);
102633965Sjdp
102738889Sjdp	  if (list->line_contents)
102833965Sjdp	    {
102938889Sjdp	      if (!((listing & LISTING_NODEBUG)
103038889Sjdp		    && debugging_pseudo (list, list->line_contents)))
1031130561Sobrien		print_lines (list,
1032130561Sobrien			     list->file->linenum == 0 ? list->line : list->file->linenum,
1033130561Sobrien			     list->line_contents, calc_hex (list));
1034130561Sobrien
103560484Sobrien	      free (list->line_contents);
103660484Sobrien	      list->line_contents = NULL;
103738889Sjdp	    }
103838889Sjdp	  else
103938889Sjdp	    {
104060484Sobrien	      while (list->file->linenum < list_line
104138889Sjdp		     && !list->file->at_end)
104238889Sjdp		{
104338889Sjdp		  unsigned int address;
104433965Sjdp
104538889Sjdp		  p = buffer_line (list->file, buffer, width);
104633965Sjdp
104760484Sobrien		  if (list->file->linenum < list_line)
104877298Sobrien		    address = ~(unsigned int) 0;
104938889Sjdp		  else
105038889Sjdp		    address = calc_hex (list);
105133965Sjdp
105238889Sjdp		  if (!((listing & LISTING_NODEBUG)
105338889Sjdp			&& debugging_pseudo (list, p)))
105438889Sjdp		    print_lines (list, list->file->linenum, p, address);
105538889Sjdp		}
105633965Sjdp	    }
105733965Sjdp
105833965Sjdp	  if (list->edict == EDICT_EJECT)
1059130561Sobrien	    eject = 1;
106033965Sjdp	}
106133965Sjdp
106277298Sobrien      if (list->edict == EDICT_NOLIST_NEXT && show_listing == 1)
106333965Sjdp	--show_listing;
106433965Sjdp
106533965Sjdp      list = list->next;
106633965Sjdp    }
106738889Sjdp
106833965Sjdp  free (buffer);
106938889Sjdp  free (data_buffer);
107038889Sjdp  data_buffer = NULL;
107133965Sjdp}
107233965Sjdp
107333965Sjdpvoid
1074130561Sobrienlisting_print (char *name)
107533965Sjdp{
107633965Sjdp  int using_stdout;
107777298Sobrien
107833965Sjdp  title = "";
107933965Sjdp  subtitle = "";
108033965Sjdp
108133965Sjdp  if (name == NULL)
108233965Sjdp    {
108333965Sjdp      list_file = stdout;
108433965Sjdp      using_stdout = 1;
108533965Sjdp    }
108633965Sjdp  else
108733965Sjdp    {
108889857Sobrien      list_file = fopen (name, FOPEN_WT);
108933965Sjdp      if (list_file != NULL)
109033965Sjdp	using_stdout = 0;
109133965Sjdp      else
109233965Sjdp	{
1093130561Sobrien#ifdef BFD_ASSEMBLER
1094130561Sobrien      bfd_set_error (bfd_error_system_call);
1095130561Sobrien#endif
109660484Sobrien	  as_perror (_("can't open list file: %s"), name);
109733965Sjdp	  list_file = stdout;
109833965Sjdp	  using_stdout = 1;
109933965Sjdp	}
110033965Sjdp    }
110133965Sjdp
110233965Sjdp  if (listing & LISTING_NOFORM)
1103130561Sobrien    paper_height = 0;
110433965Sjdp
110533965Sjdp  if (listing & LISTING_LISTING)
1106130561Sobrien    listing_listing (name);
110733965Sjdp
110833965Sjdp  if (listing & LISTING_SYMBOLS)
1109130561Sobrien    list_symbol_table ();
111033965Sjdp
111133965Sjdp  if (! using_stdout)
111233965Sjdp    {
111333965Sjdp      if (fclose (list_file) == EOF)
1114130561Sobrien	{
1115130561Sobrien#ifdef BFD_ASSEMBLER
1116130561Sobrien	  bfd_set_error (bfd_error_system_call);
1117130561Sobrien#endif
1118130561Sobrien	  as_perror (_("error closing list file: %s"), name);
1119130561Sobrien	}
112033965Sjdp    }
112133965Sjdp
112238889Sjdp  if (last_open_file)
1123130561Sobrien    fclose (last_open_file);
112433965Sjdp}
112533965Sjdp
112633965Sjdpvoid
1127130561Sobrienlisting_file (const char *name)
112833965Sjdp{
112933965Sjdp  fn = name;
113033965Sjdp}
113133965Sjdp
113233965Sjdpvoid
1133130561Sobrienlisting_eject (int ignore ATTRIBUTE_UNUSED)
113433965Sjdp{
113533965Sjdp  if (listing)
113633965Sjdp    listing_tail->edict = EDICT_EJECT;
113733965Sjdp}
113833965Sjdp
113933965Sjdpvoid
1140130561Sobrienlisting_flags (int ignore ATTRIBUTE_UNUSED)
114133965Sjdp{
114233965Sjdp  while ((*input_line_pointer++) && (*input_line_pointer != '\n'))
114333965Sjdp    input_line_pointer++;
114433965Sjdp
114533965Sjdp}
114633965Sjdp
114733965Sjdp/* Turn listing on or off.  An argument of 0 means to turn off
114833965Sjdp   listing.  An argument of 1 means to turn on listing.  An argument
114933965Sjdp   of 2 means to turn off listing, but as of the next line; that is,
115033965Sjdp   the current line should be listed, but the next line should not.  */
115133965Sjdp
115233965Sjdpvoid
1153130561Sobrienlisting_list (int on)
115433965Sjdp{
115533965Sjdp  if (listing)
115633965Sjdp    {
115733965Sjdp      switch (on)
115833965Sjdp	{
115933965Sjdp	case 0:
116033965Sjdp	  if (listing_tail->edict == EDICT_LIST)
116133965Sjdp	    listing_tail->edict = EDICT_NONE;
116233965Sjdp	  else
116333965Sjdp	    listing_tail->edict = EDICT_NOLIST;
116433965Sjdp	  break;
116533965Sjdp	case 1:
116633965Sjdp	  if (listing_tail->edict == EDICT_NOLIST
116733965Sjdp	      || listing_tail->edict == EDICT_NOLIST_NEXT)
116833965Sjdp	    listing_tail->edict = EDICT_NONE;
116933965Sjdp	  else
117033965Sjdp	    listing_tail->edict = EDICT_LIST;
117133965Sjdp	  break;
117233965Sjdp	case 2:
117333965Sjdp	  listing_tail->edict = EDICT_NOLIST_NEXT;
117433965Sjdp	  break;
117533965Sjdp	default:
117633965Sjdp	  abort ();
117733965Sjdp	}
117833965Sjdp    }
117933965Sjdp}
118033965Sjdp
118133965Sjdpvoid
1182130561Sobrienlisting_psize (int width_only)
118333965Sjdp{
118433965Sjdp  if (! width_only)
118533965Sjdp    {
118633965Sjdp      paper_height = get_absolute_expression ();
118733965Sjdp
118833965Sjdp      if (paper_height < 0 || paper_height > 1000)
118933965Sjdp	{
119033965Sjdp	  paper_height = 0;
119160484Sobrien	  as_warn (_("strange paper height, set to no form"));
119233965Sjdp	}
119333965Sjdp
119433965Sjdp      if (*input_line_pointer != ',')
119533965Sjdp	{
119633965Sjdp	  demand_empty_rest_of_line ();
119733965Sjdp	  return;
119833965Sjdp	}
119933965Sjdp
120033965Sjdp      ++input_line_pointer;
120133965Sjdp    }
120233965Sjdp
120333965Sjdp  paper_width = get_absolute_expression ();
120433965Sjdp
120533965Sjdp  demand_empty_rest_of_line ();
120633965Sjdp}
120733965Sjdp
120833965Sjdpvoid
1209130561Sobrienlisting_nopage (int ignore ATTRIBUTE_UNUSED)
121033965Sjdp{
121133965Sjdp  paper_height = 0;
121233965Sjdp}
121333965Sjdp
121433965Sjdpvoid
1215130561Sobrienlisting_title (int depth)
121633965Sjdp{
121733965Sjdp  int quoted;
121833965Sjdp  char *start;
121933965Sjdp  char *ttl;
122033965Sjdp  unsigned int length;
122133965Sjdp
122233965Sjdp  SKIP_WHITESPACE ();
122333965Sjdp  if (*input_line_pointer != '\"')
122433965Sjdp    quoted = 0;
122533965Sjdp  else
122633965Sjdp    {
122733965Sjdp      quoted = 1;
122833965Sjdp      ++input_line_pointer;
122933965Sjdp    }
123033965Sjdp
123133965Sjdp  start = input_line_pointer;
123233965Sjdp
123333965Sjdp  while (*input_line_pointer)
123433965Sjdp    {
123533965Sjdp      if (quoted
123633965Sjdp	  ? *input_line_pointer == '\"'
123733965Sjdp	  : is_end_of_line[(unsigned char) *input_line_pointer])
123833965Sjdp	{
123933965Sjdp	  if (listing)
124033965Sjdp	    {
124133965Sjdp	      length = input_line_pointer - start;
124233965Sjdp	      ttl = xmalloc (length + 1);
124333965Sjdp	      memcpy (ttl, start, length);
124433965Sjdp	      ttl[length] = 0;
124533965Sjdp	      listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
124633965Sjdp	      listing_tail->edict_arg = ttl;
124733965Sjdp	    }
124833965Sjdp	  if (quoted)
124933965Sjdp	    input_line_pointer++;
125033965Sjdp	  demand_empty_rest_of_line ();
125133965Sjdp	  return;
125233965Sjdp	}
125333965Sjdp      else if (*input_line_pointer == '\n')
125433965Sjdp	{
125589857Sobrien	  as_bad (_("new line in title"));
125633965Sjdp	  demand_empty_rest_of_line ();
125733965Sjdp	  return;
125833965Sjdp	}
125933965Sjdp      else
126033965Sjdp	{
126133965Sjdp	  input_line_pointer++;
126233965Sjdp	}
126333965Sjdp    }
126433965Sjdp}
126533965Sjdp
126633965Sjdpvoid
1267130561Sobrienlisting_source_line (unsigned int line)
126833965Sjdp{
126933965Sjdp  if (listing)
127033965Sjdp    {
127133965Sjdp      new_frag ();
127233965Sjdp      listing_tail->hll_line = line;
127333965Sjdp      new_frag ();
127433965Sjdp    }
127533965Sjdp}
127633965Sjdp
127733965Sjdpvoid
1278130561Sobrienlisting_source_file (const char *file)
127933965Sjdp{
128033965Sjdp  if (listing)
128133965Sjdp    listing_tail->hll_file = file_info (file);
128233965Sjdp}
128333965Sjdp
128433965Sjdp#else
128533965Sjdp
128677298Sobrien/* Dummy functions for when compiled without listing enabled.  */
128733965Sjdp
128833965Sjdpvoid
1289130561Sobrienlisting_flags (int ignore)
129033965Sjdp{
129133965Sjdp  s_ignore (0);
129233965Sjdp}
129333965Sjdp
129477298Sobrienvoid
1295130561Sobrienlisting_list (int on)
129633965Sjdp{
129733965Sjdp  s_ignore (0);
129833965Sjdp}
129933965Sjdp
130077298Sobrienvoid
1301130561Sobrienlisting_eject (int ignore)
130233965Sjdp{
130333965Sjdp  s_ignore (0);
130433965Sjdp}
130533965Sjdp
130677298Sobrienvoid
1307130561Sobrienlisting_psize (int ignore)
130833965Sjdp{
130933965Sjdp  s_ignore (0);
131033965Sjdp}
131133965Sjdp
131233965Sjdpvoid
1313130561Sobrienlisting_nopage (int ignore)
131433965Sjdp{
131533965Sjdp  s_ignore (0);
131633965Sjdp}
131733965Sjdp
131877298Sobrienvoid
1319130561Sobrienlisting_title (int depth)
132033965Sjdp{
132133965Sjdp  s_ignore (0);
132233965Sjdp}
132333965Sjdp
132433965Sjdpvoid
1325130561Sobrienlisting_file (const char *name)
132633965Sjdp{
132733965Sjdp}
132833965Sjdp
132977298Sobrienvoid
1330130561Sobrienlisting_newline (char *name)
133133965Sjdp{
133233965Sjdp}
133333965Sjdp
133477298Sobrienvoid
1335130561Sobrienlisting_source_line (unsigned int n)
133633965Sjdp{
133733965Sjdp}
133877298Sobrien
133977298Sobrienvoid
1340130561Sobrienlisting_source_file (const char *n)
134133965Sjdp{
134233965Sjdp}
134333965Sjdp
134433965Sjdp#endif
1345