* listing.c (calc_hex): Offset by fr_fix when examining fr_var.
[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
184 static int paper_width = 200;
185 static int paper_height = 60;
186
187 /* File to output listings to.  */
188 static 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
196 static char data_buffer[100];
197 static unsigned int data_buffer_size;
198
199
200 /* Prototypes.  */
201 static void listing_message PARAMS ((const char *name, const char *message));
202 static file_info_type *file_info PARAMS ((const char *file_name));
203 static void new_frag PARAMS ((void));
204 static char *buffer_line PARAMS ((file_info_type *file,
205                                   char *line, unsigned int size));
206 static void listing_page PARAMS ((list_info_type *list));
207 static unsigned int calc_hex PARAMS ((list_info_type *list));
208 static void print_lines PARAMS ((list_info_type *list,
209                                  char *string,
210                                  unsigned int address));
211 static void list_symbol_table PARAMS ((void));
212 static void print_source PARAMS ((file_info_type *current_file,
213                                   list_info_type *list,
214                                   char *buffer,
215                                   unsigned int width));
216 static int debugging_pseudo PARAMS ((char *line));
217 static void listing_listing PARAMS ((char *name));
218
219
220 static void
221 listing_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
235 void
236 listing_warning (message)
237      const char *message;
238 {
239   listing_message ("Warning:", message);
240 }
241
242 void
243 listing_error (message)
244      const char *message;
245 {
246   listing_message ("Error:", message);
247 }
248
249
250
251
252 static file_info_type *file_info_head;
253
254 static file_info_type *
255 file_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
286 static void
287 new_frag ()
288 {
289
290   frag_wane (frag_now);
291   frag_new (0);
292
293 }
294
295 void
296 listing_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
347 void
348 listing_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
376 static char *
377 buffer_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
422 static const char *fn;
423
424 static unsigned int eject;      /* Eject pending */
425 static unsigned int page;       /* Current page number */
426 static char *title;             /* current title */
427 static char *subtitle;          /* current subtitle */
428 static unsigned int on_page;    /* number of lines printed on current page */
429
430
431 static void
432 listing_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
476 static unsigned int
477 calc_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
557 static void
558 print_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
660 static void
661 list_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
762 static void
763 print_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
786 static int
787 debugging_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
828 static void
829 listing_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
928 void
929 listing_print (name)
930      char *name;
931 {
932   title = "";
933   subtitle = "";
934
935   if (name == NULL)
936     list_file = stdout;
937   else
938     {
939       list_file = fopen (name, "w");
940       if (list_file == NULL)
941         {
942           as_perror ("can't open list file: %s", name);
943           list_file = stdout;
944         }
945     }
946
947   if (listing & LISTING_NOFORM)
948     {
949       paper_height = 0;
950     }
951
952   if (listing & LISTING_LISTING)
953     {
954       listing_listing (name);
955
956     }
957   if (listing & LISTING_SYMBOLS)
958     {
959       list_symbol_table ();
960     }
961 }
962
963
964 void
965 listing_file (name)
966      const char *name;
967 {
968   fn = name;
969 }
970
971 void
972 listing_eject (ignore)
973      int ignore;
974 {
975   if (listing)
976     listing_tail->edict = EDICT_EJECT;
977 }
978
979 void
980 listing_flags (ignore)
981      int ignore;
982 {
983   while ((*input_line_pointer++) && (*input_line_pointer != '\n'))
984     input_line_pointer++;
985
986 }
987
988 void
989 listing_list (on)
990      int on;
991 {
992   if (listing)
993     listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST;
994 }
995
996
997 void
998 listing_psize (width_only)
999      int width_only;
1000 {
1001   if (! width_only)
1002     {
1003       paper_height = get_absolute_expression ();
1004
1005       if (paper_height < 0 || paper_height > 1000)
1006         {
1007           paper_height = 0;
1008           as_warn ("strange paper height, set to no form");
1009         }
1010
1011       if (*input_line_pointer != ',')
1012         {
1013           demand_empty_rest_of_line ();
1014           return;
1015         }
1016
1017       ++input_line_pointer;
1018     }
1019
1020   paper_width = get_absolute_expression ();
1021
1022   demand_empty_rest_of_line ();
1023 }
1024
1025 void
1026 listing_nopage (ignore)
1027      int ignore;
1028 {
1029   paper_height = 0;
1030 }
1031
1032 void
1033 listing_title (depth)
1034      int depth;
1035 {
1036   int quoted;
1037   char *start;
1038   char *ttl;
1039   unsigned int length;
1040
1041   SKIP_WHITESPACE ();
1042   if (*input_line_pointer != '\"')
1043     quoted = 0;
1044   else
1045     {
1046       quoted = 1;
1047       ++input_line_pointer;
1048     }
1049
1050   start = input_line_pointer;
1051
1052   while (*input_line_pointer)
1053     {
1054       if (quoted
1055           ? *input_line_pointer == '\"'
1056           : is_end_of_line[(unsigned char) *input_line_pointer])
1057         {
1058           if (listing)
1059             {
1060               length = input_line_pointer - start;
1061               ttl = xmalloc (length + 1);
1062               memcpy (ttl, start, length);
1063               ttl[length] = 0;
1064               listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
1065               listing_tail->edict_arg = ttl;
1066             }
1067           if (quoted)
1068             input_line_pointer++;
1069           demand_empty_rest_of_line ();
1070           return;
1071         }
1072       else if (*input_line_pointer == '\n')
1073         {
1074           as_bad ("New line in title");
1075           demand_empty_rest_of_line ();
1076           return;
1077         }
1078       else
1079         {
1080           input_line_pointer++;
1081         }
1082     }
1083 }
1084
1085
1086
1087 void
1088 listing_source_line (line)
1089      unsigned int line;
1090 {
1091   if (listing)
1092     {
1093       new_frag ();
1094       listing_tail->hll_line = line;
1095       new_frag ();
1096     }
1097 }
1098
1099 void
1100 listing_source_file (file)
1101      const char *file;
1102 {
1103   if (listing)
1104     listing_tail->hll_file = file_info (file);
1105 }
1106
1107
1108
1109 #else
1110
1111
1112 /* Dummy functions for when compiled without listing enabled */
1113
1114 void
1115 listing_flags (ignore)
1116      int ignore;
1117 {
1118   s_ignore (0);
1119 }
1120
1121 void 
1122 listing_list (on)
1123      int on;
1124 {
1125   s_ignore (0);
1126 }
1127
1128 void 
1129 listing_eject (ignore)
1130      int ignore;
1131 {
1132   s_ignore (0);
1133 }
1134
1135 void 
1136 listing_psize (ignore)
1137      int ignore;
1138 {
1139   s_ignore (0);
1140 }
1141
1142 void
1143 listing_nopage (ignore)
1144      int ignore;
1145 {
1146   s_ignore (0);
1147 }
1148
1149 void 
1150 listing_title (depth)
1151      int depth;
1152 {
1153   s_ignore (0);
1154 }
1155
1156 void
1157 listing_file (name)
1158      const char *name;
1159 {
1160
1161 }
1162
1163 void 
1164 listing_newline (name)
1165      char *name;
1166 {
1167
1168 }
1169
1170 void 
1171 listing_source_line (n)
1172      unsigned int n;
1173 {
1174
1175 }
1176 void 
1177 listing_source_file (n)
1178      const char *n;
1179 {
1180
1181 }
1182
1183 #endif