listing.c revision 33965
1/* listing.c - mainting assembly listings
2   Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc.
3
4This file is part of GAS, the GNU Assembler.
5
6GAS is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 2, or (at your option)
9any later version.
10
11GAS is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GAS; see the file COPYING.  If not, write to the Free
18Software Foundation, 59 Temple Place - Suite 330, Boston, MA
1902111-1307, USA. */
20
21/*
22 Contributed by Steve Chamberlain
23 		sac@cygnus.com
24
25
26 A listing page looks like:
27
28 LISTING_HEADER  sourcefilename pagenumber
29 TITLE LINE
30 SUBTITLE LINE
31 linenumber address data  source
32 linenumber address data  source
33 linenumber address data  source
34 linenumber address data  source
35
36 If not overridden, the listing commands are:
37
38 .title  "stuff"
39 	Put "stuff" onto the title line
40 .sbttl  "stuff"
41        Put stuff onto the subtitle line
42
43  If these commands come within 10 lines of the top of the page, they
44  will affect the page they are on, as well as any subsequent page
45
46 .eject
47 	Thow a page
48 .list
49 	Increment the enable listing counter
50 .nolist
51 	Decrement the enable listing counter
52
53 .psize Y[,X]
54 	Set the paper size to X wide and Y high. Setting a psize Y of
55	zero will suppress form feeds except where demanded by .eject
56
57 If the counter goes below zero, listing is suppressed.
58
59
60 Listings are a maintained by read calling various listing_<foo>
61 functions.  What happens most is that the macro NO_LISTING is not
62 defined (from the Makefile), then the macro LISTING_NEWLINE expands
63 into a call to listing_newline.  The call is done from read.c, every
64 time it sees a newline, and -l is on the command line.
65
66 The function listing_newline remembers the frag associated with the
67 newline, and creates a new frag - note that this is wasteful, but not
68 a big deal, since listing slows things down a lot anyway.  The
69 function also rememebers when the filename changes.
70
71 When all the input has finished, and gas has had a chance to settle
72 down, the listing is output. This is done by running down the list of
73 frag/source file records, and opening the files as needed and printing
74 out the bytes and chars associated with them.
75
76 The only things which the architecture can change about the listing
77 are defined in these macros:
78
79 LISTING_HEADER		The name of the architecture
80 LISTING_WORD_SIZE      The make of the number of bytes in a word, this determines
81 			the clumping of the output data. eg a value of
82			2 makes words look like 1234 5678, whilst 1
83			would make the same value look like 12 34 56
84			78
85 LISTING_LHS_WIDTH      Number of words of above size for the lhs
86
87 LISTING_LHS_WIDTH_SECOND   Number of words for the data on the lhs
88 			for the second line
89
90 LISTING_LHS_CONT_LINES	Max number of lines to use up for a continutation
91 LISTING_RHS_WIDTH      Number of chars from the input file to print
92                        on a line
93*/
94
95#include <ctype.h>
96
97#include "as.h"
98#include <obstack.h>
99#include "input-file.h"
100#include "subsegs.h"
101
102#ifndef NO_LISTING
103#ifndef LISTING_HEADER
104#define LISTING_HEADER "GAS LISTING"
105#endif
106#ifndef LISTING_WORD_SIZE
107#define LISTING_WORD_SIZE 4
108#endif
109#ifndef LISTING_LHS_WIDTH
110#define LISTING_LHS_WIDTH 1
111#endif
112#ifndef LISTING_LHS_WIDTH_SECOND
113#define LISTING_LHS_WIDTH_SECOND 1
114#endif
115#ifndef LISTING_RHS_WIDTH
116#define LISTING_RHS_WIDTH 100
117#endif
118#ifndef LISTING_LHS_CONT_LINES
119#define LISTING_LHS_CONT_LINES 4
120#endif
121
122
123
124
125/* This structure remembers which .s were used */
126typedef struct file_info_struct
127{
128  char *filename;
129  int linenum;
130  FILE *file;
131  struct file_info_struct *next;
132  int at_end;
133}
134
135file_info_type;
136
137
138/* this structure rememebrs which line from which file goes into which
139   frag */
140typedef struct list_info_struct
141{
142  /* Frag which this line of source is nearest to */
143  fragS *frag;
144  /* The actual line in the source file */
145  unsigned int line;
146  /* Pointer to the file info struct for the file which this line
147     belongs to */
148  file_info_type *file;
149
150  /* Next in list */
151  struct list_info_struct *next;
152
153
154  /* Pointer to the file info struct for the high level language
155     source line that belongs here */
156  file_info_type *hll_file;
157
158  /* High level language source line */
159  int hll_line;
160
161
162  /* Pointer to any error message associated with this line */
163  char *message;
164
165  enum
166    {
167      EDICT_NONE,
168      EDICT_SBTTL,
169      EDICT_TITLE,
170      EDICT_NOLIST,
171      EDICT_LIST,
172      EDICT_NOLIST_NEXT,
173      EDICT_EJECT
174    } edict;
175  char *edict_arg;
176
177}
178
179list_info_type;
180
181
182static struct list_info_struct *head;
183struct list_info_struct *listing_tail;
184extern int listing;
185
186static int paper_width = 200;
187static int paper_height = 60;
188
189/* File to output listings to.  */
190static FILE *list_file;
191
192/* this static array is used to keep the text of data to be printed
193   before the start of the line.
194    It is stored so we can give a bit more info on the next line.  To much, and large
195   initialized arrays will use up lots of paper.
196 */
197
198static char data_buffer[100];
199static unsigned int data_buffer_size;
200
201
202/* Prototypes.  */
203static void listing_message PARAMS ((const char *name, const char *message));
204static file_info_type *file_info PARAMS ((const char *file_name));
205static void new_frag PARAMS ((void));
206static char *buffer_line PARAMS ((file_info_type *file,
207				  char *line, unsigned int size));
208static void listing_page PARAMS ((list_info_type *list));
209static unsigned int calc_hex PARAMS ((list_info_type *list));
210static void print_lines PARAMS ((list_info_type *, unsigned int,
211				 char *, unsigned int));
212static void list_symbol_table PARAMS ((void));
213static void print_source PARAMS ((file_info_type *current_file,
214				  list_info_type *list,
215				  char *buffer,
216				  unsigned int width));
217static int debugging_pseudo PARAMS ((char *line));
218static void listing_listing PARAMS ((char *name));
219
220
221static void
222listing_message (name, message)
223     const char *name;
224     const char *message;
225{
226  unsigned int l = strlen (name) + strlen (message) + 1;
227  char *n = (char *) xmalloc (l);
228  strcpy (n, name);
229  strcat (n, message);
230  if (listing_tail != (list_info_type *) NULL)
231    {
232      listing_tail->message = n;
233    }
234}
235
236void
237listing_warning (message)
238     const char *message;
239{
240  listing_message ("Warning:", message);
241}
242
243void
244listing_error (message)
245     const char *message;
246{
247  listing_message ("Error:", message);
248}
249
250
251
252
253static file_info_type *file_info_head;
254
255static file_info_type *
256file_info (file_name)
257     const char *file_name;
258{
259  /* Find an entry with this file name */
260  file_info_type *p = file_info_head;
261
262  while (p != (file_info_type *) NULL)
263    {
264      if (strcmp (p->filename, file_name) == 0)
265	return p;
266      p = p->next;
267    }
268
269  /* Make new entry */
270
271  p = (file_info_type *) xmalloc (sizeof (file_info_type));
272  p->next = file_info_head;
273  file_info_head = p;
274  p->filename = xmalloc ((unsigned long) strlen (file_name) + 1);
275  strcpy (p->filename, file_name);
276  p->linenum = 0;
277  p->at_end = 0;
278
279  p->file = fopen (p->filename, "r");
280  if (p->file)
281    fgetc (p->file);
282
283  return p;
284}
285
286
287static void
288new_frag ()
289{
290
291  frag_wane (frag_now);
292  frag_new (0);
293
294}
295
296void
297listing_newline (ps)
298     char *ps;
299{
300  char *file;
301  unsigned int line;
302  static unsigned int last_line = 0xffff;
303  static char *last_file = NULL;
304  list_info_type *new;
305
306  if (listing == 0)
307    return;
308
309  if (now_seg == absolute_section)
310    return;
311
312  as_where (&file, &line);
313  if (line != last_line || (last_file && file && strcmp(file, last_file)))
314    {
315      last_line = line;
316      last_file = file;
317      new_frag ();
318
319      new = (list_info_type *) xmalloc (sizeof (list_info_type));
320      new->frag = frag_now;
321      new->line = line;
322      new->file = file_info (file);
323
324      if (listing_tail)
325	{
326	  listing_tail->next = new;
327	}
328      else
329	{
330	  head = new;
331	}
332      listing_tail = new;
333      new->next = (list_info_type *) NULL;
334      new->message = (char *) NULL;
335      new->edict = EDICT_NONE;
336      new->hll_file = (file_info_type *) NULL;
337      new->hll_line = 0;
338      new_frag ();
339    }
340}
341
342/* Attach all current frags to the previous line instead of the
343   current line.  This is called by the MIPS backend when it discovers
344   that it needs to add some NOP instructions; the added NOP
345   instructions should go with the instruction that has the delay, not
346   with the new instruction.  */
347
348void
349listing_prev_line ()
350{
351  list_info_type *l;
352  fragS *f;
353
354  if (head == (list_info_type *) NULL
355      || head == listing_tail)
356    return;
357
358  new_frag ();
359
360  for (l = head; l->next != listing_tail; l = l->next)
361    ;
362
363  for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next)
364    if (f->line == listing_tail)
365      f->line = l;
366
367  listing_tail->frag = frag_now;
368  new_frag ();
369}
370
371/*
372 This function returns the next source line from the file supplied,
373 truncated to size.  It appends a fake line to the end of each input
374 file to make
375*/
376
377static char *
378buffer_line (file, line, size)
379     file_info_type * file;
380     char *line;
381     unsigned int size;
382{
383  unsigned int count = 0;
384  int c;
385
386  char *p = line;
387
388  /* If we couldn't open the file, return an empty line */
389  if (file->file == (FILE *) NULL || file->at_end)
390    {
391      return "";
392    }
393
394  if (file->linenum == 0)
395    rewind (file->file);
396
397  c = fgetc (file->file);
398
399  size -= 1;			/* leave room for null */
400
401  while (c != EOF && c != '\n')
402    {
403      if (count < size)
404	*p++ = c;
405      count++;
406
407      c = fgetc (file->file);
408
409    }
410  if (c == EOF)
411    {
412      file->at_end = 1;
413      *p++ = '.';
414      *p++ = '.';
415      *p++ = '.';
416    }
417  file->linenum++;
418  *p++ = 0;
419  return line;
420}
421
422
423static const char *fn;
424
425static unsigned int eject;	/* Eject pending */
426static unsigned int page;	/* Current page number */
427static char *title;		/* current title */
428static char *subtitle;		/* current subtitle */
429static unsigned int on_page;	/* number of lines printed on current page */
430
431
432static void
433listing_page (list)
434     list_info_type *list;
435{
436  /* Grope around, see if we can see a title or subtitle edict coming up
437     soon  (we look down 10 lines of the page and see if it's there)*/
438  if ((eject || (on_page >= paper_height)) && paper_height != 0)
439    {
440      unsigned int c = 10;
441      int had_title = 0;
442      int had_subtitle = 0;
443
444      page++;
445
446      while (c != 0 && list)
447	{
448	  if (list->edict == EDICT_SBTTL && !had_subtitle)
449	    {
450	      had_subtitle = 1;
451	      subtitle = list->edict_arg;
452	    }
453	  if (list->edict == EDICT_TITLE && !had_title)
454	    {
455	      had_title = 1;
456	      title = list->edict_arg;
457	    }
458	  list = list->next;
459	  c--;
460	}
461
462
463      if (page > 1)
464	{
465	  fprintf (list_file, "\f");
466	}
467
468      fprintf (list_file, "%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
469      fprintf (list_file, "%s\n", title);
470      fprintf (list_file, "%s\n", subtitle);
471      on_page = 3;
472      eject = 0;
473    }
474}
475
476
477static unsigned int
478calc_hex (list)
479     list_info_type * list;
480{
481  list_info_type *first = list;
482  unsigned int address = (unsigned int) ~0;
483
484  fragS *frag;
485  fragS *frag_ptr;
486
487  unsigned int byte_in_frag;
488
489
490  /* Find first frag which says it belongs to this line */
491  frag = list->frag;
492  while (frag && frag->line != list)
493    frag = frag->fr_next;
494
495  frag_ptr = frag;
496
497  data_buffer_size = 0;
498
499  /* Dump all the frags which belong to this line */
500  while (frag_ptr != (fragS *) NULL && frag_ptr->line == first)
501    {
502      /* Print as many bytes from the fixed part as is sensible */
503      byte_in_frag = 0;
504      while (byte_in_frag < frag_ptr->fr_fix && data_buffer_size < sizeof (data_buffer) - 10)
505	{
506	  if (address == ~0)
507	    {
508	      address = frag_ptr->fr_address;
509	    }
510
511	  sprintf (data_buffer + data_buffer_size,
512		   "%02X",
513		   (frag_ptr->fr_literal[byte_in_frag]) & 0xff);
514	  data_buffer_size += 2;
515	  byte_in_frag++;
516	}
517      {
518	unsigned int var_rep_max = byte_in_frag;
519	unsigned int var_rep_idx = byte_in_frag;
520
521	/* Print as many bytes from the variable part as is sensible */
522	while ((byte_in_frag
523		< frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset)
524	       && data_buffer_size < sizeof (data_buffer) - 10)
525	  {
526	    if (address == ~0)
527	      {
528		address = frag_ptr->fr_address;
529	      }
530	    sprintf (data_buffer + data_buffer_size,
531		     "%02X",
532		     (frag_ptr->fr_literal[var_rep_idx]) & 0xff);
533#if 0
534	    data_buffer[data_buffer_size++] = '*';
535	    data_buffer[data_buffer_size++] = '*';
536#endif
537	    data_buffer_size += 2;
538
539	    var_rep_idx++;
540	    byte_in_frag++;
541
542	    if (var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var)
543	      var_rep_idx = var_rep_max;
544	  }
545      }
546
547      frag_ptr = frag_ptr->fr_next;
548    }
549  data_buffer[data_buffer_size++] = 0;
550  return address;
551}
552
553
554
555
556
557
558static void
559print_lines (list, lineno, string, address)
560     list_info_type *list;
561     unsigned int lineno;
562     char *string;
563     unsigned int address;
564{
565  unsigned int idx;
566  unsigned int nchars;
567  unsigned int lines;
568  unsigned int byte_in_word = 0;
569  char *src = data_buffer;
570
571  /* Print the stuff on the first line */
572  listing_page (list);
573  nchars = (LISTING_WORD_SIZE * 2 + 1) * LISTING_LHS_WIDTH;
574  /* Print the hex for the first line */
575  if (address == ~0)
576    {
577      fprintf (list_file, "% 4d     ", lineno);
578      for (idx = 0; idx < nchars; idx++)
579	fprintf (list_file, " ");
580
581      fprintf (list_file, "\t%s\n", string ? string : "");
582      on_page++;
583      listing_page (0);
584
585    }
586  else
587    {
588      if (had_errors ())
589	{
590	  fprintf (list_file, "% 4d ???? ", lineno);
591	}
592      else
593	{
594	  fprintf (list_file, "% 4d %04x ", lineno, address);
595	}
596
597      /* And the data to go along with it */
598      idx = 0;
599
600      while (*src && idx < nchars)
601	{
602	  fprintf (list_file, "%c%c", src[0], src[1]);
603	  src += 2;
604	  byte_in_word++;
605	  if (byte_in_word == LISTING_WORD_SIZE)
606	    {
607	      fprintf (list_file, " ");
608	      idx++;
609	      byte_in_word = 0;
610	    }
611	  idx += 2;
612	}
613
614      for (; idx < nchars; idx++)
615	fprintf (list_file, " ");
616
617      fprintf (list_file, "\t%s\n", string ? string : "");
618      on_page++;
619      listing_page (list);
620      if (list->message)
621	{
622	  fprintf (list_file, "****  %s\n", list->message);
623	  listing_page (list);
624	  on_page++;
625	}
626
627      for (lines = 0;
628	   lines < LISTING_LHS_CONT_LINES
629	   && *src;
630	   lines++)
631	{
632	  nchars = ((LISTING_WORD_SIZE * 2) + 1) * LISTING_LHS_WIDTH_SECOND - 1;
633	  idx = 0;
634	  /* Print any more lines of data, but more compactly */
635	  fprintf (list_file, "% 4d      ", lineno);
636
637	  while (*src && idx < nchars)
638	    {
639	      fprintf (list_file, "%c%c", src[0], src[1]);
640	      src += 2;
641	      idx += 2;
642	      byte_in_word++;
643	      if (byte_in_word == LISTING_WORD_SIZE)
644		{
645		  fprintf (list_file, " ");
646		  idx++;
647		  byte_in_word = 0;
648		}
649	    }
650
651	  fprintf (list_file, "\n");
652	  on_page++;
653	  listing_page (list);
654
655	}
656
657
658    }
659}
660
661
662static void
663list_symbol_table ()
664{
665  extern symbolS *symbol_rootP;
666  int got_some = 0;
667
668  symbolS *ptr;
669  eject = 1;
670  listing_page (0);
671
672  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
673    {
674      if (ptr->sy_frag->line)
675	{
676	  if (S_GET_NAME (ptr))
677	    {
678	      char buf[30], fmt[8];
679	      valueT val = S_GET_VALUE (ptr);
680
681	      /* @@ Note that this is dependent on the compilation options,
682		 not solely on the target characteristics.  */
683	      if (sizeof (val) == 4 && sizeof (int) == 4)
684		sprintf (buf, "%08lx", (unsigned long) val);
685	      else if (sizeof (val) <= sizeof (unsigned long))
686		{
687		  sprintf (fmt, "%%0%lulx",
688			   (unsigned long) (sizeof (val) * 2));
689		  sprintf (buf, fmt, (unsigned long) val);
690		}
691#if defined (BFD64)
692	      else if (sizeof (val) > 4)
693		sprintf_vma (buf, val);
694#endif
695	      else
696		abort ();
697
698	      if (!got_some)
699		{
700		  fprintf (list_file, "DEFINED SYMBOLS\n");
701		  on_page++;
702		  got_some = 1;
703		}
704
705	      fprintf (list_file, "%20s:%-5d  %s:%s %s\n",
706		       ptr->sy_frag->line->file->filename,
707		       ptr->sy_frag->line->line,
708		       segment_name (S_GET_SEGMENT (ptr)),
709		       buf, S_GET_NAME (ptr));
710
711	      on_page++;
712	      listing_page (0);
713	    }
714	}
715
716    }
717  if (!got_some)
718    {
719      fprintf (list_file, "NO DEFINED SYMBOLS\n");
720      on_page++;
721    }
722  fprintf (list_file, "\n");
723  on_page++;
724  listing_page (0);
725
726  got_some = 0;
727
728  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
729    {
730      if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
731	{
732	  if (ptr->sy_frag->line == 0
733#ifdef S_IS_REGISTER
734	      && !S_IS_REGISTER (ptr)
735#endif
736	      && S_GET_SEGMENT (ptr) != reg_section)
737	    {
738	      if (!got_some)
739		{
740		  got_some = 1;
741		  fprintf (list_file, "UNDEFINED SYMBOLS\n");
742		  on_page++;
743		  listing_page (0);
744		}
745	      fprintf (list_file, "%s\n", S_GET_NAME (ptr));
746	      on_page++;
747	      listing_page (0);
748	    }
749	}
750    }
751  if (!got_some)
752    {
753      fprintf (list_file, "NO UNDEFINED SYMBOLS\n");
754      on_page++;
755      listing_page (0);
756    }
757}
758
759static void
760print_source (current_file, list, buffer, width)
761     file_info_type *current_file;
762     list_info_type *list;
763     char *buffer;
764     unsigned int width;
765{
766  if (current_file->file)
767    {
768      while (current_file->linenum < list->hll_line
769	     && !current_file->at_end)
770	{
771	  char *p = buffer_line (current_file, buffer, width);
772	  fprintf (list_file, "%4d:%-13s **** %s\n", current_file->linenum,
773		   current_file->filename, p);
774	  on_page++;
775	  listing_page (list);
776	}
777    }
778}
779
780/* Sometimes the user doesn't want to be bothered by the debugging
781   records inserted by the compiler, see if the line is suspicious */
782
783static int
784debugging_pseudo (line)
785     char *line;
786{
787  while (isspace (*line))
788    line++;
789
790  if (*line != '.')
791    return 0;
792
793  line++;
794
795  if (strncmp (line, "def", 3) == 0)
796    return 1;
797  if (strncmp (line, "val", 3) == 0)
798    return 1;
799  if (strncmp (line, "scl", 3) == 0)
800    return 1;
801  if (strncmp (line, "line", 4) == 0)
802    return 1;
803  if (strncmp (line, "endef", 5) == 0)
804    return 1;
805  if (strncmp (line, "ln", 2) == 0)
806    return 1;
807  if (strncmp (line, "type", 4) == 0)
808    return 1;
809  if (strncmp (line, "size", 4) == 0)
810    return 1;
811  if (strncmp (line, "dim", 3) == 0)
812    return 1;
813  if (strncmp (line, "tag", 3) == 0)
814    return 1;
815
816  if (strncmp (line, "stabs", 5) == 0)
817    return 1;
818  if (strncmp (line, "stabn", 5) == 0)
819    return 1;
820
821  return 0;
822
823}
824
825static void
826listing_listing (name)
827     char *name;
828{
829  list_info_type *list = head;
830  file_info_type *current_hll_file = (file_info_type *) NULL;
831  char *message;
832  char *buffer;
833  char *p;
834  int show_listing = 1;
835  unsigned int width;
836
837  buffer = xmalloc (LISTING_RHS_WIDTH);
838  eject = 1;
839  list = head;
840
841  while (list != (list_info_type *) NULL && 0)
842    {
843      if (list->next)
844	list->frag = list->next->frag;
845      list = list->next;
846
847    }
848
849  list = head->next;
850
851
852  while (list)
853    {
854      width = LISTING_RHS_WIDTH > paper_width ? paper_width :
855	LISTING_RHS_WIDTH;
856
857      switch (list->edict)
858	{
859	case EDICT_LIST:
860	  show_listing++;
861	  break;
862	case EDICT_NOLIST:
863	  show_listing--;
864	  break;
865	case EDICT_NOLIST_NEXT:
866	  break;
867	case EDICT_EJECT:
868	  break;
869	case EDICT_NONE:
870	  break;
871	case EDICT_TITLE:
872	  title = list->edict_arg;
873	  break;
874	case EDICT_SBTTL:
875	  subtitle = list->edict_arg;
876	  break;
877	default:
878	  abort ();
879	}
880
881      if (show_listing > 0)
882	{
883	  /* Scan down the list and print all the stuff which can be done
884	     with this line (or lines).  */
885	  message = 0;
886
887	  if (list->hll_file)
888	    {
889	      current_hll_file = list->hll_file;
890	    }
891
892	  if (current_hll_file && list->hll_line && listing & LISTING_HLL)
893	    {
894	      print_source (current_hll_file, list, buffer, width);
895	    }
896
897	  while (list->file->file
898		 && list->file->linenum < list->line
899		 && !list->file->at_end)
900	    {
901	      unsigned int address;
902
903	      p = buffer_line (list->file, buffer, width);
904
905	      if (list->file->linenum < list->line)
906		address = ~ (unsigned int) 0;
907	      else
908		address = calc_hex (list);
909
910	      if (!((listing & LISTING_NODEBUG) && debugging_pseudo (p)))
911		print_lines (list, list->file->linenum, p, address);
912	    }
913
914	  if (list->edict == EDICT_EJECT)
915	    {
916	      eject = 1;
917	    }
918	}
919      else
920	{
921	  while (list->file->file
922		 && list->file->linenum < list->line
923		 && !list->file->at_end)
924	    p = buffer_line (list->file, buffer, width);
925	}
926
927      if (list->edict == EDICT_NOLIST_NEXT)
928	--show_listing;
929
930      list = list->next;
931    }
932  free (buffer);
933}
934
935void
936listing_print (name)
937     char *name;
938{
939  int using_stdout;
940  file_info_type *fi;
941
942  title = "";
943  subtitle = "";
944
945  if (name == NULL)
946    {
947      list_file = stdout;
948      using_stdout = 1;
949    }
950  else
951    {
952      list_file = fopen (name, "w");
953      if (list_file != NULL)
954	using_stdout = 0;
955      else
956	{
957	  as_perror ("can't open list file: %s", name);
958	  list_file = stdout;
959	  using_stdout = 1;
960	}
961    }
962
963  if (listing & LISTING_NOFORM)
964    {
965      paper_height = 0;
966    }
967
968  if (listing & LISTING_LISTING)
969    {
970      listing_listing (name);
971    }
972
973  if (listing & LISTING_SYMBOLS)
974    {
975      list_symbol_table ();
976    }
977
978  if (! using_stdout)
979    {
980      if (fclose (list_file) == EOF)
981	as_perror ("error closing list file: %s", name);
982    }
983
984  for (fi = file_info_head; fi != NULL; fi = fi->next)
985    {
986      if (fi->file != NULL)
987	{
988	  fclose (fi->file);
989	  fi->file = NULL;
990	}
991    }
992}
993
994
995void
996listing_file (name)
997     const char *name;
998{
999  fn = name;
1000}
1001
1002void
1003listing_eject (ignore)
1004     int ignore;
1005{
1006  if (listing)
1007    listing_tail->edict = EDICT_EJECT;
1008}
1009
1010void
1011listing_flags (ignore)
1012     int ignore;
1013{
1014  while ((*input_line_pointer++) && (*input_line_pointer != '\n'))
1015    input_line_pointer++;
1016
1017}
1018
1019/* Turn listing on or off.  An argument of 0 means to turn off
1020   listing.  An argument of 1 means to turn on listing.  An argument
1021   of 2 means to turn off listing, but as of the next line; that is,
1022   the current line should be listed, but the next line should not.  */
1023
1024void
1025listing_list (on)
1026     int on;
1027{
1028  if (listing)
1029    {
1030      switch (on)
1031	{
1032	case 0:
1033	  if (listing_tail->edict == EDICT_LIST)
1034	    listing_tail->edict = EDICT_NONE;
1035	  else
1036	    listing_tail->edict = EDICT_NOLIST;
1037	  break;
1038	case 1:
1039	  if (listing_tail->edict == EDICT_NOLIST
1040	      || listing_tail->edict == EDICT_NOLIST_NEXT)
1041	    listing_tail->edict = EDICT_NONE;
1042	  else
1043	    listing_tail->edict = EDICT_LIST;
1044	  break;
1045	case 2:
1046	  listing_tail->edict = EDICT_NOLIST_NEXT;
1047	  break;
1048	default:
1049	  abort ();
1050	}
1051    }
1052}
1053
1054
1055void
1056listing_psize (width_only)
1057     int width_only;
1058{
1059  if (! width_only)
1060    {
1061      paper_height = get_absolute_expression ();
1062
1063      if (paper_height < 0 || paper_height > 1000)
1064	{
1065	  paper_height = 0;
1066	  as_warn ("strange paper height, set to no form");
1067	}
1068
1069      if (*input_line_pointer != ',')
1070	{
1071	  demand_empty_rest_of_line ();
1072	  return;
1073	}
1074
1075      ++input_line_pointer;
1076    }
1077
1078  paper_width = get_absolute_expression ();
1079
1080  demand_empty_rest_of_line ();
1081}
1082
1083void
1084listing_nopage (ignore)
1085     int ignore;
1086{
1087  paper_height = 0;
1088}
1089
1090void
1091listing_title (depth)
1092     int depth;
1093{
1094  int quoted;
1095  char *start;
1096  char *ttl;
1097  unsigned int length;
1098
1099  SKIP_WHITESPACE ();
1100  if (*input_line_pointer != '\"')
1101    quoted = 0;
1102  else
1103    {
1104      quoted = 1;
1105      ++input_line_pointer;
1106    }
1107
1108  start = input_line_pointer;
1109
1110  while (*input_line_pointer)
1111    {
1112      if (quoted
1113	  ? *input_line_pointer == '\"'
1114	  : is_end_of_line[(unsigned char) *input_line_pointer])
1115	{
1116	  if (listing)
1117	    {
1118	      length = input_line_pointer - start;
1119	      ttl = xmalloc (length + 1);
1120	      memcpy (ttl, start, length);
1121	      ttl[length] = 0;
1122	      listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
1123	      listing_tail->edict_arg = ttl;
1124	    }
1125	  if (quoted)
1126	    input_line_pointer++;
1127	  demand_empty_rest_of_line ();
1128	  return;
1129	}
1130      else if (*input_line_pointer == '\n')
1131	{
1132	  as_bad ("New line in title");
1133	  demand_empty_rest_of_line ();
1134	  return;
1135	}
1136      else
1137	{
1138	  input_line_pointer++;
1139	}
1140    }
1141}
1142
1143
1144
1145void
1146listing_source_line (line)
1147     unsigned int line;
1148{
1149  if (listing)
1150    {
1151      new_frag ();
1152      listing_tail->hll_line = line;
1153      new_frag ();
1154    }
1155}
1156
1157void
1158listing_source_file (file)
1159     const char *file;
1160{
1161  if (listing)
1162    listing_tail->hll_file = file_info (file);
1163}
1164
1165
1166
1167#else
1168
1169
1170/* Dummy functions for when compiled without listing enabled */
1171
1172void
1173listing_flags (ignore)
1174     int ignore;
1175{
1176  s_ignore (0);
1177}
1178
1179void
1180listing_list (on)
1181     int on;
1182{
1183  s_ignore (0);
1184}
1185
1186void
1187listing_eject (ignore)
1188     int ignore;
1189{
1190  s_ignore (0);
1191}
1192
1193void
1194listing_psize (ignore)
1195     int ignore;
1196{
1197  s_ignore (0);
1198}
1199
1200void
1201listing_nopage (ignore)
1202     int ignore;
1203{
1204  s_ignore (0);
1205}
1206
1207void
1208listing_title (depth)
1209     int depth;
1210{
1211  s_ignore (0);
1212}
1213
1214void
1215listing_file (name)
1216     const char *name;
1217{
1218
1219}
1220
1221void
1222listing_newline (name)
1223     char *name;
1224{
1225
1226}
1227
1228void
1229listing_source_line (n)
1230     unsigned int n;
1231{
1232
1233}
1234void
1235listing_source_file (n)
1236     const char *n;
1237{
1238
1239}
1240
1241#endif
1242