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