Coverage Report

Created: 2023-08-28 06:31

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