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