xref: /netbsd-src/external/gpl3/binutils/dist/gas/listing.c (revision cb63e24e8d6aae7ddac1859a9015f48b1d8bd90e)
1 /* listing.c - maintain assembly listings
2    Copyright (C) 1991-2024 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 3, 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, 51 Franklin Street - Fifth Floor, Boston, MA
19    02110-1301, USA.  */
20 
21 /* Contributed by Steve Chamberlain <sac@cygnus.com>
22 
23  A listing page looks like:
24 
25  LISTING_HEADER  sourcefilename pagenumber
26  TITLE LINE
27  SUBTITLE LINE
28  linenumber address data  source
29  linenumber address data  source
30  linenumber address data  source
31  linenumber address data  source
32 
33  If not overridden, the listing commands are:
34 
35  .title  "stuff"
36  	Put "stuff" onto the title line
37  .sbttl  "stuff"
38         Put stuff onto the subtitle line
39 
40   If these commands come within 10 lines of the top of the page, they
41   will affect the page they are on, as well as any subsequent page
42 
43  .eject
44  	Throw a page
45  .list
46  	Increment the enable listing counter
47  .nolist
48  	Decrement the enable listing counter
49 
50  .psize Y[,X]
51  	Set the paper size to X wide and Y high. Setting a psize Y of
52 	zero will suppress form feeds except where demanded by .eject
53 
54  If the counter goes below zero, listing is suppressed.
55 
56  Listings are a maintained by read calling various listing_<foo>
57  functions.  What happens most is that the macro NO_LISTING is not
58  defined (from the Makefile), then the macro LISTING_NEWLINE expands
59  into a call to listing_newline.  The call is done from read.c, every
60  time it sees a newline, and -l is on the command line.
61 
62  The function listing_newline remembers the frag associated with the
63  newline, and creates a new frag - note that this is wasteful, but not
64  a big deal, since listing slows things down a lot anyway.  The
65  function also remembers when the filename changes.
66 
67  When all the input has finished, and gas has had a chance to settle
68  down, the listing is output. This is done by running down the list of
69  frag/source file records, and opening the files as needed and printing
70  out the bytes and chars associated with them.
71 
72  The only things which the architecture can change about the listing
73  are defined in these macros:
74 
75  LISTING_HEADER		The name of the architecture
76  LISTING_WORD_SIZE      The make of the number of bytes in a word, this determines
77  			the clumping of the output data. eg a value of
78 			2 makes words look like 1234 5678, whilst 1
79 			would make the same value look like 12 34 56
80 			78
81  LISTING_LHS_WIDTH      Number of words of above size for the lhs
82 
83  LISTING_LHS_WIDTH_SECOND   Number of words for the data on the lhs
84  			for the second line
85 
86  LISTING_LHS_CONT_LINES	Max number of lines to use up for a continuation
87  LISTING_RHS_WIDTH      Number of chars from the input file to print
88                         on a line.  */
89 
90 #include "as.h"
91 #include "filenames.h"
92 #include "safe-ctype.h"
93 #include "input-file.h"
94 #include "subsegs.h"
95 #include "bfdver.h"
96 #include <time.h>
97 #include <stdarg.h>
98 
99 #ifndef NO_LISTING
100 
101 #ifndef LISTING_HEADER
102 #define LISTING_HEADER "GAS LISTING"
103 #endif
104 #ifndef LISTING_WORD_SIZE
105 #define LISTING_WORD_SIZE 4
106 #endif
107 #ifndef LISTING_LHS_WIDTH
108 #define LISTING_LHS_WIDTH ((LISTING_WORD_SIZE) > 4 ? 1 : 4 / (LISTING_WORD_SIZE))
109 #endif
110 #ifndef LISTING_LHS_WIDTH_SECOND
111 #define LISTING_LHS_WIDTH_SECOND LISTING_LHS_WIDTH
112 #endif
113 #ifndef LISTING_RHS_WIDTH
114 #define LISTING_RHS_WIDTH 100
115 #endif
116 #ifndef LISTING_LHS_CONT_LINES
117 #define LISTING_LHS_CONT_LINES 4
118 #endif
119 #define MAX_DATELEN 30
120 
121 /* This structure remembers which .s were used.  */
122 typedef struct file_info_struct
123 {
124   struct file_info_struct * next;
125   char *                    filename;
126   long                      pos;
127   unsigned int              linenum;
128   int                       at_end;
129 } file_info_type;
130 
131 enum edict_enum
132 {
133   EDICT_NONE,
134   EDICT_SBTTL,
135   EDICT_TITLE,
136   EDICT_NOLIST,
137   EDICT_LIST,
138   EDICT_NOLIST_NEXT,
139   EDICT_EJECT
140 };
141 
142 
143 struct list_message
144 {
145   char *message;
146   struct list_message *next;
147 };
148 
149 /* This structure remembers which line from which file goes into which
150    frag.  */
151 struct list_info_struct
152 {
153   /* Frag which this line of source is nearest to.  */
154   fragS *frag;
155 
156   /* The actual line in the source file.  */
157   unsigned int line;
158 
159   /* Pointer to the file info struct for the file which this line
160      belongs to.  */
161   file_info_type *file;
162 
163   /* The expanded text of any macro that may have been executing.  */
164   char *line_contents;
165 
166   /* Next in list.  */
167   struct list_info_struct *next;
168 
169   /* Pointer to the file info struct for the high level language
170      source line that belongs here.  */
171   file_info_type *hll_file;
172 
173   /* High level language source line.  */
174   unsigned int hll_line;
175 
176   /* Pointers to linked list of messages associated with this line.  */
177   struct list_message *messages, *last_message;
178 
179   enum edict_enum edict;
180   char *edict_arg;
181 
182   /* Nonzero if this line is to be omitted because it contains
183      debugging information.  This can become a flags field if we come
184      up with more information to store here.  */
185   int debugging;
186 };
187 
188 typedef struct list_info_struct list_info_type;
189 
190 int listing_lhs_width        = LISTING_LHS_WIDTH;
191 int listing_lhs_width_second = LISTING_LHS_WIDTH_SECOND;
192 int listing_lhs_cont_lines   = LISTING_LHS_CONT_LINES;
193 int listing_rhs_width        = LISTING_RHS_WIDTH;
194 
195 struct list_info_struct *        listing_tail;
196 
197 static file_info_type *          file_info_head;
198 static file_info_type *          last_open_file_info;
199 static FILE *                    last_open_file;
200 static struct list_info_struct * head;
201 static int                       paper_width = 200;
202 static int                       paper_height = 60;
203 
204 extern int                       listing;
205 
206 /* File to output listings to.  */
207 static FILE *list_file;
208 
209 /* This static array is used to keep the text of data to be printed
210    before the start of the line.  */
211 
212 #define MAX_BYTES							\
213   (((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width			\
214    + ((((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second)	\
215       * listing_lhs_cont_lines)						\
216    + 20)
217 
218 static char *data_buffer;
219 
220 /* Prototypes.  */
221 static void listing_message (const char *, const char *);
222 static file_info_type *file_info (const char *);
223 static void new_frag (void);
224 static void listing_page (list_info_type *);
225 static unsigned int calc_hex (list_info_type *);
226 static void print_lines (list_info_type *, unsigned int, const char *,
227 			 unsigned int);
228 static void list_symbol_table (void);
229 static int debugging_pseudo (list_info_type *, const char *);
230 static void listing_listing (char *);
231 
232 static void
listing_message(const char * name,const char * message)233 listing_message (const char *name, const char *message)
234 {
235   if (listing_tail != (list_info_type *) NULL)
236     {
237       char *n = concat (name, message, (char *) NULL);
238       struct list_message *lm = XNEW (struct list_message);
239       lm->message = n;
240       lm->next = NULL;
241 
242       if (listing_tail->last_message)
243 	listing_tail->last_message->next = lm;
244       else
245 	listing_tail->messages = lm;
246       listing_tail->last_message = lm;
247     }
248 }
249 
250 void
listing_warning(const char * message)251 listing_warning (const char *message)
252 {
253   listing_message (_("Warning: "), message);
254 }
255 
256 void
listing_error(const char * message)257 listing_error (const char *message)
258 {
259   listing_message (_("Error: "), message);
260 }
261 
262 static file_info_type *
file_info(const char * file_name)263 file_info (const char *file_name)
264 {
265   /* Find an entry with this file name.  */
266   file_info_type *p = file_info_head;
267 
268   while (p != (file_info_type *) NULL)
269     {
270       if (filename_cmp (p->filename, file_name) == 0)
271 	return p;
272       p = p->next;
273     }
274 
275   /* Make new entry.  */
276   p = XNEW (file_info_type);
277   p->next = file_info_head;
278   file_info_head = p;
279   p->filename = xstrdup (file_name);
280   p->pos = 0;
281   p->linenum = 0;
282   p->at_end = 0;
283 
284   return p;
285 }
286 
287 static void
new_frag(void)288 new_frag (void)
289 {
290   frag_wane (frag_now);
291   frag_new (0);
292 }
293 
294 void
listing_newline(char * ps)295 listing_newline (char *ps)
296 {
297   const char *file;
298   unsigned int line;
299   static unsigned int last_line = 0xffff;
300   static const char *last_file = NULL;
301   list_info_type *new_i = NULL;
302 
303   if (listing == 0)
304     return;
305 
306   if (now_seg == absolute_section)
307     return;
308 
309 #ifdef OBJ_ELF
310   /* In ELF, anything in a section beginning with .debug or .line is
311      considered to be debugging information.  This includes the
312      statement which switches us into the debugging section, which we
313      can only set after we are already in the debugging section.  */
314   if ((listing & LISTING_NODEBUG) != 0
315       && listing_tail != NULL
316       && ! listing_tail->debugging)
317     {
318       const char *segname;
319 
320       segname = segment_name (now_seg);
321       if (startswith (segname, ".debug")
322 	  || startswith (segname, ".line"))
323 	listing_tail->debugging = 1;
324     }
325 #endif
326 
327   /* PR 21977 - use the physical file name not the logical one unless high
328      level source files are being included in the listing.  */
329   if (listing & LISTING_HLL)
330     file = as_where (&line);
331   else
332     file = as_where_physical (&line);
333 
334   if (ps == NULL)
335     {
336       if (line == last_line
337 	  && !(last_file && file && filename_cmp (file, last_file)))
338 	return;
339 
340       new_i = XNEW (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
350 	 line here (assuming of course that we actually have a line of
351 	 input to read), so that it can be displayed in the listing
352 	 that is produced at the end of the assembly.  */
353       if (strcmp (file, _("{standard input}")) == 0
354 	  && input_line_pointer != NULL)
355 	{
356 	  char *copy, *src, *dest;
357 	  int len;
358 	  int seen_quote = 0;
359 	  int seen_slash = 0;
360 
361 	  for (copy = input_line_pointer;
362 	       *copy && (seen_quote
363 			 || is_end_of_line [(unsigned char) *copy] != 1);
364 	       copy++)
365 	    {
366 	      if (seen_slash)
367 		seen_slash = 0;
368 	      else if (*copy == '\\')
369 		seen_slash = 1;
370 	      else if (*copy == '"')
371 		seen_quote = !seen_quote;
372 	    }
373 
374 	  len = copy - input_line_pointer + 1;
375 
376 	  copy = XNEWVEC (char, len);
377 
378 	  src = input_line_pointer;
379 	  dest = copy;
380 
381 	  while (--len)
382 	    {
383 	      unsigned char c = *src++;
384 
385 	      /* Omit control characters in the listing.  */
386 	      if (!ISCNTRL (c))
387 		*dest++ = c;
388 	    }
389 
390 	  *dest = 0;
391 
392 	  new_i->line_contents = copy;
393 	}
394       else
395 	new_i->line_contents = NULL;
396     }
397   else
398     {
399       new_i = XNEW (list_info_type);
400       new_i->line_contents = ps;
401     }
402 
403   last_line = line;
404   last_file = file;
405 
406   new_frag ();
407 
408   if (listing_tail)
409     listing_tail->next = new_i;
410   else
411     head = new_i;
412 
413   listing_tail = new_i;
414 
415   new_i->frag = frag_now;
416   new_i->line = line;
417   new_i->file = file_info (file);
418   new_i->next = (list_info_type *) NULL;
419   new_i->messages = NULL;
420   new_i->last_message = NULL;
421   new_i->edict = EDICT_NONE;
422   new_i->hll_file = (file_info_type *) NULL;
423   new_i->hll_line = 0;
424   new_i->debugging = 0;
425 
426   new_frag ();
427 
428 #ifdef OBJ_ELF
429   /* In ELF, anything in a section beginning with .debug or .line is
430      considered to be debugging information.  */
431   if ((listing & LISTING_NODEBUG) != 0)
432     {
433       const char *segname;
434 
435       segname = segment_name (now_seg);
436       if (startswith (segname, ".debug")
437 	  || startswith (segname, ".line"))
438 	new_i->debugging = 1;
439     }
440 #endif
441 }
442 
443 /* Attach all current frags to the previous line instead of the
444    current line.  This is called by the MIPS backend when it discovers
445    that it needs to add some NOP instructions; the added NOP
446    instructions should go with the instruction that has the delay, not
447    with the new instruction.  */
448 
449 void
listing_prev_line(void)450 listing_prev_line (void)
451 {
452   list_info_type *l;
453   fragS *f;
454 
455   if (head == (list_info_type *) NULL
456       || head == listing_tail)
457     return;
458 
459   new_frag ();
460 
461   for (l = head; l->next != listing_tail; l = l->next)
462     ;
463 
464   for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next)
465     if (f->line == listing_tail)
466       f->line = l;
467 
468   listing_tail->frag = frag_now;
469   new_frag ();
470 }
471 
472 /* This function returns the next source line from the file supplied,
473    truncated to size.  It appends a fake line to the end of each input
474    file to make using the returned buffer simpler.  */
475 
476 static const char *
buffer_line(file_info_type * file,char * line,unsigned int size)477 buffer_line (file_info_type *file, char *line, unsigned int size)
478 {
479   unsigned int count = 0;
480   int c;
481   char *p = line;
482 
483   /* If we couldn't open the file, return an empty line.  */
484   if (file->at_end)
485     return "";
486 
487   /* Check the cache and see if we last used this file.  */
488   if (!last_open_file_info || file != last_open_file_info)
489     {
490       if (last_open_file)
491 	{
492 	  last_open_file_info->pos = ftell (last_open_file);
493 	  fclose (last_open_file);
494 	}
495 
496       /* Open the file in the binary mode so that ftell above can
497 	 return a reliable value that we can feed to fseek below.  */
498       last_open_file_info = file;
499       last_open_file = fopen (file->filename, FOPEN_RB);
500       if (last_open_file == NULL)
501 	{
502 	  file->at_end = 1;
503 	  return "";
504 	}
505 
506       /* Seek to where we were last time this file was open.  */
507       if (file->pos)
508 	fseek (last_open_file, file->pos, SEEK_SET);
509     }
510 
511   c = fgetc (last_open_file);
512 
513   while (c != EOF && c != '\n' && c != '\r')
514     {
515       if (++count < size)
516 	*p++ = c;
517       c = fgetc (last_open_file);
518     }
519 
520   /* If '\r' is followed by '\n', swallow that.  Likewise, if '\n'
521      is followed by '\r', swallow that as well.  */
522   if (c == '\r' || c == '\n')
523     {
524       int next = fgetc (last_open_file);
525 
526       if ((c == '\r' && next != '\n')
527 	  || (c == '\n' && next != '\r'))
528 	ungetc (next, last_open_file);
529     }
530 
531   if (c == EOF)
532     {
533       file->at_end = 1;
534       if (count + 3 < size)
535 	{
536 	  *p++ = '.';
537 	  *p++ = '.';
538 	  *p++ = '.';
539 	}
540     }
541   file->linenum++;
542   *p++ = 0;
543   return line;
544 }
545 
546 
547 /* This function rewinds the requested file back to the line requested,
548    reads it in again into the buffer provided and then restores the file
549    back to its original location.  */
550 
551 static void
rebuffer_line(file_info_type * file,unsigned int linenum,char * buffer,unsigned int size)552 rebuffer_line (file_info_type *  file,
553 	       unsigned int      linenum,
554 	       char *            buffer,
555 	       unsigned int      size)
556 {
557   unsigned int count = 0;
558   unsigned int current_line;
559   char * p = buffer;
560   long pos;
561   long pos2;
562   int c;
563   bool found = false;
564 
565   /* Sanity checks.  */
566   if (file == NULL || buffer == NULL || size <= 1 || file->linenum <= linenum)
567     return;
568 
569   /* Check the cache and see if we last used this file.  */
570   if (last_open_file_info == NULL || file != last_open_file_info)
571     {
572       if (last_open_file)
573 	{
574 	  last_open_file_info->pos = ftell (last_open_file);
575 	  fclose (last_open_file);
576 	}
577 
578       /* Open the file in the binary mode so that ftell above can
579 	 return a reliable value that we can feed to fseek below.  */
580       last_open_file_info = file;
581       last_open_file = fopen (file->filename, FOPEN_RB);
582       if (last_open_file == NULL)
583 	{
584 	  file->at_end = 1;
585 	  return;
586 	}
587 
588       /* Seek to where we were last time this file was open.  */
589       if (file->pos)
590 	fseek (last_open_file, file->pos, SEEK_SET);
591     }
592 
593   /* Remember where we are in the current file.  */
594   pos2 = pos = ftell (last_open_file);
595   if (pos < 3)
596     return;
597   current_line = file->linenum;
598 
599   /* Leave room for the nul at the end of the buffer.  */
600   size -= 1;
601   buffer[size] = 0;
602 
603   /* Increment the current line count by one.
604      This is to allow for the fact that we are searching for the
605      start of a previous line, but we do this by detecting end-of-line
606      character(s) not start-of-line characters.  */
607   ++ current_line;
608 
609   while (pos2 > 0 && ! found)
610     {
611       char * ptr;
612 
613       /* Move backwards through the file, looking for earlier lines.  */
614       pos2 = (long) size > pos2 ? 0 : pos2 - size;
615       fseek (last_open_file, pos2, SEEK_SET);
616 
617       /* Our caller has kindly provided us with a buffer, so we use it.  */
618       if (fread (buffer, 1, size, last_open_file) != size)
619 	{
620 	  as_warn (_("unable to rebuffer file: %s\n"), file->filename);
621 	  return;
622 	}
623 
624       for (ptr = buffer + size; ptr >= buffer; -- ptr)
625 	{
626 	  if (*ptr == '\n')
627 	    {
628 	      -- current_line;
629 
630 	      if (current_line == linenum)
631 		{
632 		  /* We have found the start of the line we seek.  */
633 		  found = true;
634 
635 		  /* FIXME: We could skip the read-in-the-line code
636 		     below if we know that we already have the whole
637 		     line in the buffer.  */
638 
639 		  /* Advance pos2 to the newline character we have just located.  */
640 		  pos2 += (ptr - buffer);
641 
642 		  /* Skip the newline and, if present, the carriage return.  */
643 		  if (ptr + 1 == buffer + size)
644 		    {
645 		      ++pos2;
646 		      if (fgetc (last_open_file) == '\r')
647 			++ pos2;
648 		    }
649 		  else
650 		    pos2 += (ptr[1] == '\r' ? 2 : 1);
651 
652 		  /* Move the file pointer to this location.  */
653 		  fseek (last_open_file, pos2, SEEK_SET);
654 		  break;
655 		}
656 	    }
657 	}
658     }
659 
660   /* Read in the line.  */
661   c = fgetc (last_open_file);
662 
663   while (c != EOF && c != '\n' && c != '\r')
664     {
665       if (count < size)
666 	*p++ = c;
667       count++;
668 
669       c = fgetc (last_open_file);
670     }
671 
672   /* If '\r' is followed by '\n', swallow that.  Likewise, if '\n'
673      is followed by '\r', swallow that as well.  */
674   if (c == '\r' || c == '\n')
675     {
676       int next = fgetc (last_open_file);
677 
678       if ((c == '\r' && next != '\n')
679 	  || (c == '\n' && next != '\r'))
680 	ungetc (next, last_open_file);
681     }
682 
683   /* Terminate the line.  */
684   *p++ = 0;
685 
686   /* Reset the file position.  */
687   fseek (last_open_file, pos, SEEK_SET);
688 }
689 
690 static const char *fn;
691 static unsigned int eject;	/* Eject pending.  */
692 static unsigned int page;	/* Current page number.  */
693 static const char *title;	/* Current title.  */
694 static const char *subtitle;	/* Current subtitle.  */
695 static unsigned int on_page;	/* Number of lines printed on current page.  */
696 
697 static void
listing_page(list_info_type * list)698 listing_page (list_info_type *list)
699 {
700   /* Grope around, see if we can see a title or subtitle edict coming up
701      soon.  (we look down 10 lines of the page and see if it's there)  */
702   if ((eject || (on_page >= (unsigned int) paper_height))
703       && paper_height != 0)
704     {
705       unsigned int c = 10;
706       int had_title = 0;
707       int had_subtitle = 0;
708 
709       page++;
710 
711       while (c != 0 && list)
712 	{
713 	  if (list->edict == EDICT_SBTTL && !had_subtitle)
714 	    {
715 	      had_subtitle = 1;
716 	      subtitle = list->edict_arg;
717 	    }
718 	  if (list->edict == EDICT_TITLE && !had_title)
719 	    {
720 	      had_title = 1;
721 	      title = list->edict_arg;
722 	    }
723 	  list = list->next;
724 	  c--;
725 	}
726 
727       if (page > 1)
728 	{
729 	  fprintf (list_file, "\f");
730 	}
731 
732       fprintf (list_file, "%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page);
733       fprintf (list_file, "%s\n", title);
734       fprintf (list_file, "%s\n", subtitle);
735       on_page = 3;
736       eject = 0;
737     }
738 }
739 
740 /* Print a line into the list_file.  Update the line count
741    and if necessary start a new page.  */
742 
743 static void
emit_line(list_info_type * list,const char * format,...)744 emit_line (list_info_type * list, const char * format, ...)
745 {
746   va_list args;
747 
748   va_start (args, format);
749 
750   vfprintf (list_file, format, args);
751   on_page++;
752   listing_page (list);
753 
754   va_end (args);
755 }
756 
757 static unsigned int
calc_hex(list_info_type * list)758 calc_hex (list_info_type *list)
759 {
760   int data_buffer_size;
761   list_info_type *first = list;
762   unsigned int address = ~(unsigned int) 0;
763   fragS *frag;
764   fragS *frag_ptr;
765   unsigned int octet_in_frag;
766 
767   /* Find first frag which says it belongs to this line.  */
768   frag = list->frag;
769   while (frag && frag->line != list)
770     frag = frag->fr_next;
771 
772   frag_ptr = frag;
773 
774   data_buffer_size = 0;
775 
776   /* Dump all the frags which belong to this line.  */
777   while (frag_ptr != (fragS *) NULL && frag_ptr->line == first)
778     {
779       /* Print as many bytes from the fixed part as is sensible.  */
780       octet_in_frag = 0;
781       while (octet_in_frag < frag_ptr->fr_fix
782 	     && data_buffer_size < MAX_BYTES - 3)
783 	{
784 	  if (address == ~(unsigned int) 0)
785 	    address = frag_ptr->fr_address / OCTETS_PER_BYTE;
786 
787 	  sprintf (data_buffer + data_buffer_size,
788 		   "%02X",
789 		   (frag_ptr->fr_literal[octet_in_frag]) & 0xff);
790 	  data_buffer_size += 2;
791 	  octet_in_frag++;
792 	}
793       if (frag_ptr->fr_type == rs_fill)
794 	{
795 	  unsigned int var_rep_max = octet_in_frag;
796 	  unsigned int var_rep_idx = octet_in_frag;
797 
798 	  /* Print as many bytes from the variable part as is sensible.  */
799 	  while ((octet_in_frag
800 		  < frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset)
801 		 && data_buffer_size < MAX_BYTES - 3)
802 	    {
803 	      if (address == ~(unsigned int) 0)
804 		address = frag_ptr->fr_address / OCTETS_PER_BYTE;
805 
806 	      sprintf (data_buffer + data_buffer_size,
807 		       "%02X",
808 		       (frag_ptr->fr_literal[var_rep_idx]) & 0xff);
809 	      data_buffer_size += 2;
810 
811 	      var_rep_idx++;
812 	      octet_in_frag++;
813 
814 	      if (var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var)
815 		var_rep_idx = var_rep_max;
816 	    }
817 	}
818       else if (frag_ptr->fr_type == rs_fill_nop && frag_ptr->fr_opcode)
819 	{
820 	  gas_assert (!octet_in_frag);
821 
822 	  /* Print as many bytes from fr_opcode as is sensible.  */
823 	  while (octet_in_frag < (unsigned int) frag_ptr->fr_offset
824 		 && data_buffer_size < MAX_BYTES - 3)
825 	    {
826 	      if (address == ~(unsigned int) 0)
827 		address = frag_ptr->fr_address / OCTETS_PER_BYTE;
828 
829 	      sprintf (data_buffer + data_buffer_size,
830 		       "%02X",
831 		       frag_ptr->fr_opcode[octet_in_frag] & 0xff);
832 	      data_buffer_size += 2;
833 
834 	      octet_in_frag++;
835 	    }
836 
837 	  free (frag_ptr->fr_opcode);
838 	  frag_ptr->fr_opcode = NULL;
839 	}
840 
841       frag_ptr = frag_ptr->fr_next;
842     }
843   data_buffer[data_buffer_size] = '\0';
844   return address;
845 }
846 
847 static void
print_lines(list_info_type * list,unsigned int lineno,const char * string,unsigned int address)848 print_lines (list_info_type *list, unsigned int lineno,
849 	     const char *string, unsigned int address)
850 {
851   unsigned int idx;
852   unsigned int nchars;
853   unsigned int lines;
854   unsigned int octet_in_word = 0;
855   char *src = data_buffer;
856   int cur;
857   struct list_message *msg;
858 
859   /* Print the stuff on the first line.  */
860   listing_page (list);
861   nchars = (LISTING_WORD_SIZE * 2 + 1) * listing_lhs_width;
862 
863   /* Print the hex for the first line.  */
864   if (address == ~(unsigned int) 0)
865     {
866       fprintf (list_file, "% 4d     ", lineno);
867       for (idx = 0; idx < nchars; idx++)
868 	fprintf (list_file, " ");
869 
870       emit_line (NULL, "\t%s\n", string ? string : "");
871       return;
872     }
873 
874   if (had_errors ())
875     fprintf (list_file, "% 4d ???? ", lineno);
876   else
877     fprintf (list_file, "% 4d %04x ", lineno, address);
878 
879   /* And the data to go along with it.  */
880   idx = 0;
881   cur = 0;
882   while (src[cur] && idx < nchars)
883     {
884       int offset;
885       offset = cur;
886       fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
887       cur += 2;
888       octet_in_word++;
889 
890       if (octet_in_word == LISTING_WORD_SIZE)
891 	{
892 	  fprintf (list_file, " ");
893 	  idx++;
894 	  octet_in_word = 0;
895 	}
896 
897       idx += 2;
898     }
899 
900   for (; idx < nchars; idx++)
901     fprintf (list_file, " ");
902 
903   emit_line (list, "\t%s\n", string ? string : "");
904 
905   for (msg = list->messages; msg; msg = msg->next)
906     emit_line (list, "****  %s\n", msg->message);
907 
908   for (lines = 0;
909        lines < (unsigned int) listing_lhs_cont_lines
910 	 && src[cur];
911        lines++)
912     {
913       nchars = ((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second - 1;
914       idx = 0;
915 
916       /* Print any more lines of data, but more compactly.  */
917       fprintf (list_file, "% 4d      ", lineno);
918 
919       while (src[cur] && idx < nchars)
920 	{
921 	  int offset;
922 	  offset = cur;
923 	  fprintf (list_file, "%c%c", src[offset], src[offset + 1]);
924 	  cur += 2;
925 	  idx += 2;
926 	  octet_in_word++;
927 
928 	  if (octet_in_word == LISTING_WORD_SIZE)
929 	    {
930 	      fprintf (list_file, " ");
931 	      idx++;
932 	      octet_in_word = 0;
933 	    }
934 	}
935 
936       emit_line (list, "\n");
937     }
938 }
939 
940 static void
list_symbol_table(void)941 list_symbol_table (void)
942 {
943   extern symbolS *symbol_rootP;
944   int got_some = 0;
945 
946   symbolS *ptr;
947   eject = 1;
948   listing_page (NULL);
949 
950   for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
951     {
952       if (SEG_NORMAL (S_GET_SEGMENT (ptr))
953 	  || S_GET_SEGMENT (ptr) == absolute_section)
954 	{
955 	  /* Don't report section symbols.  They are not interesting.  */
956 	  if (symbol_section_p (ptr))
957 	    continue;
958 
959 	  if (S_GET_NAME (ptr))
960 	    {
961 	      char buf[30];
962 	      valueT val = S_GET_VALUE (ptr);
963 
964 	      bfd_sprintf_vma (stdoutput, buf, val);
965 	      if (!got_some)
966 		{
967 		  fprintf (list_file, "DEFINED SYMBOLS\n");
968 		  on_page++;
969 		  got_some = 1;
970 		}
971 
972 	      if (symbol_get_frag (ptr) && symbol_get_frag (ptr)->line)
973 		{
974 		  fprintf (list_file, "%20s:%-5d  %s:%s %s\n",
975 			   symbol_get_frag (ptr)->line->file->filename,
976 			   symbol_get_frag (ptr)->line->line,
977 			   segment_name (S_GET_SEGMENT (ptr)),
978 			   buf, S_GET_NAME (ptr));
979 		}
980 	      else
981 		{
982 		  fprintf (list_file, "%33s:%s %s\n",
983 			   segment_name (S_GET_SEGMENT (ptr)),
984 			   buf, S_GET_NAME (ptr));
985 		}
986 
987 	      on_page++;
988 	      listing_page (NULL);
989 	    }
990 	}
991 
992     }
993   if (!got_some)
994     {
995       fprintf (list_file, "NO DEFINED SYMBOLS\n");
996       on_page++;
997     }
998   emit_line (NULL, "\n");
999 
1000   got_some = 0;
1001 
1002   for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr))
1003     {
1004       if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0)
1005 	{
1006 	  if (S_GET_SEGMENT (ptr) == undefined_section)
1007 	    {
1008 	      if (!got_some)
1009 		{
1010 		  got_some = 1;
1011 
1012 		  emit_line (NULL, "UNDEFINED SYMBOLS\n");
1013 		}
1014 
1015 	      emit_line (NULL, "%s\n", S_GET_NAME (ptr));
1016 	    }
1017 	}
1018     }
1019 
1020   if (!got_some)
1021     emit_line (NULL, "NO UNDEFINED SYMBOLS\n");
1022 }
1023 
1024 typedef struct cached_line
1025 {
1026   file_info_type * file;
1027   unsigned int     line;
1028   char             buffer [LISTING_RHS_WIDTH];
1029 } cached_line;
1030 
1031 static void
print_source(file_info_type * current_file,list_info_type * list,unsigned int width)1032 print_source (file_info_type *  current_file,
1033 	      list_info_type *  list,
1034 	      unsigned int      width)
1035 {
1036 #define NUM_CACHE_LINES  3
1037   static cached_line cached_lines[NUM_CACHE_LINES];
1038   static int next_free_line = 0;
1039   cached_line * cache = NULL;
1040 
1041   if (current_file->linenum > list->hll_line
1042       && list->hll_line > 0)
1043     {
1044       /* This can happen with modern optimizing compilers.  The source
1045 	 lines from the high level language input program are split up
1046 	 and interleaved, meaning the line number we want to display
1047 	 (list->hll_line) can have already been displayed.  We have
1048 	 three choices:
1049 
1050 	   a. Do nothing, since we have already displayed the source
1051 	      line.  This was the old behaviour.
1052 
1053 	   b. Display the particular line requested again, but only
1054 	      that line.  This is the new behaviour.
1055 
1056 	   c. Display the particular line requested again and reset
1057 	      the current_file->line_num value so that we redisplay
1058 	      all the following lines as well the next time we
1059 	      encounter a larger line number.  */
1060       int i;
1061 
1062       /* Check the cache, maybe we already have the line saved.  */
1063       for (i = 0; i < NUM_CACHE_LINES; i++)
1064 	if (cached_lines[i].file == current_file
1065 	    && cached_lines[i].line == list->hll_line)
1066 	  {
1067 	    cache = cached_lines + i;
1068 	    break;
1069 	  }
1070 
1071       if (i == NUM_CACHE_LINES)
1072 	{
1073 	  cache = cached_lines + next_free_line;
1074 	  next_free_line ++;
1075 	  if (next_free_line == NUM_CACHE_LINES)
1076 	    next_free_line = 0;
1077 
1078 	  cache->file = current_file;
1079 	  cache->line = list->hll_line;
1080 	  cache->buffer[0] = 0;
1081 	  rebuffer_line (current_file, cache->line, cache->buffer, width);
1082 	}
1083 
1084       emit_line (list, "%4u:%-13s **** %s\n",
1085 		 cache->line, cache->file->filename, cache->buffer);
1086       return;
1087     }
1088 
1089   if (!current_file->at_end)
1090     {
1091       int num_lines_shown = 0;
1092 
1093       while (current_file->linenum < list->hll_line
1094 	     && !current_file->at_end)
1095 	{
1096 	  const char *p;
1097 
1098 	  cache = cached_lines + next_free_line;
1099 	  cache->file = current_file;
1100 	  cache->line = current_file->linenum + 1;
1101 	  cache->buffer[0] = 0;
1102 	  p = buffer_line (current_file, cache->buffer, width);
1103 
1104 	  /* Cache optimization:  If printing a group of lines
1105 	     cache the first and last lines in the group.  */
1106 	  if (num_lines_shown == 0)
1107 	    {
1108 	      next_free_line ++;
1109 	      if (next_free_line == NUM_CACHE_LINES)
1110 		next_free_line = 0;
1111 	    }
1112 
1113 	  emit_line (list, "%4u:%-13s **** %s\n",
1114 		     cache->line, cache->file->filename, p);
1115 	  num_lines_shown ++;
1116 	}
1117     }
1118 }
1119 
1120 /* Sometimes the user doesn't want to be bothered by the debugging
1121    records inserted by the compiler, see if the line is suspicious.  */
1122 
1123 static int
debugging_pseudo(list_info_type * list,const char * line)1124 debugging_pseudo (list_info_type *list, const char *line)
1125 {
1126 #ifdef OBJ_ELF
1127   static int in_debug;
1128   int was_debug;
1129 #endif
1130 
1131   if (list->debugging)
1132     {
1133 #ifdef OBJ_ELF
1134       in_debug = 1;
1135 #endif
1136       return 1;
1137     }
1138 #ifdef OBJ_ELF
1139   was_debug = in_debug;
1140   in_debug = 0;
1141 #endif
1142 
1143   while (ISSPACE (*line))
1144     line++;
1145 
1146   if (*line != '.')
1147     {
1148 #ifdef OBJ_ELF
1149       /* The ELF compiler sometimes emits blank lines after switching
1150          out of a debugging section.  If the next line drops us back
1151          into debugging information, then don't print the blank line.
1152          This is a hack for a particular compiler behaviour, not a
1153          general case.  */
1154       if (was_debug
1155 	  && *line == '\0'
1156 	  && list->next != NULL
1157 	  && list->next->debugging)
1158 	{
1159 	  in_debug = 1;
1160 	  return 1;
1161 	}
1162 #endif
1163 
1164       return 0;
1165     }
1166 
1167   line++;
1168 
1169   if (startswith (line, "def"))
1170     return 1;
1171   if (startswith (line, "val"))
1172     return 1;
1173   if (startswith (line, "scl"))
1174     return 1;
1175   if (startswith (line, "line"))
1176     return 1;
1177   if (startswith (line, "endef"))
1178     return 1;
1179   if (startswith (line, "ln"))
1180     return 1;
1181   if (startswith (line, "type"))
1182     return 1;
1183   if (startswith (line, "size"))
1184     return 1;
1185   if (startswith (line, "dim"))
1186     return 1;
1187   if (startswith (line, "tag"))
1188     return 1;
1189   if (startswith (line, "stabs"))
1190     return 1;
1191   if (startswith (line, "stabn"))
1192     return 1;
1193 
1194   return 0;
1195 }
1196 
1197 static void
listing_listing(char * name ATTRIBUTE_UNUSED)1198 listing_listing (char *name ATTRIBUTE_UNUSED)
1199 {
1200   list_info_type *list = head;
1201   file_info_type *current_hll_file = (file_info_type *) NULL;
1202   char *buffer;
1203   const char *p;
1204   int show_listing = 1;
1205   unsigned int width;
1206 
1207   buffer = XNEWVEC (char, listing_rhs_width);
1208   data_buffer = XNEWVEC (char, MAX_BYTES);
1209   eject = 1;
1210   list = head->next;
1211 
1212   while (list)
1213     {
1214       unsigned int list_line;
1215 
1216       width = listing_rhs_width > paper_width ? paper_width :
1217 	listing_rhs_width;
1218 
1219       list_line = list->line;
1220       switch (list->edict)
1221 	{
1222 	case EDICT_LIST:
1223 	  /* Skip all lines up to the current.  */
1224 	  list_line--;
1225 	  break;
1226 	case EDICT_NOLIST:
1227 	  show_listing--;
1228 	  break;
1229 	case EDICT_NOLIST_NEXT:
1230 	  if (show_listing == 0)
1231 	    list_line--;
1232 	  break;
1233 	case EDICT_EJECT:
1234 	  break;
1235 	case EDICT_NONE:
1236 	  break;
1237 	case EDICT_TITLE:
1238 	  title = list->edict_arg;
1239 	  break;
1240 	case EDICT_SBTTL:
1241 	  subtitle = list->edict_arg;
1242 	  break;
1243 	default:
1244 	  abort ();
1245 	}
1246 
1247       if (show_listing <= 0)
1248 	{
1249 	  while (list->file->linenum < list_line
1250 		 && !list->file->at_end)
1251 	    p = buffer_line (list->file, buffer, width);
1252 	}
1253 
1254       if (list->edict == EDICT_LIST
1255 	  || (list->edict == EDICT_NOLIST_NEXT && show_listing == 0))
1256 	{
1257 	  /* Enable listing for the single line that caused the enable.  */
1258 	  list_line++;
1259 	  show_listing++;
1260 	}
1261 
1262       if (show_listing > 0)
1263 	{
1264 	  /* Scan down the list and print all the stuff which can be done
1265 	     with this line (or lines).  */
1266 	  if (list->hll_file)
1267 	    current_hll_file = list->hll_file;
1268 
1269 	  if (current_hll_file && list->hll_line && (listing & LISTING_HLL))
1270 	    print_source (current_hll_file, list, width);
1271 
1272 	  if (!list->line_contents || list->file->linenum)
1273 	    {
1274 	      while (list->file->linenum < list_line
1275 		     && !list->file->at_end)
1276 		{
1277 		  unsigned int address;
1278 
1279 		  p = buffer_line (list->file, buffer, width);
1280 
1281 		  if (list->file->linenum < list_line)
1282 		    address = ~(unsigned int) 0;
1283 		  else
1284 		    address = calc_hex (list);
1285 
1286 		  if (!((listing & LISTING_NODEBUG)
1287 			&& debugging_pseudo (list, p)))
1288 		    print_lines (list, list->file->linenum, p, address);
1289 		}
1290 	    }
1291 
1292 	  if (list->line_contents)
1293 	    {
1294 	      if (!((listing & LISTING_NODEBUG)
1295 		    && debugging_pseudo (list, list->line_contents)))
1296 		print_lines (list, list->line, list->line_contents,
1297 			     calc_hex (list));
1298 
1299 	      free (list->line_contents);
1300 	      list->line_contents = NULL;
1301 	    }
1302 
1303 	  if (list->edict == EDICT_EJECT)
1304 	    eject = 1;
1305 	}
1306 
1307       if (list->edict == EDICT_NOLIST_NEXT && show_listing == 1)
1308 	--show_listing;
1309 
1310       list = list->next;
1311     }
1312 
1313   free (buffer);
1314   free (data_buffer);
1315   data_buffer = NULL;
1316 }
1317 
1318 /* Print time stamp in ISO format:  yyyy-mm-ddThh:mm:ss.ss+/-zzzz.  */
1319 
1320 static void
print_timestamp(void)1321 print_timestamp (void)
1322 {
1323   const time_t now = time (NULL);
1324   struct tm * timestamp;
1325   char stampstr[MAX_DATELEN];
1326 
1327   /* Any portable way to obtain subsecond values???  */
1328   timestamp = localtime (&now);
1329   strftime (stampstr, MAX_DATELEN, "%Y-%m-%dT%H:%M:%S.000%z", timestamp);
1330   fprintf (list_file, _("\n time stamp    \t: %s\n\n"), stampstr);
1331 }
1332 
1333 static void
print_single_option(char * opt,int * pos)1334 print_single_option (char * opt, int *pos)
1335 {
1336   int opt_len = strlen (opt);
1337 
1338    if ((*pos + opt_len) < paper_width)
1339      {
1340         fprintf (list_file, _("%s "), opt);
1341         *pos = *pos + opt_len;
1342      }
1343    else
1344      {
1345         fprintf (list_file, _("\n\t%s "), opt);
1346         *pos = opt_len;
1347      }
1348 }
1349 
1350 /* Print options passed to as.  */
1351 
1352 static void
print_options(char ** argv)1353 print_options (char ** argv)
1354 {
1355   const char *field_name = _("\n options passed\t: ");
1356   int pos = strlen (field_name);
1357   char **p;
1358 
1359   fputs (field_name, list_file);
1360   for (p = &argv[1]; *p != NULL; p++)
1361     if (**p == '-')
1362       {
1363         /* Ignore these.  */
1364         if (strcmp (*p, "-o") == 0)
1365           {
1366             if (p[1] != NULL)
1367               p++;
1368             continue;
1369           }
1370         if (strcmp (*p, "-v") == 0)
1371           continue;
1372 
1373         print_single_option (*p, &pos);
1374       }
1375 }
1376 
1377 /* Print a first section with basic info like file names, as version,
1378    options passed, target, and timestamp.
1379    The format of this section is as follows:
1380 
1381    AS VERSION
1382 
1383    fieldname TAB ':' fieldcontents
1384   { TAB fieldcontents-cont }  */
1385 
1386 static void
listing_general_info(char ** argv)1387 listing_general_info (char ** argv)
1388 {
1389   /* Print the stuff on the first line.  */
1390   eject = 1;
1391   listing_page (NULL);
1392 
1393   fprintf (list_file,
1394            _(" GNU assembler version %s (%s)\n\t using BFD version %s."),
1395            VERSION, TARGET_ALIAS, BFD_VERSION_STRING);
1396   print_options (argv);
1397   fprintf (list_file, _("\n input file    \t: %s"), fn);
1398   fprintf (list_file, _("\n output file   \t: %s"), out_file_name);
1399   fprintf (list_file, _("\n target        \t: %s"), TARGET_CANONICAL);
1400   print_timestamp ();
1401 }
1402 
1403 void
listing_print(char * name,char ** argv)1404 listing_print (char *name, char **argv)
1405 {
1406   int using_stdout;
1407 
1408   title = "";
1409   subtitle = "";
1410 
1411   if (name == NULL)
1412     {
1413       list_file = stdout;
1414       using_stdout = 1;
1415     }
1416   else
1417     {
1418       list_file = fopen (name, FOPEN_WT);
1419       if (list_file != NULL)
1420 	using_stdout = 0;
1421       else
1422 	{
1423 	  as_warn (_("can't open %s: %s"), name, xstrerror (errno));
1424 	  list_file = stdout;
1425 	  using_stdout = 1;
1426 	}
1427     }
1428 
1429   if (listing & LISTING_NOFORM)
1430     paper_height = 0;
1431 
1432   if (listing & LISTING_GENERAL)
1433     listing_general_info (argv);
1434 
1435   if (listing & LISTING_LISTING)
1436     listing_listing (name);
1437 
1438   if (listing & LISTING_SYMBOLS)
1439     list_symbol_table ();
1440 
1441   if (! using_stdout)
1442     {
1443       if (fclose (list_file) == EOF)
1444 	as_warn (_("can't close %s: %s"), name, xstrerror (errno));
1445     }
1446 
1447   if (last_open_file)
1448     fclose (last_open_file);
1449 }
1450 
1451 void
listing_file(const char * name)1452 listing_file (const char *name)
1453 {
1454   fn = name;
1455 }
1456 
1457 void
listing_eject(int ignore ATTRIBUTE_UNUSED)1458 listing_eject (int ignore ATTRIBUTE_UNUSED)
1459 {
1460   if (listing)
1461     listing_tail->edict = EDICT_EJECT;
1462 }
1463 
1464 /* Turn listing on or off.  An argument of 0 means to turn off
1465    listing.  An argument of 1 means to turn on listing.  An argument
1466    of 2 means to turn off listing, but as of the next line; that is,
1467    the current line should be listed, but the next line should not.  */
1468 
1469 void
listing_list(int on)1470 listing_list (int on)
1471 {
1472   if (listing)
1473     {
1474       switch (on)
1475 	{
1476 	case 0:
1477 	  if (listing_tail->edict == EDICT_LIST)
1478 	    listing_tail->edict = EDICT_NONE;
1479 	  else
1480 	    listing_tail->edict = EDICT_NOLIST;
1481 	  break;
1482 	case 1:
1483 	  if (listing_tail->edict == EDICT_NOLIST
1484 	      || listing_tail->edict == EDICT_NOLIST_NEXT)
1485 	    listing_tail->edict = EDICT_NONE;
1486 	  else
1487 	    listing_tail->edict = EDICT_LIST;
1488 	  break;
1489 	case 2:
1490 	  listing_tail->edict = EDICT_NOLIST_NEXT;
1491 	  break;
1492 	default:
1493 	  abort ();
1494 	}
1495     }
1496 }
1497 
1498 void
listing_psize(int width_only)1499 listing_psize (int width_only)
1500 {
1501   if (! width_only)
1502     {
1503       paper_height = get_absolute_expression ();
1504 
1505       if (paper_height < 0 || paper_height > 1000)
1506 	{
1507 	  paper_height = 0;
1508 	  as_warn (_("strange paper height, set to no form"));
1509 	}
1510 
1511       if (*input_line_pointer != ',')
1512 	{
1513 	  demand_empty_rest_of_line ();
1514 	  return;
1515 	}
1516 
1517       ++input_line_pointer;
1518     }
1519 
1520   {
1521     expressionS exp;
1522 
1523     (void) expression_and_evaluate (& exp);
1524 
1525     if (exp.X_op == O_constant)
1526       {
1527 	offsetT new_width = exp.X_add_number;
1528 
1529 	if (new_width > 7)
1530 	  paper_width = new_width;
1531 	else
1532 	  as_bad (_("new paper width is too small"));
1533       }
1534     else if (exp.X_op != O_absent)
1535       as_bad (_("bad or irreducible expression for paper width"));
1536     else
1537       as_bad (_("missing expression for paper width"));
1538   }
1539 
1540   demand_empty_rest_of_line ();
1541 }
1542 
1543 void
listing_nopage(int ignore ATTRIBUTE_UNUSED)1544 listing_nopage (int ignore ATTRIBUTE_UNUSED)
1545 {
1546   paper_height = 0;
1547 }
1548 
1549 void
listing_title(int depth)1550 listing_title (int depth)
1551 {
1552   int quoted;
1553   char *start;
1554   char *ttl;
1555   unsigned int length;
1556 
1557   SKIP_WHITESPACE ();
1558   if (*input_line_pointer != '\"')
1559     quoted = 0;
1560   else
1561     {
1562       quoted = 1;
1563       ++input_line_pointer;
1564     }
1565 
1566   start = input_line_pointer;
1567 
1568   while (*input_line_pointer)
1569     {
1570       if (quoted
1571 	  ? *input_line_pointer == '\"'
1572 	  : is_end_of_line[(unsigned char) *input_line_pointer])
1573 	{
1574 	  if (listing)
1575 	    {
1576 	      length = input_line_pointer - start;
1577 	      ttl = xmemdup0 (start, length);
1578 	      listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE;
1579 	      listing_tail->edict_arg = ttl;
1580 	    }
1581 	  if (quoted)
1582 	    input_line_pointer++;
1583 	  demand_empty_rest_of_line ();
1584 	  return;
1585 	}
1586       else if (*input_line_pointer == '\n')
1587 	{
1588 	  as_bad (_("new line in title"));
1589 	  demand_empty_rest_of_line ();
1590 	  return;
1591 	}
1592       else
1593 	{
1594 	  input_line_pointer++;
1595 	}
1596     }
1597 }
1598 
1599 void
listing_source_line(unsigned int line)1600 listing_source_line (unsigned int line)
1601 {
1602   if (listing)
1603     {
1604       new_frag ();
1605       listing_tail->hll_line = line;
1606       new_frag ();
1607     }
1608 }
1609 
1610 void
listing_source_file(const char * file)1611 listing_source_file (const char *file)
1612 {
1613   if (listing)
1614     listing_tail->hll_file = file_info (file);
1615 }
1616 
1617 #else
1618 
1619 /* Dummy functions for when compiled without listing enabled.  */
1620 
1621 void
listing_list(int on)1622 listing_list (int on)
1623 {
1624   s_ignore (0);
1625 }
1626 
1627 void
listing_eject(int ignore)1628 listing_eject (int ignore)
1629 {
1630   s_ignore (0);
1631 }
1632 
1633 void
listing_psize(int ignore)1634 listing_psize (int ignore)
1635 {
1636   s_ignore (0);
1637 }
1638 
1639 void
listing_nopage(int ignore)1640 listing_nopage (int ignore)
1641 {
1642   s_ignore (0);
1643 }
1644 
1645 void
listing_title(int depth)1646 listing_title (int depth)
1647 {
1648   s_ignore (0);
1649 }
1650 
1651 void
listing_file(const char * name)1652 listing_file (const char *name)
1653 {
1654 }
1655 
1656 void
listing_newline(char * name)1657 listing_newline (char *name)
1658 {
1659 }
1660 
1661 void
listing_source_line(unsigned int n)1662 listing_source_line (unsigned int n)
1663 {
1664 }
1665 
1666 void
listing_source_file(const char * n)1667 listing_source_file (const char *n)
1668 {
1669 }
1670 
1671 #endif
1672