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