listing.c revision 89857
133965Sjdp/* listing.c - mainting assembly listings 277298Sobrien Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 377298Sobrien 2001 438889Sjdp Free Software Foundation, Inc. 533965Sjdp 633965SjdpThis file is part of GAS, the GNU Assembler. 733965Sjdp 833965SjdpGAS is free software; you can redistribute it and/or modify 933965Sjdpit under the terms of the GNU General Public License as published by 1033965Sjdpthe Free Software Foundation; either version 2, or (at your option) 1133965Sjdpany later version. 1233965Sjdp 1333965SjdpGAS is distributed in the hope that it will be useful, 1433965Sjdpbut WITHOUT ANY WARRANTY; without even the implied warranty of 1533965SjdpMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 1633965SjdpGNU General Public License for more details. 1733965Sjdp 1833965SjdpYou should have received a copy of the GNU General Public License 1933965Sjdpalong with GAS; see the file COPYING. If not, write to the Free 2033965SjdpSoftware Foundation, 59 Temple Place - Suite 330, Boston, MA 2177298Sobrien02111-1307, USA. */ 2233965Sjdp 2333965Sjdp/* 2477298Sobrien Contributed by Steve Chamberlain <sac@cygnus.com> 2533965Sjdp 2633965Sjdp A listing page looks like: 2733965Sjdp 2833965Sjdp LISTING_HEADER sourcefilename pagenumber 2933965Sjdp TITLE LINE 3033965Sjdp SUBTITLE LINE 3133965Sjdp linenumber address data source 3233965Sjdp linenumber address data source 3333965Sjdp linenumber address data source 3433965Sjdp linenumber address data source 3533965Sjdp 3633965Sjdp If not overridden, the listing commands are: 3733965Sjdp 3833965Sjdp .title "stuff" 3933965Sjdp Put "stuff" onto the title line 4033965Sjdp .sbttl "stuff" 4133965Sjdp Put stuff onto the subtitle line 4233965Sjdp 4333965Sjdp If these commands come within 10 lines of the top of the page, they 4433965Sjdp will affect the page they are on, as well as any subsequent page 4533965Sjdp 4633965Sjdp .eject 4733965Sjdp Thow a page 4833965Sjdp .list 4933965Sjdp Increment the enable listing counter 5033965Sjdp .nolist 5133965Sjdp Decrement the enable listing counter 5233965Sjdp 5333965Sjdp .psize Y[,X] 5433965Sjdp Set the paper size to X wide and Y high. Setting a psize Y of 5533965Sjdp zero will suppress form feeds except where demanded by .eject 5633965Sjdp 5733965Sjdp If the counter goes below zero, listing is suppressed. 5833965Sjdp 5933965Sjdp Listings are a maintained by read calling various listing_<foo> 6033965Sjdp functions. What happens most is that the macro NO_LISTING is not 6133965Sjdp defined (from the Makefile), then the macro LISTING_NEWLINE expands 6233965Sjdp into a call to listing_newline. The call is done from read.c, every 6333965Sjdp time it sees a newline, and -l is on the command line. 6433965Sjdp 6533965Sjdp The function listing_newline remembers the frag associated with the 6633965Sjdp newline, and creates a new frag - note that this is wasteful, but not 6733965Sjdp a big deal, since listing slows things down a lot anyway. The 6833965Sjdp function also rememebers when the filename changes. 6933965Sjdp 7033965Sjdp When all the input has finished, and gas has had a chance to settle 7133965Sjdp down, the listing is output. This is done by running down the list of 7233965Sjdp frag/source file records, and opening the files as needed and printing 7333965Sjdp out the bytes and chars associated with them. 7433965Sjdp 7533965Sjdp The only things which the architecture can change about the listing 7633965Sjdp are defined in these macros: 7733965Sjdp 7833965Sjdp LISTING_HEADER The name of the architecture 7933965Sjdp LISTING_WORD_SIZE The make of the number of bytes in a word, this determines 8033965Sjdp the clumping of the output data. eg a value of 8133965Sjdp 2 makes words look like 1234 5678, whilst 1 8233965Sjdp would make the same value look like 12 34 56 8333965Sjdp 78 8433965Sjdp LISTING_LHS_WIDTH Number of words of above size for the lhs 8533965Sjdp 8633965Sjdp LISTING_LHS_WIDTH_SECOND Number of words for the data on the lhs 8733965Sjdp for the second line 8833965Sjdp 8933965Sjdp LISTING_LHS_CONT_LINES Max number of lines to use up for a continutation 9033965Sjdp LISTING_RHS_WIDTH Number of chars from the input file to print 9133965Sjdp on a line 9233965Sjdp*/ 9333965Sjdp 9433965Sjdp#include "as.h" 9533965Sjdp#include <obstack.h> 9689857Sobrien#include "safe-ctype.h" 9733965Sjdp#include "input-file.h" 9833965Sjdp#include "subsegs.h" 9933965Sjdp 10033965Sjdp#ifndef NO_LISTING 10138889Sjdp 10233965Sjdp#ifndef LISTING_HEADER 10333965Sjdp#define LISTING_HEADER "GAS LISTING" 10433965Sjdp#endif 10533965Sjdp#ifndef LISTING_WORD_SIZE 10633965Sjdp#define LISTING_WORD_SIZE 4 10733965Sjdp#endif 10833965Sjdp#ifndef LISTING_LHS_WIDTH 10960484Sobrien#define LISTING_LHS_WIDTH ((LISTING_WORD_SIZE) > 4 ? 1 : 4 / (LISTING_WORD_SIZE)) 11033965Sjdp#endif 11133965Sjdp#ifndef LISTING_LHS_WIDTH_SECOND 11260484Sobrien#define LISTING_LHS_WIDTH_SECOND LISTING_LHS_WIDTH 11333965Sjdp#endif 11433965Sjdp#ifndef LISTING_RHS_WIDTH 11533965Sjdp#define LISTING_RHS_WIDTH 100 11633965Sjdp#endif 11733965Sjdp#ifndef LISTING_LHS_CONT_LINES 11833965Sjdp#define LISTING_LHS_CONT_LINES 4 11933965Sjdp#endif 12033965Sjdp 12177298Sobrien/* This structure remembers which .s were used. */ 12277298Sobrientypedef struct file_info_struct { 12360484Sobrien struct file_info_struct * next; 12460484Sobrien char * filename; 12560484Sobrien long pos; 12660484Sobrien unsigned int linenum; 12760484Sobrien int at_end; 12877298Sobrien} file_info_type; 12933965Sjdp 13060484Sobrien/* This structure rememebrs which line from which file goes into which 13177298Sobrien frag. */ 13277298Sobrienstruct list_info_struct { 13377298Sobrien /* Frag which this line of source is nearest to. */ 13477298Sobrien fragS *frag; 13538889Sjdp 13677298Sobrien /* The actual line in the source file. */ 13733965Sjdp unsigned int line; 13833965Sjdp /* Pointer to the file info struct for the file which this line 13977298Sobrien belongs to. */ 14077298Sobrien file_info_type *file; 14133965Sjdp 14238889Sjdp /* The expanded text of any macro that may have been executing. */ 14377298Sobrien char *line_contents; 14438889Sjdp 14577298Sobrien /* Next in list. */ 14677298Sobrien struct list_info_struct *next; 14733965Sjdp 14833965Sjdp /* Pointer to the file info struct for the high level language 14977298Sobrien source line that belongs here. */ 15077298Sobrien file_info_type *hll_file; 15177298Sobrien /* High level language source line. */ 15238889Sjdp unsigned int hll_line; 15333965Sjdp 15477298Sobrien /* Pointer to any error message associated with this line. */ 15577298Sobrien char *message; 15633965Sjdp 15777298Sobrien enum { 15877298Sobrien EDICT_NONE, 15977298Sobrien EDICT_SBTTL, 16077298Sobrien EDICT_TITLE, 16177298Sobrien EDICT_NOLIST, 16277298Sobrien EDICT_LIST, 16377298Sobrien EDICT_NOLIST_NEXT, 16477298Sobrien EDICT_EJECT 16577298Sobrien } edict; 16677298Sobrien char *edict_arg; 16733965Sjdp 16838889Sjdp /* Nonzero if this line is to be omitted because it contains 16938889Sjdp debugging information. This can become a flags field if we come 17038889Sjdp up with more information to store here. */ 17138889Sjdp int debugging; 17238889Sjdp}; 17333965Sjdp 17438889Sjdptypedef struct list_info_struct list_info_type; 17533965Sjdp 17660484Sobrienint listing_lhs_width = LISTING_LHS_WIDTH; 17760484Sobrienint listing_lhs_width_second = LISTING_LHS_WIDTH_SECOND; 17860484Sobrienint listing_lhs_cont_lines = LISTING_LHS_CONT_LINES; 17960484Sobrienint listing_rhs_width = LISTING_RHS_WIDTH; 18033965Sjdp 18160484Sobrienstruct list_info_struct * listing_tail; 18260484Sobrien 18360484Sobrienstatic file_info_type * file_info_head; 18460484Sobrienstatic file_info_type * last_open_file_info; 18560484Sobrienstatic FILE * last_open_file; 18660484Sobrienstatic struct list_info_struct * head; 18760484Sobrienstatic int paper_width = 200; 18860484Sobrienstatic int paper_height = 60; 18960484Sobrien 19060484Sobrienextern int listing; 19160484Sobrien 19233965Sjdp/* File to output listings to. */ 19377298Sobrienstatic FILE *list_file; 19433965Sjdp 19538889Sjdp/* This static array is used to keep the text of data to be printed 19638889Sjdp before the start of the line. */ 19733965Sjdp 19838889Sjdp#define MAX_BYTES \ 19938889Sjdp (((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width \ 20038889Sjdp + ((((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second) \ 20138889Sjdp * listing_lhs_cont_lines) \ 20238889Sjdp + 20) 20333965Sjdp 20477298Sobrienstatic char *data_buffer; 20533965Sjdp 20633965Sjdp/* Prototypes. */ 20733965Sjdpstatic void listing_message PARAMS ((const char *name, const char *message)); 20877298Sobrienstatic file_info_type *file_info PARAMS ((const char *file_name)); 20933965Sjdpstatic void new_frag PARAMS ((void)); 21077298Sobrienstatic char *buffer_line PARAMS ((file_info_type *file, 21133965Sjdp char *line, unsigned int size)); 21233965Sjdpstatic void listing_page PARAMS ((list_info_type *list)); 21333965Sjdpstatic unsigned int calc_hex PARAMS ((list_info_type *list)); 21433965Sjdpstatic void print_lines PARAMS ((list_info_type *, unsigned int, 21533965Sjdp char *, unsigned int)); 21633965Sjdpstatic void list_symbol_table PARAMS ((void)); 21733965Sjdpstatic void print_source PARAMS ((file_info_type *current_file, 21833965Sjdp list_info_type *list, 21933965Sjdp char *buffer, 22033965Sjdp unsigned int width)); 22138889Sjdpstatic int debugging_pseudo PARAMS ((list_info_type *, const char *)); 22233965Sjdpstatic void listing_listing PARAMS ((char *name)); 22333965Sjdp 22433965Sjdpstatic void 22533965Sjdplisting_message (name, message) 22633965Sjdp const char *name; 22733965Sjdp const char *message; 22833965Sjdp{ 22933965Sjdp if (listing_tail != (list_info_type *) NULL) 23033965Sjdp { 23177298Sobrien unsigned int l = strlen (name) + strlen (message) + 1; 23277298Sobrien char *n = (char *) xmalloc (l); 23377298Sobrien strcpy (n, name); 23477298Sobrien strcat (n, message); 23533965Sjdp listing_tail->message = n; 23633965Sjdp } 23733965Sjdp} 23833965Sjdp 23933965Sjdpvoid 24033965Sjdplisting_warning (message) 24133965Sjdp const char *message; 24233965Sjdp{ 24360484Sobrien listing_message (_("Warning:"), message); 24433965Sjdp} 24533965Sjdp 24633965Sjdpvoid 24733965Sjdplisting_error (message) 24833965Sjdp const char *message; 24933965Sjdp{ 25060484Sobrien listing_message (_("Error:"), message); 25133965Sjdp} 25233965Sjdp 25333965Sjdpstatic file_info_type * 25433965Sjdpfile_info (file_name) 25533965Sjdp const char *file_name; 25633965Sjdp{ 25777298Sobrien /* Find an entry with this file name. */ 25833965Sjdp file_info_type *p = file_info_head; 25933965Sjdp 26033965Sjdp while (p != (file_info_type *) NULL) 26133965Sjdp { 26233965Sjdp if (strcmp (p->filename, file_name) == 0) 26333965Sjdp return p; 26433965Sjdp p = p->next; 26533965Sjdp } 26633965Sjdp 26777298Sobrien /* Make new entry. */ 26833965Sjdp 26933965Sjdp p = (file_info_type *) xmalloc (sizeof (file_info_type)); 27033965Sjdp p->next = file_info_head; 27133965Sjdp file_info_head = p; 27233965Sjdp p->filename = xmalloc ((unsigned long) strlen (file_name) + 1); 27333965Sjdp strcpy (p->filename, file_name); 27438889Sjdp p->pos = 0; 27533965Sjdp p->linenum = 0; 27633965Sjdp p->at_end = 0; 27733965Sjdp 27833965Sjdp return p; 27933965Sjdp} 28033965Sjdp 28133965Sjdpstatic void 28233965Sjdpnew_frag () 28333965Sjdp{ 28433965Sjdp 28533965Sjdp frag_wane (frag_now); 28633965Sjdp frag_new (0); 28733965Sjdp 28833965Sjdp} 28933965Sjdp 29033965Sjdpvoid 29133965Sjdplisting_newline (ps) 29233965Sjdp char *ps; 29333965Sjdp{ 29433965Sjdp char *file; 29533965Sjdp unsigned int line; 29633965Sjdp static unsigned int last_line = 0xffff; 29733965Sjdp static char *last_file = NULL; 29838889Sjdp list_info_type *new = NULL; 29933965Sjdp 30033965Sjdp if (listing == 0) 30133965Sjdp return; 30233965Sjdp 30333965Sjdp if (now_seg == absolute_section) 30433965Sjdp return; 30533965Sjdp 30638889Sjdp#ifdef OBJ_ELF 30738889Sjdp /* In ELF, anything in a section beginning with .debug or .line is 30838889Sjdp considered to be debugging information. This includes the 30938889Sjdp statement which switches us into the debugging section, which we 31038889Sjdp can only set after we are already in the debugging section. */ 31138889Sjdp if ((listing & LISTING_NODEBUG) != 0 31238889Sjdp && listing_tail != NULL 31338889Sjdp && ! listing_tail->debugging) 31438889Sjdp { 31538889Sjdp const char *segname; 31638889Sjdp 31738889Sjdp segname = segment_name (now_seg); 31838889Sjdp if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0 31938889Sjdp || strncmp (segname, ".line", sizeof ".line" - 1) == 0) 32038889Sjdp listing_tail->debugging = 1; 32138889Sjdp } 32238889Sjdp#endif 32338889Sjdp 32433965Sjdp as_where (&file, &line); 32538889Sjdp if (ps == NULL) 32633965Sjdp { 32777298Sobrien if (line == last_line 32877298Sobrien && !(last_file && file && strcmp (file, last_file))) 32938889Sjdp return; 33033965Sjdp 33133965Sjdp new = (list_info_type *) xmalloc (sizeof (list_info_type)); 33260484Sobrien 33360484Sobrien /* Detect if we are reading from stdin by examining the file 33460484Sobrien name returned by as_where(). 33560484Sobrien 33660484Sobrien [FIXME: We rely upon the name in the strcmp below being the 33760484Sobrien same as the one used by input_scrub_new_file(), if that is 33860484Sobrien not true, then this code will fail]. 33960484Sobrien 34077298Sobrien If we are reading from stdin, then we need to save each input 34177298Sobrien line here (assuming of course that we actually have a line of 34277298Sobrien input to read), so that it can be displayed in the listing 34377298Sobrien that is produced at the end of the assembly. */ 34460484Sobrien if (strcmp (file, _("{standard input}")) == 0 34560484Sobrien && input_line_pointer != NULL) 34660484Sobrien { 34777298Sobrien char *copy; 34860484Sobrien int len; 34960484Sobrien int seen_quote = 0; 35060484Sobrien 35160484Sobrien for (copy = input_line_pointer - 1; 35277298Sobrien *copy && (seen_quote 35377298Sobrien || (! is_end_of_line [(unsigned char) *copy])); 35477298Sobrien copy++) 35577298Sobrien if (*copy == '"' && copy[-1] != '\\') 35660484Sobrien seen_quote = ! seen_quote; 35760484Sobrien 35860484Sobrien len = (copy - input_line_pointer) + 2; 35960484Sobrien 36060484Sobrien copy = xmalloc (len); 36160484Sobrien 36260484Sobrien if (copy != NULL) 36360484Sobrien { 36477298Sobrien char *src = input_line_pointer - 1; 36577298Sobrien char *dest = copy; 36677298Sobrien 36760484Sobrien while (--len) 36860484Sobrien { 36977298Sobrien unsigned char c = *src++; 37060484Sobrien 37160484Sobrien /* Omit control characters in the listing. */ 37289857Sobrien if (!ISCNTRL (c)) 37377298Sobrien *dest++ = c; 37460484Sobrien } 37577298Sobrien 37660484Sobrien *dest = 0; 37760484Sobrien } 37877298Sobrien 37960484Sobrien new->line_contents = copy; 38060484Sobrien } 38160484Sobrien else 38260484Sobrien new->line_contents = NULL; 38338889Sjdp } 38438889Sjdp else 38538889Sjdp { 38638889Sjdp new = (list_info_type *) xmalloc (sizeof (list_info_type)); 38738889Sjdp new->line_contents = ps; 38838889Sjdp } 38933965Sjdp 39038889Sjdp last_line = line; 39138889Sjdp last_file = file; 39277298Sobrien 39338889Sjdp new_frag (); 39438889Sjdp 39538889Sjdp if (listing_tail) 39660484Sobrien listing_tail->next = new; 39738889Sjdp else 39860484Sobrien head = new; 39977298Sobrien 40038889Sjdp listing_tail = new; 40138889Sjdp 40238889Sjdp new->frag = frag_now; 40338889Sjdp new->line = line; 40438889Sjdp new->file = file_info (file); 40538889Sjdp new->next = (list_info_type *) NULL; 40638889Sjdp new->message = (char *) NULL; 40738889Sjdp new->edict = EDICT_NONE; 40838889Sjdp new->hll_file = (file_info_type *) NULL; 40938889Sjdp new->hll_line = 0; 41038889Sjdp new->debugging = 0; 41177298Sobrien 41238889Sjdp new_frag (); 41338889Sjdp 41438889Sjdp#ifdef OBJ_ELF 41538889Sjdp /* In ELF, anything in a section beginning with .debug or .line is 41638889Sjdp considered to be debugging information. */ 41738889Sjdp if ((listing & LISTING_NODEBUG) != 0) 41838889Sjdp { 41938889Sjdp const char *segname; 42038889Sjdp 42138889Sjdp segname = segment_name (now_seg); 42238889Sjdp if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0 42338889Sjdp || strncmp (segname, ".line", sizeof ".line" - 1) == 0) 42438889Sjdp new->debugging = 1; 42538889Sjdp } 42638889Sjdp#endif 42733965Sjdp} 42833965Sjdp 42933965Sjdp/* Attach all current frags to the previous line instead of the 43033965Sjdp current line. This is called by the MIPS backend when it discovers 43133965Sjdp that it needs to add some NOP instructions; the added NOP 43233965Sjdp instructions should go with the instruction that has the delay, not 43333965Sjdp with the new instruction. */ 43433965Sjdp 43533965Sjdpvoid 43633965Sjdplisting_prev_line () 43733965Sjdp{ 43833965Sjdp list_info_type *l; 43933965Sjdp fragS *f; 44033965Sjdp 44133965Sjdp if (head == (list_info_type *) NULL 44233965Sjdp || head == listing_tail) 44333965Sjdp return; 44433965Sjdp 44533965Sjdp new_frag (); 44633965Sjdp 44733965Sjdp for (l = head; l->next != listing_tail; l = l->next) 44833965Sjdp ; 44933965Sjdp 45033965Sjdp for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next) 45133965Sjdp if (f->line == listing_tail) 45233965Sjdp f->line = l; 45333965Sjdp 45433965Sjdp listing_tail->frag = frag_now; 45533965Sjdp new_frag (); 45633965Sjdp} 45733965Sjdp 45877298Sobrien/* This function returns the next source line from the file supplied, 45977298Sobrien truncated to size. It appends a fake line to the end of each input 46077298Sobrien file to make. */ 46133965Sjdp 46233965Sjdpstatic char * 46333965Sjdpbuffer_line (file, line, size) 46477298Sobrien file_info_type *file; 46533965Sjdp char *line; 46633965Sjdp unsigned int size; 46733965Sjdp{ 46833965Sjdp unsigned int count = 0; 46933965Sjdp int c; 47033965Sjdp 47133965Sjdp char *p = line; 47233965Sjdp 47377298Sobrien /* If we couldn't open the file, return an empty line. */ 47438889Sjdp if (file->at_end) 47538889Sjdp return ""; 47638889Sjdp 47738889Sjdp /* Check the cache and see if we last used this file. */ 47838889Sjdp if (!last_open_file_info || file != last_open_file_info) 47933965Sjdp { 48038889Sjdp if (last_open_file) 48138889Sjdp { 48238889Sjdp last_open_file_info->pos = ftell (last_open_file); 48338889Sjdp fclose (last_open_file); 48438889Sjdp } 48538889Sjdp 48638889Sjdp last_open_file_info = file; 48789857Sobrien last_open_file = fopen (file->filename, FOPEN_RT); 48838889Sjdp if (last_open_file == NULL) 48938889Sjdp { 49038889Sjdp file->at_end = 1; 49138889Sjdp return ""; 49238889Sjdp } 49377298Sobrien 49438889Sjdp /* Seek to where we were last time this file was open. */ 49538889Sjdp if (file->pos) 49677298Sobrien fseek (last_open_file, file->pos, SEEK_SET); 49733965Sjdp } 49833965Sjdp 49938889Sjdp c = fgetc (last_open_file); 50033965Sjdp 50177298Sobrien /* Leave room for null. */ 50277298Sobrien size -= 1; 50333965Sjdp 50433965Sjdp while (c != EOF && c != '\n') 50533965Sjdp { 50633965Sjdp if (count < size) 50733965Sjdp *p++ = c; 50833965Sjdp count++; 50933965Sjdp 51038889Sjdp c = fgetc (last_open_file); 51133965Sjdp 51233965Sjdp } 51333965Sjdp if (c == EOF) 51433965Sjdp { 51533965Sjdp file->at_end = 1; 51689857Sobrien if (count + 2 < size) 51789857Sobrien { 51889857Sobrien *p++ = '.'; 51989857Sobrien *p++ = '.'; 52089857Sobrien *p++ = '.'; 52189857Sobrien } 52233965Sjdp } 52333965Sjdp file->linenum++; 52433965Sjdp *p++ = 0; 52533965Sjdp return line; 52633965Sjdp} 52733965Sjdp 52833965Sjdpstatic const char *fn; 52933965Sjdp 53033965Sjdpstatic unsigned int eject; /* Eject pending */ 53133965Sjdpstatic unsigned int page; /* Current page number */ 53277298Sobrienstatic char *title; /* Current title */ 53377298Sobrienstatic char *subtitle; /* Current subtitle */ 53477298Sobrienstatic unsigned int on_page; /* Number of lines printed on current page */ 53533965Sjdp 53633965Sjdpstatic void 53733965Sjdplisting_page (list) 53833965Sjdp list_info_type *list; 53933965Sjdp{ 54033965Sjdp /* Grope around, see if we can see a title or subtitle edict coming up 54177298Sobrien soon. (we look down 10 lines of the page and see if it's there) */ 54277298Sobrien if ((eject || (on_page >= (unsigned int) paper_height)) 54377298Sobrien && paper_height != 0) 54433965Sjdp { 54533965Sjdp unsigned int c = 10; 54633965Sjdp int had_title = 0; 54733965Sjdp int had_subtitle = 0; 54833965Sjdp 54933965Sjdp page++; 55033965Sjdp 55133965Sjdp while (c != 0 && list) 55233965Sjdp { 55333965Sjdp if (list->edict == EDICT_SBTTL && !had_subtitle) 55433965Sjdp { 55533965Sjdp had_subtitle = 1; 55633965Sjdp subtitle = list->edict_arg; 55733965Sjdp } 55833965Sjdp if (list->edict == EDICT_TITLE && !had_title) 55933965Sjdp { 56033965Sjdp had_title = 1; 56133965Sjdp title = list->edict_arg; 56233965Sjdp } 56333965Sjdp list = list->next; 56433965Sjdp c--; 56533965Sjdp } 56633965Sjdp 56733965Sjdp if (page > 1) 56833965Sjdp { 56933965Sjdp fprintf (list_file, "\f"); 57033965Sjdp } 57133965Sjdp 57233965Sjdp fprintf (list_file, "%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page); 57333965Sjdp fprintf (list_file, "%s\n", title); 57433965Sjdp fprintf (list_file, "%s\n", subtitle); 57533965Sjdp on_page = 3; 57633965Sjdp eject = 0; 57733965Sjdp } 57833965Sjdp} 57933965Sjdp 58033965Sjdpstatic unsigned int 58133965Sjdpcalc_hex (list) 58277298Sobrien list_info_type *list; 58333965Sjdp{ 58438889Sjdp int data_buffer_size; 58533965Sjdp list_info_type *first = list; 58677298Sobrien unsigned int address = ~(unsigned int) 0; 58733965Sjdp fragS *frag; 58833965Sjdp fragS *frag_ptr; 58960484Sobrien unsigned int octet_in_frag; 59033965Sjdp 59177298Sobrien /* Find first frag which says it belongs to this line. */ 59233965Sjdp frag = list->frag; 59333965Sjdp while (frag && frag->line != list) 59433965Sjdp frag = frag->fr_next; 59533965Sjdp 59633965Sjdp frag_ptr = frag; 59733965Sjdp 59833965Sjdp data_buffer_size = 0; 59933965Sjdp 60077298Sobrien /* Dump all the frags which belong to this line. */ 60133965Sjdp while (frag_ptr != (fragS *) NULL && frag_ptr->line == first) 60233965Sjdp { 60377298Sobrien /* Print as many bytes from the fixed part as is sensible. */ 60460484Sobrien octet_in_frag = 0; 60560484Sobrien while ((offsetT) octet_in_frag < frag_ptr->fr_fix 60638889Sjdp && data_buffer_size < MAX_BYTES - 3) 60733965Sjdp { 60877298Sobrien if (address == ~(unsigned int) 0) 60933965Sjdp { 61060484Sobrien address = frag_ptr->fr_address / OCTETS_PER_BYTE; 61133965Sjdp } 61233965Sjdp 61333965Sjdp sprintf (data_buffer + data_buffer_size, 61433965Sjdp "%02X", 61560484Sobrien (frag_ptr->fr_literal[octet_in_frag]) & 0xff); 61633965Sjdp data_buffer_size += 2; 61760484Sobrien octet_in_frag++; 61833965Sjdp } 61977298Sobrien if (frag_ptr->fr_type == rs_fill) 62033965Sjdp { 62160484Sobrien unsigned int var_rep_max = octet_in_frag; 62260484Sobrien unsigned int var_rep_idx = octet_in_frag; 62333965Sjdp 62477298Sobrien /* Print as many bytes from the variable part as is sensible. */ 62560484Sobrien while (((offsetT) octet_in_frag 62660484Sobrien < (frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset)) 62738889Sjdp && data_buffer_size < MAX_BYTES - 3) 62833965Sjdp { 62977298Sobrien if (address == ~(unsigned int) 0) 63033965Sjdp { 63160484Sobrien address = frag_ptr->fr_address / OCTETS_PER_BYTE; 63233965Sjdp } 63333965Sjdp sprintf (data_buffer + data_buffer_size, 63433965Sjdp "%02X", 63533965Sjdp (frag_ptr->fr_literal[var_rep_idx]) & 0xff); 63633965Sjdp#if 0 63733965Sjdp data_buffer[data_buffer_size++] = '*'; 63833965Sjdp data_buffer[data_buffer_size++] = '*'; 63933965Sjdp#endif 64033965Sjdp data_buffer_size += 2; 64133965Sjdp 64233965Sjdp var_rep_idx++; 64360484Sobrien octet_in_frag++; 64433965Sjdp 64538889Sjdp if ((offsetT) var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var) 64633965Sjdp var_rep_idx = var_rep_max; 64733965Sjdp } 64833965Sjdp } 64933965Sjdp 65033965Sjdp frag_ptr = frag_ptr->fr_next; 65133965Sjdp } 65238889Sjdp data_buffer[data_buffer_size] = '\0'; 65333965Sjdp return address; 65433965Sjdp} 65533965Sjdp 65633965Sjdpstatic void 65733965Sjdpprint_lines (list, lineno, string, address) 65833965Sjdp list_info_type *list; 65933965Sjdp unsigned int lineno; 66033965Sjdp char *string; 66133965Sjdp unsigned int address; 66233965Sjdp{ 66333965Sjdp unsigned int idx; 66433965Sjdp unsigned int nchars; 66533965Sjdp unsigned int lines; 66660484Sobrien unsigned int octet_in_word = 0; 66733965Sjdp char *src = data_buffer; 66860484Sobrien int cur; 66933965Sjdp 67077298Sobrien /* Print the stuff on the first line. */ 67133965Sjdp listing_page (list); 67238889Sjdp nchars = (LISTING_WORD_SIZE * 2 + 1) * listing_lhs_width; 67377298Sobrien 67477298Sobrien /* Print the hex for the first line. */ 67577298Sobrien if (address == ~(unsigned int) 0) 67633965Sjdp { 67733965Sjdp fprintf (list_file, "% 4d ", lineno); 67833965Sjdp for (idx = 0; idx < nchars; idx++) 67933965Sjdp fprintf (list_file, " "); 68033965Sjdp 68133965Sjdp fprintf (list_file, "\t%s\n", string ? string : ""); 68277298Sobrien 68377298Sobrien on_page++; 68477298Sobrien 68533965Sjdp listing_page (0); 68633965Sjdp 68760484Sobrien return; 68833965Sjdp } 68960484Sobrien 69060484Sobrien if (had_errors ()) 69160484Sobrien fprintf (list_file, "% 4d ???? ", lineno); 69233965Sjdp else 69360484Sobrien fprintf (list_file, "% 4d %04x ", lineno, address); 69460484Sobrien 69577298Sobrien /* And the data to go along with it. */ 69660484Sobrien idx = 0; 69760484Sobrien cur = 0; 69860484Sobrien while (src[cur] && idx < nchars) 69933965Sjdp { 70060484Sobrien int offset; 70160484Sobrien offset = cur; 70277298Sobrien fprintf (list_file, "%c%c", src[offset], src[offset + 1]); 70360484Sobrien cur += 2; 70460484Sobrien octet_in_word++; 70577298Sobrien 70660484Sobrien if (octet_in_word == LISTING_WORD_SIZE) 70733965Sjdp { 70860484Sobrien fprintf (list_file, " "); 70960484Sobrien idx++; 71060484Sobrien octet_in_word = 0; 71133965Sjdp } 71277298Sobrien 71360484Sobrien idx += 2; 71460484Sobrien } 71577298Sobrien 71660484Sobrien for (; idx < nchars; idx++) 71760484Sobrien fprintf (list_file, " "); 71877298Sobrien 71960484Sobrien fprintf (list_file, "\t%s\n", string ? string : ""); 72060484Sobrien on_page++; 72160484Sobrien listing_page (list); 72277298Sobrien 72360484Sobrien if (list->message) 72460484Sobrien { 72560484Sobrien fprintf (list_file, "**** %s\n", list->message); 72660484Sobrien listing_page (list); 72760484Sobrien on_page++; 72860484Sobrien } 72977298Sobrien 73060484Sobrien for (lines = 0; 73160484Sobrien lines < (unsigned int) listing_lhs_cont_lines 73260484Sobrien && src[cur]; 73377298Sobrien lines++) 73460484Sobrien { 73577298Sobrien nchars = ((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second - 1; 73633965Sjdp idx = 0; 73777298Sobrien 73877298Sobrien /* Print any more lines of data, but more compactly. */ 73960484Sobrien fprintf (list_file, "% 4d ", lineno); 74077298Sobrien 74160484Sobrien while (src[cur] && idx < nchars) 74233965Sjdp { 74377298Sobrien int offset; 74477298Sobrien offset = cur; 74577298Sobrien fprintf (list_file, "%c%c", src[offset], src[offset + 1]); 74660484Sobrien cur += 2; 74760484Sobrien idx += 2; 74860484Sobrien octet_in_word++; 74977298Sobrien 75060484Sobrien if (octet_in_word == LISTING_WORD_SIZE) 75133965Sjdp { 75233965Sjdp fprintf (list_file, " "); 75333965Sjdp idx++; 75460484Sobrien octet_in_word = 0; 75533965Sjdp } 75633965Sjdp } 75777298Sobrien 75860484Sobrien fprintf (list_file, "\n"); 75977298Sobrien on_page++; 76033965Sjdp listing_page (list); 76133965Sjdp } 76233965Sjdp} 76333965Sjdp 76433965Sjdpstatic void 76533965Sjdplist_symbol_table () 76633965Sjdp{ 76733965Sjdp extern symbolS *symbol_rootP; 76833965Sjdp int got_some = 0; 76933965Sjdp 77033965Sjdp symbolS *ptr; 77133965Sjdp eject = 1; 77233965Sjdp listing_page (0); 77333965Sjdp 77433965Sjdp for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr)) 77533965Sjdp { 77638889Sjdp if (SEG_NORMAL (S_GET_SEGMENT (ptr)) 77738889Sjdp || S_GET_SEGMENT (ptr) == absolute_section) 77833965Sjdp { 77938889Sjdp#ifdef BFD_ASSEMBLER 78038889Sjdp /* Don't report section symbols. They are not interesting. */ 78160484Sobrien if (symbol_section_p (ptr)) 78238889Sjdp continue; 78338889Sjdp#endif 78433965Sjdp if (S_GET_NAME (ptr)) 78533965Sjdp { 78633965Sjdp char buf[30], fmt[8]; 78733965Sjdp valueT val = S_GET_VALUE (ptr); 78833965Sjdp 78933965Sjdp /* @@ Note that this is dependent on the compilation options, 79033965Sjdp not solely on the target characteristics. */ 79133965Sjdp if (sizeof (val) == 4 && sizeof (int) == 4) 79233965Sjdp sprintf (buf, "%08lx", (unsigned long) val); 79333965Sjdp else if (sizeof (val) <= sizeof (unsigned long)) 79433965Sjdp { 79533965Sjdp sprintf (fmt, "%%0%lulx", 79633965Sjdp (unsigned long) (sizeof (val) * 2)); 79733965Sjdp sprintf (buf, fmt, (unsigned long) val); 79833965Sjdp } 79933965Sjdp#if defined (BFD64) 80033965Sjdp else if (sizeof (val) > 4) 80133965Sjdp sprintf_vma (buf, val); 80233965Sjdp#endif 80333965Sjdp else 80433965Sjdp abort (); 80533965Sjdp 80633965Sjdp if (!got_some) 80733965Sjdp { 80833965Sjdp fprintf (list_file, "DEFINED SYMBOLS\n"); 80933965Sjdp on_page++; 81033965Sjdp got_some = 1; 81133965Sjdp } 81233965Sjdp 81360484Sobrien if (symbol_get_frag (ptr) && symbol_get_frag (ptr)->line) 81438889Sjdp { 81538889Sjdp fprintf (list_file, "%20s:%-5d %s:%s %s\n", 81660484Sobrien symbol_get_frag (ptr)->line->file->filename, 81760484Sobrien symbol_get_frag (ptr)->line->line, 81838889Sjdp segment_name (S_GET_SEGMENT (ptr)), 81938889Sjdp buf, S_GET_NAME (ptr)); 82038889Sjdp } 82138889Sjdp else 82238889Sjdp { 82338889Sjdp fprintf (list_file, "%33s:%s %s\n", 82438889Sjdp segment_name (S_GET_SEGMENT (ptr)), 82538889Sjdp buf, S_GET_NAME (ptr)); 82638889Sjdp } 82733965Sjdp 82877298Sobrien on_page++; 82933965Sjdp listing_page (0); 83033965Sjdp } 83133965Sjdp } 83233965Sjdp 83333965Sjdp } 83433965Sjdp if (!got_some) 83533965Sjdp { 83633965Sjdp fprintf (list_file, "NO DEFINED SYMBOLS\n"); 83733965Sjdp on_page++; 83833965Sjdp } 83933965Sjdp fprintf (list_file, "\n"); 84033965Sjdp on_page++; 84133965Sjdp listing_page (0); 84233965Sjdp 84333965Sjdp got_some = 0; 84433965Sjdp 84533965Sjdp for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr)) 84633965Sjdp { 84733965Sjdp if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0) 84833965Sjdp { 84938889Sjdp if (S_GET_SEGMENT (ptr) == undefined_section) 85033965Sjdp { 85133965Sjdp if (!got_some) 85233965Sjdp { 85333965Sjdp got_some = 1; 85433965Sjdp fprintf (list_file, "UNDEFINED SYMBOLS\n"); 85533965Sjdp on_page++; 85633965Sjdp listing_page (0); 85733965Sjdp } 85833965Sjdp fprintf (list_file, "%s\n", S_GET_NAME (ptr)); 85933965Sjdp on_page++; 86033965Sjdp listing_page (0); 86133965Sjdp } 86233965Sjdp } 86333965Sjdp } 86433965Sjdp if (!got_some) 86533965Sjdp { 86633965Sjdp fprintf (list_file, "NO UNDEFINED SYMBOLS\n"); 86733965Sjdp on_page++; 86833965Sjdp listing_page (0); 86933965Sjdp } 87033965Sjdp} 87133965Sjdp 87233965Sjdpstatic void 87333965Sjdpprint_source (current_file, list, buffer, width) 87433965Sjdp file_info_type *current_file; 87533965Sjdp list_info_type *list; 87633965Sjdp char *buffer; 87733965Sjdp unsigned int width; 87833965Sjdp{ 87938889Sjdp if (!current_file->at_end) 88033965Sjdp { 88133965Sjdp while (current_file->linenum < list->hll_line 88233965Sjdp && !current_file->at_end) 88333965Sjdp { 88433965Sjdp char *p = buffer_line (current_file, buffer, width); 88538889Sjdp fprintf (list_file, "%4u:%-13s **** %s\n", current_file->linenum, 88633965Sjdp current_file->filename, p); 88733965Sjdp on_page++; 88833965Sjdp listing_page (list); 88933965Sjdp } 89033965Sjdp } 89133965Sjdp} 89233965Sjdp 89333965Sjdp/* Sometimes the user doesn't want to be bothered by the debugging 89438889Sjdp records inserted by the compiler, see if the line is suspicious. */ 89533965Sjdp 89633965Sjdpstatic int 89738889Sjdpdebugging_pseudo (list, line) 89838889Sjdp list_info_type *list; 89938889Sjdp const char *line; 90033965Sjdp{ 90138889Sjdp static int in_debug; 90238889Sjdp int was_debug; 90338889Sjdp 90438889Sjdp if (list->debugging) 90538889Sjdp { 90638889Sjdp in_debug = 1; 90738889Sjdp return 1; 90838889Sjdp } 90938889Sjdp 91038889Sjdp was_debug = in_debug; 91138889Sjdp in_debug = 0; 91238889Sjdp 91389857Sobrien while (ISSPACE (*line)) 91433965Sjdp line++; 91533965Sjdp 91633965Sjdp if (*line != '.') 91738889Sjdp { 91838889Sjdp#ifdef OBJ_ELF 91938889Sjdp /* The ELF compiler sometimes emits blank lines after switching 92038889Sjdp out of a debugging section. If the next line drops us back 92138889Sjdp into debugging information, then don't print the blank line. 92238889Sjdp This is a hack for a particular compiler behaviour, not a 92338889Sjdp general case. */ 92438889Sjdp if (was_debug 92538889Sjdp && *line == '\0' 92638889Sjdp && list->next != NULL 92738889Sjdp && list->next->debugging) 92838889Sjdp { 92938889Sjdp in_debug = 1; 93038889Sjdp return 1; 93138889Sjdp } 93238889Sjdp#endif 93333965Sjdp 93438889Sjdp return 0; 93538889Sjdp } 93638889Sjdp 93733965Sjdp line++; 93833965Sjdp 93933965Sjdp if (strncmp (line, "def", 3) == 0) 94033965Sjdp return 1; 94133965Sjdp if (strncmp (line, "val", 3) == 0) 94233965Sjdp return 1; 94333965Sjdp if (strncmp (line, "scl", 3) == 0) 94433965Sjdp return 1; 94533965Sjdp if (strncmp (line, "line", 4) == 0) 94633965Sjdp return 1; 94733965Sjdp if (strncmp (line, "endef", 5) == 0) 94833965Sjdp return 1; 94933965Sjdp if (strncmp (line, "ln", 2) == 0) 95033965Sjdp return 1; 95133965Sjdp if (strncmp (line, "type", 4) == 0) 95233965Sjdp return 1; 95333965Sjdp if (strncmp (line, "size", 4) == 0) 95433965Sjdp return 1; 95533965Sjdp if (strncmp (line, "dim", 3) == 0) 95633965Sjdp return 1; 95733965Sjdp if (strncmp (line, "tag", 3) == 0) 95833965Sjdp return 1; 95933965Sjdp 96033965Sjdp if (strncmp (line, "stabs", 5) == 0) 96133965Sjdp return 1; 96233965Sjdp if (strncmp (line, "stabn", 5) == 0) 96333965Sjdp return 1; 96433965Sjdp 96533965Sjdp return 0; 96633965Sjdp} 96733965Sjdp 96833965Sjdpstatic void 96933965Sjdplisting_listing (name) 97060484Sobrien char *name ATTRIBUTE_UNUSED; 97133965Sjdp{ 97233965Sjdp list_info_type *list = head; 97333965Sjdp file_info_type *current_hll_file = (file_info_type *) NULL; 97433965Sjdp char *message; 97533965Sjdp char *buffer; 97633965Sjdp char *p; 97733965Sjdp int show_listing = 1; 97833965Sjdp unsigned int width; 97933965Sjdp 98038889Sjdp buffer = xmalloc (listing_rhs_width); 98138889Sjdp data_buffer = xmalloc (MAX_BYTES); 98233965Sjdp eject = 1; 98333965Sjdp list = head; 98433965Sjdp 98533965Sjdp while (list != (list_info_type *) NULL && 0) 98633965Sjdp { 98733965Sjdp if (list->next) 98833965Sjdp list->frag = list->next->frag; 98933965Sjdp list = list->next; 99033965Sjdp 99133965Sjdp } 99233965Sjdp 99333965Sjdp list = head->next; 99433965Sjdp 99533965Sjdp while (list) 99633965Sjdp { 99760484Sobrien unsigned int list_line; 99860484Sobrien 99938889Sjdp width = listing_rhs_width > paper_width ? paper_width : 100038889Sjdp listing_rhs_width; 100133965Sjdp 100260484Sobrien list_line = list->line; 100333965Sjdp switch (list->edict) 100433965Sjdp { 100533965Sjdp case EDICT_LIST: 100660484Sobrien /* Skip all lines up to the current. */ 100760484Sobrien list_line--; 100833965Sjdp break; 100933965Sjdp case EDICT_NOLIST: 101033965Sjdp show_listing--; 101133965Sjdp break; 101233965Sjdp case EDICT_NOLIST_NEXT: 101377298Sobrien if (show_listing == 0) 101477298Sobrien list_line--; 101533965Sjdp break; 101633965Sjdp case EDICT_EJECT: 101733965Sjdp break; 101833965Sjdp case EDICT_NONE: 101933965Sjdp break; 102033965Sjdp case EDICT_TITLE: 102133965Sjdp title = list->edict_arg; 102233965Sjdp break; 102333965Sjdp case EDICT_SBTTL: 102433965Sjdp subtitle = list->edict_arg; 102533965Sjdp break; 102633965Sjdp default: 102733965Sjdp abort (); 102833965Sjdp } 102933965Sjdp 103060484Sobrien if (show_listing <= 0) 103160484Sobrien { 103260484Sobrien while (list->file->linenum < list_line 103360484Sobrien && !list->file->at_end) 103460484Sobrien p = buffer_line (list->file, buffer, width); 103560484Sobrien } 103660484Sobrien 103777298Sobrien if (list->edict == EDICT_LIST 103877298Sobrien || (list->edict == EDICT_NOLIST_NEXT && show_listing == 0)) 103960484Sobrien { 104060484Sobrien /* Enable listing for the single line that caused the enable. */ 104160484Sobrien list_line++; 104260484Sobrien show_listing++; 104360484Sobrien } 104460484Sobrien 104533965Sjdp if (show_listing > 0) 104633965Sjdp { 104733965Sjdp /* Scan down the list and print all the stuff which can be done 104833965Sjdp with this line (or lines). */ 104933965Sjdp message = 0; 105033965Sjdp 105133965Sjdp if (list->hll_file) 105233965Sjdp { 105333965Sjdp current_hll_file = list->hll_file; 105433965Sjdp } 105533965Sjdp 105638889Sjdp if (current_hll_file && list->hll_line && (listing & LISTING_HLL)) 105733965Sjdp { 105833965Sjdp print_source (current_hll_file, list, buffer, width); 105933965Sjdp } 106033965Sjdp 106138889Sjdp if (list->line_contents) 106233965Sjdp { 106338889Sjdp if (!((listing & LISTING_NODEBUG) 106438889Sjdp && debugging_pseudo (list, list->line_contents))) 106538889Sjdp { 106660484Sobrien print_lines (list, 106760484Sobrien list->file->linenum == 0 ? list->line : list->file->linenum, 106838889Sjdp list->line_contents, calc_hex (list)); 106938889Sjdp } 107060484Sobrien free (list->line_contents); 107160484Sobrien list->line_contents = NULL; 107238889Sjdp } 107338889Sjdp else 107438889Sjdp { 107560484Sobrien while (list->file->linenum < list_line 107638889Sjdp && !list->file->at_end) 107738889Sjdp { 107838889Sjdp unsigned int address; 107933965Sjdp 108038889Sjdp p = buffer_line (list->file, buffer, width); 108133965Sjdp 108260484Sobrien if (list->file->linenum < list_line) 108377298Sobrien address = ~(unsigned int) 0; 108438889Sjdp else 108538889Sjdp address = calc_hex (list); 108633965Sjdp 108738889Sjdp if (!((listing & LISTING_NODEBUG) 108838889Sjdp && debugging_pseudo (list, p))) 108938889Sjdp print_lines (list, list->file->linenum, p, address); 109038889Sjdp } 109133965Sjdp } 109233965Sjdp 109333965Sjdp if (list->edict == EDICT_EJECT) 109433965Sjdp { 109533965Sjdp eject = 1; 109633965Sjdp } 109733965Sjdp } 109833965Sjdp 109977298Sobrien if (list->edict == EDICT_NOLIST_NEXT && show_listing == 1) 110033965Sjdp --show_listing; 110133965Sjdp 110233965Sjdp list = list->next; 110333965Sjdp } 110438889Sjdp 110533965Sjdp free (buffer); 110638889Sjdp free (data_buffer); 110738889Sjdp data_buffer = NULL; 110833965Sjdp} 110933965Sjdp 111033965Sjdpvoid 111133965Sjdplisting_print (name) 111233965Sjdp char *name; 111333965Sjdp{ 111433965Sjdp int using_stdout; 111577298Sobrien 111633965Sjdp title = ""; 111733965Sjdp subtitle = ""; 111833965Sjdp 111933965Sjdp if (name == NULL) 112033965Sjdp { 112133965Sjdp list_file = stdout; 112233965Sjdp using_stdout = 1; 112333965Sjdp } 112433965Sjdp else 112533965Sjdp { 112689857Sobrien list_file = fopen (name, FOPEN_WT); 112733965Sjdp if (list_file != NULL) 112833965Sjdp using_stdout = 0; 112933965Sjdp else 113033965Sjdp { 113160484Sobrien as_perror (_("can't open list file: %s"), name); 113233965Sjdp list_file = stdout; 113333965Sjdp using_stdout = 1; 113433965Sjdp } 113533965Sjdp } 113633965Sjdp 113733965Sjdp if (listing & LISTING_NOFORM) 113833965Sjdp { 113933965Sjdp paper_height = 0; 114033965Sjdp } 114133965Sjdp 114233965Sjdp if (listing & LISTING_LISTING) 114333965Sjdp { 114433965Sjdp listing_listing (name); 114533965Sjdp } 114633965Sjdp 114733965Sjdp if (listing & LISTING_SYMBOLS) 114833965Sjdp { 114933965Sjdp list_symbol_table (); 115033965Sjdp } 115133965Sjdp 115233965Sjdp if (! using_stdout) 115333965Sjdp { 115433965Sjdp if (fclose (list_file) == EOF) 115560484Sobrien as_perror (_("error closing list file: %s"), name); 115633965Sjdp } 115733965Sjdp 115838889Sjdp if (last_open_file) 115933965Sjdp { 116038889Sjdp fclose (last_open_file); 116133965Sjdp } 116233965Sjdp} 116333965Sjdp 116433965Sjdpvoid 116533965Sjdplisting_file (name) 116633965Sjdp const char *name; 116733965Sjdp{ 116833965Sjdp fn = name; 116933965Sjdp} 117033965Sjdp 117133965Sjdpvoid 117233965Sjdplisting_eject (ignore) 117360484Sobrien int ignore ATTRIBUTE_UNUSED; 117433965Sjdp{ 117533965Sjdp if (listing) 117633965Sjdp listing_tail->edict = EDICT_EJECT; 117733965Sjdp} 117833965Sjdp 117933965Sjdpvoid 118033965Sjdplisting_flags (ignore) 118160484Sobrien int ignore ATTRIBUTE_UNUSED; 118233965Sjdp{ 118333965Sjdp while ((*input_line_pointer++) && (*input_line_pointer != '\n')) 118433965Sjdp input_line_pointer++; 118533965Sjdp 118633965Sjdp} 118733965Sjdp 118833965Sjdp/* Turn listing on or off. An argument of 0 means to turn off 118933965Sjdp listing. An argument of 1 means to turn on listing. An argument 119033965Sjdp of 2 means to turn off listing, but as of the next line; that is, 119133965Sjdp the current line should be listed, but the next line should not. */ 119233965Sjdp 119333965Sjdpvoid 119433965Sjdplisting_list (on) 119533965Sjdp int on; 119633965Sjdp{ 119733965Sjdp if (listing) 119833965Sjdp { 119933965Sjdp switch (on) 120033965Sjdp { 120133965Sjdp case 0: 120233965Sjdp if (listing_tail->edict == EDICT_LIST) 120333965Sjdp listing_tail->edict = EDICT_NONE; 120433965Sjdp else 120533965Sjdp listing_tail->edict = EDICT_NOLIST; 120633965Sjdp break; 120733965Sjdp case 1: 120833965Sjdp if (listing_tail->edict == EDICT_NOLIST 120933965Sjdp || listing_tail->edict == EDICT_NOLIST_NEXT) 121033965Sjdp listing_tail->edict = EDICT_NONE; 121133965Sjdp else 121233965Sjdp listing_tail->edict = EDICT_LIST; 121333965Sjdp break; 121433965Sjdp case 2: 121533965Sjdp listing_tail->edict = EDICT_NOLIST_NEXT; 121633965Sjdp break; 121733965Sjdp default: 121833965Sjdp abort (); 121933965Sjdp } 122033965Sjdp } 122133965Sjdp} 122233965Sjdp 122333965Sjdpvoid 122433965Sjdplisting_psize (width_only) 122533965Sjdp int width_only; 122633965Sjdp{ 122733965Sjdp if (! width_only) 122833965Sjdp { 122933965Sjdp paper_height = get_absolute_expression (); 123033965Sjdp 123133965Sjdp if (paper_height < 0 || paper_height > 1000) 123233965Sjdp { 123333965Sjdp paper_height = 0; 123460484Sobrien as_warn (_("strange paper height, set to no form")); 123533965Sjdp } 123633965Sjdp 123733965Sjdp if (*input_line_pointer != ',') 123833965Sjdp { 123933965Sjdp demand_empty_rest_of_line (); 124033965Sjdp return; 124133965Sjdp } 124233965Sjdp 124333965Sjdp ++input_line_pointer; 124433965Sjdp } 124533965Sjdp 124633965Sjdp paper_width = get_absolute_expression (); 124733965Sjdp 124833965Sjdp demand_empty_rest_of_line (); 124933965Sjdp} 125033965Sjdp 125133965Sjdpvoid 125233965Sjdplisting_nopage (ignore) 125360484Sobrien int ignore ATTRIBUTE_UNUSED; 125433965Sjdp{ 125533965Sjdp paper_height = 0; 125633965Sjdp} 125733965Sjdp 125833965Sjdpvoid 125933965Sjdplisting_title (depth) 126033965Sjdp int depth; 126133965Sjdp{ 126233965Sjdp int quoted; 126333965Sjdp char *start; 126433965Sjdp char *ttl; 126533965Sjdp unsigned int length; 126633965Sjdp 126733965Sjdp SKIP_WHITESPACE (); 126833965Sjdp if (*input_line_pointer != '\"') 126933965Sjdp quoted = 0; 127033965Sjdp else 127133965Sjdp { 127233965Sjdp quoted = 1; 127333965Sjdp ++input_line_pointer; 127433965Sjdp } 127533965Sjdp 127633965Sjdp start = input_line_pointer; 127733965Sjdp 127833965Sjdp while (*input_line_pointer) 127933965Sjdp { 128033965Sjdp if (quoted 128133965Sjdp ? *input_line_pointer == '\"' 128233965Sjdp : is_end_of_line[(unsigned char) *input_line_pointer]) 128333965Sjdp { 128433965Sjdp if (listing) 128533965Sjdp { 128633965Sjdp length = input_line_pointer - start; 128733965Sjdp ttl = xmalloc (length + 1); 128833965Sjdp memcpy (ttl, start, length); 128933965Sjdp ttl[length] = 0; 129033965Sjdp listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE; 129133965Sjdp listing_tail->edict_arg = ttl; 129233965Sjdp } 129333965Sjdp if (quoted) 129433965Sjdp input_line_pointer++; 129533965Sjdp demand_empty_rest_of_line (); 129633965Sjdp return; 129733965Sjdp } 129833965Sjdp else if (*input_line_pointer == '\n') 129933965Sjdp { 130089857Sobrien as_bad (_("new line in title")); 130133965Sjdp demand_empty_rest_of_line (); 130233965Sjdp return; 130333965Sjdp } 130433965Sjdp else 130533965Sjdp { 130633965Sjdp input_line_pointer++; 130733965Sjdp } 130833965Sjdp } 130933965Sjdp} 131033965Sjdp 131133965Sjdpvoid 131233965Sjdplisting_source_line (line) 131333965Sjdp unsigned int line; 131433965Sjdp{ 131533965Sjdp if (listing) 131633965Sjdp { 131733965Sjdp new_frag (); 131833965Sjdp listing_tail->hll_line = line; 131933965Sjdp new_frag (); 132033965Sjdp } 132133965Sjdp} 132233965Sjdp 132333965Sjdpvoid 132433965Sjdplisting_source_file (file) 132533965Sjdp const char *file; 132633965Sjdp{ 132733965Sjdp if (listing) 132833965Sjdp listing_tail->hll_file = file_info (file); 132933965Sjdp} 133033965Sjdp 133133965Sjdp#else 133233965Sjdp 133377298Sobrien/* Dummy functions for when compiled without listing enabled. */ 133433965Sjdp 133533965Sjdpvoid 133633965Sjdplisting_flags (ignore) 133733965Sjdp int ignore; 133833965Sjdp{ 133933965Sjdp s_ignore (0); 134033965Sjdp} 134133965Sjdp 134277298Sobrienvoid 134333965Sjdplisting_list (on) 134433965Sjdp int on; 134533965Sjdp{ 134633965Sjdp s_ignore (0); 134733965Sjdp} 134833965Sjdp 134977298Sobrienvoid 135033965Sjdplisting_eject (ignore) 135133965Sjdp int ignore; 135233965Sjdp{ 135333965Sjdp s_ignore (0); 135433965Sjdp} 135533965Sjdp 135677298Sobrienvoid 135733965Sjdplisting_psize (ignore) 135833965Sjdp int ignore; 135933965Sjdp{ 136033965Sjdp s_ignore (0); 136133965Sjdp} 136233965Sjdp 136333965Sjdpvoid 136433965Sjdplisting_nopage (ignore) 136533965Sjdp int ignore; 136633965Sjdp{ 136733965Sjdp s_ignore (0); 136833965Sjdp} 136933965Sjdp 137077298Sobrienvoid 137133965Sjdplisting_title (depth) 137233965Sjdp int depth; 137333965Sjdp{ 137433965Sjdp s_ignore (0); 137533965Sjdp} 137633965Sjdp 137733965Sjdpvoid 137833965Sjdplisting_file (name) 137933965Sjdp const char *name; 138033965Sjdp{ 138133965Sjdp 138233965Sjdp} 138333965Sjdp 138477298Sobrienvoid 138533965Sjdplisting_newline (name) 138633965Sjdp char *name; 138733965Sjdp{ 138833965Sjdp 138933965Sjdp} 139033965Sjdp 139177298Sobrienvoid 139233965Sjdplisting_source_line (n) 139333965Sjdp unsigned int n; 139433965Sjdp{ 139533965Sjdp 139633965Sjdp} 139777298Sobrien 139877298Sobrienvoid 139933965Sjdplisting_source_file (n) 140033965Sjdp const char *n; 140133965Sjdp{ 140233965Sjdp 140333965Sjdp} 140433965Sjdp 140533965Sjdp#endif 1406