Home | History | Annotate | Line # | Download | only in gas
listing.c revision 1.1.1.9
      1 /* listing.c - maintain assembly listings
      2    Copyright (C) 1991-2024 Free Software Foundation, Inc.
      3 
      4    This file is part of GAS, the GNU Assembler.
      5 
      6    GAS is free software; you can redistribute it and/or modify
      7    it under the terms of the GNU General Public License as published by
      8    the Free Software Foundation; either version 3, or (at your option)
      9    any later version.
     10 
     11    GAS is distributed in the hope that it will be useful,
     12    but WITHOUT ANY WARRANTY; without even the implied warranty of
     13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14    GNU General Public License for more details.
     15 
     16    You should have received a copy of the GNU General Public License
     17    along with GAS; see the file COPYING.  If not, write to the Free
     18    Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
     19    02110-1301, USA.  */
     20 
     21 /* Contributed by Steve Chamberlain <sac (at) cygnus.com>
     22 
     23  A listing page looks like:
     24 
     25  LISTING_HEADER  sourcefilename pagenumber
     26  TITLE LINE
     27  SUBTITLE LINE
     28  linenumber address data  source
     29  linenumber address data  source
     30  linenumber address data  source
     31  linenumber address data  source
     32 
     33  If not overridden, the listing commands are:
     34 
     35  .title  "stuff"
     36  	Put "stuff" onto the title line
     37  .sbttl  "stuff"
     38         Put stuff onto the subtitle line
     39 
     40   If these commands come within 10 lines of the top of the page, they
     41   will affect the page they are on, as well as any subsequent page
     42 
     43  .eject
     44  	Throw a page
     45  .list
     46  	Increment the enable listing counter
     47  .nolist
     48  	Decrement the enable listing counter
     49 
     50  .psize Y[,X]
     51  	Set the paper size to X wide and Y high. Setting a psize Y of
     52 	zero will suppress form feeds except where demanded by .eject
     53 
     54  If the counter goes below zero, listing is suppressed.
     55 
     56  Listings are a maintained by read calling various listing_<foo>
     57  functions.  What happens most is that the macro NO_LISTING is not
     58  defined (from the Makefile), then the macro LISTING_NEWLINE expands
     59  into a call to listing_newline.  The call is done from read.c, every
     60  time it sees a newline, and -l is on the command line.
     61 
     62  The function listing_newline remembers the frag associated with the
     63  newline, and creates a new frag - note that this is wasteful, but not
     64  a big deal, since listing slows things down a lot anyway.  The
     65  function also remembers when the filename changes.
     66 
     67  When all the input has finished, and gas has had a chance to settle
     68  down, the listing is output. This is done by running down the list of
     69  frag/source file records, and opening the files as needed and printing
     70  out the bytes and chars associated with them.
     71 
     72  The only things which the architecture can change about the listing
     73  are defined in these macros:
     74 
     75  LISTING_HEADER		The name of the architecture
     76  LISTING_WORD_SIZE      The make of the number of bytes in a word, this determines
     77  			the clumping of the output data. eg a value of
     78 			2 makes words look like 1234 5678, whilst 1
     79 			would make the same value look like 12 34 56
     80 			78
     81  LISTING_LHS_WIDTH      Number of words of above size for the lhs
     82 
     83  LISTING_LHS_WIDTH_SECOND   Number of words for the data on the lhs
     84  			for the second line
     85 
     86  LISTING_LHS_CONT_LINES	Max number of lines to use up for a continuation
     87  LISTING_RHS_WIDTH      Number of chars from the input file to print
     88                         on a line.  */
     89 
     90 #include "as.h"
     91 #include "filenames.h"
     92 #include "safe-ctype.h"
     93 #include "input-file.h"
     94 #include "subsegs.h"
     95 #include "bfdver.h"
     96 #include <time.h>
     97 #include <stdarg.h>
     98 
     99 #ifndef NO_LISTING
    100 
    101 #ifndef LISTING_HEADER
    102 #define LISTING_HEADER "GAS LISTING"
    103 #endif
    104 #ifndef LISTING_WORD_SIZE
    105 #define LISTING_WORD_SIZE 4
    106 #endif
    107 #ifndef LISTING_LHS_WIDTH
    108 #define LISTING_LHS_WIDTH ((LISTING_WORD_SIZE) > 4 ? 1 : 4 / (LISTING_WORD_SIZE))
    109 #endif
    110 #ifndef LISTING_LHS_WIDTH_SECOND
    111 #define LISTING_LHS_WIDTH_SECOND LISTING_LHS_WIDTH
    112 #endif
    113 #ifndef LISTING_RHS_WIDTH
    114 #define LISTING_RHS_WIDTH 100
    115 #endif
    116 #ifndef LISTING_LHS_CONT_LINES
    117 #define LISTING_LHS_CONT_LINES 4
    118 #endif
    119 #define MAX_DATELEN 30
    120 
    121 /* This structure remembers which .s were used.  */
    122 typedef struct file_info_struct
    123 {
    124   struct file_info_struct * next;
    125   char *                    filename;
    126   long                      pos;
    127   unsigned int              linenum;
    128   int                       at_end;
    129 } file_info_type;
    130 
    131 enum edict_enum
    132 {
    133   EDICT_NONE,
    134   EDICT_SBTTL,
    135   EDICT_TITLE,
    136   EDICT_NOLIST,
    137   EDICT_LIST,
    138   EDICT_NOLIST_NEXT,
    139   EDICT_EJECT
    140 };
    141 
    142 
    143 struct list_message
    144 {
    145   char *message;
    146   struct list_message *next;
    147 };
    148 
    149 /* This structure remembers which line from which file goes into which
    150    frag.  */
    151 struct list_info_struct
    152 {
    153   /* Frag which this line of source is nearest to.  */
    154   fragS *frag;
    155 
    156   /* The actual line in the source file.  */
    157   unsigned int line;
    158 
    159   /* Pointer to the file info struct for the file which this line
    160      belongs to.  */
    161   file_info_type *file;
    162 
    163   /* The expanded text of any macro that may have been executing.  */
    164   char *line_contents;
    165 
    166   /* Next in list.  */
    167   struct list_info_struct *next;
    168 
    169   /* Pointer to the file info struct for the high level language
    170      source line that belongs here.  */
    171   file_info_type *hll_file;
    172 
    173   /* High level language source line.  */
    174   unsigned int hll_line;
    175 
    176   /* Pointers to linked list of messages associated with this line.  */
    177   struct list_message *messages, *last_message;
    178 
    179   enum edict_enum edict;
    180   char *edict_arg;
    181 
    182   /* Nonzero if this line is to be omitted because it contains
    183      debugging information.  This can become a flags field if we come
    184      up with more information to store here.  */
    185   int debugging;
    186 };
    187 
    188 typedef struct list_info_struct list_info_type;
    189 
    190 int listing_lhs_width        = LISTING_LHS_WIDTH;
    191 int listing_lhs_width_second = LISTING_LHS_WIDTH_SECOND;
    192 int listing_lhs_cont_lines   = LISTING_LHS_CONT_LINES;
    193 int listing_rhs_width        = LISTING_RHS_WIDTH;
    194 
    195 struct list_info_struct *        listing_tail;
    196 
    197 static file_info_type *          file_info_head;
    198 static file_info_type *          last_open_file_info;
    199 static FILE *                    last_open_file;
    200 static struct list_info_struct * head;
    201 static int                       paper_width = 200;
    202 static int                       paper_height = 60;
    203 
    204 extern int                       listing;
    205 
    206 /* File to output listings to.  */
    207 static FILE *list_file;
    208 
    209 /* This static array is used to keep the text of data to be printed
    210    before the start of the line.  */
    211 
    212 #define MAX_BYTES							\
    213   (((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width			\
    214    + ((((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second)	\
    215       * listing_lhs_cont_lines)						\
    216    + 20)
    217 
    218 static char *data_buffer;
    219 
    220 /* Prototypes.  */
    221 static void listing_message (const char *, const char *);
    222 static file_info_type *file_info (const char *);
    223 static void new_frag (void);
    224 static void listing_page (list_info_type *);
    225 static unsigned int calc_hex (list_info_type *);
    226 static void print_lines (list_info_type *, unsigned int, const char *,
    227 			 unsigned int);
    228 static void list_symbol_table (void);
    229 static int debugging_pseudo (list_info_type *, const char *);
    230 static void listing_listing (char *);
    231 
    232 static void
    233 listing_message (const char *name, const char *message)
    234 {
    235   if (listing_tail != (list_info_type *) NULL)
    236     {
    237       char *n = concat (name, message, (char *) NULL);
    238       struct list_message *lm = XNEW (struct list_message);
    239       lm->message = n;
    240       lm->next = NULL;
    241 
    242       if (listing_tail->last_message)
    243 	listing_tail->last_message->next = lm;
    244       else
    245 	listing_tail->messages = lm;
    246       listing_tail->last_message = lm;
    247     }
    248 }
    249 
    250 void
    251 listing_warning (const char *message)
    252 {
    253   listing_message (_("Warning: "), message);
    254 }
    255 
    256 void
    257 listing_error (const char *message)
    258 {
    259   listing_message (_("Error: "), message);
    260 }
    261 
    262 static file_info_type *
    263 file_info (const char *file_name)
    264 {
    265   /* Find an entry with this file name.  */
    266   file_info_type *p = file_info_head;
    267 
    268   while (p != (file_info_type *) NULL)
    269     {
    270       if (filename_cmp (p->filename, file_name) == 0)
    271 	return p;
    272       p = p->next;
    273     }
    274 
    275   /* Make new entry.  */
    276   p = XNEW (file_info_type);
    277   p->next = file_info_head;
    278   file_info_head = p;
    279   p->filename = xstrdup (file_name);
    280   p->pos = 0;
    281   p->linenum = 0;
    282   p->at_end = 0;
    283 
    284   return p;
    285 }
    286 
    287 static void
    288 new_frag (void)
    289 {
    290   frag_wane (frag_now);
    291   frag_new (0);
    292 }
    293 
    294 void
    295 listing_newline (char *ps)
    296 {
    297   const char *file;
    298   unsigned int line;
    299   static unsigned int last_line = 0xffff;
    300   static const char *last_file = NULL;
    301   list_info_type *new_i = NULL;
    302 
    303   if (listing == 0)
    304     return;
    305 
    306   if (now_seg == absolute_section)
    307     return;
    308 
    309 #ifdef OBJ_ELF
    310   /* In ELF, anything in a section beginning with .debug or .line is
    311      considered to be debugging information.  This includes the
    312      statement which switches us into the debugging section, which we
    313      can only set after we are already in the debugging section.  */
    314   if ((listing & LISTING_NODEBUG) != 0
    315       && listing_tail != NULL
    316       && ! listing_tail->debugging)
    317     {
    318       const char *segname;
    319 
    320       segname = segment_name (now_seg);
    321       if (startswith (segname, ".debug")
    322 	  || startswith (segname, ".line"))
    323 	listing_tail->debugging = 1;
    324     }
    325 #endif
    326 
    327   /* PR 21977 - use the physical file name not the logical one unless high
    328      level source files are being included in the listing.  */
    329   if (listing & LISTING_HLL)
    330     file = as_where (&line);
    331   else
    332     file = as_where_physical (&line);
    333 
    334   if (ps == NULL)
    335     {
    336       if (line == last_line
    337 	  && !(last_file && file && filename_cmp (file, last_file)))
    338 	return;
    339 
    340       new_i = XNEW (list_info_type);
    341 
    342       /* Detect if we are reading from stdin by examining the file
    343 	 name returned by as_where().
    344 
    345 	 [FIXME: We rely upon the name in the strcmp below being the
    346 	 same as the one used by input_scrub_new_file(), if that is
    347 	 not true, then this code will fail].
    348 
    349 	 If we are reading from stdin, then we need to save each input
    350 	 line here (assuming of course that we actually have a line of
    351 	 input to read), so that it can be displayed in the listing
    352 	 that is produced at the end of the assembly.  */
    353       if (strcmp (file, _("{standard input}")) == 0
    354 	  && input_line_pointer != NULL)
    355 	{
    356 	  char *copy, *src, *dest;
    357 	  int len;
    358 	  int seen_quote = 0;
    359 	  int seen_slash = 0;
    360 
    361 	  for (copy = input_line_pointer;
    362 	       *copy && (seen_quote
    363 			 || is_end_of_line [(unsigned char) *copy] != 1);
    364 	       copy++)
    365 	    {
    366 	      if (seen_slash)
    367 		seen_slash = 0;
    368 	      else if (*copy == '\\')
    369 		seen_slash = 1;
    370 	      else if (*copy == '"')
    371 		seen_quote = !seen_quote;
    372 	    }
    373 
    374 	  len = copy - input_line_pointer + 1;
    375 
    376 	  copy = XNEWVEC (char, len);
    377 
    378 	  src = input_line_pointer;
    379 	  dest = copy;
    380 
    381 	  while (--len)
    382 	    {
    383 	      unsigned char c = *src++;
    384 
    385 	      /* Omit control characters in the listing.  */
    386 	      if (!ISCNTRL (c))
    387 		*dest++ = c;
    388 	    }
    389 
    390 	  *dest = 0;
    391 
    392 	  new_i->line_contents = copy;
    393 	}
    394       else
    395 	new_i->line_contents = NULL;
    396     }
    397   else
    398     {
    399       new_i = XNEW (list_info_type);
    400       new_i->line_contents = ps;
    401     }
    402 
    403   last_line = line;
    404   last_file = file;
    405 
    406   new_frag ();
    407 
    408   if (listing_tail)
    409     listing_tail->next = new_i;
    410   else
    411     head = new_i;
    412 
    413   listing_tail = new_i;
    414 
    415   new_i->frag = frag_now;
    416   new_i->line = line;
    417   new_i->file = file_info (file);
    418   new_i->next = (list_info_type *) NULL;
    419   new_i->messages = NULL;
    420   new_i->last_message = NULL;
    421   new_i->edict = EDICT_NONE;
    422   new_i->hll_file = (file_info_type *) NULL;
    423   new_i->hll_line = 0;
    424   new_i->debugging = 0;
    425 
    426   new_frag ();
    427 
    428 #ifdef OBJ_ELF
    429   /* In ELF, anything in a section beginning with .debug or .line is
    430      considered to be debugging information.  */
    431   if ((listing & LISTING_NODEBUG) != 0)
    432     {
    433       const char *segname;
    434 
    435       segname = segment_name (now_seg);
    436       if (startswith (segname, ".debug")
    437 	  || startswith (segname, ".line"))
    438 	new_i->debugging = 1;
    439     }
    440 #endif
    441 }
    442 
    443 /* Attach all current frags to the previous line instead of the
    444    current line.  This is called by the MIPS backend when it discovers
    445    that it needs to add some NOP instructions; the added NOP
    446    instructions should go with the instruction that has the delay, not
    447    with the new instruction.  */
    448 
    449 void
    450 listing_prev_line (void)
    451 {
    452   list_info_type *l;
    453   fragS *f;
    454 
    455   if (head == (list_info_type *) NULL
    456       || head == listing_tail)
    457     return;
    458 
    459   new_frag ();
    460 
    461   for (l = head; l->next != listing_tail; l = l->next)
    462     ;
    463 
    464   for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next)
    465     if (f->line == listing_tail)
    466       f->line = l;
    467 
    468   listing_tail->frag = frag_now;
    469   new_frag ();
    470 }
    471 
    472 /* This function returns the next source line from the file supplied,
    473    truncated to size.  It appends a fake line to the end of each input
    474    file to make using the returned buffer simpler.  */
    475 
    476 static const char *
    477 buffer_line (file_info_type *file, char *line, unsigned int size)
    478 {
    479   unsigned int count = 0;
    480   int c;
    481   char *p = line;
    482 
    483   /* If we couldn't open the file, return an empty line.  */
    484   if (file->at_end)
    485     return "";
    486 
    487   /* Check the cache and see if we last used this file.  */
    488   if (!last_open_file_info || file != last_open_file_info)
    489     {
    490       if (last_open_file)
    491 	{
    492 	  last_open_file_info->pos = ftell (last_open_file);
    493 	  fclose (last_open_file);
    494 	}
    495 
    496       /* Open the file in the binary mode so that ftell above can
    497 	 return a reliable value that we can feed to fseek below.  */
    498       last_open_file_info = file;
    499       last_open_file = fopen (file->filename, FOPEN_RB);
    500       if (last_open_file == NULL)
    501 	{
    502 	  file->at_end = 1;
    503 	  return "";
    504 	}
    505 
    506       /* Seek to where we were last time this file was open.  */
    507       if (file->pos)
    508 	fseek (last_open_file, file->pos, SEEK_SET);
    509     }
    510 
    511   c = fgetc (last_open_file);
    512 
    513   while (c != EOF && c != '\n' && c != '\r')
    514     {
    515       if (++count < size)
    516 	*p++ = c;
    517       c = fgetc (last_open_file);
    518     }
    519 
    520   /* If '\r' is followed by '\n', swallow that.  Likewise, if '\n'
    521      is followed by '\r', swallow that as well.  */
    522   if (c == '\r' || c == '\n')
    523     {
    524       int next = fgetc (last_open_file);
    525 
    526       if ((c == '\r' && next != '\n')
    527 	  || (c == '\n' && next != '\r'))
    528 	ungetc (next, last_open_file);
    529     }
    530 
    531   if (c == EOF)
    532     {
    533       file->at_end = 1;
    534       if (count + 3 < size)
    535 	{
    536 	  *p++ = '.';
    537 	  *p++ = '.';
    538 	  *p++ = '.';
    539 	}
    540     }
    541   file->linenum++;
    542   *p++ = 0;
    543   return line;
    544 }
    545 
    546 
    547 /* This function rewinds the requested file back to the line requested,
    548    reads it in again into the buffer provided and then restores the file
    549    back to its original location.  */
    550 
    551 static void
    552 rebuffer_line (file_info_type *  file,
    553 	       unsigned int      linenum,
    554 	       char *            buffer,
    555 	       unsigned int      size)
    556 {
    557   unsigned int count = 0;
    558   unsigned int current_line;
    559   char * p = buffer;
    560   long pos;
    561   long pos2;
    562   int c;
    563   bool found = false;
    564 
    565   /* Sanity checks.  */
    566   if (file == NULL || buffer == NULL || size <= 1 || file->linenum <= linenum)
    567     return;
    568 
    569   /* Check the cache and see if we last used this file.  */
    570   if (last_open_file_info == NULL || file != last_open_file_info)
    571     {
    572       if (last_open_file)
    573 	{
    574 	  last_open_file_info->pos = ftell (last_open_file);
    575 	  fclose (last_open_file);
    576 	}
    577 
    578       /* Open the file in the binary mode so that ftell above can
    579 	 return a reliable value that we can feed to fseek below.  */
    580       last_open_file_info = file;
    581       last_open_file = fopen (file->filename, FOPEN_RB);
    582       if (last_open_file == NULL)
    583 	{
    584 	  file->at_end = 1;
    585 	  return;
    586 	}
    587 
    588       /* Seek to where we were last time this file was open.  */
    589       if (file->pos)
    590 	fseek (last_open_file, file->pos, SEEK_SET);
    591     }
    592 
    593   /* Remember where we are in the current file.  */
    594   pos2 = pos = ftell (last_open_file);
    595   if (pos < 3)
    596     return;
    597   current_line = file->linenum;
    598 
    599   /* Leave room for the nul at the end of the buffer.  */
    600   size -= 1;
    601   buffer[size] = 0;
    602 
    603   /* Increment the current line count by one.
    604      This is to allow for the fact that we are searching for the
    605      start of a previous line, but we do this by detecting end-of-line
    606      character(s) not start-of-line characters.  */
    607   ++ current_line;
    608 
    609   while (pos2 > 0 && ! found)
    610     {
    611       char * ptr;
    612 
    613       /* Move backwards through the file, looking for earlier lines.  */
    614       pos2 = (long) size > pos2 ? 0 : pos2 - size;
    615       fseek (last_open_file, pos2, SEEK_SET);
    616 
    617       /* Our caller has kindly provided us with a buffer, so we use it.  */
    618       if (fread (buffer, 1, size, last_open_file) != size)
    619 	{
    620 	  as_warn (_("unable to rebuffer file: %s\n"), file->filename);
    621 	  return;
    622 	}
    623 
    624       for (ptr = buffer + size; ptr >= buffer; -- ptr)
    625 	{
    626 	  if (*ptr == '\n')
    627 	    {
    628 	      -- current_line;
    629 
    630 	      if (current_line == linenum)
    631 		{
    632 		  /* We have found the start of the line we seek.  */
    633 		  found = true;
    634 
    635 		  /* FIXME: We could skip the read-in-the-line code
    636 		     below if we know that we already have the whole
    637 		     line in the buffer.  */
    638 
    639 		  /* Advance pos2 to the newline character we have just located.  */
    640 		  pos2 += (ptr - buffer);
    641 
    642 		  /* Skip the newline and, if present, the carriage return.  */
    643 		  if (ptr + 1 == buffer + size)
    644 		    {
    645 		      ++pos2;
    646 		      if (fgetc (last_open_file) == '\r')
    647 			++ pos2;
    648 		    }
    649 		  else
    650 		    pos2 += (ptr[1] == '\r' ? 2 : 1);
    651 
    652 		  /* Move the file pointer to this location.  */
    653 		  fseek (last_open_file, pos2, SEEK_SET);
    654 		  break;
    655 		}
    656 	    }
    657 	}
    658     }
    659 
    660   /* Read in the line.  */
    661   c = fgetc (last_open_file);
    662 
    663   while (c != EOF && c != '\n' && c != '\r')
    664     {
    665       if (count < size)
    666 	*p++ = c;
    667       count++;
    668 
    669       c = fgetc (last_open_file);
    670     }
    671 
    672   /* If '\r' is followed by '\n', swallow that.  Likewise, if '\n'
    673      is followed by '\r', swallow that as well.  */
    674   if (c == '\r' || c == '\n')
    675     {
    676       int next = fgetc (last_open_file);
    677 
    678       if ((c == '\r' && next != '\n')
    679 	  || (c == '\n' && next != '\r'))
    680 	ungetc (next, last_open_file);
    681     }
    682 
    683   /* Terminate the line.  */
    684   *p++ = 0;
    685 
    686   /* Reset the file position.  */
    687   fseek (last_open_file, pos, SEEK_SET);
    688 }
    689 
    690 static const char *fn;
    691 static unsigned int eject;	/* Eject pending.  */
    692 static unsigned int page;	/* Current page number.  */
    693 static const char *title;	/* Current title.  */
    694 static const char *subtitle;	/* Current subtitle.  */
    695 static unsigned int on_page;	/* Number of lines printed on current page.  */
    696 
    697 static void
    698 listing_page (list_info_type *list)
    699 {
    700   /* Grope around, see if we can see a title or subtitle edict coming up
    701      soon.  (we look down 10 lines of the page and see if it's there)  */
    702   if ((eject || (on_page >= (unsigned int) paper_height))
    703       && paper_height != 0)
    704     {
    705       unsigned int c = 10;
    706       int had_title = 0;
    707       int had_subtitle = 0;
    708 
    709       page++;
    710 
    711       while (c != 0 && list)
    712 	{
    713 	  if (list->edict == EDICT_SBTTL && !had_subtitle)
    714 	    {
    715 	      had_subtitle = 1;
    716 	      subtitle = list->edict_arg;
    717 	    }
    718 	  if (list->edict == EDICT_TITLE && !had_title)
    719 	    {
    720 	      had_title = 1;
    721 	      title = list->edict_arg;
    722 	    }
    723 	  list = list->next;
    724 	  c--;
    725 	}
    726 
    727       if (page > 1)
    728 	{
    729 	  fprintf (list_file, "\f");
    730 	}
    731 
    732       fprintf (list_file, "%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
    733       fprintf (list_file, "%s\n", title);
    734       fprintf (list_file, "%s\n", subtitle);
    735       on_page = 3;
    736       eject = 0;
    737     }
    738 }
    739 
    740 /* Print a line into the list_file.  Update the line count
    741    and if necessary start a new page.  */
    742 
    743 static void
    744 emit_line (list_info_type * list, const char * format, ...)
    745 {
    746   va_list args;
    747 
    748   va_start (args, format);
    749 
    750   vfprintf (list_file, format, args);
    751   on_page++;
    752   listing_page (list);
    753 
    754   va_end (args);
    755 }
    756 
    757 static unsigned int
    758 calc_hex (list_info_type *list)
    759 {
    760   int data_buffer_size;
    761   list_info_type *first = list;
    762   unsigned int address = ~(unsigned int) 0;
    763   fragS *frag;
    764   fragS *frag_ptr;
    765   unsigned int octet_in_frag;
    766 
    767   /* Find first frag which says it belongs to this line.  */
    768   frag = list->frag;
    769   while (frag && frag->line != list)
    770     frag = frag->fr_next;
    771 
    772   frag_ptr = frag;
    773 
    774   data_buffer_size = 0;
    775 
    776   /* Dump all the frags which belong to this line.  */
    777   while (frag_ptr != (fragS *) NULL && frag_ptr->line == first)
    778     {
    779       /* Print as many bytes from the fixed part as is sensible.  */
    780       octet_in_frag = 0;
    781       while (octet_in_frag < frag_ptr->fr_fix
    782 	     && data_buffer_size < MAX_BYTES - 3)
    783 	{
    784 	  if (address == ~(unsigned int) 0)
    785 	    address = frag_ptr->fr_address / OCTETS_PER_BYTE;
    786 
    787 	  sprintf (data_buffer + data_buffer_size,
    788 		   "%02X",
    789 		   (frag_ptr->fr_literal[octet_in_frag]) & 0xff);
    790 	  data_buffer_size += 2;
    791 	  octet_in_frag++;
    792 	}
    793       if (frag_ptr->fr_type == rs_fill)
    794 	{
    795 	  unsigned int var_rep_max = octet_in_frag;
    796 	  unsigned int var_rep_idx = octet_in_frag;
    797 
    798 	  /* Print as many bytes from the variable part as is sensible.  */
    799 	  while ((octet_in_frag
    800 		  < frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset)
    801 		 && data_buffer_size < MAX_BYTES - 3)
    802 	    {
    803 	      if (address == ~(unsigned int) 0)
    804 		address = frag_ptr->fr_address / OCTETS_PER_BYTE;
    805 
    806 	      sprintf (data_buffer + data_buffer_size,
    807 		       "%02X",
    808 		       (frag_ptr->fr_literal[var_rep_idx]) & 0xff);
    809 	      data_buffer_size += 2;
    810 
    811 	      var_rep_idx++;
    812 	      octet_in_frag++;
    813 
    814 	      if (var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var)
    815 		var_rep_idx = var_rep_max;
    816 	    }
    817 	}
    818       else if (frag_ptr->fr_type == rs_fill_nop && frag_ptr->fr_opcode)
    819 	{
    820 	  gas_assert (!octet_in_frag);
    821 
    822 	  /* Print as many bytes from fr_opcode as is sensible.  */
    823 	  while (octet_in_frag < (unsigned int) frag_ptr->fr_offset
    824 		 && data_buffer_size < MAX_BYTES - 3)
    825 	    {
    826 	      if (address == ~(unsigned int) 0)
    827 		address = frag_ptr->fr_address / OCTETS_PER_BYTE;
    828 
    829 	      sprintf (data_buffer + data_buffer_size,
    830 		       "%02X",
    831 		       frag_ptr->fr_opcode[octet_in_frag] & 0xff);
    832 	      data_buffer_size += 2;
    833 
    834 	      octet_in_frag++;
    835 	    }
    836 
    837 	  free (frag_ptr->fr_opcode);
    838 	  frag_ptr->fr_opcode = NULL;
    839 	}
    840 
    841       frag_ptr = frag_ptr->fr_next;
    842     }
    843   data_buffer[data_buffer_size] = '\0';
    844   return address;
    845 }
    846 
    847 static void
    848 print_lines (list_info_type *list, unsigned int lineno,
    849 	     const char *string, unsigned int address)
    850 {
    851   unsigned int idx;
    852   unsigned int nchars;
    853   unsigned int lines;
    854   unsigned int octet_in_word = 0;
    855   char *src = data_buffer;
    856   int cur;
    857   struct list_message *msg;
    858 
    859   /* Print the stuff on the first line.  */
    860   listing_page (list);
    861   nchars = (LISTING_WORD_SIZE * 2 + 1) * listing_lhs_width;
    862 
    863   /* Print the hex for the first line.  */
    864   if (address == ~(unsigned int) 0)
    865     {
    866       fprintf (list_file, "% 4d     ", lineno);
    867       for (idx = 0; idx < nchars; idx++)
    868 	fprintf (list_file, " ");
    869 
    870       emit_line (NULL, "\t%s\n", string ? string : "");
    871       return;
    872     }
    873 
    874   if (had_errors ())
    875     fprintf (list_file, "% 4d ???? ", lineno);
    876   else
    877     fprintf (list_file, "% 4d %04x ", lineno, address);
    878 
    879   /* And the data to go along with it.  */
    880   idx = 0;
    881   cur = 0;
    882   while (src[cur] && idx < nchars)
    883     {
    884       int offset;
    885       offset = cur;
    886       fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
    887       cur += 2;
    888       octet_in_word++;
    889 
    890       if (octet_in_word == LISTING_WORD_SIZE)
    891 	{
    892 	  fprintf (list_file, " ");
    893 	  idx++;
    894 	  octet_in_word = 0;
    895 	}
    896 
    897       idx += 2;
    898     }
    899 
    900   for (; idx < nchars; idx++)
    901     fprintf (list_file, " ");
    902 
    903   emit_line (list, "\t%s\n", string ? string : "");
    904 
    905   for (msg = list->messages; msg; msg = msg->next)
    906     emit_line (list, "****  %s\n", msg->message);
    907 
    908   for (lines = 0;
    909        lines < (unsigned int) listing_lhs_cont_lines
    910 	 && src[cur];
    911        lines++)
    912     {
    913       nchars = ((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second - 1;
    914       idx = 0;
    915 
    916       /* Print any more lines of data, but more compactly.  */
    917       fprintf (list_file, "% 4d      ", lineno);
    918 
    919       while (src[cur] && idx < nchars)
    920 	{
    921 	  int offset;
    922 	  offset = cur;
    923 	  fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
    924 	  cur += 2;
    925 	  idx += 2;
    926 	  octet_in_word++;
    927 
    928 	  if (octet_in_word == LISTING_WORD_SIZE)
    929 	    {
    930 	      fprintf (list_file, " ");
    931 	      idx++;
    932 	      octet_in_word = 0;
    933 	    }
    934 	}
    935 
    936       emit_line (list, "\n");
    937     }
    938 }
    939 
    940 static void
    941 list_symbol_table (void)
    942 {
    943   extern symbolS *symbol_rootP;
    944   int got_some = 0;
    945 
    946   symbolS *ptr;
    947   eject = 1;
    948   listing_page (NULL);
    949 
    950   for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
    951     {
    952       if (SEG_NORMAL (S_GET_SEGMENT (ptr))
    953 	  || S_GET_SEGMENT (ptr) == absolute_section)
    954 	{
    955 	  /* Don't report section symbols.  They are not interesting.  */
    956 	  if (symbol_section_p (ptr))
    957 	    continue;
    958 
    959 	  if (S_GET_NAME (ptr))
    960 	    {
    961 	      char buf[30];
    962 	      valueT val = S_GET_VALUE (ptr);
    963 
    964 	      bfd_sprintf_vma (stdoutput, buf, val);
    965 	      if (!got_some)
    966 		{
    967 		  fprintf (list_file, "DEFINED SYMBOLS\n");
    968 		  on_page++;
    969 		  got_some = 1;
    970 		}
    971 
    972 	      if (symbol_get_frag (ptr) && symbol_get_frag (ptr)->line)
    973 		{
    974 		  fprintf (list_file, "%20s:%-5d  %s:%s %s\n",
    975 			   symbol_get_frag (ptr)->line->file->filename,
    976 			   symbol_get_frag (ptr)->line->line,
    977 			   segment_name (S_GET_SEGMENT (ptr)),
    978 			   buf, S_GET_NAME (ptr));
    979 		}
    980 	      else
    981 		{
    982 		  fprintf (list_file, "%33s:%s %s\n",
    983 			   segment_name (S_GET_SEGMENT (ptr)),
    984 			   buf, S_GET_NAME (ptr));
    985 		}
    986 
    987 	      on_page++;
    988 	      listing_page (NULL);
    989 	    }
    990 	}
    991 
    992     }
    993   if (!got_some)
    994     {
    995       fprintf (list_file, "NO DEFINED SYMBOLS\n");
    996       on_page++;
    997     }
    998   emit_line (NULL, "\n");
    999 
   1000   got_some = 0;
   1001 
   1002   for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
   1003     {
   1004       if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
   1005 	{
   1006 	  if (S_GET_SEGMENT (ptr) == undefined_section)
   1007 	    {
   1008 	      if (!got_some)
   1009 		{
   1010 		  got_some = 1;
   1011 
   1012 		  emit_line (NULL, "UNDEFINED SYMBOLS\n");
   1013 		}
   1014 
   1015 	      emit_line (NULL, "%s\n", S_GET_NAME (ptr));
   1016 	    }
   1017 	}
   1018     }
   1019 
   1020   if (!got_some)
   1021     emit_line (NULL, "NO UNDEFINED SYMBOLS\n");
   1022 }
   1023 
   1024 typedef struct cached_line
   1025 {
   1026   file_info_type * file;
   1027   unsigned int     line;
   1028   char             buffer [LISTING_RHS_WIDTH];
   1029 } cached_line;
   1030 
   1031 static void
   1032 print_source (file_info_type *  current_file,
   1033 	      list_info_type *  list,
   1034 	      unsigned int      width)
   1035 {
   1036 #define NUM_CACHE_LINES  3
   1037   static cached_line cached_lines[NUM_CACHE_LINES];
   1038   static int next_free_line = 0;
   1039   cached_line * cache = NULL;
   1040 
   1041   if (current_file->linenum > list->hll_line
   1042       && list->hll_line > 0)
   1043     {
   1044       /* This can happen with modern optimizing compilers.  The source
   1045 	 lines from the high level language input program are split up
   1046 	 and interleaved, meaning the line number we want to display
   1047 	 (list->hll_line) can have already been displayed.  We have
   1048 	 three choices:
   1049 
   1050 	   a. Do nothing, since we have already displayed the source
   1051 	      line.  This was the old behaviour.
   1052 
   1053 	   b. Display the particular line requested again, but only
   1054 	      that line.  This is the new behaviour.
   1055 
   1056 	   c. Display the particular line requested again and reset
   1057 	      the current_file->line_num value so that we redisplay
   1058 	      all the following lines as well the next time we
   1059 	      encounter a larger line number.  */
   1060       int i;
   1061 
   1062       /* Check the cache, maybe we already have the line saved.  */
   1063       for (i = 0; i < NUM_CACHE_LINES; i++)
   1064 	if (cached_lines[i].file == current_file
   1065 	    && cached_lines[i].line == list->hll_line)
   1066 	  {
   1067 	    cache = cached_lines + i;
   1068 	    break;
   1069 	  }
   1070 
   1071       if (i == NUM_CACHE_LINES)
   1072 	{
   1073 	  cache = cached_lines + next_free_line;
   1074 	  next_free_line ++;
   1075 	  if (next_free_line == NUM_CACHE_LINES)
   1076 	    next_free_line = 0;
   1077 
   1078 	  cache->file = current_file;
   1079 	  cache->line = list->hll_line;
   1080 	  cache->buffer[0] = 0;
   1081 	  rebuffer_line (current_file, cache->line, cache->buffer, width);
   1082 	}
   1083 
   1084       emit_line (list, "%4u:%-13s **** %s\n",
   1085 		 cache->line, cache->file->filename, cache->buffer);
   1086       return;
   1087     }
   1088 
   1089   if (!current_file->at_end)
   1090     {
   1091       int num_lines_shown = 0;
   1092 
   1093       while (current_file->linenum < list->hll_line
   1094 	     && !current_file->at_end)
   1095 	{
   1096 	  const char *p;
   1097 
   1098 	  cache = cached_lines + next_free_line;
   1099 	  cache->file = current_file;
   1100 	  cache->line = current_file->linenum + 1;
   1101 	  cache->buffer[0] = 0;
   1102 	  p = buffer_line (current_file, cache->buffer, width);
   1103 
   1104 	  /* Cache optimization:  If printing a group of lines
   1105 	     cache the first and last lines in the group.  */
   1106 	  if (num_lines_shown == 0)
   1107 	    {
   1108 	      next_free_line ++;
   1109 	      if (next_free_line == NUM_CACHE_LINES)
   1110 		next_free_line = 0;
   1111 	    }
   1112 
   1113 	  emit_line (list, "%4u:%-13s **** %s\n",
   1114 		     cache->line, cache->file->filename, p);
   1115 	  num_lines_shown ++;
   1116 	}
   1117     }
   1118 }
   1119 
   1120 /* Sometimes the user doesn't want to be bothered by the debugging
   1121    records inserted by the compiler, see if the line is suspicious.  */
   1122 
   1123 static int
   1124 debugging_pseudo (list_info_type *list, const char *line)
   1125 {
   1126 #ifdef OBJ_ELF
   1127   static int in_debug;
   1128   int was_debug;
   1129 #endif
   1130 
   1131   if (list->debugging)
   1132     {
   1133 #ifdef OBJ_ELF
   1134       in_debug = 1;
   1135 #endif
   1136       return 1;
   1137     }
   1138 #ifdef OBJ_ELF
   1139   was_debug = in_debug;
   1140   in_debug = 0;
   1141 #endif
   1142 
   1143   while (ISSPACE (*line))
   1144     line++;
   1145 
   1146   if (*line != '.')
   1147     {
   1148 #ifdef OBJ_ELF
   1149       /* The ELF compiler sometimes emits blank lines after switching
   1150          out of a debugging section.  If the next line drops us back
   1151          into debugging information, then don't print the blank line.
   1152          This is a hack for a particular compiler behaviour, not a
   1153          general case.  */
   1154       if (was_debug
   1155 	  && *line == '\0'
   1156 	  && list->next != NULL
   1157 	  && list->next->debugging)
   1158 	{
   1159 	  in_debug = 1;
   1160 	  return 1;
   1161 	}
   1162 #endif
   1163 
   1164       return 0;
   1165     }
   1166 
   1167   line++;
   1168 
   1169   if (startswith (line, "def"))
   1170     return 1;
   1171   if (startswith (line, "val"))
   1172     return 1;
   1173   if (startswith (line, "scl"))
   1174     return 1;
   1175   if (startswith (line, "line"))
   1176     return 1;
   1177   if (startswith (line, "endef"))
   1178     return 1;
   1179   if (startswith (line, "ln"))
   1180     return 1;
   1181   if (startswith (line, "type"))
   1182     return 1;
   1183   if (startswith (line, "size"))
   1184     return 1;
   1185   if (startswith (line, "dim"))
   1186     return 1;
   1187   if (startswith (line, "tag"))
   1188     return 1;
   1189   if (startswith (line, "stabs"))
   1190     return 1;
   1191   if (startswith (line, "stabn"))
   1192     return 1;
   1193 
   1194   return 0;
   1195 }
   1196 
   1197 static void
   1198 listing_listing (char *name ATTRIBUTE_UNUSED)
   1199 {
   1200   list_info_type *list = head;
   1201   file_info_type *current_hll_file = (file_info_type *) NULL;
   1202   char *buffer;
   1203   const char *p;
   1204   int show_listing = 1;
   1205   unsigned int width;
   1206 
   1207   buffer = XNEWVEC (char, listing_rhs_width);
   1208   data_buffer = XNEWVEC (char, MAX_BYTES);
   1209   eject = 1;
   1210   list = head->next;
   1211 
   1212   while (list)
   1213     {
   1214       unsigned int list_line;
   1215 
   1216       width = listing_rhs_width > paper_width ? paper_width :
   1217 	listing_rhs_width;
   1218 
   1219       list_line = list->line;
   1220       switch (list->edict)
   1221 	{
   1222 	case EDICT_LIST:
   1223 	  /* Skip all lines up to the current.  */
   1224 	  list_line--;
   1225 	  break;
   1226 	case EDICT_NOLIST:
   1227 	  show_listing--;
   1228 	  break;
   1229 	case EDICT_NOLIST_NEXT:
   1230 	  if (show_listing == 0)
   1231 	    list_line--;
   1232 	  break;
   1233 	case EDICT_EJECT:
   1234 	  break;
   1235 	case EDICT_NONE:
   1236 	  break;
   1237 	case EDICT_TITLE:
   1238 	  title = list->edict_arg;
   1239 	  break;
   1240 	case EDICT_SBTTL:
   1241 	  subtitle = list->edict_arg;
   1242 	  break;
   1243 	default:
   1244 	  abort ();
   1245 	}
   1246 
   1247       if (show_listing <= 0)
   1248 	{
   1249 	  while (list->file->linenum < list_line
   1250 		 && !list->file->at_end)
   1251 	    p = buffer_line (list->file, buffer, width);
   1252 	}
   1253 
   1254       if (list->edict == EDICT_LIST
   1255 	  || (list->edict == EDICT_NOLIST_NEXT && show_listing == 0))
   1256 	{
   1257 	  /* Enable listing for the single line that caused the enable.  */
   1258 	  list_line++;
   1259 	  show_listing++;
   1260 	}
   1261 
   1262       if (show_listing > 0)
   1263 	{
   1264 	  /* Scan down the list and print all the stuff which can be done
   1265 	     with this line (or lines).  */
   1266 	  if (list->hll_file)
   1267 	    current_hll_file = list->hll_file;
   1268 
   1269 	  if (current_hll_file && list->hll_line && (listing & LISTING_HLL))
   1270 	    print_source (current_hll_file, list, width);
   1271 
   1272 	  if (!list->line_contents || list->file->linenum)
   1273 	    {
   1274 	      while (list->file->linenum < list_line
   1275 		     && !list->file->at_end)
   1276 		{
   1277 		  unsigned int address;
   1278 
   1279 		  p = buffer_line (list->file, buffer, width);
   1280 
   1281 		  if (list->file->linenum < list_line)
   1282 		    address = ~(unsigned int) 0;
   1283 		  else
   1284 		    address = calc_hex (list);
   1285 
   1286 		  if (!((listing & LISTING_NODEBUG)
   1287 			&& debugging_pseudo (list, p)))
   1288 		    print_lines (list, list->file->linenum, p, address);
   1289 		}
   1290 	    }
   1291 
   1292 	  if (list->line_contents)
   1293 	    {
   1294 	      if (!((listing & LISTING_NODEBUG)
   1295 		    && debugging_pseudo (list, list->line_contents)))
   1296 		print_lines (list, list->line, list->line_contents,
   1297 			     calc_hex (list));
   1298 
   1299 	      free (list->line_contents);
   1300 	      list->line_contents = NULL;
   1301 	    }
   1302 
   1303 	  if (list->edict == EDICT_EJECT)
   1304 	    eject = 1;
   1305 	}
   1306 
   1307       if (list->edict == EDICT_NOLIST_NEXT && show_listing == 1)
   1308 	--show_listing;
   1309 
   1310       list = list->next;
   1311     }
   1312 
   1313   free (buffer);
   1314   free (data_buffer);
   1315   data_buffer = NULL;
   1316 }
   1317 
   1318 /* Print time stamp in ISO format:  yyyy-mm-ddThh:mm:ss.ss+/-zzzz.  */
   1319 
   1320 static void
   1321 print_timestamp (void)
   1322 {
   1323   const time_t now = time (NULL);
   1324   struct tm * timestamp;
   1325   char stampstr[MAX_DATELEN];
   1326 
   1327   /* Any portable way to obtain subsecond values???  */
   1328   timestamp = localtime (&now);
   1329   strftime (stampstr, MAX_DATELEN, "%Y-%m-%dT%H:%M:%S.000%z", timestamp);
   1330   fprintf (list_file, _("\n time stamp    \t: %s\n\n"), stampstr);
   1331 }
   1332 
   1333 static void
   1334 print_single_option (char * opt, int *pos)
   1335 {
   1336   int opt_len = strlen (opt);
   1337 
   1338    if ((*pos + opt_len) < paper_width)
   1339      {
   1340         fprintf (list_file, _("%s "), opt);
   1341         *pos = *pos + opt_len;
   1342      }
   1343    else
   1344      {
   1345         fprintf (list_file, _("\n\t%s "), opt);
   1346         *pos = opt_len;
   1347      }
   1348 }
   1349 
   1350 /* Print options passed to as.  */
   1351 
   1352 static void
   1353 print_options (char ** argv)
   1354 {
   1355   const char *field_name = _("\n options passed\t: ");
   1356   int pos = strlen (field_name);
   1357   char **p;
   1358 
   1359   fputs (field_name, list_file);
   1360   for (p = &argv[1]; *p != NULL; p++)
   1361     if (**p == '-')
   1362       {
   1363         /* Ignore these.  */
   1364         if (strcmp (*p, "-o") == 0)
   1365           {
   1366             if (p[1] != NULL)
   1367               p++;
   1368             continue;
   1369           }
   1370         if (strcmp (*p, "-v") == 0)
   1371           continue;
   1372 
   1373         print_single_option (*p, &pos);
   1374       }
   1375 }
   1376 
   1377 /* Print a first section with basic info like file names, as version,
   1378    options passed, target, and timestamp.
   1379    The format of this section is as follows:
   1380 
   1381    AS VERSION
   1382 
   1383    fieldname TAB ':' fieldcontents
   1384   { TAB fieldcontents-cont }  */
   1385 
   1386 static void
   1387 listing_general_info (char ** argv)
   1388 {
   1389   /* Print the stuff on the first line.  */
   1390   eject = 1;
   1391   listing_page (NULL);
   1392 
   1393   fprintf (list_file,
   1394            _(" GNU assembler version %s (%s)\n\t using BFD version %s."),
   1395            VERSION, TARGET_ALIAS, BFD_VERSION_STRING);
   1396   print_options (argv);
   1397   fprintf (list_file, _("\n input file    \t: %s"), fn);
   1398   fprintf (list_file, _("\n output file   \t: %s"), out_file_name);
   1399   fprintf (list_file, _("\n target        \t: %s"), TARGET_CANONICAL);
   1400   print_timestamp ();
   1401 }
   1402 
   1403 void
   1404 listing_print (char *name, char **argv)
   1405 {
   1406   int using_stdout;
   1407 
   1408   title = "";
   1409   subtitle = "";
   1410 
   1411   if (name == NULL)
   1412     {
   1413       list_file = stdout;
   1414       using_stdout = 1;
   1415     }
   1416   else
   1417     {
   1418       list_file = fopen (name, FOPEN_WT);
   1419       if (list_file != NULL)
   1420 	using_stdout = 0;
   1421       else
   1422 	{
   1423 	  as_warn (_("can't open %s: %s"), name, xstrerror (errno));
   1424 	  list_file = stdout;
   1425 	  using_stdout = 1;
   1426 	}
   1427     }
   1428 
   1429   if (listing & LISTING_NOFORM)
   1430     paper_height = 0;
   1431 
   1432   if (listing & LISTING_GENERAL)
   1433     listing_general_info (argv);
   1434 
   1435   if (listing & LISTING_LISTING)
   1436     listing_listing (name);
   1437 
   1438   if (listing & LISTING_SYMBOLS)
   1439     list_symbol_table ();
   1440 
   1441   if (! using_stdout)
   1442     {
   1443       if (fclose (list_file) == EOF)
   1444 	as_warn (_("can't close %s: %s"), name, xstrerror (errno));
   1445     }
   1446 
   1447   if (last_open_file)
   1448     fclose (last_open_file);
   1449 }
   1450 
   1451 void
   1452 listing_file (const char *name)
   1453 {
   1454   fn = name;
   1455 }
   1456 
   1457 void
   1458 listing_eject (int ignore ATTRIBUTE_UNUSED)
   1459 {
   1460   if (listing)
   1461     listing_tail->edict = EDICT_EJECT;
   1462 }
   1463 
   1464 /* Turn listing on or off.  An argument of 0 means to turn off
   1465    listing.  An argument of 1 means to turn on listing.  An argument
   1466    of 2 means to turn off listing, but as of the next line; that is,
   1467    the current line should be listed, but the next line should not.  */
   1468 
   1469 void
   1470 listing_list (int on)
   1471 {
   1472   if (listing)
   1473     {
   1474       switch (on)
   1475 	{
   1476 	case 0:
   1477 	  if (listing_tail->edict == EDICT_LIST)
   1478 	    listing_tail->edict = EDICT_NONE;
   1479 	  else
   1480 	    listing_tail->edict = EDICT_NOLIST;
   1481 	  break;
   1482 	case 1:
   1483 	  if (listing_tail->edict == EDICT_NOLIST
   1484 	      || listing_tail->edict == EDICT_NOLIST_NEXT)
   1485 	    listing_tail->edict = EDICT_NONE;
   1486 	  else
   1487 	    listing_tail->edict = EDICT_LIST;
   1488 	  break;
   1489 	case 2:
   1490 	  listing_tail->edict = EDICT_NOLIST_NEXT;
   1491 	  break;
   1492 	default:
   1493 	  abort ();
   1494 	}
   1495     }
   1496 }
   1497 
   1498 void
   1499 listing_psize (int width_only)
   1500 {
   1501   if (! width_only)
   1502     {
   1503       paper_height = get_absolute_expression ();
   1504 
   1505       if (paper_height < 0 || paper_height > 1000)
   1506 	{
   1507 	  paper_height = 0;
   1508 	  as_warn (_("strange paper height, set to no form"));
   1509 	}
   1510 
   1511       if (*input_line_pointer != ',')
   1512 	{
   1513 	  demand_empty_rest_of_line ();
   1514 	  return;
   1515 	}
   1516 
   1517       ++input_line_pointer;
   1518     }
   1519 
   1520   {
   1521     expressionS exp;
   1522 
   1523     (void) expression_and_evaluate (& exp);
   1524 
   1525     if (exp.X_op == O_constant)
   1526       {
   1527 	offsetT new_width = exp.X_add_number;
   1528 
   1529 	if (new_width > 7)
   1530 	  paper_width = new_width;
   1531 	else
   1532 	  as_bad (_("new paper width is too small"));
   1533       }
   1534     else if (exp.X_op != O_absent)
   1535       as_bad (_("bad or irreducible expression for paper width"));
   1536     else
   1537       as_bad (_("missing expression for paper width"));
   1538   }
   1539 
   1540   demand_empty_rest_of_line ();
   1541 }
   1542 
   1543 void
   1544 listing_nopage (int ignore ATTRIBUTE_UNUSED)
   1545 {
   1546   paper_height = 0;
   1547 }
   1548 
   1549 void
   1550 listing_title (int depth)
   1551 {
   1552   int quoted;
   1553   char *start;
   1554   char *ttl;
   1555   unsigned int length;
   1556 
   1557   SKIP_WHITESPACE ();
   1558   if (*input_line_pointer != '\"')
   1559     quoted = 0;
   1560   else
   1561     {
   1562       quoted = 1;
   1563       ++input_line_pointer;
   1564     }
   1565 
   1566   start = input_line_pointer;
   1567 
   1568   while (*input_line_pointer)
   1569     {
   1570       if (quoted
   1571 	  ? *input_line_pointer == '\"'
   1572 	  : is_end_of_line[(unsigned char) *input_line_pointer])
   1573 	{
   1574 	  if (listing)
   1575 	    {
   1576 	      length = input_line_pointer - start;
   1577 	      ttl = xmemdup0 (start, length);
   1578 	      listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
   1579 	      listing_tail->edict_arg = ttl;
   1580 	    }
   1581 	  if (quoted)
   1582 	    input_line_pointer++;
   1583 	  demand_empty_rest_of_line ();
   1584 	  return;
   1585 	}
   1586       else if (*input_line_pointer == '\n')
   1587 	{
   1588 	  as_bad (_("new line in title"));
   1589 	  demand_empty_rest_of_line ();
   1590 	  return;
   1591 	}
   1592       else
   1593 	{
   1594 	  input_line_pointer++;
   1595 	}
   1596     }
   1597 }
   1598 
   1599 void
   1600 listing_source_line (unsigned int line)
   1601 {
   1602   if (listing)
   1603     {
   1604       new_frag ();
   1605       listing_tail->hll_line = line;
   1606       new_frag ();
   1607     }
   1608 }
   1609 
   1610 void
   1611 listing_source_file (const char *file)
   1612 {
   1613   if (listing)
   1614     listing_tail->hll_file = file_info (file);
   1615 }
   1616 
   1617 #else
   1618 
   1619 /* Dummy functions for when compiled without listing enabled.  */
   1620 
   1621 void
   1622 listing_list (int on)
   1623 {
   1624   s_ignore (0);
   1625 }
   1626 
   1627 void
   1628 listing_eject (int ignore)
   1629 {
   1630   s_ignore (0);
   1631 }
   1632 
   1633 void
   1634 listing_psize (int ignore)
   1635 {
   1636   s_ignore (0);
   1637 }
   1638 
   1639 void
   1640 listing_nopage (int ignore)
   1641 {
   1642   s_ignore (0);
   1643 }
   1644 
   1645 void
   1646 listing_title (int depth)
   1647 {
   1648   s_ignore (0);
   1649 }
   1650 
   1651 void
   1652 listing_file (const char *name)
   1653 {
   1654 }
   1655 
   1656 void
   1657 listing_newline (char *name)
   1658 {
   1659 }
   1660 
   1661 void
   1662 listing_source_line (unsigned int n)
   1663 {
   1664 }
   1665 
   1666 void
   1667 listing_source_file (const char *n)
   1668 {
   1669 }
   1670 
   1671 #endif
   1672