* listing.c (listing_psize): Treat argument as indicating whether
[external/binutils.git] / gas / listing.c
1 /* listing.c - mainting assembly listings
2    Copyright (C) 1991, 1992 Free Software Foundation, Inc.
3
4 This file is part of GAS, the GNU Assembler.
5
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GAS is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GAS; see the file COPYING.  If not, write to
18 the 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 */
125 typedef 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
134 file_info_type;
135
136
137 /* this structure rememebrs which line from which file goes into which
138    frag */
139 typedef 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
177 list_info_type;
178
179
180 static struct list_info_struct *head;
181 struct list_info_struct *listing_tail;
182 extern int listing;
183 extern fragS *frag_now;
184
185
186 static int paper_width = 200;
187 static int paper_height = 60;
188
189 /* File to output listings to.  */
190 static 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
198 static char data_buffer[100];
199 static unsigned int data_buffer_size;
200
201
202 /* Prototypes.  */
203 static void listing_message PARAMS ((const char *name, const char *message));
204 static file_info_type *file_info PARAMS ((const char *file_name));
205 static void new_frag PARAMS ((void));
206 static char *buffer_line PARAMS ((file_info_type *file,
207                                   char *line, unsigned int size));
208 static void listing_page PARAMS ((list_info_type *list));
209 static unsigned int calc_hex PARAMS ((list_info_type *list));
210 static void print_lines PARAMS ((list_info_type *list,
211                                  char *string,
212                                  unsigned int address));
213 static void list_symbol_table PARAMS ((void));
214 static void print_source PARAMS ((file_info_type *current_file,
215                                   list_info_type *list,
216                                   char *buffer,
217                                   unsigned int width));
218 static int debugging_pseudo PARAMS ((char *line));
219 static void listing_listing PARAMS ((char *name));
220
221
222 static void
223 listing_message (name, message)
224      const char *name;
225      const char *message;
226 {
227   unsigned int l = strlen (name) + strlen (message) + 1;
228   char *n = (char *) xmalloc (l);
229   strcpy (n, name);
230   strcat (n, message);
231   if (listing_tail != (list_info_type *) NULL)
232     {
233       listing_tail->message = n;
234     }
235 }
236
237 void
238 listing_warning (message)
239      const char *message;
240 {
241   listing_message ("Warning:", message);
242 }
243
244 void
245 listing_error (message)
246      const char *message;
247 {
248   listing_message ("Error:", message);
249 }
250
251
252
253
254 static file_info_type *file_info_head;
255
256 static file_info_type *
257 file_info (file_name)
258      const char *file_name;
259 {
260   /* Find an entry with this file name */
261   file_info_type *p = file_info_head;
262
263   while (p != (file_info_type *) NULL)
264     {
265       if (strcmp (p->filename, file_name) == 0)
266         return p;
267       p = p->next;
268     }
269
270   /* Make new entry */
271
272   p = (file_info_type *) xmalloc (sizeof (file_info_type));
273   p->next = file_info_head;
274   file_info_head = p;
275   p->filename = xmalloc ((unsigned long) strlen (file_name) + 1);
276   strcpy (p->filename, file_name);
277   p->linenum = 0;
278   p->at_end = 0;
279
280   p->file = fopen (p->filename, "r");
281   if (p->file)
282     fgetc (p->file);
283
284   return p;
285 }
286
287
288 static void
289 new_frag ()
290 {
291
292   frag_wane (frag_now);
293   frag_new (0);
294
295 }
296
297 void
298 listing_newline (ps)
299      char *ps;
300 {
301   char *file;
302   unsigned int line;
303   static unsigned int last_line = 0xffff;
304   static char *last_file = NULL;
305   list_info_type *new;
306
307   as_where (&file, &line);
308   if (line != last_line || (last_file && file && strcmp(file, last_file)))
309     {
310       last_line = line;
311       last_file = file;
312       new_frag ();
313
314       new = (list_info_type *) xmalloc (sizeof (list_info_type));
315       new->frag = frag_now;
316       new->line = line;
317       new->file = file_info (file);
318
319       if (listing_tail)
320         {
321           listing_tail->next = new;
322         }
323       else
324         {
325           head = new;
326         }
327       listing_tail = new;
328       new->next = (list_info_type *) NULL;
329       new->message = (char *) NULL;
330       new->edict = EDICT_NONE;
331       new->hll_file = (file_info_type *) NULL;
332       new->hll_line = 0;
333       new_frag ();
334     }
335 }
336
337 /* Attach all current frags to the previous line instead of the
338    current line.  This is called by the MIPS backend when it discovers
339    that it needs to add some NOP instructions; the added NOP
340    instructions should go with the instruction that has the delay, not
341    with the new instruction.  */
342
343 void
344 listing_prev_line ()
345 {
346   list_info_type *l;
347   fragS *f;
348
349   if (head == (list_info_type *) NULL
350       || head == listing_tail)
351     return;
352
353   new_frag ();
354
355   for (l = head; l->next != listing_tail; l = l->next)
356     ;
357
358   for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next)
359     if (f->line == listing_tail)
360       f->line = l;
361
362   listing_tail->frag = frag_now;
363   new_frag ();
364 }
365
366 /*
367  This function returns the next source line from the file supplied,
368  truncated to size.  It appends a fake line to the end of each input
369  file to make
370 */
371
372 static char *
373 buffer_line (file, line, size)
374      file_info_type * file;
375      char *line;
376      unsigned int size;
377 {
378   unsigned int count = 0;
379   int c;
380
381   char *p = line;
382
383   /* If we couldn't open the file, return an empty line */
384   if (file->file == (FILE *) NULL || file->at_end)
385     {
386       return "";
387     }
388
389   if (file->linenum == 0)
390     rewind (file->file);
391
392   c = fgetc (file->file);
393
394   size -= 1;                    /* leave room for null */
395
396   while (c != EOF && c != '\n')
397     {
398       if (count < size)
399         *p++ = c;
400       count++;
401
402       c = fgetc (file->file);
403
404     }
405   if (c == EOF)
406     {
407       file->at_end = 1;
408       *p++ = '.';
409       *p++ = '.';
410       *p++ = '.';
411     }
412   file->linenum++;
413   *p++ = 0;
414   return line;
415 }
416
417
418 static const char *fn;
419
420 static unsigned int eject;      /* Eject pending */
421 static unsigned int page;       /* Current page number */
422 static char *title;             /* current title */
423 static char *subtitle;          /* current subtitle */
424 static unsigned int on_page;    /* number of lines printed on current page */
425
426
427 static void
428 listing_page (list)
429      list_info_type *list;
430 {
431   /* Grope around, see if we can see a title or subtitle edict coming up
432      soon  (we look down 10 lines of the page and see if it's there)*/
433   if ((eject || (on_page >= paper_height)) && paper_height != 0)
434     {
435       unsigned int c = 10;
436       int had_title = 0;
437       int had_subtitle = 0;
438
439       page++;
440
441       while (c != 0 && list)
442         {
443           if (list->edict == EDICT_SBTTL && !had_subtitle)
444             {
445               had_subtitle = 1;
446               subtitle = list->edict_arg;
447             }
448           if (list->edict == EDICT_TITLE && !had_title)
449             {
450               had_title = 1;
451               title = list->edict_arg;
452             }
453           list = list->next;
454           c--;
455         }
456
457
458       if (page > 1)
459         {
460           fprintf (list_file, "\f");
461         }
462
463       fprintf (list_file, "%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
464       fprintf (list_file, "%s\n", title);
465       fprintf (list_file, "%s\n", subtitle);
466       on_page = 3;
467       eject = 0;
468     }
469 }
470
471
472 static unsigned int
473 calc_hex (list)
474      list_info_type * list;
475 {
476   list_info_type *first = list;
477   unsigned int address = (unsigned int) ~0;
478
479   fragS *frag;
480   fragS *frag_ptr;
481
482   unsigned int byte_in_frag;
483
484
485   /* Find first frag which says it belongs to this line */
486   frag = list->frag;
487   while (frag && frag->line != list)
488     frag = frag->fr_next;
489
490   frag_ptr = frag;
491
492   data_buffer_size = 0;
493
494   /* Dump all the frags which belong to this line */
495   while (frag_ptr != (fragS *) NULL && frag_ptr->line == first)
496     {
497       /* Print as many bytes from the fixed part as is sensible */
498       byte_in_frag = 0;
499       while (byte_in_frag < frag_ptr->fr_fix && data_buffer_size < sizeof (data_buffer) - 10)
500         {
501           if (address == ~0)
502             {
503               address = frag_ptr->fr_address;
504             }
505
506           sprintf (data_buffer + data_buffer_size,
507                    "%02X",
508                    (frag_ptr->fr_literal[byte_in_frag]) & 0xff);
509           data_buffer_size += 2;
510           byte_in_frag++;
511         }
512       {
513         unsigned int var_rep_max = byte_in_frag;
514         unsigned int var_rep_idx = byte_in_frag;
515
516         /* Print as many bytes from the variable part as is sensible */
517         while (byte_in_frag < frag_ptr->fr_var * frag_ptr->fr_offset
518                && data_buffer_size < sizeof (data_buffer) - 10)
519           {
520             if (address == ~0)
521               {
522                 address = frag_ptr->fr_address;
523               }
524             sprintf (data_buffer + data_buffer_size,
525                      "%02X",
526                      (frag_ptr->fr_literal[var_rep_idx]) & 0xff);
527 #if 0
528             data_buffer[data_buffer_size++] = '*';
529             data_buffer[data_buffer_size++] = '*';
530 #endif
531             data_buffer_size += 2;
532
533             var_rep_idx++;
534             byte_in_frag++;
535
536             if (var_rep_idx >= frag_ptr->fr_var)
537               var_rep_idx = var_rep_max;
538           }
539       }
540
541       frag_ptr = frag_ptr->fr_next;
542     }
543   data_buffer[data_buffer_size++] = 0;
544   return address;
545 }
546
547
548
549
550
551
552 static void
553 print_lines (list, string, address)
554      list_info_type *list;
555      char *string;
556      unsigned int address;
557 {
558   unsigned int idx;
559   unsigned int nchars;
560   unsigned int lines;
561   unsigned int byte_in_word = 0;
562   char *src = data_buffer;
563
564   /* Print the stuff on the first line */
565   listing_page (list);
566   nchars = (LISTING_WORD_SIZE * 2 + 1) * LISTING_LHS_WIDTH;
567   /* Print the hex for the first line */
568   if (address == ~0)
569     {
570       fprintf (list_file, "% 4d     ", list->line);
571       for (idx = 0; idx < nchars; idx++)
572         fprintf (list_file, " ");
573
574       fprintf (list_file, "\t%s\n", string ? string : "");
575       on_page++;
576       listing_page (0);
577
578     }
579   else
580     {
581       if (had_errors ())
582         {
583           fprintf (list_file, "% 4d ???? ", list->line);
584         }
585       else
586         {
587           fprintf (list_file, "% 4d %04x ", list->line, address);
588         }
589
590       /* And the data to go along with it */
591       idx = 0;
592
593       while (*src && idx < nchars)
594         {
595           fprintf (list_file, "%c%c", src[0], src[1]);
596           src += 2;
597           byte_in_word++;
598           if (byte_in_word == LISTING_WORD_SIZE)
599             {
600               fprintf (list_file, " ");
601               idx++;
602               byte_in_word = 0;
603             }
604           idx += 2;
605         }
606
607       for (; idx < nchars; idx++)
608         fprintf (list_file, " ");
609
610       fprintf (list_file, "\t%s\n", string ? string : "");
611       on_page++;
612       listing_page (list);
613       if (list->message)
614         {
615           fprintf (list_file, "****  %s\n", list->message);
616           listing_page (list);
617           on_page++;
618         }
619
620       for (lines = 0;
621            lines < LISTING_LHS_CONT_LINES
622            && *src;
623            lines++)
624         {
625           nchars = ((LISTING_WORD_SIZE * 2) + 1) * LISTING_LHS_WIDTH_SECOND - 1;
626           idx = 0;
627           /* Print any more lines of data, but more compactly */
628           fprintf (list_file, "% 4d      ", list->line);
629
630           while (*src && idx < nchars)
631             {
632               fprintf (list_file, "%c%c", src[0], src[1]);
633               src += 2;
634               idx += 2;
635               byte_in_word++;
636               if (byte_in_word == LISTING_WORD_SIZE)
637                 {
638                   fprintf (list_file, " ");
639                   idx++;
640                   byte_in_word = 0;
641                 }
642             }
643
644           fprintf (list_file, "\n");
645           on_page++;
646           listing_page (list);
647
648         }
649
650
651     }
652 }
653
654
655 static void
656 list_symbol_table ()
657 {
658   extern symbolS *symbol_rootP;
659   int got_some = 0;
660
661   symbolS *ptr;
662   eject = 1;
663   listing_page (0);
664
665   for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
666     {
667       if (ptr->sy_frag->line)
668         {
669           if (S_GET_NAME (ptr))
670             {
671               char buf[30], fmt[8];
672               valueT val = S_GET_VALUE (ptr);
673
674               /* @@ Note that this is dependent on the compilation options,
675                  not solely on the target characteristics.  */
676               if (sizeof (val) == 4 && sizeof (int) == 4)
677                 sprintf (buf, "%08lx", (unsigned long) val);
678               else if (sizeof (val) <= sizeof (unsigned long))
679                 {
680                   sprintf (fmt, "%%0%lulx",
681                            (unsigned long) (sizeof (val) * 2));
682                   sprintf (buf, fmt, (unsigned long) val);
683                 }
684 #if defined (BFD64)
685               else if (sizeof (val) > 4)
686                 {
687                   char buf1[30];
688                   sprintf_vma (buf1, val);
689                   strcpy (buf, "00000000");
690                   strcpy (buf + 8 - strlen (buf1), buf1);
691                 }
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
757 static void
758 print_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
781 static int
782 debugging_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
823 static void
824 listing_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
923 void
924 listing_print (name)
925      char *name;
926 {
927   title = "";
928   subtitle = "";
929
930   if (name == NULL)
931     list_file = stdout;
932   else
933     {
934       list_file = fopen (name, "w");
935       if (list_file == NULL)
936         {
937           as_perror ("can't open list file: %s", name);
938           list_file = stdout;
939         }
940     }
941
942   if (listing & LISTING_NOFORM)
943     {
944       paper_height = 0;
945     }
946
947   if (listing & LISTING_LISTING)
948     {
949       listing_listing (name);
950
951     }
952   if (listing & LISTING_SYMBOLS)
953     {
954       list_symbol_table ();
955     }
956 }
957
958
959 void
960 listing_file (name)
961      const char *name;
962 {
963   fn = name;
964 }
965
966 void
967 listing_eject (ignore)
968      int ignore;
969 {
970   listing_tail->edict = EDICT_EJECT;
971 }
972
973 void
974 listing_flags (ignore)
975      int ignore;
976 {
977   while ((*input_line_pointer++) && (*input_line_pointer != '\n'))
978     input_line_pointer++;
979
980 }
981
982 void
983 listing_list (on)
984      int on;
985 {
986   listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST;
987 }
988
989
990 void
991 listing_psize (width_only)
992      int width_only;
993 {
994   if (! width_only)
995     {
996       paper_height = get_absolute_expression ();
997
998       if (paper_height < 0 || paper_height > 1000)
999         {
1000           paper_height = 0;
1001           as_warn ("strange paper height, set to no form");
1002         }
1003
1004       if (*input_line_pointer != ',')
1005         {
1006           demand_empty_rest_of_line ();
1007           return;
1008         }
1009
1010       ++input_line_pointer;
1011     }
1012
1013   paper_width = get_absolute_expression ();
1014
1015   demand_empty_rest_of_line ();
1016 }
1017
1018 void
1019 listing_title (depth)
1020      int depth;
1021 {
1022   char *start;
1023   char *ttl;
1024   unsigned int length;
1025
1026   SKIP_WHITESPACE ();
1027   if (*input_line_pointer == '\"')
1028     {
1029       input_line_pointer++;
1030       start = input_line_pointer;
1031
1032       while (*input_line_pointer)
1033         {
1034           if (*input_line_pointer == '\"')
1035             {
1036               length = input_line_pointer - start;
1037               ttl = xmalloc (length + 1);
1038               memcpy (ttl, start, length);
1039               ttl[length] = 0;
1040               listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
1041               listing_tail->edict_arg = ttl;
1042               input_line_pointer++;
1043               demand_empty_rest_of_line ();
1044               return;
1045             }
1046           else if (*input_line_pointer == '\n')
1047             {
1048               as_bad ("New line in title");
1049               demand_empty_rest_of_line ();
1050               return;
1051             }
1052           else
1053             {
1054               input_line_pointer++;
1055             }
1056         }
1057     }
1058   else
1059     {
1060       as_bad ("expecting title in quotes");
1061     }
1062 }
1063
1064
1065
1066 void
1067 listing_source_line (line)
1068      unsigned int line;
1069 {
1070   new_frag ();
1071   listing_tail->hll_line = line;
1072   new_frag ();
1073
1074 }
1075
1076 void
1077 listing_source_file (file)
1078      const char *file;
1079 {
1080   if (listing_tail)
1081     listing_tail->hll_file = file_info (file);
1082 }
1083
1084
1085
1086 #else
1087
1088
1089 /* Dummy functions for when compiled without listing enabled */
1090
1091 void
1092 listing_flags (ignore)
1093      int ignore;
1094 {
1095   s_ignore (0);
1096 }
1097
1098 void 
1099 listing_list (on)
1100      int on;
1101 {
1102   s_ignore (0);
1103 }
1104
1105 void 
1106 listing_eject (ignore)
1107      int ignore;
1108 {
1109   s_ignore (0);
1110 }
1111
1112 void 
1113 listing_psize (ignore)
1114      int ignore;
1115 {
1116   s_ignore (0);
1117 }
1118
1119 void 
1120 listing_title (depth)
1121      int depth;
1122 {
1123   s_ignore (0);
1124 }
1125
1126 void
1127 listing_file (name)
1128      const char *name;
1129 {
1130
1131 }
1132
1133 void 
1134 listing_newline (name)
1135      char *name;
1136 {
1137
1138 }
1139
1140 void 
1141 listing_source_line (n)
1142      unsigned int n;
1143 {
1144
1145 }
1146 void 
1147 listing_source_file (n)
1148      const char *n;
1149 {
1150
1151 }
1152
1153 #endif