listing.c revision 1.3
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		sprintf_vma (buf, val);
692#endif
693	      else
694		abort ();
695
696	      if (!got_some)
697		{
698		  fprintf (list_file, "DEFINED SYMBOLS\n");
699		  on_page++;
700		  got_some = 1;
701		}
702
703	      fprintf (list_file, "%20s:%-5d  %s:%s %s\n",
704		       ptr->sy_frag->line->file->filename,
705		       ptr->sy_frag->line->line,
706		       segment_name (S_GET_SEGMENT (ptr)),
707		       buf, S_GET_NAME (ptr));
708
709	      on_page++;
710	      listing_page (0);
711	    }
712	}
713
714    }
715  if (!got_some)
716    {
717      fprintf (list_file, "NO DEFINED SYMBOLS\n");
718      on_page++;
719    }
720  fprintf (list_file, "\n");
721  on_page++;
722  listing_page (0);
723
724  got_some = 0;
725
726  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
727    {
728      if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
729	{
730	  if (ptr->sy_frag->line == 0
731#ifdef S_IS_REGISTER
732	      && !S_IS_REGISTER (ptr)
733#endif
734	      && S_GET_SEGMENT (ptr) != reg_section)
735	    {
736	      if (!got_some)
737		{
738		  got_some = 1;
739		  fprintf (list_file, "UNDEFINED SYMBOLS\n");
740		  on_page++;
741		  listing_page (0);
742		}
743	      fprintf (list_file, "%s\n", S_GET_NAME (ptr));
744	      on_page++;
745	      listing_page (0);
746	    }
747	}
748    }
749  if (!got_some)
750    {
751      fprintf (list_file, "NO UNDEFINED SYMBOLS\n");
752      on_page++;
753      listing_page (0);
754    }
755}
756
757static void
758print_source (current_file, list, buffer, width)
759     file_info_type *current_file;
760     list_info_type *list;
761     char *buffer;
762     unsigned int width;
763{
764  if (current_file->file)
765    {
766      while (current_file->linenum < list->hll_line
767	     && !current_file->at_end)
768	{
769	  char *p = buffer_line (current_file, buffer, width);
770	  fprintf (list_file, "%4d:%-13s **** %s\n", current_file->linenum,
771		   current_file->filename, p);
772	  on_page++;
773	  listing_page (list);
774	}
775    }
776}
777
778/* Sometimes the user doesn't want to be bothered by the debugging
779   records inserted by the compiler, see if the line is suspicious */
780
781static int
782debugging_pseudo (line)
783     char *line;
784{
785  while (isspace (*line))
786    line++;
787
788  if (*line != '.')
789    return 0;
790
791  line++;
792
793  if (strncmp (line, "def", 3) == 0)
794    return 1;
795  if (strncmp (line, "val", 3) == 0)
796    return 1;
797  if (strncmp (line, "scl", 3) == 0)
798    return 1;
799  if (strncmp (line, "line", 4) == 0)
800    return 1;
801  if (strncmp (line, "endef", 5) == 0)
802    return 1;
803  if (strncmp (line, "ln", 2) == 0)
804    return 1;
805  if (strncmp (line, "type", 4) == 0)
806    return 1;
807  if (strncmp (line, "size", 4) == 0)
808    return 1;
809  if (strncmp (line, "dim", 3) == 0)
810    return 1;
811  if (strncmp (line, "tag", 3) == 0)
812    return 1;
813
814  if (strncmp (line, "stabs", 5) == 0)
815    return 1;
816  if (strncmp (line, "stabn", 5) == 0)
817    return 1;
818
819  return 0;
820
821}
822
823static void
824listing_listing (name)
825     char *name;
826{
827  list_info_type *list = head;
828  file_info_type *current_hll_file = (file_info_type *) NULL;
829  char *message;
830  char *buffer;
831  char *p;
832  int show_listing = 1;
833  unsigned int width;
834
835  buffer = xmalloc (LISTING_RHS_WIDTH);
836  eject = 1;
837  list = head;
838
839  while (list != (list_info_type *) NULL && 0)
840    {
841      if (list->next)
842	list->frag = list->next->frag;
843      list = list->next;
844
845    }
846
847  list = head->next;
848
849
850  while (list)
851    {
852      width = LISTING_RHS_WIDTH > paper_width ? paper_width :
853	LISTING_RHS_WIDTH;
854
855      switch (list->edict)
856	{
857	case EDICT_LIST:
858	  show_listing++;
859	  break;
860	case EDICT_NOLIST:
861	  show_listing--;
862	  break;
863	case EDICT_EJECT:
864	  break;
865	case EDICT_NONE:
866	  break;
867	case EDICT_TITLE:
868	  title = list->edict_arg;
869	  break;
870	case EDICT_SBTTL:
871	  subtitle = list->edict_arg;
872	  break;
873	default:
874	  abort ();
875	}
876
877      if (show_listing > 0)
878	{
879	  /* Scan down the list and print all the stuff which can be done
880	     with this line (or lines).  */
881	  message = 0;
882
883	  if (list->hll_file)
884	    {
885	      current_hll_file = list->hll_file;
886	    }
887
888	  if (current_hll_file && list->hll_line && listing & LISTING_HLL)
889	    {
890	      print_source (current_hll_file, list, buffer, width);
891	    }
892
893	  while (list->file->file
894		 && list->file->linenum < list->line
895		 && !list->file->at_end)
896	    {
897	      p = buffer_line (list->file, buffer, width);
898
899	      if (!((listing & LISTING_NODEBUG) && debugging_pseudo (p)))
900		{
901		  print_lines (list, p, calc_hex (list));
902		}
903	    }
904
905	  if (list->edict == EDICT_EJECT)
906	    {
907	      eject = 1;
908	    }
909	}
910      else
911	{
912	  while (list->file->file
913		 && list->file->linenum < list->line
914		 && !list->file->at_end)
915	    p = buffer_line (list->file, buffer, width);
916	}
917
918      list = list->next;
919    }
920  free (buffer);
921}
922
923void
924listing_print (name)
925     char *name;
926{
927  int using_stdout;
928  file_info_type *fi;
929
930  title = "";
931  subtitle = "";
932
933  if (name == NULL)
934    {
935      list_file = stdout;
936      using_stdout = 1;
937    }
938  else
939    {
940      list_file = fopen (name, "w");
941      if (list_file != NULL)
942	using_stdout = 0;
943      else
944	{
945	  as_perror ("can't open list file: %s", name);
946	  list_file = stdout;
947	  using_stdout = 1;
948	}
949    }
950
951  if (listing & LISTING_NOFORM)
952    {
953      paper_height = 0;
954    }
955
956  if (listing & LISTING_LISTING)
957    {
958      listing_listing (name);
959    }
960
961  if (listing & LISTING_SYMBOLS)
962    {
963      list_symbol_table ();
964    }
965
966  if (! using_stdout)
967    {
968      if (fclose (list_file) == EOF)
969	as_perror ("error closing list file: %s", name);
970    }
971
972  for (fi = file_info_head; fi != NULL; fi = fi->next)
973    {
974      if (fi->file != NULL)
975	{
976	  fclose (fi->file);
977	  fi->file = NULL;
978	}
979    }
980}
981
982
983void
984listing_file (name)
985     const char *name;
986{
987  fn = name;
988}
989
990void
991listing_eject (ignore)
992     int ignore;
993{
994  if (listing)
995    listing_tail->edict = EDICT_EJECT;
996}
997
998void
999listing_flags (ignore)
1000     int ignore;
1001{
1002  while ((*input_line_pointer++) && (*input_line_pointer != '\n'))
1003    input_line_pointer++;
1004
1005}
1006
1007void
1008listing_list (on)
1009     int on;
1010{
1011  if (listing)
1012    listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST;
1013}
1014
1015
1016void
1017listing_psize (width_only)
1018     int width_only;
1019{
1020  if (! width_only)
1021    {
1022      paper_height = get_absolute_expression ();
1023
1024      if (paper_height < 0 || paper_height > 1000)
1025	{
1026	  paper_height = 0;
1027	  as_warn ("strange paper height, set to no form");
1028	}
1029
1030      if (*input_line_pointer != ',')
1031	{
1032	  demand_empty_rest_of_line ();
1033	  return;
1034	}
1035
1036      ++input_line_pointer;
1037    }
1038
1039  paper_width = get_absolute_expression ();
1040
1041  demand_empty_rest_of_line ();
1042}
1043
1044void
1045listing_nopage (ignore)
1046     int ignore;
1047{
1048  paper_height = 0;
1049}
1050
1051void
1052listing_title (depth)
1053     int depth;
1054{
1055  int quoted;
1056  char *start;
1057  char *ttl;
1058  unsigned int length;
1059
1060  SKIP_WHITESPACE ();
1061  if (*input_line_pointer != '\"')
1062    quoted = 0;
1063  else
1064    {
1065      quoted = 1;
1066      ++input_line_pointer;
1067    }
1068
1069  start = input_line_pointer;
1070
1071  while (*input_line_pointer)
1072    {
1073      if (quoted
1074	  ? *input_line_pointer == '\"'
1075	  : is_end_of_line[(unsigned char) *input_line_pointer])
1076	{
1077	  if (listing)
1078	    {
1079	      length = input_line_pointer - start;
1080	      ttl = xmalloc (length + 1);
1081	      memcpy (ttl, start, length);
1082	      ttl[length] = 0;
1083	      listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
1084	      listing_tail->edict_arg = ttl;
1085	    }
1086	  if (quoted)
1087	    input_line_pointer++;
1088	  demand_empty_rest_of_line ();
1089	  return;
1090	}
1091      else if (*input_line_pointer == '\n')
1092	{
1093	  as_bad ("New line in title");
1094	  demand_empty_rest_of_line ();
1095	  return;
1096	}
1097      else
1098	{
1099	  input_line_pointer++;
1100	}
1101    }
1102}
1103
1104
1105
1106void
1107listing_source_line (line)
1108     unsigned int line;
1109{
1110  if (listing)
1111    {
1112      new_frag ();
1113      listing_tail->hll_line = line;
1114      new_frag ();
1115    }
1116}
1117
1118void
1119listing_source_file (file)
1120     const char *file;
1121{
1122  if (listing)
1123    listing_tail->hll_file = file_info (file);
1124}
1125
1126
1127
1128#else
1129
1130
1131/* Dummy functions for when compiled without listing enabled */
1132
1133void
1134listing_flags (ignore)
1135     int ignore;
1136{
1137  s_ignore (0);
1138}
1139
1140void
1141listing_list (on)
1142     int on;
1143{
1144  s_ignore (0);
1145}
1146
1147void
1148listing_eject (ignore)
1149     int ignore;
1150{
1151  s_ignore (0);
1152}
1153
1154void
1155listing_psize (ignore)
1156     int ignore;
1157{
1158  s_ignore (0);
1159}
1160
1161void
1162listing_nopage (ignore)
1163     int ignore;
1164{
1165  s_ignore (0);
1166}
1167
1168void
1169listing_title (depth)
1170     int depth;
1171{
1172  s_ignore (0);
1173}
1174
1175void
1176listing_file (name)
1177     const char *name;
1178{
1179
1180}
1181
1182void
1183listing_newline (name)
1184     char *name;
1185{
1186
1187}
1188
1189void
1190listing_source_line (n)
1191     unsigned int n;
1192{
1193
1194}
1195void
1196listing_source_file (n)
1197     const char *n;
1198{
1199
1200}
1201
1202#endif
1203