From 7b7a88d0e1b202635670ee85f7150cf387931d48 Mon Sep 17 00:00:00 2001 From: Richard Henderson Date: Tue, 27 Jan 1998 14:45:09 +0000 Subject: [PATCH] Bring over lost listing bits from emc-97r1-branch. --- gas/ChangeLog | 11 ++ gas/as.c | 43 +++++- gas/listing.c | 368 +++++++++++++++++++++++++++++++++++--------------- 3 files changed, 312 insertions(+), 110 deletions(-) diff --git a/gas/ChangeLog b/gas/ChangeLog index 70cb618c3be..8379fe70798 100644 --- a/gas/ChangeLog +++ b/gas/ChangeLog @@ -1,3 +1,14 @@ +Tue Jan 27 06:38:35 1998 Richard Henderson + + * as.c (parse_args): Add --listing-lhs-width, --listing-lhs-width2, + --listing-rhs-width, --listing-cont-lines. + (show_usage): Update. + * listing.c (listing_lhs_width, listing_lhs_width_second): New vars. + (listing_lhs_cont_lines, listing_rhs_width): New vars. + (print_lines): Use the variables instead of the constants. + (listing_listing): Likewise. + * listing.h: Declare the new vars. + Tue Jan 27 05:32:05 1998 Richard Henderson * as.c (parse_args): Add --keep-locals alias for -L. diff --git a/gas/as.c b/gas/as.c index 1d7bd8b7040..42613087ca6 100644 --- a/gas/as.c +++ b/gas/as.c @@ -166,6 +166,16 @@ Options:\n\ -w ignored\n\ -X ignored\n\ -Z generate object file even after errors\n"); + fprintf (stream, "\ +--listing-lhs-width set the width in words of the output data column of\n\ + the listing\n\ +--listing-lhs-width2 set the width in words of the continuation lines\n\ + of the output data column; ignored if smaller than\n\ + the width of the first line\n\ +--listing-rhs-width set the max width in characters of the lines from\n\ + the source file\n\ +--listing-cont-lines set the maximum number of continuation lines used\n\ + for the output data column of the listing\n"); md_show_usage (stream); @@ -333,11 +343,19 @@ parse_args (pargc, pargv) formats are added to the built-in set of instructions, and mnemonics for new registers may also be defined. */ {"itbl", required_argument, NULL, OPTION_INSTTBL}, -#define OPTION_DEPFILE (OPTION_STD_BASE + 9) +#define OPTION_LISTING_LHS_WIDTH (OPTION_STD_BASE + 9) + {"listing-lhs-width", required_argument, NULL, OPTION_LISTING_LHS_WIDTH}, +#define OPTION_LISTING_LHS_WIDTH2 (OPTION_STD_BASE + 10) + {"listing-lhs-width", required_argument, NULL, OPTION_LISTING_LHS_WIDTH2}, +#define OPTION_LISTING_RHS_WIDTH (OPTION_STD_BASE + 11) + {"listing-rhs-width", required_argument, NULL, OPTION_LISTING_RHS_WIDTH}, +#define OPTION_LISTING_CONT_LINES (OPTION_STD_BASE + 12) + {"listing-cont-lines", required_argument, NULL, OPTION_LISTING_CONT_LINES}, +#define OPTION_DEPFILE (OPTION_STD_BASE + 13) {"MD", required_argument, NULL, OPTION_DEPFILE}, -#define OPTION_GSTABS (OPTION_STD_BASE + 10) +#define OPTION_GSTABS (OPTION_STD_BASE + 14) {"gstabs", no_argument, NULL, OPTION_GSTABS}, -#define OPTION_STRIP_LOCAL_ABSOLUTE (OPTION_STD_BASE + 11) +#define OPTION_STRIP_LOCAL_ABSOLUTE (OPTION_STD_BASE + 15) {"strip-local-absolute", no_argument, NULL, OPTION_STRIP_LOCAL_ABSOLUTE} }; @@ -529,6 +547,25 @@ the GNU General Public License. This program has absolutely no warranty.\n"); flag_keep_locals = 1; break; + case OPTION_LISTING_LHS_WIDTH: + listing_lhs_width = atoi(optarg); + if (listing_lhs_width_second < listing_lhs_width) + listing_lhs_width_second = listing_lhs_width; + break; + case OPTION_LISTING_LHS_WIDTH2: + { + int tmp = atoi(optarg); + if (tmp > listing_lhs_width) + listing_lhs_width_second = tmp; + } + break; + case OPTION_LISTING_RHS_WIDTH: + listing_rhs_width = atoi(optarg); + break; + case OPTION_LISTING_CONT_LINES: + listing_lhs_cont_lines = atoi(optarg); + break; + case 'M': flag_mri = 1; #ifdef TC_M68K diff --git a/gas/listing.c b/gas/listing.c index b42f146de59..5e23e662943 100644 --- a/gas/listing.c +++ b/gas/listing.c @@ -1,5 +1,5 @@ /* listing.c - mainting assembly listings - Copyright (C) 1991, 1992 Free Software Foundation, Inc. + Copyright (C) 1991, 92, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. This file is part of GAS, the GNU Assembler. @@ -14,8 +14,9 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License -along with GAS; see the file COPYING. If not, write to -the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +along with GAS; see the file COPYING. If not, write to the Free +Software Foundation, 59 Temple Place - Suite 330, Boston, MA +02111-1307, USA. */ /* Contributed by Steve Chamberlain @@ -99,6 +100,7 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307 #include "subsegs.h" #ifndef NO_LISTING + #ifndef LISTING_HEADER #define LISTING_HEADER "GAS LISTING" #endif @@ -118,46 +120,43 @@ the Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307 #define LISTING_LHS_CONT_LINES 4 #endif - - - /* This structure remembers which .s were used */ typedef struct file_info_struct { + struct file_info_struct *next; char *filename; + long pos; int linenum; - FILE *file; - struct file_info_struct *next; int at_end; } - file_info_type; /* this structure rememebrs which line from which file goes into which frag */ -typedef struct list_info_struct +struct list_info_struct { /* Frag which this line of source is nearest to */ fragS *frag; + /* The actual line in the source file */ unsigned int line; /* Pointer to the file info struct for the file which this line belongs to */ file_info_type *file; + /* The expanded text of any macro that may have been executing. */ + char *line_contents; + /* Next in list */ struct list_info_struct *next; - /* Pointer to the file info struct for the high level language source line that belongs here */ file_info_type *hll_file; - /* High level language source line */ int hll_line; - /* Pointer to any error message associated with this line */ char *message; @@ -168,14 +167,18 @@ typedef struct list_info_struct EDICT_TITLE, EDICT_NOLIST, EDICT_LIST, + EDICT_NOLIST_NEXT, EDICT_EJECT } edict; char *edict_arg; -} - -list_info_type; + /* Nonzero if this line is to be omitted because it contains + debugging information. This can become a flags field if we come + up with more information to store here. */ + int debugging; +}; +typedef struct list_info_struct list_info_type; static struct list_info_struct *head; struct list_info_struct *listing_tail; @@ -187,15 +190,16 @@ static int paper_height = 60; /* File to output listings to. */ static FILE *list_file; -/* this static array is used to keep the text of data to be printed - before the start of the line. - It is stored so we can give a bit more info on the next line. To much, and large - initialized arrays will use up lots of paper. - */ +/* This static array is used to keep the text of data to be printed + before the start of the line. */ -static char data_buffer[100]; -static unsigned int data_buffer_size; +#define MAX_BYTES \ + (((LISTING_WORD_SIZE * 2) + 1) * LISTING_LHS_WIDTH \ + + ((((LISTING_WORD_SIZE * 2) + 1) * LISTING_LHS_WIDTH_SECOND) \ + * LISTING_LHS_CONT_LINES) \ + + 20) +static char data_buffer[MAX_BYTES]; /* Prototypes. */ static void listing_message PARAMS ((const char *name, const char *message)); @@ -205,15 +209,14 @@ static char *buffer_line PARAMS ((file_info_type *file, char *line, unsigned int size)); static void listing_page PARAMS ((list_info_type *list)); static unsigned int calc_hex PARAMS ((list_info_type *list)); -static void print_lines PARAMS ((list_info_type *list, - char *string, - unsigned int address)); +static void print_lines PARAMS ((list_info_type *, unsigned int, + char *, unsigned int)); static void list_symbol_table PARAMS ((void)); static void print_source PARAMS ((file_info_type *current_file, list_info_type *list, char *buffer, unsigned int width)); -static int debugging_pseudo PARAMS ((char *line)); +static int debugging_pseudo PARAMS ((list_info_type *, const char *)); static void listing_listing PARAMS ((char *name)); @@ -247,9 +250,15 @@ listing_error (message) } +int listing_lhs_width = LISTING_LHS_WIDTH; +int listing_lhs_width_second = LISTING_LHS_WIDTH_SECOND; +int listing_lhs_cont_lines = LISTING_LHS_CONT_LINES; +int listing_rhs_width = LISTING_RHS_WIDTH; static file_info_type *file_info_head; +static file_info_type *last_open_file_info; +static FILE *last_open_file; static file_info_type * file_info (file_name) @@ -272,13 +281,10 @@ file_info (file_name) file_info_head = p; p->filename = xmalloc ((unsigned long) strlen (file_name) + 1); strcpy (p->filename, file_name); + p->pos = 0; p->linenum = 0; p->at_end = 0; - p->file = fopen (p->filename, "r"); - if (p->file) - fgetc (p->file); - return p; } @@ -300,7 +306,7 @@ listing_newline (ps) unsigned int line; static unsigned int last_line = 0xffff; static char *last_file = NULL; - list_info_type *new; + list_info_type *new = NULL; if (listing == 0) return; @@ -308,34 +314,77 @@ listing_newline (ps) if (now_seg == absolute_section) return; +#ifdef OBJ_ELF + /* In ELF, anything in a section beginning with .debug or .line is + considered to be debugging information. This includes the + statement which switches us into the debugging section, which we + can only set after we are already in the debugging section. */ + if ((listing & LISTING_NODEBUG) != 0 + && listing_tail != NULL + && ! listing_tail->debugging) + { + const char *segname; + + segname = segment_name (now_seg); + if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0 + || strncmp (segname, ".line", sizeof ".line" - 1) == 0) + listing_tail->debugging = 1; + } +#endif + as_where (&file, &line); - if (line != last_line || (last_file && file && strcmp(file, last_file))) + if (ps == NULL) { - last_line = line; - last_file = file; - new_frag (); + if (line == last_line && !(last_file && file && strcmp(file, last_file))) + return; new = (list_info_type *) xmalloc (sizeof (list_info_type)); - new->frag = frag_now; - new->line = line; - new->file = file_info (file); + new->line_contents = NULL; + } + else + { + new = (list_info_type *) xmalloc (sizeof (list_info_type)); + new->line_contents = ps; + } - if (listing_tail) - { - listing_tail->next = new; - } - else - { - head = new; - } - listing_tail = new; - new->next = (list_info_type *) NULL; - new->message = (char *) NULL; - new->edict = EDICT_NONE; - new->hll_file = (file_info_type *) NULL; - new->hll_line = 0; - new_frag (); + last_line = line; + last_file = file; + new_frag (); + + if (listing_tail) + { + listing_tail->next = new; + } + else + { + head = new; } + listing_tail = new; + + new->frag = frag_now; + new->line = line; + new->file = file_info (file); + new->next = (list_info_type *) NULL; + new->message = (char *) NULL; + new->edict = EDICT_NONE; + new->hll_file = (file_info_type *) NULL; + new->hll_line = 0; + new->debugging = 0; + new_frag (); + +#ifdef OBJ_ELF + /* In ELF, anything in a section beginning with .debug or .line is + considered to be debugging information. */ + if ((listing & LISTING_NODEBUG) != 0) + { + const char *segname; + + segname = segment_name (now_seg); + if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0 + || strncmp (segname, ".line", sizeof ".line" - 1) == 0) + new->debugging = 1; + } +#endif } /* Attach all current frags to the previous line instead of the @@ -385,15 +434,29 @@ buffer_line (file, line, size) char *p = line; /* If we couldn't open the file, return an empty line */ - if (file->file == (FILE *) NULL || file->at_end) + if (file->at_end) + return ""; + + /* Check the cache and see if we last used this file. */ + if (!last_open_file_info || file != last_open_file_info) { - return ""; - } + if (last_open_file) + { + last_open_file_info->pos = ftell (last_open_file); + fclose (last_open_file); + } - if (file->linenum == 0) - rewind (file->file); + last_open_file_info = file; + last_open_file = fopen (file->filename, "r"); + if (!last_open_file) + return ""; - c = fgetc (file->file); + /* Seek to where we were last time this file was open. */ + if (file->pos) + fseek(last_open_file, file->pos, SEEK_SET); + } + + c = fgetc (last_open_file); size -= 1; /* leave room for null */ @@ -403,7 +466,7 @@ buffer_line (file, line, size) *p++ = c; count++; - c = fgetc (file->file); + c = fgetc (last_open_file); } if (c == EOF) @@ -477,15 +540,13 @@ static unsigned int calc_hex (list) list_info_type * list; { + int data_buffer_size; list_info_type *first = list; unsigned int address = (unsigned int) ~0; - fragS *frag; fragS *frag_ptr; - unsigned int byte_in_frag; - /* Find first frag which says it belongs to this line */ frag = list->frag; while (frag && frag->line != list) @@ -500,7 +561,8 @@ calc_hex (list) { /* Print as many bytes from the fixed part as is sensible */ byte_in_frag = 0; - while (byte_in_frag < frag_ptr->fr_fix && data_buffer_size < sizeof (data_buffer) - 10) + while (byte_in_frag < frag_ptr->fr_fix + && data_buffer_size < sizeof (data_buffer) - 3) { if (address == ~0) { @@ -520,7 +582,7 @@ calc_hex (list) /* Print as many bytes from the variable part as is sensible */ while ((byte_in_frag < frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset) - && data_buffer_size < sizeof (data_buffer) - 10) + && data_buffer_size < sizeof (data_buffer) - 3) { if (address == ~0) { @@ -545,7 +607,7 @@ calc_hex (list) frag_ptr = frag_ptr->fr_next; } - data_buffer[data_buffer_size++] = 0; + data_buffer[data_buffer_size] = '\0'; return address; } @@ -555,8 +617,9 @@ calc_hex (list) static void -print_lines (list, string, address) +print_lines (list, lineno, string, address) list_info_type *list; + unsigned int lineno; char *string; unsigned int address; { @@ -568,11 +631,11 @@ print_lines (list, string, address) /* Print the stuff on the first line */ listing_page (list); - nchars = (LISTING_WORD_SIZE * 2 + 1) * LISTING_LHS_WIDTH; + nchars = (LISTING_WORD_SIZE * 2 + 1) * listing_lhs_width; /* Print the hex for the first line */ if (address == ~0) { - fprintf (list_file, "% 4d ", list->line); + fprintf (list_file, "% 4d ", lineno); for (idx = 0; idx < nchars; idx++) fprintf (list_file, " "); @@ -585,11 +648,11 @@ print_lines (list, string, address) { if (had_errors ()) { - fprintf (list_file, "% 4d ???? ", list->line); + fprintf (list_file, "% 4d ???? ", lineno); } else { - fprintf (list_file, "% 4d %04x ", list->line, address); + fprintf (list_file, "% 4d %04x ", lineno, address); } /* And the data to go along with it */ @@ -622,15 +685,13 @@ print_lines (list, string, address) on_page++; } - for (lines = 0; - lines < LISTING_LHS_CONT_LINES - && *src; - lines++) + for (lines = 0; lines < listing_lhs_cont_lines && *src; lines++) { - nchars = ((LISTING_WORD_SIZE * 2) + 1) * LISTING_LHS_WIDTH_SECOND - 1; + nchars = (((LISTING_WORD_SIZE * 2) + 1) + * listing_lhs_width_second - 1); idx = 0; /* Print any more lines of data, but more compactly */ - fprintf (list_file, "% 4d ", list->line); + fprintf (list_file, "% 4d ", lineno); while (*src && idx < nchars) { @@ -688,12 +749,7 @@ list_symbol_table () } #if defined (BFD64) else if (sizeof (val) > 4) - { - char buf1[30]; - sprintf_vma (buf1, val); - strcpy (buf, "00000000"); - strcpy (buf + 8 - strlen (buf1), buf1); - } + sprintf_vma (buf, val); #endif else abort (); @@ -766,7 +822,7 @@ print_source (current_file, list, buffer, width) char *buffer; unsigned int width; { - if (current_file->file) + if (!current_file->at_end) { while (current_file->linenum < list->hll_line && !current_file->at_end) @@ -781,17 +837,48 @@ print_source (current_file, list, buffer, width) } /* Sometimes the user doesn't want to be bothered by the debugging - records inserted by the compiler, see if the line is suspicious */ + records inserted by the compiler, see if the line is suspicious. */ static int -debugging_pseudo (line) - char *line; +debugging_pseudo (list, line) + list_info_type *list; + const char *line; { + static int in_debug; + int was_debug; + + if (list->debugging) + { + in_debug = 1; + return 1; + } + + was_debug = in_debug; + in_debug = 0; + while (isspace (*line)) line++; if (*line != '.') - return 0; + { +#ifdef OBJ_ELF + /* The ELF compiler sometimes emits blank lines after switching + out of a debugging section. If the next line drops us back + into debugging information, then don't print the blank line. + This is a hack for a particular compiler behaviour, not a + general case. */ + if (was_debug + && *line == '\0' + && list->next != NULL + && list->next->debugging) + { + in_debug = 1; + return 1; + } +#endif + + return 0; + } line++; @@ -822,7 +909,6 @@ debugging_pseudo (line) return 1; return 0; - } static void @@ -837,7 +923,7 @@ listing_listing (name) int show_listing = 1; unsigned int width; - buffer = xmalloc (LISTING_RHS_WIDTH); + buffer = xmalloc (listing_rhs_width); eject = 1; list = head; @@ -854,8 +940,8 @@ listing_listing (name) while (list) { - width = LISTING_RHS_WIDTH > paper_width ? paper_width : - LISTING_RHS_WIDTH; + width = listing_rhs_width > paper_width ? paper_width : + listing_rhs_width; switch (list->edict) { @@ -865,6 +951,8 @@ listing_listing (name) case EDICT_NOLIST: show_listing--; break; + case EDICT_NOLIST_NEXT: + break; case EDICT_EJECT: break; case EDICT_NONE: @@ -890,20 +978,37 @@ listing_listing (name) current_hll_file = list->hll_file; } - if (current_hll_file && list->hll_line && listing & LISTING_HLL) + if (current_hll_file && list->hll_line && (listing & LISTING_HLL)) { print_source (current_hll_file, list, buffer, width); } - while (list->file->file - && list->file->linenum < list->line - && !list->file->at_end) + if (list->line_contents) { - p = buffer_line (list->file, buffer, width); - - if (!((listing & LISTING_NODEBUG) && debugging_pseudo (p))) + if (!((listing & LISTING_NODEBUG) + && debugging_pseudo (list, list->line_contents))) { - print_lines (list, p, calc_hex (list)); + print_lines (list, list->file->linenum, + list->line_contents, calc_hex (list)); + } + } + else + { + while (list->file->linenum < list->line + && !list->file->at_end) + { + unsigned int address; + + p = buffer_line (list->file, buffer, width); + + if (list->file->linenum < list->line) + address = ~ (unsigned int) 0; + else + address = calc_hex (list); + + if (!((listing & LISTING_NODEBUG) + && debugging_pseudo (list, p))) + print_lines (list, list->file->linenum, p, address); } } @@ -914,12 +1019,14 @@ listing_listing (name) } else { - while (list->file->file - && list->file->linenum < list->line + while (list->file->linenum < list->line && !list->file->at_end) p = buffer_line (list->file, buffer, width); } + if (list->edict == EDICT_NOLIST_NEXT) + --show_listing; + list = list->next; } free (buffer); @@ -929,18 +1036,27 @@ void listing_print (name) char *name; { + int using_stdout; + file_info_type *fi; + title = ""; subtitle = ""; if (name == NULL) - list_file = stdout; + { + list_file = stdout; + using_stdout = 1; + } else { list_file = fopen (name, "w"); - if (list_file == NULL) + if (list_file != NULL) + using_stdout = 0; + else { as_perror ("can't open list file: %s", name); list_file = stdout; + using_stdout = 1; } } @@ -952,12 +1068,23 @@ listing_print (name) if (listing & LISTING_LISTING) { listing_listing (name); - } + if (listing & LISTING_SYMBOLS) { list_symbol_table (); } + + if (! using_stdout) + { + if (fclose (list_file) == EOF) + as_perror ("error closing list file: %s", name); + } + + if (last_open_file) + { + fclose (last_open_file); + } } @@ -985,12 +1112,39 @@ listing_flags (ignore) } +/* Turn listing on or off. An argument of 0 means to turn off + listing. An argument of 1 means to turn on listing. An argument + of 2 means to turn off listing, but as of the next line; that is, + the current line should be listed, but the next line should not. */ + void listing_list (on) int on; { if (listing) - listing_tail->edict = on ? EDICT_LIST : EDICT_NOLIST; + { + switch (on) + { + case 0: + if (listing_tail->edict == EDICT_LIST) + listing_tail->edict = EDICT_NONE; + else + listing_tail->edict = EDICT_NOLIST; + break; + case 1: + if (listing_tail->edict == EDICT_NOLIST + || listing_tail->edict == EDICT_NOLIST_NEXT) + listing_tail->edict = EDICT_NONE; + else + listing_tail->edict = EDICT_LIST; + break; + case 2: + listing_tail->edict = EDICT_NOLIST_NEXT; + break; + default: + abort (); + } + } } -- 2.30.2