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