Add the DragonFly cvs id and perform general cleanups on cvs/rcs/sccs ids. Most
[dragonfly.git] / gnu / usr.bin / as / 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, 675 Mass Ave, Cambridge, MA 02139, 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 /*
95  * $FreeBSD: src/gnu/usr.bin/as/listing.c,v 1.6 1999/08/27 23:34:18 peter Exp $
96  * $DragonFly: src/gnu/usr.bin/as/Attic/listing.c,v 1.2 2003/06/17 04:25:44 dillon Exp $
97  */
98 #include <ctype.h>
99
100 #include "as.h"
101 #include <obstack.h>
102 #include "input-file.h"
103 #include "subsegs.h"
104
105 #ifndef NO_LISTING
106 #ifndef LISTING_HEADER
107 #define LISTING_HEADER "GAS LISTING"
108 #endif
109 #ifndef LISTING_WORD_SIZE
110 #define LISTING_WORD_SIZE 4
111 #endif
112 #ifndef LISTING_LHS_WIDTH
113 #define LISTING_LHS_WIDTH 1
114 #endif
115 #ifndef LISTING_LHS_WIDTH_SECOND
116 #define LISTING_LHS_WIDTH_SECOND 1
117 #endif
118 #ifndef LISTING_RHS_WIDTH
119 #define LISTING_RHS_WIDTH 100
120 #endif
121 #ifndef LISTING_LHS_CONT_LINES
122 #define LISTING_LHS_CONT_LINES 4
123 #endif
124
125
126
127
128 static struct list_info_struct *head;
129 struct list_info_struct *listing_tail;
130 extern int listing;
131 extern fragS *frag_now;
132
133
134 static int paper_width = 200;
135 static int paper_height = 60;
136
137
138 /* this static array is used to keep the text of data to be printed
139    before the start of the line.
140     It is stored so we can give a bit more info on the next line.  To much, and large
141    initialized arrays will use up lots of paper.
142  */
143
144 static char data_buffer[100];
145 static unsigned int data_buffer_size;
146
147
148 /* Prototypes.  */
149 static void listing_message PARAMS ((const char *name, const char *message));
150 static file_info_type *file_info PARAMS ((const char *file_name));
151 static void new_frag PARAMS ((void));
152 static char *buffer_line PARAMS ((file_info_type *file,
153                                   char *line, unsigned int size));
154 static void listing_page PARAMS ((list_info_type *list));
155 static unsigned int calc_hex PARAMS ((list_info_type *list));
156 static void print_lines PARAMS ((list_info_type *list,
157                                  char *string,
158                                  unsigned int address));
159 static void list_symbol_table PARAMS ((void));
160 static void print_source PARAMS ((file_info_type *current_file,
161                                   list_info_type *list,
162                                   char *buffer,
163                                   unsigned int width));
164 static int debugging_pseudo PARAMS ((char *line));
165 static void listing_listing PARAMS ((char *name));
166
167
168 static void
169 listing_message (name, message)
170      const char *name;
171      const char *message;
172 {
173   unsigned int l = strlen (name) + strlen (message) + 1;
174   char *n = (char *) xmalloc (l);
175   strcpy (n, name);
176   strcat (n, message);
177   if (listing_tail != (list_info_type *) NULL)
178     {
179       listing_tail->message = n;
180     }
181 }
182
183 void
184 listing_warning (message)
185      const char *message;
186 {
187   listing_message ("Warning:", message);
188 }
189
190 void
191 listing_error (message)
192      const char *message;
193 {
194   listing_message ("Error:", message);
195 }
196
197
198
199
200 static file_info_type *file_info_head;
201
202 static file_info_type *
203 file_info (file_name)
204      const char *file_name;
205 {
206   /* Find an entry with this file name */
207   file_info_type *p = file_info_head;
208
209   while (p != (file_info_type *) NULL)
210     {
211       if (strcmp (p->filename, file_name) == 0)
212         return p;
213       p = p->next;
214     }
215
216   /* Make new entry */
217
218   p = (file_info_type *) xmalloc (sizeof (file_info_type));
219   p->next = file_info_head;
220   file_info_head = p;
221   p->filename = xmalloc ((unsigned long) strlen (file_name) + 1);
222   strcpy (p->filename, file_name);
223   p->linenum = 0;
224   p->end_pending = 0;
225
226   /* Do we really prefer binary mode for this??  */
227 #define FOPEN_RB "r"
228   p->file = fopen (p->filename, FOPEN_RB);
229   if (p->file)
230     fgetc (p->file);
231
232   return p;
233 }
234
235
236 static void
237 new_frag ()
238 {
239
240   frag_wane (frag_now);
241   frag_new (0);
242
243 }
244
245 void
246 listing_newline (ps)
247      char *ps;
248 {
249   char *file;
250   unsigned int line;
251   static unsigned int last_line = 0xffff;
252   static char *last_file = NULL;
253   list_info_type *new;
254
255   as_where (&file, &line);
256   if (line != last_line || last_file && file && strcmp(file, last_file))
257     {
258       last_line = line;
259       last_file = file;
260       new_frag ();
261
262       new = (list_info_type *) xmalloc (sizeof (list_info_type));
263       new->frag = frag_now;
264       new->line = line;
265       new->file = file_info (file);
266
267       if (listing_tail)
268         {
269           listing_tail->next = new;
270         }
271       else
272         {
273           head = new;
274         }
275       listing_tail = new;
276       new->next = (list_info_type *) NULL;
277       new->message = (char *) NULL;
278       new->edict = EDICT_NONE;
279       new->hll_file = (file_info_type *) NULL;
280       new->hll_line = 0;
281       new_frag ();
282     }
283 }
284
285 /* Attach all current frags to the previous line instead of the
286    current line.  This is called by the MIPS backend when it discovers
287    that it needs to add some NOP instructions; the added NOP
288    instructions should go with the instruction that has the delay, not
289    with the new instruction.  */
290
291 void
292 listing_prev_line ()
293 {
294   list_info_type *l;
295   fragS *f;
296
297   if (head == (list_info_type *) NULL
298       || head == listing_tail)
299     return;
300
301   new_frag ();
302
303   for (l = head; l->next != listing_tail; l = l->next)
304     ;
305
306   for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next)
307     if (f->line == listing_tail)
308       f->line = l;
309
310   listing_tail->frag = frag_now;
311   new_frag ();
312 }
313
314 /*
315  This function returns the next source line from the file supplied,
316  truncated to size.  It appends a fake line to the end of each input
317  file to make
318 */
319
320 static char *
321 buffer_line (file, line, size)
322      file_info_type * file;
323      char *line;
324      unsigned int size;
325 {
326   unsigned int count = 0;
327   int c;
328
329   char *p = line;
330
331   /* If we couldn't open the file, return an empty line */
332   if (file->file == (FILE *) NULL)
333     {
334       return "";
335     }
336
337   if (file->linenum == 0)
338     rewind (file->file);
339
340   if (file->end_pending == 10)
341     {
342       *p++ = '\n';
343       fseek (file->file, 0, 0);
344       file->linenum = 0;
345       file->end_pending = 0;
346     }
347   c = fgetc (file->file);
348
349
350   size -= 1;                    /* leave room for null */
351
352   while (c != EOF && c != '\n')
353     {
354       if (count < size)
355         *p++ = c;
356       count++;
357
358       c = fgetc (file->file);
359
360     }
361   if (c == EOF)
362     {
363       file->end_pending++;
364       *p++ = '.';
365       *p++ = '.';
366       *p++ = '.';
367     }
368   file->linenum++;
369   *p++ = 0;
370   return line;
371 }
372
373
374 static const char *fn;
375
376 static unsigned int eject;      /* Eject pending */
377 static unsigned int page;       /* Current page number */
378 static char *title;             /* current title */
379 static char *subtitle;          /* current subtitle */
380 static unsigned int on_page;    /* number of lines printed on current page */
381
382
383 static void
384 listing_page (list)
385      list_info_type *list;
386 {
387   /* Grope around, see if we can see a title or subtitle edict coming up
388      soon  (we look down 10 lines of the page and see if it's there)*/
389   if ((eject || (on_page >= paper_height)) && paper_height != 0)
390     {
391       unsigned int c = 10;
392       int had_title = 0;
393       int had_subtitle = 0;
394
395       page++;
396
397       while (c != 0 && list)
398         {
399           if (list->edict == EDICT_SBTTL && !had_subtitle)
400             {
401               had_subtitle = 1;
402               subtitle = list->edict_arg;
403             }
404           if (list->edict == EDICT_TITLE && !had_title)
405             {
406               had_title = 1;
407               title = list->edict_arg;
408             }
409           list = list->next;
410           c--;
411         }
412
413
414       if (page > 1)
415         {
416           printf ("\f");
417         }
418
419       printf ("%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
420       printf ("%s\n", title);
421       printf ("%s\n", subtitle);
422       on_page = 3;
423       eject = 0;
424     }
425 }
426
427
428 static unsigned int
429 calc_hex (list)
430      list_info_type * list;
431 {
432   list_info_type *first = list;
433   unsigned int address = (unsigned int) ~0;
434
435   fragS *frag;
436   fragS *frag_ptr;
437
438   unsigned int byte_in_frag;
439
440
441   /* Find first frag which says it belongs to this line */
442   frag = list->frag;
443   while (frag && frag->line != list)
444     frag = frag->fr_next;
445
446   frag_ptr = frag;
447
448   data_buffer_size = 0;
449
450   /* Dump all the frags which belong to this line */
451   while (frag_ptr != (fragS *) NULL && frag_ptr->line == first)
452     {
453       /* Print as many bytes from the fixed part as is sensible */
454       byte_in_frag = 0;
455       while (byte_in_frag < frag_ptr->fr_fix && data_buffer_size < sizeof (data_buffer) - 10)
456         {
457           if (address == ~0)
458             {
459               address = frag_ptr->fr_address;
460             }
461
462           sprintf (data_buffer + data_buffer_size,
463                    "%02X",
464                    (frag_ptr->fr_literal[byte_in_frag]) & 0xff);
465           data_buffer_size += 2;
466           byte_in_frag++;
467         }
468       {
469         unsigned int var_rep_max = byte_in_frag;
470         unsigned int var_rep_idx = byte_in_frag;
471
472         /* Print as many bytes from the variable part as is sensible */
473         while (byte_in_frag < frag_ptr->fr_var * frag_ptr->fr_offset
474                && data_buffer_size < sizeof (data_buffer) - 10)
475           {
476             if (address == ~0)
477               {
478                 address = frag_ptr->fr_address;
479               }
480             sprintf (data_buffer + data_buffer_size,
481                      "%02X",
482                      (frag_ptr->fr_literal[var_rep_idx]) & 0xff);
483 #if 0
484             data_buffer[data_buffer_size++] = '*';
485             data_buffer[data_buffer_size++] = '*';
486 #endif
487             data_buffer_size += 2;
488
489             var_rep_idx++;
490             byte_in_frag++;
491
492             if (var_rep_idx >= frag_ptr->fr_var)
493               var_rep_idx = var_rep_max;
494           }
495       }
496
497       frag_ptr = frag_ptr->fr_next;
498     }
499   data_buffer[data_buffer_size++] = 0;
500   return address;
501 }
502
503
504
505
506
507
508 static void
509 print_lines (list, string, address)
510      list_info_type *list;
511      char *string;
512      unsigned int address;
513 {
514   unsigned int idx;
515   unsigned int nchars;
516   unsigned int lines;
517   unsigned int byte_in_word = 0;
518   char *src = data_buffer;
519
520   /* Print the stuff on the first line */
521   listing_page (list);
522   nchars = (LISTING_WORD_SIZE * 2 + 1) * LISTING_LHS_WIDTH;
523   /* Print the hex for the first line */
524   if (address == ~0)
525     {
526       printf ("% 4d     ", list->line);
527       for (idx = 0; idx < nchars; idx++)
528         printf (" ");
529
530       printf ("\t%s\n", string ? string : "");
531       on_page++;
532       listing_page (0);
533
534     }
535   else
536     {
537       if (had_errors ())
538         {
539           printf ("% 4d ???? ", list->line);
540         }
541       else
542         {
543           printf ("% 4d %04x ", list->line, address);
544         }
545
546       /* And the data to go along with it */
547       idx = 0;
548
549       while (*src && idx < nchars)
550         {
551           printf ("%c%c", src[0], src[1]);
552           src += 2;
553           byte_in_word++;
554           if (byte_in_word == LISTING_WORD_SIZE)
555             {
556               printf (" ");
557               idx++;
558               byte_in_word = 0;
559             }
560           idx += 2;
561         }
562
563       for (; idx < nchars; idx++)
564         printf (" ");
565
566       printf ("\t%s\n", string ? string : "");
567       on_page++;
568       listing_page (list);
569       if (list->message)
570         {
571           printf ("****  %s\n", list->message);
572           listing_page (list);
573           on_page++;
574         }
575
576       for (lines = 0;
577            lines < LISTING_LHS_CONT_LINES
578            && *src;
579            lines++)
580         {
581           nchars = ((LISTING_WORD_SIZE * 2) + 1) * LISTING_LHS_WIDTH_SECOND - 1;
582           idx = 0;
583           /* Print any more lines of data, but more compactly */
584           printf ("% 4d      ", list->line);
585
586           while (*src && idx < nchars)
587             {
588               printf ("%c%c", src[0], src[1]);
589               src += 2;
590               idx += 2;
591               byte_in_word++;
592               if (byte_in_word == LISTING_WORD_SIZE)
593                 {
594                   printf (" ");
595                   idx++;
596                   byte_in_word = 0;
597                 }
598             }
599
600           printf ("\n");
601           on_page++;
602           listing_page (list);
603
604         }
605
606
607     }
608 }
609
610
611 static void
612 list_symbol_table ()
613 {
614   extern symbolS *symbol_rootP;
615   int got_some = 0;
616
617   symbolS *ptr;
618   eject = 1;
619   listing_page (0);
620
621   for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
622     {
623       if (ptr->sy_frag->line)
624         {
625           if (S_GET_NAME (ptr))
626             {
627               char buf[30];
628               valueT val = S_GET_VALUE (ptr);
629
630               /* @@ Note that this is dependent on the compilation options,
631                  not solely on the target characteristics.  */
632               if (sizeof (val) == 4 && sizeof (int) == 4)
633                 sprintf (buf, "%08lx", (unsigned long) val);
634 #if defined (BFD64)
635               else if (sizeof (val) > 4)
636                 {
637                   char buf1[30];
638                   sprintf_vma (buf1, val);
639                   strcpy (buf, "00000000");
640                   strcpy (buf + 8 - strlen (buf1), buf1);
641                 }
642 #endif
643               else
644                 abort ();
645
646               if (!got_some)
647                 {
648                   printf ("DEFINED SYMBOLS\n");
649                   on_page++;
650                   got_some = 1;
651                 }
652
653               printf ("%20s:%-5d  %s:%s %s\n",
654                       ptr->sy_frag->line->file->filename,
655                       ptr->sy_frag->line->line,
656                       segment_name (S_GET_SEGMENT (ptr)),
657                       buf, S_GET_NAME (ptr));
658
659               on_page++;
660               listing_page (0);
661             }
662         }
663
664     }
665   if (!got_some)
666     {
667       printf ("NO DEFINED SYMBOLS\n");
668       on_page++;
669     }
670   printf ("\n");
671   on_page++;
672   listing_page (0);
673
674   got_some = 0;
675
676   for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
677     {
678       if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
679         {
680           if (ptr->sy_frag->line == 0
681 #ifdef notyet
682               && S_GET_SEGMENT (ptr) != reg_section)
683 #else
684               && !S_IS_REGISTER(ptr))
685 #endif
686             {
687               if (!got_some)
688                 {
689                   got_some = 1;
690                   printf ("UNDEFINED SYMBOLS\n");
691                   on_page++;
692                   listing_page (0);
693                 }
694               printf ("%s\n", S_GET_NAME (ptr));
695               on_page++;
696               listing_page (0);
697             }
698         }
699     }
700   if (!got_some)
701     {
702       printf ("NO UNDEFINED SYMBOLS\n");
703       on_page++;
704       listing_page (0);
705     }
706 }
707
708 static void
709 print_source (current_file, list, buffer, width)
710      file_info_type *current_file;
711      list_info_type *list;
712      char *buffer;
713      unsigned int width;
714 {
715   if (current_file->file)
716     {
717       while (current_file->linenum < list->hll_line)
718         {
719           char *p = buffer_line (current_file, buffer, width);
720           printf ("%4d:%-13s **** %s\n", current_file->linenum, current_file->filename, p);
721           on_page++;
722           listing_page (list);
723         }
724     }
725 }
726
727 /* Sometimes the user doesn't want to be bothered by the debugging
728    records inserted by the compiler, see if the line is suspicious */
729
730 static int
731 debugging_pseudo (line)
732      char *line;
733 {
734   while (isspace (*line))
735     line++;
736
737   if (*line != '.')
738     return 0;
739
740   line++;
741
742   if (strncmp (line, "def", 3) == 0)
743     return 1;
744   if (strncmp (line, "val", 3) == 0)
745     return 1;
746   if (strncmp (line, "scl", 3) == 0)
747     return 1;
748   if (strncmp (line, "line", 4) == 0)
749     return 1;
750   if (strncmp (line, "endef", 5) == 0)
751     return 1;
752   if (strncmp (line, "ln", 2) == 0)
753     return 1;
754   if (strncmp (line, "type", 4) == 0)
755     return 1;
756   if (strncmp (line, "size", 4) == 0)
757     return 1;
758   if (strncmp (line, "dim", 3) == 0)
759     return 1;
760   if (strncmp (line, "tag", 3) == 0)
761     return 1;
762
763   if (strncmp (line, "stabs", 5) == 0)
764     return 1;
765   if (strncmp (line, "stabn", 5) == 0)
766     return 1;
767
768   return 0;
769
770 }
771
772 static void
773 listing_listing (name)
774      char *name;
775 {
776   list_info_type *list = head;
777   file_info_type *current_hll_file = (file_info_type *) NULL;
778   char *message;
779   char *buffer;
780   char *p;
781   int show_listing = 1;
782   unsigned int width;
783
784   buffer = xmalloc (LISTING_RHS_WIDTH);
785   eject = 1;
786   list = head;
787
788   while (list != (list_info_type *) NULL && 0)
789     {
790       if (list->next)
791         list->frag = list->next->frag;
792       list = list->next;
793
794     }
795
796   list = head->next;
797
798
799   while (list)
800     {
801       width = LISTING_RHS_WIDTH > paper_width ? paper_width :
802         LISTING_RHS_WIDTH;
803
804       switch (list->edict)
805         {
806         case EDICT_LIST:
807           show_listing++;
808           break;
809         case EDICT_NOLIST:
810           show_listing--;
811           break;
812         case EDICT_EJECT:
813           break;
814         case EDICT_NONE:
815           break;
816         case EDICT_TITLE:
817           title = list->edict_arg;
818           break;
819         case EDICT_SBTTL:
820           subtitle = list->edict_arg;
821           break;
822         default:
823           abort ();
824         }
825
826       if (show_listing > 0)
827         {
828           /* Scan down the list and print all the stuff which can be done
829              with this line (or lines).  */
830           message = 0;
831
832           if (list->hll_file)
833             {
834               current_hll_file = list->hll_file;
835             }
836
837           if (current_hll_file && list->hll_line && listing & LISTING_HLL)
838             {
839               print_source (current_hll_file, list, buffer, width);
840             }
841
842           while (list->file->file &&
843                  list->file->linenum < list->line && !list->file->end_pending) {
844                   p = buffer_line (list->file, buffer, width);
845
846                   if (!((listing & LISTING_NODEBUG) && debugging_pseudo (p)))
847                     {
848                       print_lines (list, p, calc_hex (list));
849                     }
850           }
851
852           if (list->edict == EDICT_EJECT)
853             {
854               eject = 1;
855             }
856         }
857       else
858         {
859
860           while (list->file->file &&
861                  list->file->linenum < list->line && !list->file->end_pending)
862                   p = buffer_line (list->file, buffer, width);
863         }
864
865       list = list->next;
866     }
867   free (buffer);
868 }
869
870 void
871 listing_print (name)
872      char *name;
873 {
874   title = "";
875   subtitle = "";
876
877   if (listing & LISTING_NOFORM)
878     {
879       paper_height = 0;
880     }
881
882   if (listing & LISTING_LISTING)
883     {
884       listing_listing (name);
885
886     }
887   if (listing & LISTING_SYMBOLS)
888     {
889       list_symbol_table ();
890     }
891 }
892
893
894 void
895 listing_file (name)
896      const char *name;
897 {
898   fn = name;
899 }
900
901 void
902 listing_eject (ignore)
903      int ignore;
904 {
905   listing_tail->edict = EDICT_EJECT;
906 }
907
908 void
909 listing_flags (ignore)
910      int ignore;
911 {
912   while ((*input_line_pointer++) && (*input_line_pointer != '\n'))
913     input_line_pointer++;
914
915 }
916
917 void
918 listing_list (on)
919      int on;
920 {
921   listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST;
922 }
923
924
925 void
926 listing_psize (ignore)
927      int ignore;
928 {
929   paper_height = get_absolute_expression ();
930
931   if (paper_height < 0 || paper_height > 1000)
932     {
933       paper_height = 0;
934       as_warn ("strange paper height, set to no form");
935     }
936   if (*input_line_pointer == ',')
937     {
938       input_line_pointer++;
939       paper_width = get_absolute_expression ();
940     }
941 }
942
943
944 void
945 listing_title (depth)
946      int depth;
947 {
948   char *start;
949   char *ttl;
950   unsigned int length;
951
952   SKIP_WHITESPACE ();
953   if (*input_line_pointer == '\"')
954     {
955       input_line_pointer++;
956       start = input_line_pointer;
957
958       while (*input_line_pointer)
959         {
960           if (*input_line_pointer == '\"')
961             {
962               length = input_line_pointer - start;
963               ttl = xmalloc (length + 1);
964               memcpy (ttl, start, length);
965               ttl[length] = 0;
966               listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
967               listing_tail->edict_arg = ttl;
968               input_line_pointer++;
969               demand_empty_rest_of_line ();
970               return;
971             }
972           else if (*input_line_pointer == '\n')
973             {
974               as_bad ("New line in title");
975               demand_empty_rest_of_line ();
976               return;
977             }
978           else
979             {
980               input_line_pointer++;
981             }
982         }
983     }
984   else
985     {
986       as_bad ("expecting title in quotes");
987     }
988 }
989
990
991
992 void
993 listing_source_line (line)
994      unsigned int line;
995 {
996   new_frag ();
997   listing_tail->hll_line = line;
998   new_frag ();
999
1000 }
1001
1002 void
1003 listing_source_file (file)
1004      const char *file;
1005 {
1006   if (listing_tail)
1007     listing_tail->hll_file = file_info (file);
1008 }
1009
1010
1011
1012 #else
1013
1014
1015 /* Dummy functions for when compiled without listing enabled */
1016
1017 void
1018 listing_flags (ignore)
1019      int ignore;
1020 {
1021   s_ignore (0);
1022 }
1023
1024 void
1025 listing_list (on)
1026      int on;
1027 {
1028   s_ignore (0);
1029 }
1030
1031 void
1032 listing_eject (ignore)
1033      int ignore;
1034 {
1035   s_ignore (0);
1036 }
1037
1038 void
1039 listing_psize (ignore)
1040      int ignore;
1041 {
1042   s_ignore (0);
1043 }
1044
1045 void
1046 listing_title (depth)
1047      int depth;
1048 {
1049   s_ignore (0);
1050 }
1051
1052 void
1053 listing_file (name)
1054      const char *name;
1055 {
1056
1057 }
1058
1059 void
1060 listing_newline (name)
1061      char *name;
1062 {
1063
1064 }
1065
1066 void
1067 listing_source_line (n)
1068      unsigned int n;
1069 {
1070
1071 }
1072 void
1073 listing_source_file (n)
1074      const char *n;
1075 {
1076
1077 }
1078
1079 #endif