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