1 /* listing.c - mainting assembly listings
2 Copyright (C) 1991, 1992 Free Software Foundation, Inc.
4 This file is part of GAS, the GNU Assembler.
6 GAS is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2, or (at your option)
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.
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
18 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 Contributed by Steve Chamberlain
25 A listing page looks like:
27 LISTING_HEADER sourcefilename pagenumber
30 linenumber address data source
31 linenumber address data source
32 linenumber address data source
33 linenumber address data source
35 If not overridden, the listing commands are:
38 Put "stuff" onto the title line
40 Put stuff onto the subtitle line
42 If these commands come within 10 lines of the top of the page, they
43 will affect the page they are on, as well as any subsequent page
48 Increment the enable listing counter
50 Decrement the enable listing counter
53 Set the paper size to X wide and Y high. Setting a psize Y of
54 zero will suppress form feeds except where demanded by .eject
56 If the counter goes below zero, listing is suppressed.
59 Listings are a maintained by read calling various listing_<foo>
60 functions. What happens most is that the macro NO_LISTING is not
61 defined (from the Makefile), then the macro LISTING_NEWLINE expands
62 into a call to listing_newline. The call is done from read.c, every
63 time it sees a newline, and -l is on the command line.
65 The function listing_newline remembers the frag associated with the
66 newline, and creates a new frag - note that this is wasteful, but not
67 a big deal, since listing slows things down a lot anyway. The
68 function also rememebers when the filename changes.
70 When all the input has finished, and gas has had a chance to settle
71 down, the listing is output. This is done by running down the list of
72 frag/source file records, and opening the files as needed and printing
73 out the bytes and chars associated with them.
75 The only things which the architecture can change about the listing
76 are defined in these macros:
78 LISTING_HEADER The name of the architecture
79 LISTING_WORD_SIZE The make of the number of bytes in a word, this determines
80 the clumping of the output data. eg a value of
81 2 makes words look like 1234 5678, whilst 1
82 would make the same value look like 12 34 56
84 LISTING_LHS_WIDTH Number of words of above size for the lhs
86 LISTING_LHS_WIDTH_SECOND Number of words for the data on the lhs
89 LISTING_LHS_CONT_LINES Max number of lines to use up for a continutation
90 LISTING_RHS_WIDTH Number of chars from the input file to print
96 #include "input-file.h"
101 #ifndef LISTING_HEADER
102 #define LISTING_HEADER "GAS LISTING"
104 #ifndef LISTING_WORD_SIZE
105 #define LISTING_WORD_SIZE 4
107 #ifndef LISTING_LHS_WIDTH
108 #define LISTING_LHS_WIDTH 1
110 #ifndef LISTING_LHS_WIDTH_SECOND
111 #define LISTING_LHS_WIDTH_SECOND 1
113 #ifndef LISTING_RHS_WIDTH
114 #define LISTING_RHS_WIDTH 100
116 #ifndef LISTING_LHS_CONT_LINES
117 #define LISTING_LHS_CONT_LINES 4
121 /* This structure remembers which .s were used */
122 typedef struct file_info_struct
{
126 struct file_info_struct
*next
;
131 /* this structure rememebrs which line from which file goes into which frag */
132 typedef struct list_info_struct
{
133 /* Frag which this line of source is nearest to */
135 /* The actual line in the source file */
137 /* Pointer to the file info struct for the file which this line
139 file_info_type
*file
;
142 struct list_info_struct
*next
;
145 /* Pointer to the file info struct for the high level language
146 source line that belongs here */
147 file_info_type
*hll_file
;
149 /* High level language source line */
153 /* Pointer to any error message associated with this line */
167 static struct list_info_struct
*head
;
168 struct list_info_struct
*listing_tail
;
170 extern unsigned int physical_input_line
;
171 extern fragS
*frag_now
;
173 static int paper_width
= 200;
174 static int paper_height
= 60;
176 /* this static array is used to keep the text of data to be printed
177 before the start of the line. It is stored so we can give a bit
178 more info on the next line. To much, and large initialized arrays
179 will use up lots of paper. */
181 static char data_buffer
[100];
182 static unsigned int data_buffer_size
;
185 listing_message(name
, message
)
189 unsigned int l
= strlen(name
) + strlen(message
) + 1;
193 if (listing_tail
!= (list_info_type
*)NULL
) {
194 listing_tail
->message
= n
;
198 } /* lising_message() */
201 listing_warning(message
)
204 listing_message("Warning:", message
);
208 listing_error(message
)
211 listing_message("Error:", message
);
214 static file_info_type
*file_info_head
;
216 static file_info_type
*
220 /* Find an entry with this file name */
221 file_info_type
*p
= file_info_head
;
223 while (p
!= (file_info_type
*)NULL
) {
224 if (strcmp(p
->filename
, file_name
) == 0)
231 p
= (file_info_type
*) xmalloc(sizeof(file_info_type
));
232 p
->next
= file_info_head
;
234 p
->filename
= xmalloc(strlen(file_name
)+1);
235 strcpy(p
->filename
, file_name
);
239 p
->file
= fopen(p
->filename
,"r");
256 extern char *file_name
;
257 static unsigned int last_line
= 0xffff ;
261 if (physical_input_line
!= last_line
) {
262 last_line
= physical_input_line
;
265 new = (list_info_type
*) malloc(sizeof(list_info_type
));
266 new->frag
= frag_now
;
267 new->line
= physical_input_line
;
268 new->file
= file_info(file_name
);
271 listing_tail
->next
= new;
277 new->next
= (list_info_type
*) NULL
;
278 new->message
= (char *) NULL
;
279 new->edict
= EDICT_NONE
;
280 new->hll_file
= (file_info_type
*) NULL
;
286 } /* listing_newline() */
289 /* This function returns the next source line from the file supplied,
290 truncated to size. It appends a fake line to the end of each input
294 buffer_line(file
, line
, size
)
295 file_info_type
*file
;
299 unsigned int count
= 0;
304 /* If we couldn't open the file, return an empty line */
305 if (file
->file
== (FILE*) NULL
) {
309 if (file
->end_pending
== 10) {
313 file
->end_pending
= 0;
316 c
= fgetc(file
->file
);
317 size
-= 1; /* leave room for null */
319 while (c
!= EOF
&& c
!= '\n') {
324 c
= fgetc(file
->file
);
328 file
->end_pending
++;
337 } /* buffer_line() */
341 static unsigned int eject
; /* Eject pending */
342 static unsigned int page
; /* Current page number */
343 static char *title
; /* current title */
344 static char *subtitle
; /* current subtitle */
345 static unsigned int on_page
; /* number of lines printed on current page */
349 list_info_type
*list
;
351 /* Grope around, see if we can see a title or subtitle edict
352 coming up soon (we look down 10 lines of the page and see
355 if ((eject
|| (on_page
>= paper_height
)) && paper_height
!= 0) {
358 int had_subtitle
= 0;
362 while (c
!= 0 && list
) {
363 if (list
->edict
== EDICT_SBTTL
&& !had_subtitle
) {
365 subtitle
= list
->edict_arg
;
368 if (list
->edict
== EDICT_TITLE
&& !had_title
) {
370 title
= list
->edict_arg
;
380 printf("%s %s \t\t\tpage %d\n", LISTING_HEADER
, fn
, page
);
381 printf("%s\n", title
);
382 printf("%s\n", subtitle
);
388 } /* listing_page() */
393 list_info_type
*list
;
395 list_info_type
*first
= list
;
396 list_info_type
*last
= first
;
397 unsigned int address
= ~0;
402 unsigned int byte_in_frag
= 0;
406 /* Find first frag which says it belongs to this line */
408 while (frag
&& frag
->line
!= list
)
409 frag
= frag
->fr_next
;
413 data_buffer_size
= 0;
415 /* Dump all the frags which belong to this line */
416 while (frag_ptr
!= (fragS
*)NULL
&& frag_ptr
->line
== first
) {
417 /* Print as many bytes from the fixed part as is sensible */
418 while(byte_in_frag
< frag_ptr
->fr_fix
&& data_buffer_size
< sizeof(data_buffer
)-10) {
420 address
= frag_ptr
->fr_address
;
423 sprintf(data_buffer
+ data_buffer_size
, "%02X", (frag_ptr
->fr_literal
[byte_in_frag
]) & 0xff);
424 data_buffer_size
+= 2;
428 /* Print as many bytes from the variable part as is sensible */
429 while (byte_in_frag
< frag_ptr
->fr_var
* frag_ptr
->fr_offset
430 && data_buffer_size
< sizeof(data_buffer
)-10) {
432 address
= frag_ptr
->fr_address
;
434 data_buffer
[data_buffer_size
++] = '*';
435 data_buffer
[data_buffer_size
++] = '*';
440 frag_ptr
= frag_ptr
->fr_next
;
443 data_buffer
[data_buffer_size
++] = 0;
448 print_lines(list
, string
, address
)
449 list_info_type
*list
;
451 unsigned int address
;
456 unsigned int byte_in_word
=0;
457 char *src
= data_buffer
;
459 /* Print the stuff on the first line */
461 nchars
= (LISTING_WORD_SIZE
* 2 + 1) * LISTING_LHS_WIDTH
;
463 /* Print the hex for the first line */
465 printf("% 4d ", list
->line
);
466 for (idx
= 0; idx
< nchars
; idx
++)
469 printf("\t%s\n", string
? string
: "");
474 printf("% 4d ???? ", list
->line
);
476 printf("% 4d %04x ", list
->line
, address
);
479 /* And the data to go along with it */
482 while (*src
&& idx
< nchars
) {
483 printf("%c%c", src
[0], src
[1]);
487 if (byte_in_word
== LISTING_WORD_SIZE
) {
495 for (;idx
< nchars
; idx
++)
498 printf("\t%s\n", string
? string
: "");
502 printf("**** %s\n",list
->message
);
507 for (lines
= 0; lines
< LISTING_LHS_CONT_LINES
&& *src
; lines
++) {
508 nchars
= ((LISTING_WORD_SIZE
*2) +1) * LISTING_LHS_WIDTH_SECOND
-1;
510 /* Print any more lines of data, but more compactly */
511 printf("% 4d ", list
->line
);
513 while (*src
&& idx
< nchars
) {
514 printf("%c%c", src
[0], src
[1]);
518 if (byte_in_word
== LISTING_WORD_SIZE
) {
530 } /* print_lines() */
536 extern symbolS
*symbol_rootP
;
541 printf("DEFINED SYMBOLS\n");
544 for (ptr
= symbol_rootP
; ptr
!= (symbolS
*)NULL
; ptr
= symbol_next(ptr
)) {
545 if (ptr
->sy_frag
->line
) {
546 if (strlen(S_GET_NAME(ptr
))) {
547 printf("%20s:%-5d %2d:%08x %s \n",
548 ptr
->sy_frag
->line
->file
->filename
,
549 ptr
->sy_frag
->line
->line
,
564 printf("UNDEFINED SYMBOLS\n");
568 for (ptr
= symbol_rootP
; ptr
!= (symbolS
*)NULL
; ptr
= symbol_next(ptr
)) {
569 if (ptr
&& strlen(S_GET_NAME(ptr
)) != 0) {
570 if (ptr
->sy_frag
->line
== 0) {
571 printf("%s\n", S_GET_NAME(ptr
));
579 } /* list_symbol_table() */
582 print_source(current_file
, list
, buffer
, width
)
583 file_info_type
*current_file
;
584 list_info_type
*list
;
588 if (current_file
->file
) {
589 while (current_file
->linenum
< list
->hll_line
) {
590 char * p
= buffer_line(current_file
, buffer
, width
);
591 printf("%4d:%-13s **** %s\n", current_file
->linenum
, current_file
->filename
, p
);
598 } /* print_source() */
600 /* Sometimes the user doesn't want to be bothered by the debugging
601 records inserted by the compiler, see if the line is suspicioous */
604 debugging_pseudo(line
)
607 while (isspace(*line
))
610 if (*line
!= '.') return 0;
614 if (strncmp(line
, "def",3) == 0) return 1;
615 if (strncmp(line
, "val",3) == 0) return 1;
616 if (strncmp(line
, "scl",3) == 0) return 1;
617 if (strncmp(line
, "line",4) == 0) return 1;
618 if (strncmp(line
, "endef",5) == 0) return 1;
619 if (strncmp(line
, "ln",2) ==0) return 1;
620 if (strncmp(line
, "type",4) ==0) return 1;
621 if (strncmp(line
, "size",4) == 0) return 1;
622 if (strncmp(line
, "dim",3) ==0) return 1;
623 if (strncmp(line
, "tag",3) == 0) return 1;
626 } /* debugging_pseudo() */
629 listing_listing(name
)
635 file_info_type
*current_hll_file
= (file_info_type
*) NULL
;
637 int show_listing
= 1;
638 list_info_type
*list
= head
;
639 unsigned int addr
= 0;
640 unsigned int page
= 1;
641 unsigned int prev
= 0;
644 buffer
= malloc(LISTING_RHS_WIDTH
);
648 while (list
!= (list_info_type
*)NULL
&& 0) {
650 list
->frag
= list
->next
->frag
;
657 width
= LISTING_RHS_WIDTH
> paper_width
? paper_width
: LISTING_RHS_WIDTH
;
659 switch (list
->edict
) {
671 title
= list
->edict_arg
;
674 subtitle
= list
->edict_arg
;
680 if (show_listing
> 0) {
681 /* Scan down the list and print all the stuff which can be done
682 with this line (or lines) */
685 if (list
->hll_file
) {
686 current_hll_file
= list
->hll_file
;
689 if (current_hll_file
&& list
->hll_line
&& listing
& LISTING_HLL
) {
690 print_source(current_hll_file
, list
, buffer
, width
);
693 p
= buffer_line(list
->file
, buffer
, width
);
695 if (! ((listing
& LISTING_NODEBUG
) && debugging_pseudo(p
))) {
696 print_lines(list
, p
, calc_hex(list
));
699 if (list
->edict
== EDICT_EJECT
) {
704 p
= buffer_line(list
->file
, buffer
, width
);
710 } /* listing_listing() */
719 if (listing
& LISTING_NOFORM
)
724 if (listing
& LISTING_LISTING
)
726 listing_listing(name
);
729 if (listing
& LISTING_SYMBOLS
)
733 } /* listing_print() */
746 listing_tail
->edict
= EDICT_EJECT
;
760 listing_tail
->edict
= on
? EDICT_LIST
: EDICT_NOLIST
;
767 paper_height
= get_absolute_expression();
769 if (paper_height
< 0 || paper_height
> 1000) {
771 as_warn("strantge paper height, set to no form");
774 if (*input_line_pointer
== ',') {
775 input_line_pointer
++;
776 paper_width
= get_absolute_expression();
780 } /* listing_psize() */
793 if (*input_line_pointer
=='\"') {
794 input_line_pointer
++;
795 start
= input_line_pointer
;
797 while (*input_line_pointer
) {
798 if (*input_line_pointer
== '\"') {
799 length
= input_line_pointer
- start
;
800 title
= malloc(length
+ 1);
801 memcpy(title
, start
, length
);
803 listing_tail
->edict
= depth
? EDICT_SBTTL
: EDICT_TITLE
;
804 listing_tail
->edict_arg
= title
;
805 input_line_pointer
++;
806 demand_empty_rest_of_line();
808 } else if (*input_line_pointer
== '\n') {
809 as_bad("New line in title");
810 demand_empty_rest_of_line();
813 input_line_pointer
++;
817 as_bad("expecting title in quotes");
821 } /* listing_title() */
826 listing_source_line(line
)
830 listing_tail
->hll_line
= line
;
833 } /* lising_source_line() */
836 listing_source_file(file
)
839 listing_tail
->hll_file
= file_info(file
);
842 #endif /* not NO_LISTING */
844 /* end of listing.c */
This page took 0.045718 seconds and 4 git commands to generate.