listing.c revision 89857
133965Sjdp/* listing.c - mainting assembly listings
277298Sobrien   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
377298Sobrien   2001
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"
9533965Sjdp#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;
27233965Sjdp  p->filename = xmalloc ((unsigned long) strlen (file_name) + 1);
27333965Sjdp  strcpy (p->filename, file_name);
27438889Sjdp  p->pos = 0;
27533965Sjdp  p->linenum = 0;
27633965Sjdp  p->at_end = 0;
27733965Sjdp
27833965Sjdp  return p;
27933965Sjdp}
28033965Sjdp
28133965Sjdpstatic void
28233965Sjdpnew_frag ()
28333965Sjdp{
28433965Sjdp
28533965Sjdp  frag_wane (frag_now);
28633965Sjdp  frag_new (0);
28733965Sjdp
28833965Sjdp}
28933965Sjdp
29033965Sjdpvoid
29133965Sjdplisting_newline (ps)
29233965Sjdp     char *ps;
29333965Sjdp{
29433965Sjdp  char *file;
29533965Sjdp  unsigned int line;
29633965Sjdp  static unsigned int last_line = 0xffff;
29733965Sjdp  static char *last_file = NULL;
29838889Sjdp  list_info_type *new = NULL;
29933965Sjdp
30033965Sjdp  if (listing == 0)
30133965Sjdp    return;
30233965Sjdp
30333965Sjdp  if (now_seg == absolute_section)
30433965Sjdp    return;
30533965Sjdp
30638889Sjdp#ifdef OBJ_ELF
30738889Sjdp  /* In ELF, anything in a section beginning with .debug or .line is
30838889Sjdp     considered to be debugging information.  This includes the
30938889Sjdp     statement which switches us into the debugging section, which we
31038889Sjdp     can only set after we are already in the debugging section.  */
31138889Sjdp  if ((listing & LISTING_NODEBUG) != 0
31238889Sjdp      && listing_tail != NULL
31338889Sjdp      && ! listing_tail->debugging)
31438889Sjdp    {
31538889Sjdp      const char *segname;
31638889Sjdp
31738889Sjdp      segname = segment_name (now_seg);
31838889Sjdp      if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
31938889Sjdp	  || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
32038889Sjdp	listing_tail->debugging = 1;
32138889Sjdp    }
32238889Sjdp#endif
32338889Sjdp
32433965Sjdp  as_where (&file, &line);
32538889Sjdp  if (ps == NULL)
32633965Sjdp    {
32777298Sobrien      if (line == last_line
32877298Sobrien	  && !(last_file && file && strcmp (file, last_file)))
32938889Sjdp	return;
33033965Sjdp
33133965Sjdp      new = (list_info_type *) xmalloc (sizeof (list_info_type));
33260484Sobrien
33360484Sobrien      /* Detect if we are reading from stdin by examining the file
33460484Sobrien	 name returned by as_where().
33560484Sobrien
33660484Sobrien	 [FIXME: We rely upon the name in the strcmp below being the
33760484Sobrien	 same as the one used by input_scrub_new_file(), if that is
33860484Sobrien	 not true, then this code will fail].
33960484Sobrien
34077298Sobrien	 If we are reading from stdin, then we need to save each input
34177298Sobrien	 line here (assuming of course that we actually have a line of
34277298Sobrien	 input to read), so that it can be displayed in the listing
34377298Sobrien	 that is produced at the end of the assembly.  */
34460484Sobrien      if (strcmp (file, _("{standard input}")) == 0
34560484Sobrien	  && input_line_pointer != NULL)
34660484Sobrien	{
34777298Sobrien	  char *copy;
34860484Sobrien	  int len;
34960484Sobrien	  int seen_quote = 0;
35060484Sobrien
35160484Sobrien	  for (copy = input_line_pointer - 1;
35277298Sobrien	       *copy && (seen_quote
35377298Sobrien			 || (! is_end_of_line [(unsigned char) *copy]));
35477298Sobrien	       copy++)
35577298Sobrien	    if (*copy == '"' && copy[-1] != '\\')
35660484Sobrien	      seen_quote = ! seen_quote;
35760484Sobrien
35860484Sobrien	  len = (copy - input_line_pointer) + 2;
35960484Sobrien
36060484Sobrien	  copy = xmalloc (len);
36160484Sobrien
36260484Sobrien	  if (copy != NULL)
36360484Sobrien	    {
36477298Sobrien	      char *src = input_line_pointer - 1;
36577298Sobrien	      char *dest = copy;
36677298Sobrien
36760484Sobrien	      while (--len)
36860484Sobrien		{
36977298Sobrien		  unsigned char c = *src++;
37060484Sobrien
37160484Sobrien		  /* Omit control characters in the listing.  */
37289857Sobrien		  if (!ISCNTRL (c))
37377298Sobrien		    *dest++ = c;
37460484Sobrien		}
37577298Sobrien
37660484Sobrien	      *dest = 0;
37760484Sobrien	    }
37877298Sobrien
37960484Sobrien	  new->line_contents = copy;
38060484Sobrien	}
38160484Sobrien      else
38260484Sobrien	new->line_contents = NULL;
38338889Sjdp    }
38438889Sjdp  else
38538889Sjdp    {
38638889Sjdp      new = (list_info_type *) xmalloc (sizeof (list_info_type));
38738889Sjdp      new->line_contents = ps;
38838889Sjdp    }
38933965Sjdp
39038889Sjdp  last_line = line;
39138889Sjdp  last_file = file;
39277298Sobrien
39338889Sjdp  new_frag ();
39438889Sjdp
39538889Sjdp  if (listing_tail)
39660484Sobrien    listing_tail->next = new;
39738889Sjdp  else
39860484Sobrien    head = new;
39977298Sobrien
40038889Sjdp  listing_tail = new;
40138889Sjdp
40238889Sjdp  new->frag = frag_now;
40338889Sjdp  new->line = line;
40438889Sjdp  new->file = file_info (file);
40538889Sjdp  new->next = (list_info_type *) NULL;
40638889Sjdp  new->message = (char *) NULL;
40738889Sjdp  new->edict = EDICT_NONE;
40838889Sjdp  new->hll_file = (file_info_type *) NULL;
40938889Sjdp  new->hll_line = 0;
41038889Sjdp  new->debugging = 0;
41177298Sobrien
41238889Sjdp  new_frag ();
41338889Sjdp
41438889Sjdp#ifdef OBJ_ELF
41538889Sjdp  /* In ELF, anything in a section beginning with .debug or .line is
41638889Sjdp     considered to be debugging information.  */
41738889Sjdp  if ((listing & LISTING_NODEBUG) != 0)
41838889Sjdp    {
41938889Sjdp      const char *segname;
42038889Sjdp
42138889Sjdp      segname = segment_name (now_seg);
42238889Sjdp      if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
42338889Sjdp	  || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
42438889Sjdp	new->debugging = 1;
42538889Sjdp    }
42638889Sjdp#endif
42733965Sjdp}
42833965Sjdp
42933965Sjdp/* Attach all current frags to the previous line instead of the
43033965Sjdp   current line.  This is called by the MIPS backend when it discovers
43133965Sjdp   that it needs to add some NOP instructions; the added NOP
43233965Sjdp   instructions should go with the instruction that has the delay, not
43333965Sjdp   with the new instruction.  */
43433965Sjdp
43533965Sjdpvoid
43633965Sjdplisting_prev_line ()
43733965Sjdp{
43833965Sjdp  list_info_type *l;
43933965Sjdp  fragS *f;
44033965Sjdp
44133965Sjdp  if (head == (list_info_type *) NULL
44233965Sjdp      || head == listing_tail)
44333965Sjdp    return;
44433965Sjdp
44533965Sjdp  new_frag ();
44633965Sjdp
44733965Sjdp  for (l = head; l->next != listing_tail; l = l->next)
44833965Sjdp    ;
44933965Sjdp
45033965Sjdp  for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next)
45133965Sjdp    if (f->line == listing_tail)
45233965Sjdp      f->line = l;
45333965Sjdp
45433965Sjdp  listing_tail->frag = frag_now;
45533965Sjdp  new_frag ();
45633965Sjdp}
45733965Sjdp
45877298Sobrien/* This function returns the next source line from the file supplied,
45977298Sobrien   truncated to size.  It appends a fake line to the end of each input
46077298Sobrien   file to make.  */
46133965Sjdp
46233965Sjdpstatic char *
46333965Sjdpbuffer_line (file, line, size)
46477298Sobrien     file_info_type *file;
46533965Sjdp     char *line;
46633965Sjdp     unsigned int size;
46733965Sjdp{
46833965Sjdp  unsigned int count = 0;
46933965Sjdp  int c;
47033965Sjdp
47133965Sjdp  char *p = line;
47233965Sjdp
47377298Sobrien  /* If we couldn't open the file, return an empty line.  */
47438889Sjdp  if (file->at_end)
47538889Sjdp    return "";
47638889Sjdp
47738889Sjdp  /* Check the cache and see if we last used this file.  */
47838889Sjdp  if (!last_open_file_info || file != last_open_file_info)
47933965Sjdp    {
48038889Sjdp      if (last_open_file)
48138889Sjdp	{
48238889Sjdp	  last_open_file_info->pos = ftell (last_open_file);
48338889Sjdp	  fclose (last_open_file);
48438889Sjdp	}
48538889Sjdp
48638889Sjdp      last_open_file_info = file;
48789857Sobrien      last_open_file = fopen (file->filename, FOPEN_RT);
48838889Sjdp      if (last_open_file == NULL)
48938889Sjdp	{
49038889Sjdp	  file->at_end = 1;
49138889Sjdp	  return "";
49238889Sjdp	}
49377298Sobrien
49438889Sjdp      /* Seek to where we were last time this file was open.  */
49538889Sjdp      if (file->pos)
49677298Sobrien	fseek (last_open_file, file->pos, SEEK_SET);
49733965Sjdp    }
49833965Sjdp
49938889Sjdp  c = fgetc (last_open_file);
50033965Sjdp
50177298Sobrien  /* Leave room for null.  */
50277298Sobrien  size -= 1;
50333965Sjdp
50433965Sjdp  while (c != EOF && c != '\n')
50533965Sjdp    {
50633965Sjdp      if (count < size)
50733965Sjdp	*p++ = c;
50833965Sjdp      count++;
50933965Sjdp
51038889Sjdp      c = fgetc (last_open_file);
51133965Sjdp
51233965Sjdp    }
51333965Sjdp  if (c == EOF)
51433965Sjdp    {
51533965Sjdp      file->at_end = 1;
51689857Sobrien      if (count + 2 < size)
51789857Sobrien	{
51889857Sobrien	  *p++ = '.';
51989857Sobrien	  *p++ = '.';
52089857Sobrien	  *p++ = '.';
52189857Sobrien	}
52233965Sjdp    }
52333965Sjdp  file->linenum++;
52433965Sjdp  *p++ = 0;
52533965Sjdp  return line;
52633965Sjdp}
52733965Sjdp
52833965Sjdpstatic const char *fn;
52933965Sjdp
53033965Sjdpstatic unsigned int eject;	/* Eject pending */
53133965Sjdpstatic unsigned int page;	/* Current page number */
53277298Sobrienstatic char *title;		/* Current title */
53377298Sobrienstatic char *subtitle;		/* Current subtitle */
53477298Sobrienstatic unsigned int on_page;	/* Number of lines printed on current page */
53533965Sjdp
53633965Sjdpstatic void
53733965Sjdplisting_page (list)
53833965Sjdp     list_info_type *list;
53933965Sjdp{
54033965Sjdp  /* Grope around, see if we can see a title or subtitle edict coming up
54177298Sobrien     soon.  (we look down 10 lines of the page and see if it's there)  */
54277298Sobrien  if ((eject || (on_page >= (unsigned int) paper_height))
54377298Sobrien      && paper_height != 0)
54433965Sjdp    {
54533965Sjdp      unsigned int c = 10;
54633965Sjdp      int had_title = 0;
54733965Sjdp      int had_subtitle = 0;
54833965Sjdp
54933965Sjdp      page++;
55033965Sjdp
55133965Sjdp      while (c != 0 && list)
55233965Sjdp	{
55333965Sjdp	  if (list->edict == EDICT_SBTTL && !had_subtitle)
55433965Sjdp	    {
55533965Sjdp	      had_subtitle = 1;
55633965Sjdp	      subtitle = list->edict_arg;
55733965Sjdp	    }
55833965Sjdp	  if (list->edict == EDICT_TITLE && !had_title)
55933965Sjdp	    {
56033965Sjdp	      had_title = 1;
56133965Sjdp	      title = list->edict_arg;
56233965Sjdp	    }
56333965Sjdp	  list = list->next;
56433965Sjdp	  c--;
56533965Sjdp	}
56633965Sjdp
56733965Sjdp      if (page > 1)
56833965Sjdp	{
56933965Sjdp	  fprintf (list_file, "\f");
57033965Sjdp	}
57133965Sjdp
57233965Sjdp      fprintf (list_file, "%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
57333965Sjdp      fprintf (list_file, "%s\n", title);
57433965Sjdp      fprintf (list_file, "%s\n", subtitle);
57533965Sjdp      on_page = 3;
57633965Sjdp      eject = 0;
57733965Sjdp    }
57833965Sjdp}
57933965Sjdp
58033965Sjdpstatic unsigned int
58133965Sjdpcalc_hex (list)
58277298Sobrien     list_info_type *list;
58333965Sjdp{
58438889Sjdp  int data_buffer_size;
58533965Sjdp  list_info_type *first = list;
58677298Sobrien  unsigned int address = ~(unsigned int) 0;
58733965Sjdp  fragS *frag;
58833965Sjdp  fragS *frag_ptr;
58960484Sobrien  unsigned int octet_in_frag;
59033965Sjdp
59177298Sobrien  /* Find first frag which says it belongs to this line.  */
59233965Sjdp  frag = list->frag;
59333965Sjdp  while (frag && frag->line != list)
59433965Sjdp    frag = frag->fr_next;
59533965Sjdp
59633965Sjdp  frag_ptr = frag;
59733965Sjdp
59833965Sjdp  data_buffer_size = 0;
59933965Sjdp
60077298Sobrien  /* Dump all the frags which belong to this line.  */
60133965Sjdp  while (frag_ptr != (fragS *) NULL && frag_ptr->line == first)
60233965Sjdp    {
60377298Sobrien      /* Print as many bytes from the fixed part as is sensible.  */
60460484Sobrien      octet_in_frag = 0;
60560484Sobrien      while ((offsetT) octet_in_frag < frag_ptr->fr_fix
60638889Sjdp	     && data_buffer_size < MAX_BYTES - 3)
60733965Sjdp	{
60877298Sobrien	  if (address == ~(unsigned int) 0)
60933965Sjdp	    {
61060484Sobrien	      address = frag_ptr->fr_address / OCTETS_PER_BYTE;
61133965Sjdp	    }
61233965Sjdp
61333965Sjdp	  sprintf (data_buffer + data_buffer_size,
61433965Sjdp		   "%02X",
61560484Sobrien		   (frag_ptr->fr_literal[octet_in_frag]) & 0xff);
61633965Sjdp	  data_buffer_size += 2;
61760484Sobrien	  octet_in_frag++;
61833965Sjdp	}
61977298Sobrien    if (frag_ptr->fr_type == rs_fill)
62033965Sjdp      {
62160484Sobrien	unsigned int var_rep_max = octet_in_frag;
62260484Sobrien	unsigned int var_rep_idx = octet_in_frag;
62333965Sjdp
62477298Sobrien	/* Print as many bytes from the variable part as is sensible.  */
62560484Sobrien	while (((offsetT) octet_in_frag
62660484Sobrien		< (frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset))
62738889Sjdp	       && data_buffer_size < MAX_BYTES - 3)
62833965Sjdp	  {
62977298Sobrien	    if (address == ~(unsigned int) 0)
63033965Sjdp	      {
63160484Sobrien		address = frag_ptr->fr_address / OCTETS_PER_BYTE;
63233965Sjdp	      }
63333965Sjdp	    sprintf (data_buffer + data_buffer_size,
63433965Sjdp		     "%02X",
63533965Sjdp		     (frag_ptr->fr_literal[var_rep_idx]) & 0xff);
63633965Sjdp#if 0
63733965Sjdp	    data_buffer[data_buffer_size++] = '*';
63833965Sjdp	    data_buffer[data_buffer_size++] = '*';
63933965Sjdp#endif
64033965Sjdp	    data_buffer_size += 2;
64133965Sjdp
64233965Sjdp	    var_rep_idx++;
64360484Sobrien	    octet_in_frag++;
64433965Sjdp
64538889Sjdp	    if ((offsetT) var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var)
64633965Sjdp	      var_rep_idx = var_rep_max;
64733965Sjdp	  }
64833965Sjdp      }
64933965Sjdp
65033965Sjdp      frag_ptr = frag_ptr->fr_next;
65133965Sjdp    }
65238889Sjdp  data_buffer[data_buffer_size] = '\0';
65333965Sjdp  return address;
65433965Sjdp}
65533965Sjdp
65633965Sjdpstatic void
65733965Sjdpprint_lines (list, lineno, string, address)
65833965Sjdp     list_info_type *list;
65933965Sjdp     unsigned int lineno;
66033965Sjdp     char *string;
66133965Sjdp     unsigned int address;
66233965Sjdp{
66333965Sjdp  unsigned int idx;
66433965Sjdp  unsigned int nchars;
66533965Sjdp  unsigned int lines;
66660484Sobrien  unsigned int octet_in_word = 0;
66733965Sjdp  char *src = data_buffer;
66860484Sobrien  int cur;
66933965Sjdp
67077298Sobrien  /* Print the stuff on the first line.  */
67133965Sjdp  listing_page (list);
67238889Sjdp  nchars = (LISTING_WORD_SIZE * 2 + 1) * listing_lhs_width;
67377298Sobrien
67477298Sobrien  /* Print the hex for the first line.  */
67577298Sobrien  if (address == ~(unsigned int) 0)
67633965Sjdp    {
67733965Sjdp      fprintf (list_file, "% 4d     ", lineno);
67833965Sjdp      for (idx = 0; idx < nchars; idx++)
67933965Sjdp	fprintf (list_file, " ");
68033965Sjdp
68133965Sjdp      fprintf (list_file, "\t%s\n", string ? string : "");
68277298Sobrien
68377298Sobrien      on_page++;
68477298Sobrien
68533965Sjdp      listing_page (0);
68633965Sjdp
68760484Sobrien      return;
68833965Sjdp    }
68960484Sobrien
69060484Sobrien  if (had_errors ())
69160484Sobrien    fprintf (list_file, "% 4d ???? ", lineno);
69233965Sjdp  else
69360484Sobrien    fprintf (list_file, "% 4d %04x ", lineno, address);
69460484Sobrien
69577298Sobrien  /* And the data to go along with it.  */
69660484Sobrien  idx = 0;
69760484Sobrien  cur = 0;
69860484Sobrien  while (src[cur] && idx < nchars)
69933965Sjdp    {
70060484Sobrien      int offset;
70160484Sobrien      offset = cur;
70277298Sobrien      fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
70360484Sobrien      cur += 2;
70460484Sobrien      octet_in_word++;
70577298Sobrien
70660484Sobrien      if (octet_in_word == LISTING_WORD_SIZE)
70733965Sjdp	{
70860484Sobrien	  fprintf (list_file, " ");
70960484Sobrien	  idx++;
71060484Sobrien	  octet_in_word = 0;
71133965Sjdp	}
71277298Sobrien
71360484Sobrien      idx += 2;
71460484Sobrien    }
71577298Sobrien
71660484Sobrien  for (; idx < nchars; idx++)
71760484Sobrien    fprintf (list_file, " ");
71877298Sobrien
71960484Sobrien  fprintf (list_file, "\t%s\n", string ? string : "");
72060484Sobrien  on_page++;
72160484Sobrien  listing_page (list);
72277298Sobrien
72360484Sobrien  if (list->message)
72460484Sobrien    {
72560484Sobrien      fprintf (list_file, "****  %s\n", list->message);
72660484Sobrien      listing_page (list);
72760484Sobrien      on_page++;
72860484Sobrien    }
72977298Sobrien
73060484Sobrien  for (lines = 0;
73160484Sobrien       lines < (unsigned int) listing_lhs_cont_lines
73260484Sobrien	 && src[cur];
73377298Sobrien       lines++)
73460484Sobrien    {
73577298Sobrien      nchars = ((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second - 1;
73633965Sjdp      idx = 0;
73777298Sobrien
73877298Sobrien      /* Print any more lines of data, but more compactly.  */
73960484Sobrien      fprintf (list_file, "% 4d      ", lineno);
74077298Sobrien
74160484Sobrien      while (src[cur] && idx < nchars)
74233965Sjdp	{
74377298Sobrien	  int offset;
74477298Sobrien	  offset = cur;
74577298Sobrien	  fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
74660484Sobrien	  cur += 2;
74760484Sobrien	  idx += 2;
74860484Sobrien	  octet_in_word++;
74977298Sobrien
75060484Sobrien	  if (octet_in_word == LISTING_WORD_SIZE)
75133965Sjdp	    {
75233965Sjdp	      fprintf (list_file, " ");
75333965Sjdp	      idx++;
75460484Sobrien	      octet_in_word = 0;
75533965Sjdp	    }
75633965Sjdp	}
75777298Sobrien
75860484Sobrien      fprintf (list_file, "\n");
75977298Sobrien      on_page++;
76033965Sjdp      listing_page (list);
76133965Sjdp    }
76233965Sjdp}
76333965Sjdp
76433965Sjdpstatic void
76533965Sjdplist_symbol_table ()
76633965Sjdp{
76733965Sjdp  extern symbolS *symbol_rootP;
76833965Sjdp  int got_some = 0;
76933965Sjdp
77033965Sjdp  symbolS *ptr;
77133965Sjdp  eject = 1;
77233965Sjdp  listing_page (0);
77333965Sjdp
77433965Sjdp  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
77533965Sjdp    {
77638889Sjdp      if (SEG_NORMAL (S_GET_SEGMENT (ptr))
77738889Sjdp	  || S_GET_SEGMENT (ptr) == absolute_section)
77833965Sjdp	{
77938889Sjdp#ifdef BFD_ASSEMBLER
78038889Sjdp	  /* Don't report section symbols.  They are not interesting.  */
78160484Sobrien	  if (symbol_section_p (ptr))
78238889Sjdp	    continue;
78338889Sjdp#endif
78433965Sjdp	  if (S_GET_NAME (ptr))
78533965Sjdp	    {
78633965Sjdp	      char buf[30], fmt[8];
78733965Sjdp	      valueT val = S_GET_VALUE (ptr);
78833965Sjdp
78933965Sjdp	      /* @@ Note that this is dependent on the compilation options,
79033965Sjdp		 not solely on the target characteristics.  */
79133965Sjdp	      if (sizeof (val) == 4 && sizeof (int) == 4)
79233965Sjdp		sprintf (buf, "%08lx", (unsigned long) val);
79333965Sjdp	      else if (sizeof (val) <= sizeof (unsigned long))
79433965Sjdp		{
79533965Sjdp		  sprintf (fmt, "%%0%lulx",
79633965Sjdp			   (unsigned long) (sizeof (val) * 2));
79733965Sjdp		  sprintf (buf, fmt, (unsigned long) val);
79833965Sjdp		}
79933965Sjdp#if defined (BFD64)
80033965Sjdp	      else if (sizeof (val) > 4)
80133965Sjdp		sprintf_vma (buf, val);
80233965Sjdp#endif
80333965Sjdp	      else
80433965Sjdp		abort ();
80533965Sjdp
80633965Sjdp	      if (!got_some)
80733965Sjdp		{
80833965Sjdp		  fprintf (list_file, "DEFINED SYMBOLS\n");
80933965Sjdp		  on_page++;
81033965Sjdp		  got_some = 1;
81133965Sjdp		}
81233965Sjdp
81360484Sobrien	      if (symbol_get_frag (ptr) && symbol_get_frag (ptr)->line)
81438889Sjdp		{
81538889Sjdp		  fprintf (list_file, "%20s:%-5d  %s:%s %s\n",
81660484Sobrien			   symbol_get_frag (ptr)->line->file->filename,
81760484Sobrien			   symbol_get_frag (ptr)->line->line,
81838889Sjdp			   segment_name (S_GET_SEGMENT (ptr)),
81938889Sjdp			   buf, S_GET_NAME (ptr));
82038889Sjdp		}
82138889Sjdp	      else
82238889Sjdp		{
82338889Sjdp		  fprintf (list_file, "%33s:%s %s\n",
82438889Sjdp			   segment_name (S_GET_SEGMENT (ptr)),
82538889Sjdp			   buf, S_GET_NAME (ptr));
82638889Sjdp		}
82733965Sjdp
82877298Sobrien	      on_page++;
82933965Sjdp	      listing_page (0);
83033965Sjdp	    }
83133965Sjdp	}
83233965Sjdp
83333965Sjdp    }
83433965Sjdp  if (!got_some)
83533965Sjdp    {
83633965Sjdp      fprintf (list_file, "NO DEFINED SYMBOLS\n");
83733965Sjdp      on_page++;
83833965Sjdp    }
83933965Sjdp  fprintf (list_file, "\n");
84033965Sjdp  on_page++;
84133965Sjdp  listing_page (0);
84233965Sjdp
84333965Sjdp  got_some = 0;
84433965Sjdp
84533965Sjdp  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
84633965Sjdp    {
84733965Sjdp      if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
84833965Sjdp	{
84938889Sjdp	  if (S_GET_SEGMENT (ptr) == undefined_section)
85033965Sjdp	    {
85133965Sjdp	      if (!got_some)
85233965Sjdp		{
85333965Sjdp		  got_some = 1;
85433965Sjdp		  fprintf (list_file, "UNDEFINED SYMBOLS\n");
85533965Sjdp		  on_page++;
85633965Sjdp		  listing_page (0);
85733965Sjdp		}
85833965Sjdp	      fprintf (list_file, "%s\n", S_GET_NAME (ptr));
85933965Sjdp	      on_page++;
86033965Sjdp	      listing_page (0);
86133965Sjdp	    }
86233965Sjdp	}
86333965Sjdp    }
86433965Sjdp  if (!got_some)
86533965Sjdp    {
86633965Sjdp      fprintf (list_file, "NO UNDEFINED SYMBOLS\n");
86733965Sjdp      on_page++;
86833965Sjdp      listing_page (0);
86933965Sjdp    }
87033965Sjdp}
87133965Sjdp
87233965Sjdpstatic void
87333965Sjdpprint_source (current_file, list, buffer, width)
87433965Sjdp     file_info_type *current_file;
87533965Sjdp     list_info_type *list;
87633965Sjdp     char *buffer;
87733965Sjdp     unsigned int width;
87833965Sjdp{
87938889Sjdp  if (!current_file->at_end)
88033965Sjdp    {
88133965Sjdp      while (current_file->linenum < list->hll_line
88233965Sjdp	     && !current_file->at_end)
88333965Sjdp	{
88433965Sjdp	  char *p = buffer_line (current_file, buffer, width);
88538889Sjdp	  fprintf (list_file, "%4u:%-13s **** %s\n", current_file->linenum,
88633965Sjdp		   current_file->filename, p);
88733965Sjdp	  on_page++;
88833965Sjdp	  listing_page (list);
88933965Sjdp	}
89033965Sjdp    }
89133965Sjdp}
89233965Sjdp
89333965Sjdp/* Sometimes the user doesn't want to be bothered by the debugging
89438889Sjdp   records inserted by the compiler, see if the line is suspicious.  */
89533965Sjdp
89633965Sjdpstatic int
89738889Sjdpdebugging_pseudo (list, line)
89838889Sjdp     list_info_type *list;
89938889Sjdp     const char *line;
90033965Sjdp{
90138889Sjdp  static int in_debug;
90238889Sjdp  int was_debug;
90338889Sjdp
90438889Sjdp  if (list->debugging)
90538889Sjdp    {
90638889Sjdp      in_debug = 1;
90738889Sjdp      return 1;
90838889Sjdp    }
90938889Sjdp
91038889Sjdp  was_debug = in_debug;
91138889Sjdp  in_debug = 0;
91238889Sjdp
91389857Sobrien  while (ISSPACE (*line))
91433965Sjdp    line++;
91533965Sjdp
91633965Sjdp  if (*line != '.')
91738889Sjdp    {
91838889Sjdp#ifdef OBJ_ELF
91938889Sjdp      /* The ELF compiler sometimes emits blank lines after switching
92038889Sjdp         out of a debugging section.  If the next line drops us back
92138889Sjdp         into debugging information, then don't print the blank line.
92238889Sjdp         This is a hack for a particular compiler behaviour, not a
92338889Sjdp         general case.  */
92438889Sjdp      if (was_debug
92538889Sjdp	  && *line == '\0'
92638889Sjdp	  && list->next != NULL
92738889Sjdp	  && list->next->debugging)
92838889Sjdp	{
92938889Sjdp	  in_debug = 1;
93038889Sjdp	  return 1;
93138889Sjdp	}
93238889Sjdp#endif
93333965Sjdp
93438889Sjdp      return 0;
93538889Sjdp    }
93638889Sjdp
93733965Sjdp  line++;
93833965Sjdp
93933965Sjdp  if (strncmp (line, "def", 3) == 0)
94033965Sjdp    return 1;
94133965Sjdp  if (strncmp (line, "val", 3) == 0)
94233965Sjdp    return 1;
94333965Sjdp  if (strncmp (line, "scl", 3) == 0)
94433965Sjdp    return 1;
94533965Sjdp  if (strncmp (line, "line", 4) == 0)
94633965Sjdp    return 1;
94733965Sjdp  if (strncmp (line, "endef", 5) == 0)
94833965Sjdp    return 1;
94933965Sjdp  if (strncmp (line, "ln", 2) == 0)
95033965Sjdp    return 1;
95133965Sjdp  if (strncmp (line, "type", 4) == 0)
95233965Sjdp    return 1;
95333965Sjdp  if (strncmp (line, "size", 4) == 0)
95433965Sjdp    return 1;
95533965Sjdp  if (strncmp (line, "dim", 3) == 0)
95633965Sjdp    return 1;
95733965Sjdp  if (strncmp (line, "tag", 3) == 0)
95833965Sjdp    return 1;
95933965Sjdp
96033965Sjdp  if (strncmp (line, "stabs", 5) == 0)
96133965Sjdp    return 1;
96233965Sjdp  if (strncmp (line, "stabn", 5) == 0)
96333965Sjdp    return 1;
96433965Sjdp
96533965Sjdp  return 0;
96633965Sjdp}
96733965Sjdp
96833965Sjdpstatic void
96933965Sjdplisting_listing (name)
97060484Sobrien     char *name ATTRIBUTE_UNUSED;
97133965Sjdp{
97233965Sjdp  list_info_type *list = head;
97333965Sjdp  file_info_type *current_hll_file = (file_info_type *) NULL;
97433965Sjdp  char *message;
97533965Sjdp  char *buffer;
97633965Sjdp  char *p;
97733965Sjdp  int show_listing = 1;
97833965Sjdp  unsigned int width;
97933965Sjdp
98038889Sjdp  buffer = xmalloc (listing_rhs_width);
98138889Sjdp  data_buffer = xmalloc (MAX_BYTES);
98233965Sjdp  eject = 1;
98333965Sjdp  list = head;
98433965Sjdp
98533965Sjdp  while (list != (list_info_type *) NULL && 0)
98633965Sjdp    {
98733965Sjdp      if (list->next)
98833965Sjdp	list->frag = list->next->frag;
98933965Sjdp      list = list->next;
99033965Sjdp
99133965Sjdp    }
99233965Sjdp
99333965Sjdp  list = head->next;
99433965Sjdp
99533965Sjdp  while (list)
99633965Sjdp    {
99760484Sobrien      unsigned int list_line;
99860484Sobrien
99938889Sjdp      width = listing_rhs_width > paper_width ? paper_width :
100038889Sjdp	listing_rhs_width;
100133965Sjdp
100260484Sobrien      list_line = list->line;
100333965Sjdp      switch (list->edict)
100433965Sjdp	{
100533965Sjdp	case EDICT_LIST:
100660484Sobrien	  /* Skip all lines up to the current.  */
100760484Sobrien	  list_line--;
100833965Sjdp	  break;
100933965Sjdp	case EDICT_NOLIST:
101033965Sjdp	  show_listing--;
101133965Sjdp	  break;
101233965Sjdp	case EDICT_NOLIST_NEXT:
101377298Sobrien	  if (show_listing == 0)
101477298Sobrien	    list_line--;
101533965Sjdp	  break;
101633965Sjdp	case EDICT_EJECT:
101733965Sjdp	  break;
101833965Sjdp	case EDICT_NONE:
101933965Sjdp	  break;
102033965Sjdp	case EDICT_TITLE:
102133965Sjdp	  title = list->edict_arg;
102233965Sjdp	  break;
102333965Sjdp	case EDICT_SBTTL:
102433965Sjdp	  subtitle = list->edict_arg;
102533965Sjdp	  break;
102633965Sjdp	default:
102733965Sjdp	  abort ();
102833965Sjdp	}
102933965Sjdp
103060484Sobrien      if (show_listing <= 0)
103160484Sobrien	{
103260484Sobrien	  while (list->file->linenum < list_line
103360484Sobrien		 && !list->file->at_end)
103460484Sobrien	    p = buffer_line (list->file, buffer, width);
103560484Sobrien	}
103660484Sobrien
103777298Sobrien      if (list->edict == EDICT_LIST
103877298Sobrien	  || (list->edict == EDICT_NOLIST_NEXT && show_listing == 0))
103960484Sobrien	{
104060484Sobrien	  /* Enable listing for the single line that caused the enable.  */
104160484Sobrien	  list_line++;
104260484Sobrien	  show_listing++;
104360484Sobrien	}
104460484Sobrien
104533965Sjdp      if (show_listing > 0)
104633965Sjdp	{
104733965Sjdp	  /* Scan down the list and print all the stuff which can be done
104833965Sjdp	     with this line (or lines).  */
104933965Sjdp	  message = 0;
105033965Sjdp
105133965Sjdp	  if (list->hll_file)
105233965Sjdp	    {
105333965Sjdp	      current_hll_file = list->hll_file;
105433965Sjdp	    }
105533965Sjdp
105638889Sjdp	  if (current_hll_file && list->hll_line && (listing & LISTING_HLL))
105733965Sjdp	    {
105833965Sjdp	      print_source (current_hll_file, list, buffer, width);
105933965Sjdp	    }
106033965Sjdp
106138889Sjdp	  if (list->line_contents)
106233965Sjdp	    {
106338889Sjdp	      if (!((listing & LISTING_NODEBUG)
106438889Sjdp		    && debugging_pseudo (list, list->line_contents)))
106538889Sjdp		{
106660484Sobrien 		  print_lines (list,
106760484Sobrien			       list->file->linenum == 0 ? list->line : list->file->linenum,
106838889Sjdp			       list->line_contents, calc_hex (list));
106938889Sjdp		}
107060484Sobrien	      free (list->line_contents);
107160484Sobrien	      list->line_contents = NULL;
107238889Sjdp	    }
107338889Sjdp	  else
107438889Sjdp	    {
107560484Sobrien	      while (list->file->linenum < list_line
107638889Sjdp		     && !list->file->at_end)
107738889Sjdp		{
107838889Sjdp		  unsigned int address;
107933965Sjdp
108038889Sjdp		  p = buffer_line (list->file, buffer, width);
108133965Sjdp
108260484Sobrien		  if (list->file->linenum < list_line)
108377298Sobrien		    address = ~(unsigned int) 0;
108438889Sjdp		  else
108538889Sjdp		    address = calc_hex (list);
108633965Sjdp
108738889Sjdp		  if (!((listing & LISTING_NODEBUG)
108838889Sjdp			&& debugging_pseudo (list, p)))
108938889Sjdp		    print_lines (list, list->file->linenum, p, address);
109038889Sjdp		}
109133965Sjdp	    }
109233965Sjdp
109333965Sjdp	  if (list->edict == EDICT_EJECT)
109433965Sjdp	    {
109533965Sjdp	      eject = 1;
109633965Sjdp	    }
109733965Sjdp	}
109833965Sjdp
109977298Sobrien      if (list->edict == EDICT_NOLIST_NEXT && show_listing == 1)
110033965Sjdp	--show_listing;
110133965Sjdp
110233965Sjdp      list = list->next;
110333965Sjdp    }
110438889Sjdp
110533965Sjdp  free (buffer);
110638889Sjdp  free (data_buffer);
110738889Sjdp  data_buffer = NULL;
110833965Sjdp}
110933965Sjdp
111033965Sjdpvoid
111133965Sjdplisting_print (name)
111233965Sjdp     char *name;
111333965Sjdp{
111433965Sjdp  int using_stdout;
111577298Sobrien
111633965Sjdp  title = "";
111733965Sjdp  subtitle = "";
111833965Sjdp
111933965Sjdp  if (name == NULL)
112033965Sjdp    {
112133965Sjdp      list_file = stdout;
112233965Sjdp      using_stdout = 1;
112333965Sjdp    }
112433965Sjdp  else
112533965Sjdp    {
112689857Sobrien      list_file = fopen (name, FOPEN_WT);
112733965Sjdp      if (list_file != NULL)
112833965Sjdp	using_stdout = 0;
112933965Sjdp      else
113033965Sjdp	{
113160484Sobrien	  as_perror (_("can't open list file: %s"), name);
113233965Sjdp	  list_file = stdout;
113333965Sjdp	  using_stdout = 1;
113433965Sjdp	}
113533965Sjdp    }
113633965Sjdp
113733965Sjdp  if (listing & LISTING_NOFORM)
113833965Sjdp    {
113933965Sjdp      paper_height = 0;
114033965Sjdp    }
114133965Sjdp
114233965Sjdp  if (listing & LISTING_LISTING)
114333965Sjdp    {
114433965Sjdp      listing_listing (name);
114533965Sjdp    }
114633965Sjdp
114733965Sjdp  if (listing & LISTING_SYMBOLS)
114833965Sjdp    {
114933965Sjdp      list_symbol_table ();
115033965Sjdp    }
115133965Sjdp
115233965Sjdp  if (! using_stdout)
115333965Sjdp    {
115433965Sjdp      if (fclose (list_file) == EOF)
115560484Sobrien	as_perror (_("error closing list file: %s"), name);
115633965Sjdp    }
115733965Sjdp
115838889Sjdp  if (last_open_file)
115933965Sjdp    {
116038889Sjdp      fclose (last_open_file);
116133965Sjdp    }
116233965Sjdp}
116333965Sjdp
116433965Sjdpvoid
116533965Sjdplisting_file (name)
116633965Sjdp     const char *name;
116733965Sjdp{
116833965Sjdp  fn = name;
116933965Sjdp}
117033965Sjdp
117133965Sjdpvoid
117233965Sjdplisting_eject (ignore)
117360484Sobrien     int ignore ATTRIBUTE_UNUSED;
117433965Sjdp{
117533965Sjdp  if (listing)
117633965Sjdp    listing_tail->edict = EDICT_EJECT;
117733965Sjdp}
117833965Sjdp
117933965Sjdpvoid
118033965Sjdplisting_flags (ignore)
118160484Sobrien     int ignore ATTRIBUTE_UNUSED;
118233965Sjdp{
118333965Sjdp  while ((*input_line_pointer++) && (*input_line_pointer != '\n'))
118433965Sjdp    input_line_pointer++;
118533965Sjdp
118633965Sjdp}
118733965Sjdp
118833965Sjdp/* Turn listing on or off.  An argument of 0 means to turn off
118933965Sjdp   listing.  An argument of 1 means to turn on listing.  An argument
119033965Sjdp   of 2 means to turn off listing, but as of the next line; that is,
119133965Sjdp   the current line should be listed, but the next line should not.  */
119233965Sjdp
119333965Sjdpvoid
119433965Sjdplisting_list (on)
119533965Sjdp     int on;
119633965Sjdp{
119733965Sjdp  if (listing)
119833965Sjdp    {
119933965Sjdp      switch (on)
120033965Sjdp	{
120133965Sjdp	case 0:
120233965Sjdp	  if (listing_tail->edict == EDICT_LIST)
120333965Sjdp	    listing_tail->edict = EDICT_NONE;
120433965Sjdp	  else
120533965Sjdp	    listing_tail->edict = EDICT_NOLIST;
120633965Sjdp	  break;
120733965Sjdp	case 1:
120833965Sjdp	  if (listing_tail->edict == EDICT_NOLIST
120933965Sjdp	      || listing_tail->edict == EDICT_NOLIST_NEXT)
121033965Sjdp	    listing_tail->edict = EDICT_NONE;
121133965Sjdp	  else
121233965Sjdp	    listing_tail->edict = EDICT_LIST;
121333965Sjdp	  break;
121433965Sjdp	case 2:
121533965Sjdp	  listing_tail->edict = EDICT_NOLIST_NEXT;
121633965Sjdp	  break;
121733965Sjdp	default:
121833965Sjdp	  abort ();
121933965Sjdp	}
122033965Sjdp    }
122133965Sjdp}
122233965Sjdp
122333965Sjdpvoid
122433965Sjdplisting_psize (width_only)
122533965Sjdp     int width_only;
122633965Sjdp{
122733965Sjdp  if (! width_only)
122833965Sjdp    {
122933965Sjdp      paper_height = get_absolute_expression ();
123033965Sjdp
123133965Sjdp      if (paper_height < 0 || paper_height > 1000)
123233965Sjdp	{
123333965Sjdp	  paper_height = 0;
123460484Sobrien	  as_warn (_("strange paper height, set to no form"));
123533965Sjdp	}
123633965Sjdp
123733965Sjdp      if (*input_line_pointer != ',')
123833965Sjdp	{
123933965Sjdp	  demand_empty_rest_of_line ();
124033965Sjdp	  return;
124133965Sjdp	}
124233965Sjdp
124333965Sjdp      ++input_line_pointer;
124433965Sjdp    }
124533965Sjdp
124633965Sjdp  paper_width = get_absolute_expression ();
124733965Sjdp
124833965Sjdp  demand_empty_rest_of_line ();
124933965Sjdp}
125033965Sjdp
125133965Sjdpvoid
125233965Sjdplisting_nopage (ignore)
125360484Sobrien     int ignore ATTRIBUTE_UNUSED;
125433965Sjdp{
125533965Sjdp  paper_height = 0;
125633965Sjdp}
125733965Sjdp
125833965Sjdpvoid
125933965Sjdplisting_title (depth)
126033965Sjdp     int depth;
126133965Sjdp{
126233965Sjdp  int quoted;
126333965Sjdp  char *start;
126433965Sjdp  char *ttl;
126533965Sjdp  unsigned int length;
126633965Sjdp
126733965Sjdp  SKIP_WHITESPACE ();
126833965Sjdp  if (*input_line_pointer != '\"')
126933965Sjdp    quoted = 0;
127033965Sjdp  else
127133965Sjdp    {
127233965Sjdp      quoted = 1;
127333965Sjdp      ++input_line_pointer;
127433965Sjdp    }
127533965Sjdp
127633965Sjdp  start = input_line_pointer;
127733965Sjdp
127833965Sjdp  while (*input_line_pointer)
127933965Sjdp    {
128033965Sjdp      if (quoted
128133965Sjdp	  ? *input_line_pointer == '\"'
128233965Sjdp	  : is_end_of_line[(unsigned char) *input_line_pointer])
128333965Sjdp	{
128433965Sjdp	  if (listing)
128533965Sjdp	    {
128633965Sjdp	      length = input_line_pointer - start;
128733965Sjdp	      ttl = xmalloc (length + 1);
128833965Sjdp	      memcpy (ttl, start, length);
128933965Sjdp	      ttl[length] = 0;
129033965Sjdp	      listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
129133965Sjdp	      listing_tail->edict_arg = ttl;
129233965Sjdp	    }
129333965Sjdp	  if (quoted)
129433965Sjdp	    input_line_pointer++;
129533965Sjdp	  demand_empty_rest_of_line ();
129633965Sjdp	  return;
129733965Sjdp	}
129833965Sjdp      else if (*input_line_pointer == '\n')
129933965Sjdp	{
130089857Sobrien	  as_bad (_("new line in title"));
130133965Sjdp	  demand_empty_rest_of_line ();
130233965Sjdp	  return;
130333965Sjdp	}
130433965Sjdp      else
130533965Sjdp	{
130633965Sjdp	  input_line_pointer++;
130733965Sjdp	}
130833965Sjdp    }
130933965Sjdp}
131033965Sjdp
131133965Sjdpvoid
131233965Sjdplisting_source_line (line)
131333965Sjdp     unsigned int line;
131433965Sjdp{
131533965Sjdp  if (listing)
131633965Sjdp    {
131733965Sjdp      new_frag ();
131833965Sjdp      listing_tail->hll_line = line;
131933965Sjdp      new_frag ();
132033965Sjdp    }
132133965Sjdp}
132233965Sjdp
132333965Sjdpvoid
132433965Sjdplisting_source_file (file)
132533965Sjdp     const char *file;
132633965Sjdp{
132733965Sjdp  if (listing)
132833965Sjdp    listing_tail->hll_file = file_info (file);
132933965Sjdp}
133033965Sjdp
133133965Sjdp#else
133233965Sjdp
133377298Sobrien/* Dummy functions for when compiled without listing enabled.  */
133433965Sjdp
133533965Sjdpvoid
133633965Sjdplisting_flags (ignore)
133733965Sjdp     int ignore;
133833965Sjdp{
133933965Sjdp  s_ignore (0);
134033965Sjdp}
134133965Sjdp
134277298Sobrienvoid
134333965Sjdplisting_list (on)
134433965Sjdp     int on;
134533965Sjdp{
134633965Sjdp  s_ignore (0);
134733965Sjdp}
134833965Sjdp
134977298Sobrienvoid
135033965Sjdplisting_eject (ignore)
135133965Sjdp     int ignore;
135233965Sjdp{
135333965Sjdp  s_ignore (0);
135433965Sjdp}
135533965Sjdp
135677298Sobrienvoid
135733965Sjdplisting_psize (ignore)
135833965Sjdp     int ignore;
135933965Sjdp{
136033965Sjdp  s_ignore (0);
136133965Sjdp}
136233965Sjdp
136333965Sjdpvoid
136433965Sjdplisting_nopage (ignore)
136533965Sjdp     int ignore;
136633965Sjdp{
136733965Sjdp  s_ignore (0);
136833965Sjdp}
136933965Sjdp
137077298Sobrienvoid
137133965Sjdplisting_title (depth)
137233965Sjdp     int depth;
137333965Sjdp{
137433965Sjdp  s_ignore (0);
137533965Sjdp}
137633965Sjdp
137733965Sjdpvoid
137833965Sjdplisting_file (name)
137933965Sjdp     const char *name;
138033965Sjdp{
138133965Sjdp
138233965Sjdp}
138333965Sjdp
138477298Sobrienvoid
138533965Sjdplisting_newline (name)
138633965Sjdp     char *name;
138733965Sjdp{
138833965Sjdp
138933965Sjdp}
139033965Sjdp
139177298Sobrienvoid
139233965Sjdplisting_source_line (n)
139333965Sjdp     unsigned int n;
139433965Sjdp{
139533965Sjdp
139633965Sjdp}
139777298Sobrien
139877298Sobrienvoid
139933965Sjdplisting_source_file (n)
140033965Sjdp     const char *n;
140133965Sjdp{
140233965Sjdp
140333965Sjdp}
140433965Sjdp
140533965Sjdp#endif
1406