binutils  2.23.2
About: GNU Binutils are a collection of binary tools. The main ones are "ld" the GNU linker and "(g)as" the GNU assembler.
  Fossies Dox: binutils-2.23.2.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

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