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