listing.c revision 1.1
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 (now_seg == absolute_section)
306    return;
307
308  as_where (&file, &line);
309  if (line != last_line || (last_file && file && strcmp(file, last_file)))
310    {
311      last_line = line;
312      last_file = file;
313      new_frag ();
314
315      new = (list_info_type *) xmalloc (sizeof (list_info_type));
316      new->frag = frag_now;
317      new->line = line;
318      new->file = file_info (file);
319
320      if (listing_tail)
321	{
322	  listing_tail->next = new;
323	}
324      else
325	{
326	  head = new;
327	}
328      listing_tail = new;
329      new->next = (list_info_type *) NULL;
330      new->message = (char *) NULL;
331      new->edict = EDICT_NONE;
332      new->hll_file = (file_info_type *) NULL;
333      new->hll_line = 0;
334      new_frag ();
335    }
336}
337
338/* Attach all current frags to the previous line instead of the
339   current line.  This is called by the MIPS backend when it discovers
340   that it needs to add some NOP instructions; the added NOP
341   instructions should go with the instruction that has the delay, not
342   with the new instruction.  */
343
344void
345listing_prev_line ()
346{
347  list_info_type *l;
348  fragS *f;
349
350  if (head == (list_info_type *) NULL
351      || head == listing_tail)
352    return;
353
354  new_frag ();
355
356  for (l = head; l->next != listing_tail; l = l->next)
357    ;
358
359  for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next)
360    if (f->line == listing_tail)
361      f->line = l;
362
363  listing_tail->frag = frag_now;
364  new_frag ();
365}
366
367/*
368 This function returns the next source line from the file supplied,
369 truncated to size.  It appends a fake line to the end of each input
370 file to make
371*/
372
373static char *
374buffer_line (file, line, size)
375     file_info_type * file;
376     char *line;
377     unsigned int size;
378{
379  unsigned int count = 0;
380  int c;
381
382  char *p = line;
383
384  /* If we couldn't open the file, return an empty line */
385  if (file->file == (FILE *) NULL || file->at_end)
386    {
387      return "";
388    }
389
390  if (file->linenum == 0)
391    rewind (file->file);
392
393  c = fgetc (file->file);
394
395  size -= 1;			/* leave room for null */
396
397  while (c != EOF && c != '\n')
398    {
399      if (count < size)
400	*p++ = c;
401      count++;
402
403      c = fgetc (file->file);
404
405    }
406  if (c == EOF)
407    {
408      file->at_end = 1;
409      *p++ = '.';
410      *p++ = '.';
411      *p++ = '.';
412    }
413  file->linenum++;
414  *p++ = 0;
415  return line;
416}
417
418
419static const char *fn;
420
421static unsigned int eject;	/* Eject pending */
422static unsigned int page;	/* Current page number */
423static char *title;		/* current title */
424static char *subtitle;		/* current subtitle */
425static unsigned int on_page;	/* number of lines printed on current page */
426
427
428static void
429listing_page (list)
430     list_info_type *list;
431{
432  /* Grope around, see if we can see a title or subtitle edict coming up
433     soon  (we look down 10 lines of the page and see if it's there)*/
434  if ((eject || (on_page >= paper_height)) && paper_height != 0)
435    {
436      unsigned int c = 10;
437      int had_title = 0;
438      int had_subtitle = 0;
439
440      page++;
441
442      while (c != 0 && list)
443	{
444	  if (list->edict == EDICT_SBTTL && !had_subtitle)
445	    {
446	      had_subtitle = 1;
447	      subtitle = list->edict_arg;
448	    }
449	  if (list->edict == EDICT_TITLE && !had_title)
450	    {
451	      had_title = 1;
452	      title = list->edict_arg;
453	    }
454	  list = list->next;
455	  c--;
456	}
457
458
459      if (page > 1)
460	{
461	  fprintf (list_file, "\f");
462	}
463
464      fprintf (list_file, "%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
465      fprintf (list_file, "%s\n", title);
466      fprintf (list_file, "%s\n", subtitle);
467      on_page = 3;
468      eject = 0;
469    }
470}
471
472
473static unsigned int
474calc_hex (list)
475     list_info_type * list;
476{
477  list_info_type *first = list;
478  unsigned int address = (unsigned int) ~0;
479
480  fragS *frag;
481  fragS *frag_ptr;
482
483  unsigned int byte_in_frag;
484
485
486  /* Find first frag which says it belongs to this line */
487  frag = list->frag;
488  while (frag && frag->line != list)
489    frag = frag->fr_next;
490
491  frag_ptr = frag;
492
493  data_buffer_size = 0;
494
495  /* Dump all the frags which belong to this line */
496  while (frag_ptr != (fragS *) NULL && frag_ptr->line == first)
497    {
498      /* Print as many bytes from the fixed part as is sensible */
499      byte_in_frag = 0;
500      while (byte_in_frag < frag_ptr->fr_fix && data_buffer_size < sizeof (data_buffer) - 10)
501	{
502	  if (address == ~0)
503	    {
504	      address = frag_ptr->fr_address;
505	    }
506
507	  sprintf (data_buffer + data_buffer_size,
508		   "%02X",
509		   (frag_ptr->fr_literal[byte_in_frag]) & 0xff);
510	  data_buffer_size += 2;
511	  byte_in_frag++;
512	}
513      {
514	unsigned int var_rep_max = byte_in_frag;
515	unsigned int var_rep_idx = byte_in_frag;
516
517	/* Print as many bytes from the variable part as is sensible */
518	while (byte_in_frag < frag_ptr->fr_var * frag_ptr->fr_offset
519	       && data_buffer_size < sizeof (data_buffer) - 10)
520	  {
521	    if (address == ~0)
522	      {
523		address = frag_ptr->fr_address;
524	      }
525	    sprintf (data_buffer + data_buffer_size,
526		     "%02X",
527		     (frag_ptr->fr_literal[var_rep_idx]) & 0xff);
528#if 0
529	    data_buffer[data_buffer_size++] = '*';
530	    data_buffer[data_buffer_size++] = '*';
531#endif
532	    data_buffer_size += 2;
533
534	    var_rep_idx++;
535	    byte_in_frag++;
536
537	    if (var_rep_idx >= frag_ptr->fr_var)
538	      var_rep_idx = var_rep_max;
539	  }
540      }
541
542      frag_ptr = frag_ptr->fr_next;
543    }
544  data_buffer[data_buffer_size++] = 0;
545  return address;
546}
547
548
549
550
551
552
553static void
554print_lines (list, string, address)
555     list_info_type *list;
556     char *string;
557     unsigned int address;
558{
559  unsigned int idx;
560  unsigned int nchars;
561  unsigned int lines;
562  unsigned int byte_in_word = 0;
563  char *src = data_buffer;
564
565  /* Print the stuff on the first line */
566  listing_page (list);
567  nchars = (LISTING_WORD_SIZE * 2 + 1) * LISTING_LHS_WIDTH;
568  /* Print the hex for the first line */
569  if (address == ~0)
570    {
571      fprintf (list_file, "% 4d     ", list->line);
572      for (idx = 0; idx < nchars; idx++)
573	fprintf (list_file, " ");
574
575      fprintf (list_file, "\t%s\n", string ? string : "");
576      on_page++;
577      listing_page (0);
578
579    }
580  else
581    {
582      if (had_errors ())
583	{
584	  fprintf (list_file, "% 4d ???? ", list->line);
585	}
586      else
587	{
588	  fprintf (list_file, "% 4d %04x ", list->line, address);
589	}
590
591      /* And the data to go along with it */
592      idx = 0;
593
594      while (*src && idx < nchars)
595	{
596	  fprintf (list_file, "%c%c", src[0], src[1]);
597	  src += 2;
598	  byte_in_word++;
599	  if (byte_in_word == LISTING_WORD_SIZE)
600	    {
601	      fprintf (list_file, " ");
602	      idx++;
603	      byte_in_word = 0;
604	    }
605	  idx += 2;
606	}
607
608      for (; idx < nchars; idx++)
609	fprintf (list_file, " ");
610
611      fprintf (list_file, "\t%s\n", string ? string : "");
612      on_page++;
613      listing_page (list);
614      if (list->message)
615	{
616	  fprintf (list_file, "****  %s\n", list->message);
617	  listing_page (list);
618	  on_page++;
619	}
620
621      for (lines = 0;
622	   lines < LISTING_LHS_CONT_LINES
623	   && *src;
624	   lines++)
625	{
626	  nchars = ((LISTING_WORD_SIZE * 2) + 1) * LISTING_LHS_WIDTH_SECOND - 1;
627	  idx = 0;
628	  /* Print any more lines of data, but more compactly */
629	  fprintf (list_file, "% 4d      ", list->line);
630
631	  while (*src && idx < nchars)
632	    {
633	      fprintf (list_file, "%c%c", src[0], src[1]);
634	      src += 2;
635	      idx += 2;
636	      byte_in_word++;
637	      if (byte_in_word == LISTING_WORD_SIZE)
638		{
639		  fprintf (list_file, " ");
640		  idx++;
641		  byte_in_word = 0;
642		}
643	    }
644
645	  fprintf (list_file, "\n");
646	  on_page++;
647	  listing_page (list);
648
649	}
650
651
652    }
653}
654
655
656static void
657list_symbol_table ()
658{
659  extern symbolS *symbol_rootP;
660  int got_some = 0;
661
662  symbolS *ptr;
663  eject = 1;
664  listing_page (0);
665
666  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
667    {
668      if (ptr->sy_frag->line)
669	{
670	  if (S_GET_NAME (ptr))
671	    {
672	      char buf[30], fmt[8];
673	      valueT val = S_GET_VALUE (ptr);
674
675	      /* @@ Note that this is dependent on the compilation options,
676		 not solely on the target characteristics.  */
677	      if (sizeof (val) == 4 && sizeof (int) == 4)
678		sprintf (buf, "%08lx", (unsigned long) val);
679	      else if (sizeof (val) <= sizeof (unsigned long))
680		{
681		  sprintf (fmt, "%%0%lulx",
682			   (unsigned long) (sizeof (val) * 2));
683		  sprintf (buf, fmt, (unsigned long) val);
684		}
685#if defined (BFD64)
686	      else if (sizeof (val) > 4)
687		{
688		  char buf1[30];
689		  sprintf_vma (buf1, val);
690		  strcpy (buf, "00000000");
691		  strcpy (buf + 8 - strlen (buf1), buf1);
692		}
693#endif
694	      else
695		abort ();
696
697	      if (!got_some)
698		{
699		  fprintf (list_file, "DEFINED SYMBOLS\n");
700		  on_page++;
701		  got_some = 1;
702		}
703
704	      fprintf (list_file, "%20s:%-5d  %s:%s %s\n",
705		       ptr->sy_frag->line->file->filename,
706		       ptr->sy_frag->line->line,
707		       segment_name (S_GET_SEGMENT (ptr)),
708		       buf, S_GET_NAME (ptr));
709
710	      on_page++;
711	      listing_page (0);
712	    }
713	}
714
715    }
716  if (!got_some)
717    {
718      fprintf (list_file, "NO DEFINED SYMBOLS\n");
719      on_page++;
720    }
721  fprintf (list_file, "\n");
722  on_page++;
723  listing_page (0);
724
725  got_some = 0;
726
727  for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
728    {
729      if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
730	{
731	  if (ptr->sy_frag->line == 0
732#ifdef S_IS_REGISTER
733	      && !S_IS_REGISTER (ptr)
734#endif
735	      && S_GET_SEGMENT (ptr) != reg_section)
736	    {
737	      if (!got_some)
738		{
739		  got_some = 1;
740		  fprintf (list_file, "UNDEFINED SYMBOLS\n");
741		  on_page++;
742		  listing_page (0);
743		}
744	      fprintf (list_file, "%s\n", S_GET_NAME (ptr));
745	      on_page++;
746	      listing_page (0);
747	    }
748	}
749    }
750  if (!got_some)
751    {
752      fprintf (list_file, "NO UNDEFINED SYMBOLS\n");
753      on_page++;
754      listing_page (0);
755    }
756}
757
758static void
759print_source (current_file, list, buffer, width)
760     file_info_type *current_file;
761     list_info_type *list;
762     char *buffer;
763     unsigned int width;
764{
765  if (current_file->file)
766    {
767      while (current_file->linenum < list->hll_line
768	     && !current_file->at_end)
769	{
770	  char *p = buffer_line (current_file, buffer, width);
771	  fprintf (list_file, "%4d:%-13s **** %s\n", current_file->linenum,
772		   current_file->filename, p);
773	  on_page++;
774	  listing_page (list);
775	}
776    }
777}
778
779/* Sometimes the user doesn't want to be bothered by the debugging
780   records inserted by the compiler, see if the line is suspicious */
781
782static int
783debugging_pseudo (line)
784     char *line;
785{
786  while (isspace (*line))
787    line++;
788
789  if (*line != '.')
790    return 0;
791
792  line++;
793
794  if (strncmp (line, "def", 3) == 0)
795    return 1;
796  if (strncmp (line, "val", 3) == 0)
797    return 1;
798  if (strncmp (line, "scl", 3) == 0)
799    return 1;
800  if (strncmp (line, "line", 4) == 0)
801    return 1;
802  if (strncmp (line, "endef", 5) == 0)
803    return 1;
804  if (strncmp (line, "ln", 2) == 0)
805    return 1;
806  if (strncmp (line, "type", 4) == 0)
807    return 1;
808  if (strncmp (line, "size", 4) == 0)
809    return 1;
810  if (strncmp (line, "dim", 3) == 0)
811    return 1;
812  if (strncmp (line, "tag", 3) == 0)
813    return 1;
814
815  if (strncmp (line, "stabs", 5) == 0)
816    return 1;
817  if (strncmp (line, "stabn", 5) == 0)
818    return 1;
819
820  return 0;
821
822}
823
824static void
825listing_listing (name)
826     char *name;
827{
828  list_info_type *list = head;
829  file_info_type *current_hll_file = (file_info_type *) NULL;
830  char *message;
831  char *buffer;
832  char *p;
833  int show_listing = 1;
834  unsigned int width;
835
836  buffer = xmalloc (LISTING_RHS_WIDTH);
837  eject = 1;
838  list = head;
839
840  while (list != (list_info_type *) NULL && 0)
841    {
842      if (list->next)
843	list->frag = list->next->frag;
844      list = list->next;
845
846    }
847
848  list = head->next;
849
850
851  while (list)
852    {
853      width = LISTING_RHS_WIDTH > paper_width ? paper_width :
854	LISTING_RHS_WIDTH;
855
856      switch (list->edict)
857	{
858	case EDICT_LIST:
859	  show_listing++;
860	  break;
861	case EDICT_NOLIST:
862	  show_listing--;
863	  break;
864	case EDICT_EJECT:
865	  break;
866	case EDICT_NONE:
867	  break;
868	case EDICT_TITLE:
869	  title = list->edict_arg;
870	  break;
871	case EDICT_SBTTL:
872	  subtitle = list->edict_arg;
873	  break;
874	default:
875	  abort ();
876	}
877
878      if (show_listing > 0)
879	{
880	  /* Scan down the list and print all the stuff which can be done
881	     with this line (or lines).  */
882	  message = 0;
883
884	  if (list->hll_file)
885	    {
886	      current_hll_file = list->hll_file;
887	    }
888
889	  if (current_hll_file && list->hll_line && listing & LISTING_HLL)
890	    {
891	      print_source (current_hll_file, list, buffer, width);
892	    }
893
894	  while (list->file->file
895		 && list->file->linenum < list->line
896		 && !list->file->at_end)
897	    {
898	      p = buffer_line (list->file, buffer, width);
899
900	      if (!((listing & LISTING_NODEBUG) && debugging_pseudo (p)))
901		{
902		  print_lines (list, p, calc_hex (list));
903		}
904	    }
905
906	  if (list->edict == EDICT_EJECT)
907	    {
908	      eject = 1;
909	    }
910	}
911      else
912	{
913	  while (list->file->file
914		 && list->file->linenum < list->line
915		 && !list->file->at_end)
916	    p = buffer_line (list->file, buffer, width);
917	}
918
919      list = list->next;
920    }
921  free (buffer);
922}
923
924void
925listing_print (name)
926     char *name;
927{
928  title = "";
929  subtitle = "";
930
931  if (name == NULL)
932    list_file = stdout;
933  else
934    {
935      list_file = fopen (name, "w");
936      if (list_file == NULL)
937	{
938	  as_perror ("can't open list file: %s", name);
939	  list_file = stdout;
940	}
941    }
942
943  if (listing & LISTING_NOFORM)
944    {
945      paper_height = 0;
946    }
947
948  if (listing & LISTING_LISTING)
949    {
950      listing_listing (name);
951
952    }
953  if (listing & LISTING_SYMBOLS)
954    {
955      list_symbol_table ();
956    }
957}
958
959
960void
961listing_file (name)
962     const char *name;
963{
964  fn = name;
965}
966
967void
968listing_eject (ignore)
969     int ignore;
970{
971  listing_tail->edict = EDICT_EJECT;
972}
973
974void
975listing_flags (ignore)
976     int ignore;
977{
978  while ((*input_line_pointer++) && (*input_line_pointer != '\n'))
979    input_line_pointer++;
980
981}
982
983void
984listing_list (on)
985     int on;
986{
987  listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST;
988}
989
990
991void
992listing_psize (width_only)
993     int width_only;
994{
995  if (! width_only)
996    {
997      paper_height = get_absolute_expression ();
998
999      if (paper_height < 0 || paper_height > 1000)
1000	{
1001	  paper_height = 0;
1002	  as_warn ("strange paper height, set to no form");
1003	}
1004
1005      if (*input_line_pointer != ',')
1006	{
1007	  demand_empty_rest_of_line ();
1008	  return;
1009	}
1010
1011      ++input_line_pointer;
1012    }
1013
1014  paper_width = get_absolute_expression ();
1015
1016  demand_empty_rest_of_line ();
1017}
1018
1019void
1020listing_nopage (ignore)
1021     int ignore;
1022{
1023  paper_height = 0;
1024}
1025
1026void
1027listing_title (depth)
1028     int depth;
1029{
1030  int quoted;
1031  char *start;
1032  char *ttl;
1033  unsigned int length;
1034
1035  SKIP_WHITESPACE ();
1036  if (*input_line_pointer != '\"')
1037    quoted = 0;
1038  else
1039    {
1040      quoted = 1;
1041      ++input_line_pointer;
1042    }
1043
1044  start = input_line_pointer;
1045
1046  while (*input_line_pointer)
1047    {
1048      if (quoted
1049	  ? *input_line_pointer == '\"'
1050	  : is_end_of_line[(unsigned char) *input_line_pointer])
1051	{
1052	  length = input_line_pointer - start;
1053	  ttl = xmalloc (length + 1);
1054	  memcpy (ttl, start, length);
1055	  ttl[length] = 0;
1056	  listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
1057	  listing_tail->edict_arg = ttl;
1058	  if (quoted)
1059	    input_line_pointer++;
1060	  demand_empty_rest_of_line ();
1061	  return;
1062	}
1063      else if (*input_line_pointer == '\n')
1064	{
1065	  as_bad ("New line in title");
1066	  demand_empty_rest_of_line ();
1067	  return;
1068	}
1069      else
1070	{
1071	  input_line_pointer++;
1072	}
1073    }
1074}
1075
1076
1077
1078void
1079listing_source_line (line)
1080     unsigned int line;
1081{
1082  new_frag ();
1083  listing_tail->hll_line = line;
1084  new_frag ();
1085
1086}
1087
1088void
1089listing_source_file (file)
1090     const char *file;
1091{
1092  if (listing_tail)
1093    listing_tail->hll_file = file_info (file);
1094}
1095
1096
1097
1098#else
1099
1100
1101/* Dummy functions for when compiled without listing enabled */
1102
1103void
1104listing_flags (ignore)
1105     int ignore;
1106{
1107  s_ignore (0);
1108}
1109
1110void
1111listing_list (on)
1112     int on;
1113{
1114  s_ignore (0);
1115}
1116
1117void
1118listing_eject (ignore)
1119     int ignore;
1120{
1121  s_ignore (0);
1122}
1123
1124void
1125listing_psize (ignore)
1126     int ignore;
1127{
1128  s_ignore (0);
1129}
1130
1131void
1132listing_nopage (ignore)
1133     int ignore;
1134{
1135  s_ignore (0);
1136}
1137
1138void
1139listing_title (depth)
1140     int depth;
1141{
1142  s_ignore (0);
1143}
1144
1145void
1146listing_file (name)
1147     const char *name;
1148{
1149
1150}
1151
1152void
1153listing_newline (name)
1154     char *name;
1155{
1156
1157}
1158
1159void
1160listing_source_line (n)
1161     unsigned int n;
1162{
1163
1164}
1165void
1166listing_source_file (n)
1167     const char *n;
1168{
1169
1170}
1171
1172#endif
1173