1/* listing.c - maintain assembly listings
2   Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3   2001, 2002, 2003, 2005, 2006
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 2, 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 "obstack.h"
94#include "safe-ctype.h"
95#include "input-file.h"
96#include "subsegs.h"
97
98#ifndef NO_LISTING
99
100#ifndef LISTING_HEADER
101#define LISTING_HEADER "GAS LISTING"
102#endif
103#ifndef LISTING_WORD_SIZE
104#define LISTING_WORD_SIZE 4
105#endif
106#ifndef LISTING_LHS_WIDTH
107#define LISTING_LHS_WIDTH ((LISTING_WORD_SIZE) > 4 ? 1 : 4 / (LISTING_WORD_SIZE))
108#endif
109#ifndef LISTING_LHS_WIDTH_SECOND
110#define LISTING_LHS_WIDTH_SECOND LISTING_LHS_WIDTH
111#endif
112#ifndef LISTING_RHS_WIDTH
113#define LISTING_RHS_WIDTH 100
114#endif
115#ifndef LISTING_LHS_CONT_LINES
116#define LISTING_LHS_CONT_LINES 4
117#endif
118
119/* This structure remembers which .s were used.  */
120typedef struct file_info_struct
121{
122  struct file_info_struct * next;
123  char *                    filename;
124  long                      pos;
125  unsigned int              linenum;
126  int                       at_end;
127} file_info_type;
128
129/* This structure remembers which line from which file goes into which
130   frag.  */
131struct list_info_struct
132{
133  /* Frag which this line of source is nearest to.  */
134  fragS *frag;
135
136  /* The actual line in the source file.  */
137  unsigned int line;
138
139  /* Pointer to the file info struct for the file which this line
140     belongs to.  */
141  file_info_type *file;
142
143  /* The expanded text of any macro that may have been executing.  */
144  char *line_contents;
145
146  /* Next in list.  */
147  struct list_info_struct *next;
148
149  /* Pointer to the file info struct for the high level language
150     source line that belongs here.  */
151  file_info_type *hll_file;
152
153  /* High level language source line.  */
154  unsigned int hll_line;
155
156  /* Pointer to any error message associated with this line.  */
157  char *message;
158
159  enum
160    {
161      EDICT_NONE,
162      EDICT_SBTTL,
163      EDICT_TITLE,
164      EDICT_NOLIST,
165      EDICT_LIST,
166      EDICT_NOLIST_NEXT,
167      EDICT_EJECT
168    } edict;
169  char *edict_arg;
170
171  /* Nonzero if this line is to be omitted because it contains
172     debugging information.  This can become a flags field if we come
173     up with more information to store here.  */
174  int debugging;
175};
176
177typedef struct list_info_struct list_info_type;
178
179int listing_lhs_width        = LISTING_LHS_WIDTH;
180int listing_lhs_width_second = LISTING_LHS_WIDTH_SECOND;
181int listing_lhs_cont_lines   = LISTING_LHS_CONT_LINES;
182int listing_rhs_width        = LISTING_RHS_WIDTH;
183
184struct list_info_struct *        listing_tail;
185
186static file_info_type *          file_info_head;
187static file_info_type *          last_open_file_info;
188static FILE *                    last_open_file;
189static struct list_info_struct * head;
190static int                       paper_width = 200;
191static int                       paper_height = 60;
192
193extern int                       listing;
194
195/* File to output listings to.  */
196static FILE *list_file;
197
198/* This static array is used to keep the text of data to be printed
199   before the start of the line.  */
200
201#define MAX_BYTES							\
202  (((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width			\
203   + ((((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second)	\
204      * listing_lhs_cont_lines)						\
205   + 20)
206
207static char *data_buffer;
208
209/* Prototypes.  */
210static void listing_message (const char *, const char *);
211static file_info_type *file_info (const char *);
212static void new_frag (void);
213static char *buffer_line (file_info_type *, char *, unsigned int);
214static void listing_page (list_info_type *);
215static unsigned int calc_hex (list_info_type *);
216static void print_lines (list_info_type *, unsigned int, char *, unsigned int);
217static void list_symbol_table (void);
218static void print_source (file_info_type *, list_info_type *, char *, unsigned int);
219static int debugging_pseudo (list_info_type *, const char *);
220static void listing_listing (char *);
221
222static void
223listing_message (const char *name, const char *message)
224{
225  if (listing_tail != (list_info_type *) NULL)
226    {
227      unsigned int l = strlen (name) + strlen (message) + 1;
228      char *n = (char *) xmalloc (l);
229      strcpy (n, name);
230      strcat (n, message);
231      listing_tail->message = n;
232    }
233}
234
235void
236listing_warning (const char *message)
237{
238  listing_message (_("Warning:"), message);
239}
240
241void
242listing_error (const char *message)
243{
244  listing_message (_("Error:"), message);
245}
246
247static file_info_type *
248file_info (const char *file_name)
249{
250  /* Find an entry with this file name.  */
251  file_info_type *p = file_info_head;
252
253  while (p != (file_info_type *) NULL)
254    {
255      if (strcmp (p->filename, file_name) == 0)
256	return p;
257      p = p->next;
258    }
259
260  /* Make new entry.  */
261  p = xmalloc (sizeof (file_info_type));
262  p->next = file_info_head;
263  file_info_head = p;
264  p->filename = xstrdup (file_name);
265  p->pos = 0;
266  p->linenum = 0;
267  p->at_end = 0;
268
269  return p;
270}
271
272static void
273new_frag (void)
274{
275  frag_wane (frag_now);
276  frag_new (0);
277}
278
279void
280listing_newline (char *ps)
281{
282  char *file;
283  unsigned int line;
284  static unsigned int last_line = 0xffff;
285  static char *last_file = NULL;
286  list_info_type *new = NULL;
287
288  if (listing == 0)
289    return;
290
291  if (now_seg == absolute_section)
292    return;
293
294#ifdef OBJ_ELF
295  /* In ELF, anything in a section beginning with .debug or .line is
296     considered to be debugging information.  This includes the
297     statement which switches us into the debugging section, which we
298     can only set after we are already in the debugging section.  */
299  if ((listing & LISTING_NODEBUG) != 0
300      && listing_tail != NULL
301      && ! listing_tail->debugging)
302    {
303      const char *segname;
304
305      segname = segment_name (now_seg);
306      if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
307	  || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
308	listing_tail->debugging = 1;
309    }
310#endif
311
312  as_where (&file, &line);
313  if (ps == NULL)
314    {
315      if (line == last_line
316	  && !(last_file && file && strcmp (file, last_file)))
317	return;
318
319      new = (list_info_type *) xmalloc (sizeof (list_info_type));
320
321      /* Detect if we are reading from stdin by examining the file
322	 name returned by as_where().
323
324	 [FIXME: We rely upon the name in the strcmp below being the
325	 same as the one used by input_scrub_new_file(), if that is
326	 not true, then this code will fail].
327
328	 If we are reading from stdin, then we need to save each input
329	 line here (assuming of course that we actually have a line of
330	 input to read), so that it can be displayed in the listing
331	 that is produced at the end of the assembly.  */
332      if (strcmp (file, _("{standard input}")) == 0
333	  && input_line_pointer != NULL)
334	{
335	  char *copy;
336	  int len;
337	  int seen_quote = 0;
338
339	  for (copy = input_line_pointer - 1;
340	       *copy && (seen_quote
341			 || (! is_end_of_line [(unsigned char) *copy]));
342	       copy++)
343	    if (*copy == '"' && copy[-1] != '\\')
344	      seen_quote = ! seen_quote;
345
346	  len = (copy - input_line_pointer) + 2;
347
348	  copy = xmalloc (len);
349
350	  if (copy != NULL)
351	    {
352	      char *src = input_line_pointer - 1;
353	      char *dest = copy;
354
355	      while (--len)
356		{
357		  unsigned char c = *src++;
358
359		  /* Omit control characters in the listing.  */
360		  if (!ISCNTRL (c))
361		    *dest++ = c;
362		}
363
364	      *dest = 0;
365	    }
366
367	  new->line_contents = copy;
368	}
369      else
370	new->line_contents = NULL;
371    }
372  else
373    {
374      new = xmalloc (sizeof (list_info_type));
375      new->line_contents = ps;
376    }
377
378  last_line = line;
379  last_file = file;
380
381  new_frag ();
382
383  if (listing_tail)
384    listing_tail->next = new;
385  else
386    head = new;
387
388  listing_tail = new;
389
390  new->frag = frag_now;
391  new->line = line;
392  new->file = file_info (file);
393  new->next = (list_info_type *) NULL;
394  new->message = (char *) NULL;
395  new->edict = EDICT_NONE;
396  new->hll_file = (file_info_type *) NULL;
397  new->hll_line = 0;
398  new->debugging = 0;
399
400  new_frag ();
401
402#ifdef OBJ_ELF
403  /* In ELF, anything in a section beginning with .debug or .line is
404     considered to be debugging information.  */
405  if ((listing & LISTING_NODEBUG) != 0)
406    {
407      const char *segname;
408
409      segname = segment_name (now_seg);
410      if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
411	  || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
412	new->debugging = 1;
413    }
414#endif
415}
416
417/* Attach all current frags to the previous line instead of the
418   current line.  This is called by the MIPS backend when it discovers
419   that it needs to add some NOP instructions; the added NOP
420   instructions should go with the instruction that has the delay, not
421   with the new instruction.  */
422
423void
424listing_prev_line (void)
425{
426  list_info_type *l;
427  fragS *f;
428
429  if (head == (list_info_type *) NULL
430      || head == listing_tail)
431    return;
432
433  new_frag ();
434
435  for (l = head; l->next != listing_tail; l = l->next)
436    ;
437
438  for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next)
439    if (f->line == listing_tail)
440      f->line = l;
441
442  listing_tail->frag = frag_now;
443  new_frag ();
444}
445
446/* This function returns the next source line from the file supplied,
447   truncated to size.  It appends a fake line to the end of each input
448   file to make.  */
449
450static char *
451buffer_line (file_info_type *file, char *line, unsigned int size)
452{
453  unsigned int count = 0;
454  int c;
455
456  char *p = line;
457
458  /* If we couldn't open the file, return an empty line.  */
459  if (file->at_end)
460    return "";
461
462  /* Check the cache and see if we last used this file.  */
463  if (!last_open_file_info || file != last_open_file_info)
464    {
465      if (last_open_file)
466	{
467	  last_open_file_info->pos = ftell (last_open_file);
468	  fclose (last_open_file);
469	}
470
471      last_open_file_info = file;
472      last_open_file = fopen (file->filename, FOPEN_RT);
473      if (last_open_file == NULL)
474	{
475	  file->at_end = 1;
476	  return "";
477	}
478
479      /* Seek to where we were last time this file was open.  */
480      if (file->pos)
481	fseek (last_open_file, file->pos, SEEK_SET);
482    }
483
484  c = fgetc (last_open_file);
485
486  /* Leave room for null.  */
487  size -= 1;
488
489  while (c != EOF && c != '\n')
490    {
491      if (count < size)
492	*p++ = c;
493      count++;
494
495      c = fgetc (last_open_file);
496
497    }
498  if (c == EOF)
499    {
500      file->at_end = 1;
501      if (count + 2 < size)
502	{
503	  *p++ = '.';
504	  *p++ = '.';
505	  *p++ = '.';
506	}
507    }
508  file->linenum++;
509  *p++ = 0;
510  return line;
511}
512
513static const char *fn;
514
515static unsigned int eject;	/* Eject pending */
516static unsigned int page;	/* Current page number */
517static char *title;		/* Current title */
518static char *subtitle;		/* Current subtitle */
519static unsigned int on_page;	/* Number of lines printed on current page */
520
521static void
522listing_page (list_info_type *list)
523{
524  /* Grope around, see if we can see a title or subtitle edict coming up
525     soon.  (we look down 10 lines of the page and see if it's there)  */
526  if ((eject || (on_page >= (unsigned int) paper_height))
527      && paper_height != 0)
528    {
529      unsigned int c = 10;
530      int had_title = 0;
531      int had_subtitle = 0;
532
533      page++;
534
535      while (c != 0 && list)
536	{
537	  if (list->edict == EDICT_SBTTL && !had_subtitle)
538	    {
539	      had_subtitle = 1;
540	      subtitle = list->edict_arg;
541	    }
542	  if (list->edict == EDICT_TITLE && !had_title)
543	    {
544	      had_title = 1;
545	      title = list->edict_arg;
546	    }
547	  list = list->next;
548	  c--;
549	}
550
551      if (page > 1)
552	{
553	  fprintf (list_file, "\f");
554	}
555
556      fprintf (list_file, "%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
557      fprintf (list_file, "%s\n", title);
558      fprintf (list_file, "%s\n", subtitle);
559      on_page = 3;
560      eject = 0;
561    }
562}
563
564static unsigned int
565calc_hex (list_info_type *list)
566{
567  int data_buffer_size;
568  list_info_type *first = list;
569  unsigned int address = ~(unsigned int) 0;
570  fragS *frag;
571  fragS *frag_ptr;
572  unsigned int octet_in_frag;
573
574  /* Find first frag which says it belongs to this line.  */
575  frag = list->frag;
576  while (frag && frag->line != list)
577    frag = frag->fr_next;
578
579  frag_ptr = frag;
580
581  data_buffer_size = 0;
582
583  /* Dump all the frags which belong to this line.  */
584  while (frag_ptr != (fragS *) NULL && frag_ptr->line == first)
585    {
586      /* Print as many bytes from the fixed part as is sensible.  */
587      octet_in_frag = 0;
588      while ((offsetT) octet_in_frag < frag_ptr->fr_fix
589	     && data_buffer_size < MAX_BYTES - 3)
590	{
591	  if (address == ~(unsigned int) 0)
592	    address = frag_ptr->fr_address / OCTETS_PER_BYTE;
593
594	  sprintf (data_buffer + data_buffer_size,
595		   "%02X",
596		   (frag_ptr->fr_literal[octet_in_frag]) & 0xff);
597	  data_buffer_size += 2;
598	  octet_in_frag++;
599	}
600      if (frag_ptr->fr_type == rs_fill)
601	{
602	  unsigned int var_rep_max = octet_in_frag;
603	  unsigned int var_rep_idx = octet_in_frag;
604
605	  /* Print as many bytes from the variable part as is sensible.  */
606	  while (((offsetT) octet_in_frag
607		  < (frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset))
608		 && data_buffer_size < MAX_BYTES - 3)
609	    {
610	      if (address == ~(unsigned int) 0)
611		address = frag_ptr->fr_address / OCTETS_PER_BYTE;
612
613	      sprintf (data_buffer + data_buffer_size,
614		       "%02X",
615		       (frag_ptr->fr_literal[var_rep_idx]) & 0xff);
616	      data_buffer_size += 2;
617
618	      var_rep_idx++;
619	      octet_in_frag++;
620
621	      if ((offsetT) var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var)
622		var_rep_idx = var_rep_max;
623	    }
624	}
625
626      frag_ptr = frag_ptr->fr_next;
627    }
628  data_buffer[data_buffer_size] = '\0';
629  return address;
630}
631
632static void
633print_lines (list_info_type *list, unsigned int lineno,
634	     char *string, unsigned int address)
635{
636  unsigned int idx;
637  unsigned int nchars;
638  unsigned int lines;
639  unsigned int octet_in_word = 0;
640  char *src = data_buffer;
641  int cur;
642
643  /* Print the stuff on the first line.  */
644  listing_page (list);
645  nchars = (LISTING_WORD_SIZE * 2 + 1) * listing_lhs_width;
646
647  /* Print the hex for the first line.  */
648  if (address == ~(unsigned int) 0)
649    {
650      fprintf (list_file, "% 4d     ", lineno);
651      for (idx = 0; idx < nchars; idx++)
652	fprintf (list_file, " ");
653
654      fprintf (list_file, "\t%s\n", string ? string : "");
655
656      on_page++;
657
658      listing_page (0);
659
660      return;
661    }
662
663  if (had_errors ())
664    fprintf (list_file, "% 4d ???? ", lineno);
665  else
666    fprintf (list_file, "% 4d %04x ", lineno, address);
667
668  /* And the data to go along with it.  */
669  idx = 0;
670  cur = 0;
671  while (src[cur] && idx < nchars)
672    {
673      int offset;
674      offset = cur;
675      fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
676      cur += 2;
677      octet_in_word++;
678
679      if (octet_in_word == LISTING_WORD_SIZE)
680	{
681	  fprintf (list_file, " ");
682	  idx++;
683	  octet_in_word = 0;
684	}
685
686      idx += 2;
687    }
688
689  for (; idx < nchars; idx++)
690    fprintf (list_file, " ");
691
692  fprintf (list_file, "\t%s\n", string ? string : "");
693  on_page++;
694  listing_page (list);
695
696  if (list->message)
697    {
698      fprintf (list_file, "****  %s\n", list->message);
699      listing_page (list);
700      on_page++;
701    }
702
703  for (lines = 0;
704       lines < (unsigned int) listing_lhs_cont_lines
705	 && src[cur];
706       lines++)
707    {
708      nchars = ((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second - 1;
709      idx = 0;
710
711      /* Print any more lines of data, but more compactly.  */
712      fprintf (list_file, "% 4d      ", lineno);
713
714      while (src[cur] && idx < nchars)
715	{
716	  int offset;
717	  offset = cur;
718	  fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
719	  cur += 2;
720	  idx += 2;
721	  octet_in_word++;
722
723	  if (octet_in_word == LISTING_WORD_SIZE)
724	    {
725	      fprintf (list_file, " ");
726	      idx++;
727	      octet_in_word = 0;
728	    }
729	}
730
731      fprintf (list_file, "\n");
732      on_page++;
733      listing_page (list);
734    }
735}
736
737static void
738list_symbol_table (void)
739{
740  extern symbolS *symbol_rootP;
741  int got_some = 0;
742
743  symbolS *ptr;
744  eject = 1;
745  listing_page (0);
746
747  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
748    {
749      if (SEG_NORMAL (S_GET_SEGMENT (ptr))
750	  || S_GET_SEGMENT (ptr) == absolute_section)
751	{
752	  /* Don't report section symbols.  They are not interesting.  */
753	  if (symbol_section_p (ptr))
754	    continue;
755
756	  if (S_GET_NAME (ptr))
757	    {
758	      char buf[30], fmt[8];
759	      valueT val = S_GET_VALUE (ptr);
760
761	      /* @@ Note that this is dependent on the compilation options,
762		 not solely on the target characteristics.  */
763	      if (sizeof (val) == 4 && sizeof (int) == 4)
764		sprintf (buf, "%08lx", (unsigned long) val);
765	      else if (sizeof (val) <= sizeof (unsigned long))
766		{
767		  sprintf (fmt, "%%0%lulx",
768			   (unsigned long) (sizeof (val) * 2));
769		  sprintf (buf, fmt, (unsigned long) val);
770		}
771#if defined (BFD64)
772	      else if (sizeof (val) > 4)
773		sprintf_vma (buf, val);
774#endif
775	      else
776		abort ();
777
778	      if (!got_some)
779		{
780		  fprintf (list_file, "DEFINED SYMBOLS\n");
781		  on_page++;
782		  got_some = 1;
783		}
784
785	      if (symbol_get_frag (ptr) && symbol_get_frag (ptr)->line)
786		{
787		  fprintf (list_file, "%20s:%-5d  %s:%s %s\n",
788			   symbol_get_frag (ptr)->line->file->filename,
789			   symbol_get_frag (ptr)->line->line,
790			   segment_name (S_GET_SEGMENT (ptr)),
791			   buf, S_GET_NAME (ptr));
792		}
793	      else
794		{
795		  fprintf (list_file, "%33s:%s %s\n",
796			   segment_name (S_GET_SEGMENT (ptr)),
797			   buf, S_GET_NAME (ptr));
798		}
799
800	      on_page++;
801	      listing_page (0);
802	    }
803	}
804
805    }
806  if (!got_some)
807    {
808      fprintf (list_file, "NO DEFINED SYMBOLS\n");
809      on_page++;
810    }
811  fprintf (list_file, "\n");
812  on_page++;
813  listing_page (0);
814
815  got_some = 0;
816
817  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
818    {
819      if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
820	{
821	  if (S_GET_SEGMENT (ptr) == undefined_section)
822	    {
823	      if (!got_some)
824		{
825		  got_some = 1;
826		  fprintf (list_file, "UNDEFINED SYMBOLS\n");
827		  on_page++;
828		  listing_page (0);
829		}
830	      fprintf (list_file, "%s\n", S_GET_NAME (ptr));
831	      on_page++;
832	      listing_page (0);
833	    }
834	}
835    }
836  if (!got_some)
837    {
838      fprintf (list_file, "NO UNDEFINED SYMBOLS\n");
839      on_page++;
840      listing_page (0);
841    }
842}
843
844static void
845print_source (file_info_type *current_file, list_info_type *list,
846	      char *buffer, unsigned int width)
847{
848  if (!current_file->at_end)
849    {
850      while (current_file->linenum < list->hll_line
851	     && !current_file->at_end)
852	{
853	  char *p = buffer_line (current_file, buffer, width);
854
855	  fprintf (list_file, "%4u:%-13s **** %s\n", current_file->linenum,
856		   current_file->filename, p);
857	  on_page++;
858	  listing_page (list);
859	}
860    }
861}
862
863/* Sometimes the user doesn't want to be bothered by the debugging
864   records inserted by the compiler, see if the line is suspicious.  */
865
866static int
867debugging_pseudo (list_info_type *list, const char *line)
868{
869  static int in_debug;
870  int was_debug;
871
872  if (list->debugging)
873    {
874      in_debug = 1;
875      return 1;
876    }
877
878  was_debug = in_debug;
879  in_debug = 0;
880
881  while (ISSPACE (*line))
882    line++;
883
884  if (*line != '.')
885    {
886#ifdef OBJ_ELF
887      /* The ELF compiler sometimes emits blank lines after switching
888         out of a debugging section.  If the next line drops us back
889         into debugging information, then don't print the blank line.
890         This is a hack for a particular compiler behaviour, not a
891         general case.  */
892      if (was_debug
893	  && *line == '\0'
894	  && list->next != NULL
895	  && list->next->debugging)
896	{
897	  in_debug = 1;
898	  return 1;
899	}
900#endif
901
902      return 0;
903    }
904
905  line++;
906
907  if (strncmp (line, "def", 3) == 0)
908    return 1;
909  if (strncmp (line, "val", 3) == 0)
910    return 1;
911  if (strncmp (line, "scl", 3) == 0)
912    return 1;
913  if (strncmp (line, "line", 4) == 0)
914    return 1;
915  if (strncmp (line, "endef", 5) == 0)
916    return 1;
917  if (strncmp (line, "ln", 2) == 0)
918    return 1;
919  if (strncmp (line, "type", 4) == 0)
920    return 1;
921  if (strncmp (line, "size", 4) == 0)
922    return 1;
923  if (strncmp (line, "dim", 3) == 0)
924    return 1;
925  if (strncmp (line, "tag", 3) == 0)
926    return 1;
927  if (strncmp (line, "stabs", 5) == 0)
928    return 1;
929  if (strncmp (line, "stabn", 5) == 0)
930    return 1;
931
932  return 0;
933}
934
935static void
936listing_listing (char *name ATTRIBUTE_UNUSED)
937{
938  list_info_type *list = head;
939  file_info_type *current_hll_file = (file_info_type *) NULL;
940  char *message;
941  char *buffer;
942  char *p;
943  int show_listing = 1;
944  unsigned int width;
945
946  buffer = xmalloc (listing_rhs_width);
947  data_buffer = xmalloc (MAX_BYTES);
948  eject = 1;
949  list = head->next;
950
951  while (list)
952    {
953      unsigned int list_line;
954
955      width = listing_rhs_width > paper_width ? paper_width :
956	listing_rhs_width;
957
958      list_line = list->line;
959      switch (list->edict)
960	{
961	case EDICT_LIST:
962	  /* Skip all lines up to the current.  */
963	  list_line--;
964	  break;
965	case EDICT_NOLIST:
966	  show_listing--;
967	  break;
968	case EDICT_NOLIST_NEXT:
969	  if (show_listing == 0)
970	    list_line--;
971	  break;
972	case EDICT_EJECT:
973	  break;
974	case EDICT_NONE:
975	  break;
976	case EDICT_TITLE:
977	  title = list->edict_arg;
978	  break;
979	case EDICT_SBTTL:
980	  subtitle = list->edict_arg;
981	  break;
982	default:
983	  abort ();
984	}
985
986      if (show_listing <= 0)
987	{
988	  while (list->file->linenum < list_line
989		 && !list->file->at_end)
990	    p = buffer_line (list->file, buffer, width);
991	}
992
993      if (list->edict == EDICT_LIST
994	  || (list->edict == EDICT_NOLIST_NEXT && show_listing == 0))
995	{
996	  /* Enable listing for the single line that caused the enable.  */
997	  list_line++;
998	  show_listing++;
999	}
1000
1001      if (show_listing > 0)
1002	{
1003	  /* Scan down the list and print all the stuff which can be done
1004	     with this line (or lines).  */
1005	  message = 0;
1006
1007	  if (list->hll_file)
1008	    current_hll_file = list->hll_file;
1009
1010	  if (current_hll_file && list->hll_line && (listing & LISTING_HLL))
1011	    print_source (current_hll_file, list, buffer, width);
1012
1013	  if (list->line_contents)
1014	    {
1015	      if (!((listing & LISTING_NODEBUG)
1016		    && debugging_pseudo (list, list->line_contents)))
1017		print_lines (list,
1018			     list->file->linenum == 0 ? list->line : list->file->linenum,
1019			     list->line_contents, calc_hex (list));
1020
1021	      free (list->line_contents);
1022	      list->line_contents = NULL;
1023	    }
1024	  else
1025	    {
1026	      while (list->file->linenum < list_line
1027		     && !list->file->at_end)
1028		{
1029		  unsigned int address;
1030
1031		  p = buffer_line (list->file, buffer, width);
1032
1033		  if (list->file->linenum < list_line)
1034		    address = ~(unsigned int) 0;
1035		  else
1036		    address = calc_hex (list);
1037
1038		  if (!((listing & LISTING_NODEBUG)
1039			&& debugging_pseudo (list, p)))
1040		    print_lines (list, list->file->linenum, p, address);
1041		}
1042	    }
1043
1044	  if (list->edict == EDICT_EJECT)
1045	    eject = 1;
1046	}
1047
1048      if (list->edict == EDICT_NOLIST_NEXT && show_listing == 1)
1049	--show_listing;
1050
1051      list = list->next;
1052    }
1053
1054  free (buffer);
1055  free (data_buffer);
1056  data_buffer = NULL;
1057}
1058
1059void
1060listing_print (char *name)
1061{
1062  int using_stdout;
1063
1064  title = "";
1065  subtitle = "";
1066
1067  if (name == NULL)
1068    {
1069      list_file = stdout;
1070      using_stdout = 1;
1071    }
1072  else
1073    {
1074      list_file = fopen (name, FOPEN_WT);
1075      if (list_file != NULL)
1076	using_stdout = 0;
1077      else
1078	{
1079	  as_warn (_("can't open %s: %s"), name, xstrerror (errno));
1080	  list_file = stdout;
1081	  using_stdout = 1;
1082	}
1083    }
1084
1085  if (listing & LISTING_NOFORM)
1086    paper_height = 0;
1087
1088  if (listing & LISTING_LISTING)
1089    listing_listing (name);
1090
1091  if (listing & LISTING_SYMBOLS)
1092    list_symbol_table ();
1093
1094  if (! using_stdout)
1095    {
1096      if (fclose (list_file) == EOF)
1097	as_warn (_("can't close %s: %s"), name, xstrerror (errno));
1098    }
1099
1100  if (last_open_file)
1101    fclose (last_open_file);
1102}
1103
1104void
1105listing_file (const char *name)
1106{
1107  fn = name;
1108}
1109
1110void
1111listing_eject (int ignore ATTRIBUTE_UNUSED)
1112{
1113  if (listing)
1114    listing_tail->edict = EDICT_EJECT;
1115}
1116
1117void
1118listing_flags (int ignore ATTRIBUTE_UNUSED)
1119{
1120  while ((*input_line_pointer++) && (*input_line_pointer != '\n'))
1121    input_line_pointer++;
1122
1123}
1124
1125/* Turn listing on or off.  An argument of 0 means to turn off
1126   listing.  An argument of 1 means to turn on listing.  An argument
1127   of 2 means to turn off listing, but as of the next line; that is,
1128   the current line should be listed, but the next line should not.  */
1129
1130void
1131listing_list (int on)
1132{
1133  if (listing)
1134    {
1135      switch (on)
1136	{
1137	case 0:
1138	  if (listing_tail->edict == EDICT_LIST)
1139	    listing_tail->edict = EDICT_NONE;
1140	  else
1141	    listing_tail->edict = EDICT_NOLIST;
1142	  break;
1143	case 1:
1144	  if (listing_tail->edict == EDICT_NOLIST
1145	      || listing_tail->edict == EDICT_NOLIST_NEXT)
1146	    listing_tail->edict = EDICT_NONE;
1147	  else
1148	    listing_tail->edict = EDICT_LIST;
1149	  break;
1150	case 2:
1151	  listing_tail->edict = EDICT_NOLIST_NEXT;
1152	  break;
1153	default:
1154	  abort ();
1155	}
1156    }
1157}
1158
1159void
1160listing_psize (int width_only)
1161{
1162  if (! width_only)
1163    {
1164      paper_height = get_absolute_expression ();
1165
1166      if (paper_height < 0 || paper_height > 1000)
1167	{
1168	  paper_height = 0;
1169	  as_warn (_("strange paper height, set to no form"));
1170	}
1171
1172      if (*input_line_pointer != ',')
1173	{
1174	  demand_empty_rest_of_line ();
1175	  return;
1176	}
1177
1178      ++input_line_pointer;
1179    }
1180
1181  paper_width = get_absolute_expression ();
1182
1183  demand_empty_rest_of_line ();
1184}
1185
1186void
1187listing_nopage (int ignore ATTRIBUTE_UNUSED)
1188{
1189  paper_height = 0;
1190}
1191
1192void
1193listing_title (int depth)
1194{
1195  int quoted;
1196  char *start;
1197  char *ttl;
1198  unsigned int length;
1199
1200  SKIP_WHITESPACE ();
1201  if (*input_line_pointer != '\"')
1202    quoted = 0;
1203  else
1204    {
1205      quoted = 1;
1206      ++input_line_pointer;
1207    }
1208
1209  start = input_line_pointer;
1210
1211  while (*input_line_pointer)
1212    {
1213      if (quoted
1214	  ? *input_line_pointer == '\"'
1215	  : is_end_of_line[(unsigned char) *input_line_pointer])
1216	{
1217	  if (listing)
1218	    {
1219	      length = input_line_pointer - start;
1220	      ttl = xmalloc (length + 1);
1221	      memcpy (ttl, start, length);
1222	      ttl[length] = 0;
1223	      listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
1224	      listing_tail->edict_arg = ttl;
1225	    }
1226	  if (quoted)
1227	    input_line_pointer++;
1228	  demand_empty_rest_of_line ();
1229	  return;
1230	}
1231      else if (*input_line_pointer == '\n')
1232	{
1233	  as_bad (_("new line in title"));
1234	  demand_empty_rest_of_line ();
1235	  return;
1236	}
1237      else
1238	{
1239	  input_line_pointer++;
1240	}
1241    }
1242}
1243
1244void
1245listing_source_line (unsigned int line)
1246{
1247  if (listing)
1248    {
1249      new_frag ();
1250      listing_tail->hll_line = line;
1251      new_frag ();
1252    }
1253}
1254
1255void
1256listing_source_file (const char *file)
1257{
1258  if (listing)
1259    listing_tail->hll_file = file_info (file);
1260}
1261
1262#else
1263
1264/* Dummy functions for when compiled without listing enabled.  */
1265
1266void
1267listing_flags (int ignore)
1268{
1269  s_ignore (0);
1270}
1271
1272void
1273listing_list (int on)
1274{
1275  s_ignore (0);
1276}
1277
1278void
1279listing_eject (int ignore)
1280{
1281  s_ignore (0);
1282}
1283
1284void
1285listing_psize (int ignore)
1286{
1287  s_ignore (0);
1288}
1289
1290void
1291listing_nopage (int ignore)
1292{
1293  s_ignore (0);
1294}
1295
1296void
1297listing_title (int depth)
1298{
1299  s_ignore (0);
1300}
1301
1302void
1303listing_file (const char *name)
1304{
1305}
1306
1307void
1308listing_newline (char *name)
1309{
1310}
1311
1312void
1313listing_source_line (unsigned int n)
1314{
1315}
1316
1317void
1318listing_source_file (const char *n)
1319{
1320}
1321
1322#endif
1323