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