Subversion Repositories Kolibri OS

Rev

Rev 5222 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

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