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