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