This commit was generated by cvs2svn to track changes on a CVS vendor
[external/binutils.git] / gas / listing.c
1 /* listing.c - mainting assembly listings
2    Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 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 the Free
18 Software Foundation, 59 Temple Place - Suite 330, Boston, MA
19 02111-1307, USA. */
20
21 /*
22  Contributed by Steve Chamberlain
23                 sac@cygnus.com
24
25
26  A listing page looks like:
27
28  LISTING_HEADER  sourcefilename pagenumber
29  TITLE LINE
30  SUBTITLE LINE
31  linenumber address data  source
32  linenumber address data  source
33  linenumber address data  source
34  linenumber address data  source
35
36  If not overridden, the listing commands are:
37
38  .title  "stuff"
39         Put "stuff" onto the title line
40  .sbttl  "stuff"
41         Put stuff onto the subtitle line
42
43   If these commands come within 10 lines of the top of the page, they
44   will affect the page they are on, as well as any subsequent page
45
46  .eject
47         Thow a page
48  .list
49         Increment the enable listing counter
50  .nolist
51         Decrement the enable listing counter
52
53  .psize Y[,X]
54         Set the paper size to X wide and Y high. Setting a psize Y of
55         zero will suppress form feeds except where demanded by .eject
56
57  If the counter goes below zero, listing is suppressed.
58
59
60  Listings are a maintained by read calling various listing_<foo>
61  functions.  What happens most is that the macro NO_LISTING is not
62  defined (from the Makefile), then the macro LISTING_NEWLINE expands
63  into a call to listing_newline.  The call is done from read.c, every
64  time it sees a newline, and -l is on the command line.
65
66  The function listing_newline remembers the frag associated with the
67  newline, and creates a new frag - note that this is wasteful, but not
68  a big deal, since listing slows things down a lot anyway.  The
69  function also rememebers when the filename changes.
70
71  When all the input has finished, and gas has had a chance to settle
72  down, the listing is output. This is done by running down the list of
73  frag/source file records, and opening the files as needed and printing
74  out the bytes and chars associated with them.
75
76  The only things which the architecture can change about the listing
77  are defined in these macros:
78
79  LISTING_HEADER         The name of the architecture
80  LISTING_WORD_SIZE      The make of the number of bytes in a word, this determines
81                         the clumping of the output data. eg a value of
82                         2 makes words look like 1234 5678, whilst 1
83                         would make the same value look like 12 34 56
84                         78
85  LISTING_LHS_WIDTH      Number of words of above size for the lhs
86
87  LISTING_LHS_WIDTH_SECOND   Number of words for the data on the lhs
88                         for the second line
89
90  LISTING_LHS_CONT_LINES Max number of lines to use up for a continutation
91  LISTING_RHS_WIDTH      Number of chars from the input file to print
92                         on a line
93 */
94
95 #include <ctype.h>
96
97 #include "as.h"
98 #include <obstack.h>
99 #include "input-file.h"
100 #include "subsegs.h"
101
102 #ifndef NO_LISTING
103
104 #ifndef LISTING_HEADER
105 #define LISTING_HEADER "GAS LISTING"
106 #endif
107 #ifndef LISTING_WORD_SIZE
108 #define LISTING_WORD_SIZE 4
109 #endif
110 #ifndef LISTING_LHS_WIDTH
111 #define LISTING_LHS_WIDTH 1
112 #endif
113 #ifndef LISTING_LHS_WIDTH_SECOND
114 #define LISTING_LHS_WIDTH_SECOND 1
115 #endif
116 #ifndef LISTING_RHS_WIDTH
117 #define LISTING_RHS_WIDTH 100
118 #endif
119 #ifndef LISTING_LHS_CONT_LINES
120 #define LISTING_LHS_CONT_LINES 4
121 #endif
122
123 /* This structure remembers which .s were used */
124 typedef struct file_info_struct
125 {
126   struct file_info_struct *next;
127   char *filename;
128   long pos;
129   int linenum;
130   int at_end;
131 }
132 file_info_type;
133
134
135 /* this structure rememebrs which line from which file goes into which
136    frag */
137 struct list_info_struct
138 {
139   /* Frag which this line of source is nearest to */
140   fragS *frag;
141
142   /* The actual line in the source file */
143   unsigned int line;
144   /* Pointer to the file info struct for the file which this line
145      belongs to */
146   file_info_type *file;
147
148   /* The expanded text of any macro that may have been executing.  */
149   char *line_contents;
150
151   /* Next in list */
152   struct list_info_struct *next;
153
154   /* Pointer to the file info struct for the high level language
155      source line that belongs here */
156   file_info_type *hll_file;
157   /* High level language source line */
158   int hll_line;
159
160   /* Pointer to any error message associated with this line */
161   char *message;
162
163   enum
164     {
165       EDICT_NONE,
166       EDICT_SBTTL,
167       EDICT_TITLE,
168       EDICT_NOLIST,
169       EDICT_LIST,
170       EDICT_NOLIST_NEXT,
171       EDICT_EJECT
172     } edict;
173   char *edict_arg;
174
175   /* Nonzero if this line is to be omitted because it contains
176      debugging information.  This can become a flags field if we come
177      up with more information to store here.  */
178   int debugging;
179 };
180
181 typedef struct list_info_struct list_info_type;
182
183 static struct list_info_struct *head;
184 struct list_info_struct *listing_tail;
185 extern int listing;
186
187 static int paper_width = 200;
188 static int paper_height = 60;
189
190 /* File to output listings to.  */
191 static FILE *list_file;
192
193 /* This static array is used to keep the text of data to be printed
194    before the start of the line.  */
195
196 #define MAX_BYTES                                                       \
197   (((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width                    \
198    + ((((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second)        \
199       * listing_lhs_cont_lines)                                         \
200    + 20)
201
202 static char *data_buffer;
203
204 /* Prototypes.  */
205 static void listing_message PARAMS ((const char *name, const char *message));
206 static file_info_type *file_info PARAMS ((const char *file_name));
207 static void new_frag PARAMS ((void));
208 static char *buffer_line PARAMS ((file_info_type *file,
209                                   char *line, unsigned int size));
210 static void listing_page PARAMS ((list_info_type *list));
211 static unsigned int calc_hex PARAMS ((list_info_type *list));
212 static void print_lines PARAMS ((list_info_type *, unsigned int,
213                                  char *, unsigned int));
214 static void list_symbol_table PARAMS ((void));
215 static void print_source PARAMS ((file_info_type *current_file,
216                                   list_info_type *list,
217                                   char *buffer,
218                                   unsigned int width));
219 static int debugging_pseudo PARAMS ((list_info_type *, const char *));
220 static void listing_listing PARAMS ((char *name));
221
222
223 static void
224 listing_message (name, message)
225      const char *name;
226      const char *message;
227 {
228   unsigned int l = strlen (name) + strlen (message) + 1;
229   char *n = (char *) xmalloc (l);
230   strcpy (n, name);
231   strcat (n, message);
232   if (listing_tail != (list_info_type *) NULL)
233     {
234       listing_tail->message = n;
235     }
236 }
237
238 void
239 listing_warning (message)
240      const char *message;
241 {
242   listing_message ("Warning:", message);
243 }
244
245 void
246 listing_error (message)
247      const char *message;
248 {
249   listing_message ("Error:", message);
250 }
251
252
253 int listing_lhs_width = LISTING_LHS_WIDTH;
254 int listing_lhs_width_second = LISTING_LHS_WIDTH_SECOND;
255 int listing_lhs_cont_lines = LISTING_LHS_CONT_LINES;
256 int listing_rhs_width = LISTING_RHS_WIDTH;
257
258
259 static file_info_type *file_info_head;
260 static file_info_type *last_open_file_info;
261 static FILE *last_open_file;
262
263 static file_info_type *
264 file_info (file_name)
265      const char *file_name;
266 {
267   /* Find an entry with this file name */
268   file_info_type *p = file_info_head;
269
270   while (p != (file_info_type *) NULL)
271     {
272       if (strcmp (p->filename, file_name) == 0)
273         return p;
274       p = p->next;
275     }
276
277   /* Make new entry */
278
279   p = (file_info_type *) xmalloc (sizeof (file_info_type));
280   p->next = file_info_head;
281   file_info_head = p;
282   p->filename = xmalloc ((unsigned long) strlen (file_name) + 1);
283   strcpy (p->filename, file_name);
284   p->pos = 0;
285   p->linenum = 0;
286   p->at_end = 0;
287
288   return p;
289 }
290
291
292 static void
293 new_frag ()
294 {
295
296   frag_wane (frag_now);
297   frag_new (0);
298
299 }
300
301 void
302 listing_newline (ps)
303      char *ps;
304 {
305   char *file;
306   unsigned int line;
307   static unsigned int last_line = 0xffff;
308   static char *last_file = NULL;
309   list_info_type *new = NULL;
310
311   if (listing == 0)
312     return;
313
314   if (now_seg == absolute_section)
315     return;
316
317 #ifdef OBJ_ELF
318   /* In ELF, anything in a section beginning with .debug or .line is
319      considered to be debugging information.  This includes the
320      statement which switches us into the debugging section, which we
321      can only set after we are already in the debugging section.  */
322   if ((listing & LISTING_NODEBUG) != 0
323       && listing_tail != NULL
324       && ! listing_tail->debugging)
325     {
326       const char *segname;
327
328       segname = segment_name (now_seg);
329       if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
330           || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
331         listing_tail->debugging = 1;
332     }
333 #endif
334
335   as_where (&file, &line);
336   if (ps == NULL)
337     {
338       if (line == last_line && !(last_file && file && strcmp(file, last_file)))
339         return;
340
341       new = (list_info_type *) xmalloc (sizeof (list_info_type));
342       new->line_contents = NULL;
343     }
344   else
345     {
346       new = (list_info_type *) xmalloc (sizeof (list_info_type));
347       new->line_contents = ps;
348     }
349
350   last_line = line;
351   last_file = file;
352   new_frag ();
353
354   if (listing_tail)
355     {
356       listing_tail->next = new;
357     }
358   else
359     {
360       head = new;
361     }
362   listing_tail = new;
363
364   new->frag = frag_now;
365   new->line = line;
366   new->file = file_info (file);
367   new->next = (list_info_type *) NULL;
368   new->message = (char *) NULL;
369   new->edict = EDICT_NONE;
370   new->hll_file = (file_info_type *) NULL;
371   new->hll_line = 0;
372   new->debugging = 0;
373   new_frag ();
374
375 #ifdef OBJ_ELF
376   /* In ELF, anything in a section beginning with .debug or .line is
377      considered to be debugging information.  */
378   if ((listing & LISTING_NODEBUG) != 0)
379     {
380       const char *segname;
381
382       segname = segment_name (now_seg);
383       if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0
384           || strncmp (segname, ".line", sizeof ".line" - 1) == 0)
385         new->debugging = 1;
386     }
387 #endif
388 }
389
390 /* Attach all current frags to the previous line instead of the
391    current line.  This is called by the MIPS backend when it discovers
392    that it needs to add some NOP instructions; the added NOP
393    instructions should go with the instruction that has the delay, not
394    with the new instruction.  */
395
396 void
397 listing_prev_line ()
398 {
399   list_info_type *l;
400   fragS *f;
401
402   if (head == (list_info_type *) NULL
403       || head == listing_tail)
404     return;
405
406   new_frag ();
407
408   for (l = head; l->next != listing_tail; l = l->next)
409     ;
410
411   for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next)
412     if (f->line == listing_tail)
413       f->line = l;
414
415   listing_tail->frag = frag_now;
416   new_frag ();
417 }
418
419 /*
420  This function returns the next source line from the file supplied,
421  truncated to size.  It appends a fake line to the end of each input
422  file to make
423 */
424
425 static char *
426 buffer_line (file, line, size)
427      file_info_type * file;
428      char *line;
429      unsigned int size;
430 {
431   unsigned int count = 0;
432   int c;
433
434   char *p = line;
435
436   /* If we couldn't open the file, return an empty line */
437   if (file->at_end)
438     return "";
439
440   /* Check the cache and see if we last used this file.  */
441   if (!last_open_file_info || file != last_open_file_info)
442     {
443       if (last_open_file)
444         {
445           last_open_file_info->pos = ftell (last_open_file);
446           fclose (last_open_file);
447         }
448
449       last_open_file_info = file;
450       last_open_file = fopen (file->filename, "r");
451       if (!last_open_file)
452         return "";
453
454       /* Seek to where we were last time this file was open.  */
455       if (file->pos)
456         fseek(last_open_file, file->pos, SEEK_SET);
457     }
458
459   c = fgetc (last_open_file);
460
461   size -= 1;                    /* leave room for null */
462
463   while (c != EOF && c != '\n')
464     {
465       if (count < size)
466         *p++ = c;
467       count++;
468
469       c = fgetc (last_open_file);
470
471     }
472   if (c == EOF)
473     {
474       file->at_end = 1;
475       *p++ = '.';
476       *p++ = '.';
477       *p++ = '.';
478     }
479   file->linenum++;
480   *p++ = 0;
481   return line;
482 }
483
484
485 static const char *fn;
486
487 static unsigned int eject;      /* Eject pending */
488 static unsigned int page;       /* Current page number */
489 static char *title;             /* current title */
490 static char *subtitle;          /* current subtitle */
491 static unsigned int on_page;    /* number of lines printed on current page */
492
493
494 static void
495 listing_page (list)
496      list_info_type *list;
497 {
498   /* Grope around, see if we can see a title or subtitle edict coming up
499      soon  (we look down 10 lines of the page and see if it's there)*/
500   if ((eject || (on_page >= paper_height)) && paper_height != 0)
501     {
502       unsigned int c = 10;
503       int had_title = 0;
504       int had_subtitle = 0;
505
506       page++;
507
508       while (c != 0 && list)
509         {
510           if (list->edict == EDICT_SBTTL && !had_subtitle)
511             {
512               had_subtitle = 1;
513               subtitle = list->edict_arg;
514             }
515           if (list->edict == EDICT_TITLE && !had_title)
516             {
517               had_title = 1;
518               title = list->edict_arg;
519             }
520           list = list->next;
521           c--;
522         }
523
524
525       if (page > 1)
526         {
527           fprintf (list_file, "\f");
528         }
529
530       fprintf (list_file, "%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
531       fprintf (list_file, "%s\n", title);
532       fprintf (list_file, "%s\n", subtitle);
533       on_page = 3;
534       eject = 0;
535     }
536 }
537
538
539 static unsigned int
540 calc_hex (list)
541      list_info_type * list;
542 {
543   int data_buffer_size;
544   list_info_type *first = list;
545   unsigned int address = (unsigned int) ~0;
546   fragS *frag;
547   fragS *frag_ptr;
548   unsigned int byte_in_frag;
549
550   /* Find first frag which says it belongs to this line */
551   frag = list->frag;
552   while (frag && frag->line != list)
553     frag = frag->fr_next;
554
555   frag_ptr = frag;
556
557   data_buffer_size = 0;
558
559   /* Dump all the frags which belong to this line */
560   while (frag_ptr != (fragS *) NULL && frag_ptr->line == first)
561     {
562       /* Print as many bytes from the fixed part as is sensible */
563       byte_in_frag = 0;
564       while (byte_in_frag < frag_ptr->fr_fix
565              && data_buffer_size < MAX_BYTES - 3)
566         {
567           if (address == ~0)
568             {
569               address = frag_ptr->fr_address;
570             }
571
572           sprintf (data_buffer + data_buffer_size,
573                    "%02X",
574                    (frag_ptr->fr_literal[byte_in_frag]) & 0xff);
575           data_buffer_size += 2;
576           byte_in_frag++;
577         }
578       {
579         unsigned int var_rep_max = byte_in_frag;
580         unsigned int var_rep_idx = byte_in_frag;
581
582         /* Print as many bytes from the variable part as is sensible */
583         while ((byte_in_frag
584                 < frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset)
585                && data_buffer_size < MAX_BYTES - 3)
586           {
587             if (address == ~0)
588               {
589                 address = frag_ptr->fr_address;
590               }
591             sprintf (data_buffer + data_buffer_size,
592                      "%02X",
593                      (frag_ptr->fr_literal[var_rep_idx]) & 0xff);
594 #if 0
595             data_buffer[data_buffer_size++] = '*';
596             data_buffer[data_buffer_size++] = '*';
597 #endif
598             data_buffer_size += 2;
599
600             var_rep_idx++;
601             byte_in_frag++;
602
603             if (var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var)
604               var_rep_idx = var_rep_max;
605           }
606       }
607
608       frag_ptr = frag_ptr->fr_next;
609     }
610   data_buffer[data_buffer_size] = '\0';
611   return address;
612 }
613
614
615
616
617
618
619 static void
620 print_lines (list, lineno, string, address)
621      list_info_type *list;
622      unsigned int lineno;
623      char *string;
624      unsigned int address;
625 {
626   unsigned int idx;
627   unsigned int nchars;
628   unsigned int lines;
629   unsigned int byte_in_word = 0;
630   char *src = data_buffer;
631
632   /* Print the stuff on the first line */
633   listing_page (list);
634   nchars = (LISTING_WORD_SIZE * 2 + 1) * listing_lhs_width;
635   /* Print the hex for the first line */
636   if (address == ~0)
637     {
638       fprintf (list_file, "% 4d     ", lineno);
639       for (idx = 0; idx < nchars; idx++)
640         fprintf (list_file, " ");
641
642       fprintf (list_file, "\t%s\n", string ? string : "");
643       on_page++;
644       listing_page (0);
645
646     }
647   else
648     {
649       if (had_errors ())
650         {
651           fprintf (list_file, "% 4d ???? ", lineno);
652         }
653       else
654         {
655           fprintf (list_file, "% 4d %04x ", lineno, address);
656         }
657
658       /* And the data to go along with it */
659       idx = 0;
660
661       while (*src && idx < nchars)
662         {
663           fprintf (list_file, "%c%c", src[0], src[1]);
664           src += 2;
665           byte_in_word++;
666           if (byte_in_word == LISTING_WORD_SIZE)
667             {
668               fprintf (list_file, " ");
669               idx++;
670               byte_in_word = 0;
671             }
672           idx += 2;
673         }
674
675       for (; idx < nchars; idx++)
676         fprintf (list_file, " ");
677
678       fprintf (list_file, "\t%s\n", string ? string : "");
679       on_page++;
680       listing_page (list);
681       if (list->message)
682         {
683           fprintf (list_file, "****  %s\n", list->message);
684           listing_page (list);
685           on_page++;
686         }
687
688       for (lines = 0; lines < listing_lhs_cont_lines && *src; lines++)
689         {
690           nchars = (((LISTING_WORD_SIZE * 2) + 1)
691                     * listing_lhs_width_second - 1);
692           idx = 0;
693           /* Print any more lines of data, but more compactly */
694           fprintf (list_file, "% 4d      ", lineno);
695
696           while (*src && idx < nchars)
697             {
698               fprintf (list_file, "%c%c", src[0], src[1]);
699               src += 2;
700               idx += 2;
701               byte_in_word++;
702               if (byte_in_word == LISTING_WORD_SIZE)
703                 {
704                   fprintf (list_file, " ");
705                   idx++;
706                   byte_in_word = 0;
707                 }
708             }
709
710           fprintf (list_file, "\n");
711           on_page++;
712           listing_page (list);
713
714         }
715
716
717     }
718 }
719
720
721 static void
722 list_symbol_table ()
723 {
724   extern symbolS *symbol_rootP;
725   int got_some = 0;
726
727   symbolS *ptr;
728   eject = 1;
729   listing_page (0);
730
731   for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
732     {
733       if (ptr->sy_frag->line)
734         {
735           if (S_GET_NAME (ptr))
736             {
737               char buf[30], fmt[8];
738               valueT val = S_GET_VALUE (ptr);
739
740               /* @@ Note that this is dependent on the compilation options,
741                  not solely on the target characteristics.  */
742               if (sizeof (val) == 4 && sizeof (int) == 4)
743                 sprintf (buf, "%08lx", (unsigned long) val);
744               else if (sizeof (val) <= sizeof (unsigned long))
745                 {
746                   sprintf (fmt, "%%0%lulx",
747                            (unsigned long) (sizeof (val) * 2));
748                   sprintf (buf, fmt, (unsigned long) val);
749                 }
750 #if defined (BFD64)
751               else if (sizeof (val) > 4)
752                 sprintf_vma (buf, val);
753 #endif
754               else
755                 abort ();
756
757               if (!got_some)
758                 {
759                   fprintf (list_file, "DEFINED SYMBOLS\n");
760                   on_page++;
761                   got_some = 1;
762                 }
763
764               fprintf (list_file, "%20s:%-5d  %s:%s %s\n",
765                        ptr->sy_frag->line->file->filename,
766                        ptr->sy_frag->line->line,
767                        segment_name (S_GET_SEGMENT (ptr)),
768                        buf, S_GET_NAME (ptr));
769
770               on_page++;
771               listing_page (0);
772             }
773         }
774
775     }
776   if (!got_some)
777     {
778       fprintf (list_file, "NO DEFINED SYMBOLS\n");
779       on_page++;
780     }
781   fprintf (list_file, "\n");
782   on_page++;
783   listing_page (0);
784
785   got_some = 0;
786
787   for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
788     {
789       if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
790         {
791           if (ptr->sy_frag->line == 0
792 #ifdef S_IS_REGISTER
793               && !S_IS_REGISTER (ptr)
794 #endif
795               && S_GET_SEGMENT (ptr) != reg_section)
796             {
797               if (!got_some)
798                 {
799                   got_some = 1;
800                   fprintf (list_file, "UNDEFINED SYMBOLS\n");
801                   on_page++;
802                   listing_page (0);
803                 }
804               fprintf (list_file, "%s\n", S_GET_NAME (ptr));
805               on_page++;
806               listing_page (0);
807             }
808         }
809     }
810   if (!got_some)
811     {
812       fprintf (list_file, "NO UNDEFINED SYMBOLS\n");
813       on_page++;
814       listing_page (0);
815     }
816 }
817
818 static void
819 print_source (current_file, list, buffer, width)
820      file_info_type *current_file;
821      list_info_type *list;
822      char *buffer;
823      unsigned int width;
824 {
825   if (!current_file->at_end)
826     {
827       while (current_file->linenum < list->hll_line
828              && !current_file->at_end)
829         {
830           char *p = buffer_line (current_file, buffer, width);
831           fprintf (list_file, "%4d:%-13s **** %s\n", current_file->linenum,
832                    current_file->filename, p);
833           on_page++;
834           listing_page (list);
835         }
836     }
837 }
838
839 /* Sometimes the user doesn't want to be bothered by the debugging
840    records inserted by the compiler, see if the line is suspicious.  */
841
842 static int
843 debugging_pseudo (list, line)
844      list_info_type *list;
845      const char *line;
846 {
847   static int in_debug;
848   int was_debug;
849
850   if (list->debugging)
851     {
852       in_debug = 1;
853       return 1;
854     }
855
856   was_debug = in_debug;
857   in_debug = 0;
858
859   while (isspace (*line))
860     line++;
861
862   if (*line != '.')
863     {
864 #ifdef OBJ_ELF
865       /* The ELF compiler sometimes emits blank lines after switching
866          out of a debugging section.  If the next line drops us back
867          into debugging information, then don't print the blank line.
868          This is a hack for a particular compiler behaviour, not a
869          general case.  */
870       if (was_debug
871           && *line == '\0'
872           && list->next != NULL
873           && list->next->debugging)
874         {
875           in_debug = 1;
876           return 1;
877         }
878 #endif
879
880       return 0;
881     }
882
883   line++;
884
885   if (strncmp (line, "def", 3) == 0)
886     return 1;
887   if (strncmp (line, "val", 3) == 0)
888     return 1;
889   if (strncmp (line, "scl", 3) == 0)
890     return 1;
891   if (strncmp (line, "line", 4) == 0)
892     return 1;
893   if (strncmp (line, "endef", 5) == 0)
894     return 1;
895   if (strncmp (line, "ln", 2) == 0)
896     return 1;
897   if (strncmp (line, "type", 4) == 0)
898     return 1;
899   if (strncmp (line, "size", 4) == 0)
900     return 1;
901   if (strncmp (line, "dim", 3) == 0)
902     return 1;
903   if (strncmp (line, "tag", 3) == 0)
904     return 1;
905
906   if (strncmp (line, "stabs", 5) == 0)
907     return 1;
908   if (strncmp (line, "stabn", 5) == 0)
909     return 1;
910
911   return 0;
912 }
913
914 static void
915 listing_listing (name)
916      char *name;
917 {
918   list_info_type *list = head;
919   file_info_type *current_hll_file = (file_info_type *) NULL;
920   char *message;
921   char *buffer;
922   char *p;
923   int show_listing = 1;
924   unsigned int width;
925
926   buffer = xmalloc (listing_rhs_width);
927   data_buffer = xmalloc (MAX_BYTES);
928   eject = 1;
929   list = head;
930
931   while (list != (list_info_type *) NULL && 0)
932     {
933       if (list->next)
934         list->frag = list->next->frag;
935       list = list->next;
936
937     }
938
939   list = head->next;
940
941
942   while (list)
943     {
944       width = listing_rhs_width > paper_width ? paper_width :
945         listing_rhs_width;
946
947       switch (list->edict)
948         {
949         case EDICT_LIST:
950           show_listing++;
951           break;
952         case EDICT_NOLIST:
953           show_listing--;
954           break;
955         case EDICT_NOLIST_NEXT:
956           break;
957         case EDICT_EJECT:
958           break;
959         case EDICT_NONE:
960           break;
961         case EDICT_TITLE:
962           title = list->edict_arg;
963           break;
964         case EDICT_SBTTL:
965           subtitle = list->edict_arg;
966           break;
967         default:
968           abort ();
969         }
970
971       if (show_listing > 0)
972         {
973           /* Scan down the list and print all the stuff which can be done
974              with this line (or lines).  */
975           message = 0;
976
977           if (list->hll_file)
978             {
979               current_hll_file = list->hll_file;
980             }
981
982           if (current_hll_file && list->hll_line && (listing & LISTING_HLL))
983             {
984               print_source (current_hll_file, list, buffer, width);
985             }
986
987           if (list->line_contents)
988             {
989               if (!((listing & LISTING_NODEBUG)
990                     && debugging_pseudo (list, list->line_contents)))
991                 {
992                   print_lines (list, list->file->linenum,
993                                list->line_contents, calc_hex (list));
994                 }
995             }
996           else
997             {
998               while (list->file->linenum < list->line
999                      && !list->file->at_end)
1000                 {
1001                   unsigned int address;
1002
1003                   p = buffer_line (list->file, buffer, width);
1004
1005                   if (list->file->linenum < list->line)
1006                     address = ~ (unsigned int) 0;
1007                   else
1008                     address = calc_hex (list);
1009
1010                   if (!((listing & LISTING_NODEBUG)
1011                         && debugging_pseudo (list, p)))
1012                     print_lines (list, list->file->linenum, p, address);
1013                 }
1014             }
1015
1016           if (list->edict == EDICT_EJECT)
1017             {
1018               eject = 1;
1019             }
1020         }
1021       else
1022         {
1023           while (list->file->linenum < list->line
1024                  && !list->file->at_end)
1025             p = buffer_line (list->file, buffer, width);
1026         }
1027
1028       if (list->edict == EDICT_NOLIST_NEXT)
1029         --show_listing;
1030
1031       list = list->next;
1032     }
1033
1034   free (buffer);
1035   free (data_buffer);
1036   data_buffer = NULL;
1037 }
1038
1039 void
1040 listing_print (name)
1041      char *name;
1042 {
1043   int using_stdout;
1044   file_info_type *fi;
1045
1046   title = "";
1047   subtitle = "";
1048
1049   if (name == NULL)
1050     {
1051       list_file = stdout;
1052       using_stdout = 1;
1053     }
1054   else
1055     {
1056       list_file = fopen (name, "w");
1057       if (list_file != NULL)
1058         using_stdout = 0;
1059       else
1060         {
1061           as_perror ("can't open list file: %s", name);
1062           list_file = stdout;
1063           using_stdout = 1;
1064         }
1065     }
1066
1067   if (listing & LISTING_NOFORM)
1068     {
1069       paper_height = 0;
1070     }
1071
1072   if (listing & LISTING_LISTING)
1073     {
1074       listing_listing (name);
1075     }
1076
1077   if (listing & LISTING_SYMBOLS)
1078     {
1079       list_symbol_table ();
1080     }
1081
1082   if (! using_stdout)
1083     {
1084       if (fclose (list_file) == EOF)
1085         as_perror ("error closing list file: %s", name);
1086     }
1087
1088   if (last_open_file)
1089     {
1090       fclose (last_open_file);
1091     }
1092 }
1093
1094
1095 void
1096 listing_file (name)
1097      const char *name;
1098 {
1099   fn = name;
1100 }
1101
1102 void
1103 listing_eject (ignore)
1104      int ignore;
1105 {
1106   if (listing)
1107     listing_tail->edict = EDICT_EJECT;
1108 }
1109
1110 void
1111 listing_flags (ignore)
1112      int ignore;
1113 {
1114   while ((*input_line_pointer++) && (*input_line_pointer != '\n'))
1115     input_line_pointer++;
1116
1117 }
1118
1119 /* Turn listing on or off.  An argument of 0 means to turn off
1120    listing.  An argument of 1 means to turn on listing.  An argument
1121    of 2 means to turn off listing, but as of the next line; that is,
1122    the current line should be listed, but the next line should not.  */
1123
1124 void
1125 listing_list (on)
1126      int on;
1127 {
1128   if (listing)
1129     {
1130       switch (on)
1131         {
1132         case 0:
1133           if (listing_tail->edict == EDICT_LIST)
1134             listing_tail->edict = EDICT_NONE;
1135           else
1136             listing_tail->edict = EDICT_NOLIST;
1137           break;
1138         case 1:
1139           if (listing_tail->edict == EDICT_NOLIST
1140               || listing_tail->edict == EDICT_NOLIST_NEXT)
1141             listing_tail->edict = EDICT_NONE;
1142           else
1143             listing_tail->edict = EDICT_LIST;
1144           break;
1145         case 2:
1146           listing_tail->edict = EDICT_NOLIST_NEXT;
1147           break;
1148         default:
1149           abort ();
1150         }
1151     }
1152 }
1153
1154
1155 void
1156 listing_psize (width_only)
1157      int width_only;
1158 {
1159   if (! width_only)
1160     {
1161       paper_height = get_absolute_expression ();
1162
1163       if (paper_height < 0 || paper_height > 1000)
1164         {
1165           paper_height = 0;
1166           as_warn ("strange paper height, set to no form");
1167         }
1168
1169       if (*input_line_pointer != ',')
1170         {
1171           demand_empty_rest_of_line ();
1172           return;
1173         }
1174
1175       ++input_line_pointer;
1176     }
1177
1178   paper_width = get_absolute_expression ();
1179
1180   demand_empty_rest_of_line ();
1181 }
1182
1183 void
1184 listing_nopage (ignore)
1185      int ignore;
1186 {
1187   paper_height = 0;
1188 }
1189
1190 void
1191 listing_title (depth)
1192      int depth;
1193 {
1194   int quoted;
1195   char *start;
1196   char *ttl;
1197   unsigned int length;
1198
1199   SKIP_WHITESPACE ();
1200   if (*input_line_pointer != '\"')
1201     quoted = 0;
1202   else
1203     {
1204       quoted = 1;
1205       ++input_line_pointer;
1206     }
1207
1208   start = input_line_pointer;
1209
1210   while (*input_line_pointer)
1211     {
1212       if (quoted
1213           ? *input_line_pointer == '\"'
1214           : is_end_of_line[(unsigned char) *input_line_pointer])
1215         {
1216           if (listing)
1217             {
1218               length = input_line_pointer - start;
1219               ttl = xmalloc (length + 1);
1220               memcpy (ttl, start, length);
1221               ttl[length] = 0;
1222               listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
1223               listing_tail->edict_arg = ttl;
1224             }
1225           if (quoted)
1226             input_line_pointer++;
1227           demand_empty_rest_of_line ();
1228           return;
1229         }
1230       else if (*input_line_pointer == '\n')
1231         {
1232           as_bad ("New line in title");
1233           demand_empty_rest_of_line ();
1234           return;
1235         }
1236       else
1237         {
1238           input_line_pointer++;
1239         }
1240     }
1241 }
1242
1243
1244
1245 void
1246 listing_source_line (line)
1247      unsigned int line;
1248 {
1249   if (listing)
1250     {
1251       new_frag ();
1252       listing_tail->hll_line = line;
1253       new_frag ();
1254     }
1255 }
1256
1257 void
1258 listing_source_file (file)
1259      const char *file;
1260 {
1261   if (listing)
1262     listing_tail->hll_file = file_info (file);
1263 }
1264
1265
1266
1267 #else
1268
1269
1270 /* Dummy functions for when compiled without listing enabled */
1271
1272 void
1273 listing_flags (ignore)
1274      int ignore;
1275 {
1276   s_ignore (0);
1277 }
1278
1279 void 
1280 listing_list (on)
1281      int on;
1282 {
1283   s_ignore (0);
1284 }
1285
1286 void 
1287 listing_eject (ignore)
1288      int ignore;
1289 {
1290   s_ignore (0);
1291 }
1292
1293 void 
1294 listing_psize (ignore)
1295      int ignore;
1296 {
1297   s_ignore (0);
1298 }
1299
1300 void
1301 listing_nopage (ignore)
1302      int ignore;
1303 {
1304   s_ignore (0);
1305 }
1306
1307 void 
1308 listing_title (depth)
1309      int depth;
1310 {
1311   s_ignore (0);
1312 }
1313
1314 void
1315 listing_file (name)
1316      const char *name;
1317 {
1318
1319 }
1320
1321 void 
1322 listing_newline (name)
1323      char *name;
1324 {
1325
1326 }
1327
1328 void 
1329 listing_source_line (n)
1330      unsigned int n;
1331 {
1332
1333 }
1334 void 
1335 listing_source_file (n)
1336      const char *n;
1337 {
1338
1339 }
1340
1341 #endif