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