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