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