1130561Sobrien/* listing.c - maintain assembly listings 277298Sobrien Copyright 1991, 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 3218822Sdim 2001, 2002, 2003, 2005, 2006 438889Sjdp Free Software Foundation, Inc. 533965Sjdp 6130561Sobrien This file is part of GAS, the GNU Assembler. 733965Sjdp 8130561Sobrien GAS is free software; you can redistribute it and/or modify 9130561Sobrien it under the terms of the GNU General Public License as published by 10130561Sobrien the Free Software Foundation; either version 2, or (at your option) 11130561Sobrien any later version. 1233965Sjdp 13130561Sobrien GAS is distributed in the hope that it will be useful, 14130561Sobrien but WITHOUT ANY WARRANTY; without even the implied warranty of 15130561Sobrien MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16130561Sobrien GNU General Public License for more details. 1733965Sjdp 18130561Sobrien You should have received a copy of the GNU General Public License 19130561Sobrien along with GAS; see the file COPYING. If not, write to the Free 20218822Sdim Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA 21218822Sdim 02110-1301, USA. */ 2233965Sjdp 23130561Sobrien/* Contributed by Steve Chamberlain <sac@cygnus.com> 2433965Sjdp 2533965Sjdp A listing page looks like: 2633965Sjdp 2733965Sjdp LISTING_HEADER sourcefilename pagenumber 2833965Sjdp TITLE LINE 2933965Sjdp SUBTITLE LINE 3033965Sjdp linenumber address data source 3133965Sjdp linenumber address data source 3233965Sjdp linenumber address data source 3333965Sjdp linenumber address data source 3433965Sjdp 3533965Sjdp If not overridden, the listing commands are: 3633965Sjdp 3733965Sjdp .title "stuff" 3833965Sjdp Put "stuff" onto the title line 3933965Sjdp .sbttl "stuff" 4033965Sjdp Put stuff onto the subtitle line 4133965Sjdp 4233965Sjdp If these commands come within 10 lines of the top of the page, they 4333965Sjdp will affect the page they are on, as well as any subsequent page 4433965Sjdp 4533965Sjdp .eject 4633965Sjdp Thow a page 4733965Sjdp .list 4833965Sjdp Increment the enable listing counter 4933965Sjdp .nolist 5033965Sjdp Decrement the enable listing counter 5133965Sjdp 5233965Sjdp .psize Y[,X] 5333965Sjdp Set the paper size to X wide and Y high. Setting a psize Y of 5433965Sjdp zero will suppress form feeds except where demanded by .eject 5533965Sjdp 5633965Sjdp If the counter goes below zero, listing is suppressed. 5733965Sjdp 5833965Sjdp Listings are a maintained by read calling various listing_<foo> 5933965Sjdp functions. What happens most is that the macro NO_LISTING is not 6033965Sjdp defined (from the Makefile), then the macro LISTING_NEWLINE expands 6133965Sjdp into a call to listing_newline. The call is done from read.c, every 6233965Sjdp time it sees a newline, and -l is on the command line. 6333965Sjdp 6433965Sjdp The function listing_newline remembers the frag associated with the 6533965Sjdp newline, and creates a new frag - note that this is wasteful, but not 6633965Sjdp a big deal, since listing slows things down a lot anyway. The 67130561Sobrien function also remembers when the filename changes. 6833965Sjdp 6933965Sjdp When all the input has finished, and gas has had a chance to settle 7033965Sjdp down, the listing is output. This is done by running down the list of 7133965Sjdp frag/source file records, and opening the files as needed and printing 7233965Sjdp out the bytes and chars associated with them. 7333965Sjdp 7433965Sjdp The only things which the architecture can change about the listing 7533965Sjdp are defined in these macros: 7633965Sjdp 7733965Sjdp LISTING_HEADER The name of the architecture 7833965Sjdp LISTING_WORD_SIZE The make of the number of bytes in a word, this determines 7933965Sjdp the clumping of the output data. eg a value of 8033965Sjdp 2 makes words look like 1234 5678, whilst 1 8133965Sjdp would make the same value look like 12 34 56 8233965Sjdp 78 8333965Sjdp LISTING_LHS_WIDTH Number of words of above size for the lhs 8433965Sjdp 8533965Sjdp LISTING_LHS_WIDTH_SECOND Number of words for the data on the lhs 8633965Sjdp for the second line 8733965Sjdp 88130561Sobrien LISTING_LHS_CONT_LINES Max number of lines to use up for a continuation 8933965Sjdp LISTING_RHS_WIDTH Number of chars from the input file to print 90130561Sobrien on a line. */ 9133965Sjdp 9233965Sjdp#include "as.h" 93104834Sobrien#include "obstack.h" 9489857Sobrien#include "safe-ctype.h" 9533965Sjdp#include "input-file.h" 9633965Sjdp#include "subsegs.h" 9733965Sjdp 9833965Sjdp#ifndef NO_LISTING 9938889Sjdp 10033965Sjdp#ifndef LISTING_HEADER 10133965Sjdp#define LISTING_HEADER "GAS LISTING" 10233965Sjdp#endif 10333965Sjdp#ifndef LISTING_WORD_SIZE 10433965Sjdp#define LISTING_WORD_SIZE 4 10533965Sjdp#endif 10633965Sjdp#ifndef LISTING_LHS_WIDTH 10760484Sobrien#define LISTING_LHS_WIDTH ((LISTING_WORD_SIZE) > 4 ? 1 : 4 / (LISTING_WORD_SIZE)) 10833965Sjdp#endif 10933965Sjdp#ifndef LISTING_LHS_WIDTH_SECOND 11060484Sobrien#define LISTING_LHS_WIDTH_SECOND LISTING_LHS_WIDTH 11133965Sjdp#endif 11233965Sjdp#ifndef LISTING_RHS_WIDTH 11333965Sjdp#define LISTING_RHS_WIDTH 100 11433965Sjdp#endif 11533965Sjdp#ifndef LISTING_LHS_CONT_LINES 11633965Sjdp#define LISTING_LHS_CONT_LINES 4 11733965Sjdp#endif 11833965Sjdp 11977298Sobrien/* This structure remembers which .s were used. */ 120130561Sobrientypedef struct file_info_struct 121130561Sobrien{ 12260484Sobrien struct file_info_struct * next; 12360484Sobrien char * filename; 12460484Sobrien long pos; 12560484Sobrien unsigned int linenum; 12660484Sobrien int at_end; 12777298Sobrien} file_info_type; 12833965Sjdp 129130561Sobrien/* This structure remembers which line from which file goes into which 13077298Sobrien frag. */ 131130561Sobrienstruct list_info_struct 132130561Sobrien{ 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; 138130561Sobrien 13933965Sjdp /* Pointer to the file info struct for the file which this line 14077298Sobrien belongs to. */ 14177298Sobrien file_info_type *file; 14233965Sjdp 14338889Sjdp /* The expanded text of any macro that may have been executing. */ 14477298Sobrien char *line_contents; 14538889Sjdp 14677298Sobrien /* Next in list. */ 14777298Sobrien struct list_info_struct *next; 14833965Sjdp 14933965Sjdp /* Pointer to the file info struct for the high level language 15077298Sobrien source line that belongs here. */ 15177298Sobrien file_info_type *hll_file; 152130561Sobrien 15377298Sobrien /* High level language source line. */ 15438889Sjdp unsigned int hll_line; 15533965Sjdp 15677298Sobrien /* Pointer to any error message associated with this line. */ 15777298Sobrien char *message; 15833965Sjdp 159130561Sobrien enum 160130561Sobrien { 161130561Sobrien EDICT_NONE, 162130561Sobrien EDICT_SBTTL, 163130561Sobrien EDICT_TITLE, 164130561Sobrien EDICT_NOLIST, 165130561Sobrien EDICT_LIST, 166130561Sobrien EDICT_NOLIST_NEXT, 167130561Sobrien EDICT_EJECT 168130561Sobrien } edict; 16977298Sobrien char *edict_arg; 17033965Sjdp 17138889Sjdp /* Nonzero if this line is to be omitted because it contains 17238889Sjdp debugging information. This can become a flags field if we come 17338889Sjdp up with more information to store here. */ 17438889Sjdp int debugging; 17538889Sjdp}; 17633965Sjdp 17738889Sjdptypedef struct list_info_struct list_info_type; 17833965Sjdp 17960484Sobrienint listing_lhs_width = LISTING_LHS_WIDTH; 18060484Sobrienint listing_lhs_width_second = LISTING_LHS_WIDTH_SECOND; 18160484Sobrienint listing_lhs_cont_lines = LISTING_LHS_CONT_LINES; 18260484Sobrienint listing_rhs_width = LISTING_RHS_WIDTH; 18333965Sjdp 18460484Sobrienstruct list_info_struct * listing_tail; 18560484Sobrien 18660484Sobrienstatic file_info_type * file_info_head; 18760484Sobrienstatic file_info_type * last_open_file_info; 18860484Sobrienstatic FILE * last_open_file; 18960484Sobrienstatic struct list_info_struct * head; 19060484Sobrienstatic int paper_width = 200; 19160484Sobrienstatic int paper_height = 60; 19260484Sobrien 19360484Sobrienextern int listing; 19460484Sobrien 19533965Sjdp/* File to output listings to. */ 19677298Sobrienstatic FILE *list_file; 19733965Sjdp 19838889Sjdp/* This static array is used to keep the text of data to be printed 19938889Sjdp before the start of the line. */ 20033965Sjdp 20138889Sjdp#define MAX_BYTES \ 20238889Sjdp (((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width \ 20338889Sjdp + ((((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second) \ 20438889Sjdp * listing_lhs_cont_lines) \ 20538889Sjdp + 20) 20633965Sjdp 20777298Sobrienstatic char *data_buffer; 20833965Sjdp 20933965Sjdp/* Prototypes. */ 210130561Sobrienstatic void listing_message (const char *, const char *); 211130561Sobrienstatic file_info_type *file_info (const char *); 212130561Sobrienstatic void new_frag (void); 213130561Sobrienstatic char *buffer_line (file_info_type *, char *, unsigned int); 214130561Sobrienstatic void listing_page (list_info_type *); 215130561Sobrienstatic unsigned int calc_hex (list_info_type *); 216130561Sobrienstatic void print_lines (list_info_type *, unsigned int, char *, unsigned int); 217130561Sobrienstatic void list_symbol_table (void); 218130561Sobrienstatic void print_source (file_info_type *, list_info_type *, char *, unsigned int); 219130561Sobrienstatic int debugging_pseudo (list_info_type *, const char *); 220130561Sobrienstatic void listing_listing (char *); 22133965Sjdp 22233965Sjdpstatic void 223130561Sobrienlisting_message (const char *name, const char *message) 22433965Sjdp{ 22533965Sjdp if (listing_tail != (list_info_type *) NULL) 22633965Sjdp { 22777298Sobrien unsigned int l = strlen (name) + strlen (message) + 1; 22877298Sobrien char *n = (char *) xmalloc (l); 22977298Sobrien strcpy (n, name); 23077298Sobrien strcat (n, message); 23133965Sjdp listing_tail->message = n; 23233965Sjdp } 23333965Sjdp} 23433965Sjdp 23533965Sjdpvoid 236130561Sobrienlisting_warning (const char *message) 23733965Sjdp{ 23860484Sobrien listing_message (_("Warning:"), message); 23933965Sjdp} 24033965Sjdp 24133965Sjdpvoid 242130561Sobrienlisting_error (const char *message) 24333965Sjdp{ 24460484Sobrien listing_message (_("Error:"), message); 24533965Sjdp} 24633965Sjdp 24733965Sjdpstatic file_info_type * 248130561Sobrienfile_info (const char *file_name) 24933965Sjdp{ 25077298Sobrien /* Find an entry with this file name. */ 25133965Sjdp file_info_type *p = file_info_head; 25233965Sjdp 25333965Sjdp while (p != (file_info_type *) NULL) 25433965Sjdp { 25533965Sjdp if (strcmp (p->filename, file_name) == 0) 25633965Sjdp return p; 25733965Sjdp p = p->next; 25833965Sjdp } 25933965Sjdp 26077298Sobrien /* Make new entry. */ 261130561Sobrien p = xmalloc (sizeof (file_info_type)); 26233965Sjdp p->next = file_info_head; 26333965Sjdp file_info_head = p; 264104834Sobrien p->filename = xstrdup (file_name); 26538889Sjdp p->pos = 0; 26633965Sjdp p->linenum = 0; 26733965Sjdp p->at_end = 0; 26833965Sjdp 26933965Sjdp return p; 27033965Sjdp} 27133965Sjdp 27233965Sjdpstatic void 273130561Sobriennew_frag (void) 27433965Sjdp{ 27533965Sjdp frag_wane (frag_now); 27633965Sjdp frag_new (0); 27733965Sjdp} 27833965Sjdp 27933965Sjdpvoid 280130561Sobrienlisting_newline (char *ps) 28133965Sjdp{ 28233965Sjdp char *file; 28333965Sjdp unsigned int line; 28433965Sjdp static unsigned int last_line = 0xffff; 28533965Sjdp static char *last_file = NULL; 28638889Sjdp list_info_type *new = NULL; 28733965Sjdp 28833965Sjdp if (listing == 0) 28933965Sjdp return; 29033965Sjdp 29133965Sjdp if (now_seg == absolute_section) 29233965Sjdp return; 29333965Sjdp 29438889Sjdp#ifdef OBJ_ELF 29538889Sjdp /* In ELF, anything in a section beginning with .debug or .line is 29638889Sjdp considered to be debugging information. This includes the 29738889Sjdp statement which switches us into the debugging section, which we 29838889Sjdp can only set after we are already in the debugging section. */ 29938889Sjdp if ((listing & LISTING_NODEBUG) != 0 30038889Sjdp && listing_tail != NULL 30138889Sjdp && ! listing_tail->debugging) 30238889Sjdp { 30338889Sjdp const char *segname; 30438889Sjdp 30538889Sjdp segname = segment_name (now_seg); 30638889Sjdp if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0 30738889Sjdp || strncmp (segname, ".line", sizeof ".line" - 1) == 0) 30838889Sjdp listing_tail->debugging = 1; 30938889Sjdp } 31038889Sjdp#endif 31138889Sjdp 31233965Sjdp as_where (&file, &line); 31338889Sjdp if (ps == NULL) 31433965Sjdp { 31577298Sobrien if (line == last_line 31677298Sobrien && !(last_file && file && strcmp (file, last_file))) 31738889Sjdp return; 31833965Sjdp 31933965Sjdp new = (list_info_type *) xmalloc (sizeof (list_info_type)); 32060484Sobrien 32160484Sobrien /* Detect if we are reading from stdin by examining the file 32260484Sobrien name returned by as_where(). 32360484Sobrien 32460484Sobrien [FIXME: We rely upon the name in the strcmp below being the 32560484Sobrien same as the one used by input_scrub_new_file(), if that is 32660484Sobrien not true, then this code will fail]. 32760484Sobrien 32877298Sobrien If we are reading from stdin, then we need to save each input 32977298Sobrien line here (assuming of course that we actually have a line of 33077298Sobrien input to read), so that it can be displayed in the listing 33177298Sobrien that is produced at the end of the assembly. */ 33260484Sobrien if (strcmp (file, _("{standard input}")) == 0 33360484Sobrien && input_line_pointer != NULL) 33460484Sobrien { 33577298Sobrien char *copy; 33660484Sobrien int len; 33760484Sobrien int seen_quote = 0; 33860484Sobrien 33960484Sobrien for (copy = input_line_pointer - 1; 34077298Sobrien *copy && (seen_quote 34177298Sobrien || (! is_end_of_line [(unsigned char) *copy])); 34277298Sobrien copy++) 34377298Sobrien if (*copy == '"' && copy[-1] != '\\') 34460484Sobrien seen_quote = ! seen_quote; 34560484Sobrien 34660484Sobrien len = (copy - input_line_pointer) + 2; 34760484Sobrien 34860484Sobrien copy = xmalloc (len); 34960484Sobrien 35060484Sobrien if (copy != NULL) 35160484Sobrien { 35277298Sobrien char *src = input_line_pointer - 1; 35377298Sobrien char *dest = copy; 35477298Sobrien 35560484Sobrien while (--len) 35660484Sobrien { 35777298Sobrien unsigned char c = *src++; 35860484Sobrien 35960484Sobrien /* Omit control characters in the listing. */ 36089857Sobrien if (!ISCNTRL (c)) 36177298Sobrien *dest++ = c; 36260484Sobrien } 36377298Sobrien 36460484Sobrien *dest = 0; 36560484Sobrien } 36677298Sobrien 36760484Sobrien new->line_contents = copy; 36860484Sobrien } 36960484Sobrien else 37060484Sobrien new->line_contents = NULL; 37138889Sjdp } 37238889Sjdp else 37338889Sjdp { 374130561Sobrien new = xmalloc (sizeof (list_info_type)); 37538889Sjdp new->line_contents = ps; 37638889Sjdp } 37733965Sjdp 37838889Sjdp last_line = line; 37938889Sjdp last_file = file; 38077298Sobrien 38138889Sjdp new_frag (); 38238889Sjdp 38338889Sjdp if (listing_tail) 38460484Sobrien listing_tail->next = new; 38538889Sjdp else 38660484Sobrien head = new; 38777298Sobrien 38838889Sjdp listing_tail = new; 38938889Sjdp 39038889Sjdp new->frag = frag_now; 39138889Sjdp new->line = line; 39238889Sjdp new->file = file_info (file); 39338889Sjdp new->next = (list_info_type *) NULL; 39438889Sjdp new->message = (char *) NULL; 39538889Sjdp new->edict = EDICT_NONE; 39638889Sjdp new->hll_file = (file_info_type *) NULL; 39738889Sjdp new->hll_line = 0; 39838889Sjdp new->debugging = 0; 39977298Sobrien 40038889Sjdp new_frag (); 40138889Sjdp 40238889Sjdp#ifdef OBJ_ELF 40338889Sjdp /* In ELF, anything in a section beginning with .debug or .line is 40438889Sjdp considered to be debugging information. */ 40538889Sjdp if ((listing & LISTING_NODEBUG) != 0) 40638889Sjdp { 40738889Sjdp const char *segname; 40838889Sjdp 40938889Sjdp segname = segment_name (now_seg); 41038889Sjdp if (strncmp (segname, ".debug", sizeof ".debug" - 1) == 0 41138889Sjdp || strncmp (segname, ".line", sizeof ".line" - 1) == 0) 41238889Sjdp new->debugging = 1; 41338889Sjdp } 41438889Sjdp#endif 41533965Sjdp} 41633965Sjdp 41733965Sjdp/* Attach all current frags to the previous line instead of the 41833965Sjdp current line. This is called by the MIPS backend when it discovers 41933965Sjdp that it needs to add some NOP instructions; the added NOP 42033965Sjdp instructions should go with the instruction that has the delay, not 42133965Sjdp with the new instruction. */ 42233965Sjdp 42333965Sjdpvoid 424130561Sobrienlisting_prev_line (void) 42533965Sjdp{ 42633965Sjdp list_info_type *l; 42733965Sjdp fragS *f; 42833965Sjdp 42933965Sjdp if (head == (list_info_type *) NULL 43033965Sjdp || head == listing_tail) 43133965Sjdp return; 43233965Sjdp 43333965Sjdp new_frag (); 43433965Sjdp 43533965Sjdp for (l = head; l->next != listing_tail; l = l->next) 43633965Sjdp ; 43733965Sjdp 43833965Sjdp for (f = frchain_now->frch_root; f != (fragS *) NULL; f = f->fr_next) 43933965Sjdp if (f->line == listing_tail) 44033965Sjdp f->line = l; 44133965Sjdp 44233965Sjdp listing_tail->frag = frag_now; 44333965Sjdp new_frag (); 44433965Sjdp} 44533965Sjdp 44677298Sobrien/* This function returns the next source line from the file supplied, 44777298Sobrien truncated to size. It appends a fake line to the end of each input 44877298Sobrien file to make. */ 44933965Sjdp 45033965Sjdpstatic char * 451130561Sobrienbuffer_line (file_info_type *file, char *line, unsigned int size) 45233965Sjdp{ 45333965Sjdp unsigned int count = 0; 45433965Sjdp int c; 45533965Sjdp 45633965Sjdp char *p = line; 45733965Sjdp 45877298Sobrien /* If we couldn't open the file, return an empty line. */ 45938889Sjdp if (file->at_end) 46038889Sjdp return ""; 46138889Sjdp 46238889Sjdp /* Check the cache and see if we last used this file. */ 46338889Sjdp if (!last_open_file_info || file != last_open_file_info) 46433965Sjdp { 46538889Sjdp if (last_open_file) 46638889Sjdp { 46738889Sjdp last_open_file_info->pos = ftell (last_open_file); 46838889Sjdp fclose (last_open_file); 46938889Sjdp } 47038889Sjdp 47138889Sjdp last_open_file_info = file; 47289857Sobrien last_open_file = fopen (file->filename, FOPEN_RT); 47338889Sjdp if (last_open_file == NULL) 47438889Sjdp { 47538889Sjdp file->at_end = 1; 47638889Sjdp return ""; 47738889Sjdp } 47877298Sobrien 47938889Sjdp /* Seek to where we were last time this file was open. */ 48038889Sjdp if (file->pos) 48177298Sobrien fseek (last_open_file, file->pos, SEEK_SET); 48233965Sjdp } 48333965Sjdp 48438889Sjdp c = fgetc (last_open_file); 48533965Sjdp 48677298Sobrien /* Leave room for null. */ 48777298Sobrien size -= 1; 48833965Sjdp 48933965Sjdp while (c != EOF && c != '\n') 49033965Sjdp { 49133965Sjdp if (count < size) 49233965Sjdp *p++ = c; 49333965Sjdp count++; 49433965Sjdp 49538889Sjdp c = fgetc (last_open_file); 49633965Sjdp 49733965Sjdp } 49833965Sjdp if (c == EOF) 49933965Sjdp { 50033965Sjdp file->at_end = 1; 50189857Sobrien if (count + 2 < size) 50289857Sobrien { 50389857Sobrien *p++ = '.'; 50489857Sobrien *p++ = '.'; 50589857Sobrien *p++ = '.'; 50689857Sobrien } 50733965Sjdp } 50833965Sjdp file->linenum++; 50933965Sjdp *p++ = 0; 51033965Sjdp return line; 51133965Sjdp} 51233965Sjdp 51333965Sjdpstatic const char *fn; 51433965Sjdp 51533965Sjdpstatic unsigned int eject; /* Eject pending */ 51633965Sjdpstatic unsigned int page; /* Current page number */ 51777298Sobrienstatic char *title; /* Current title */ 51877298Sobrienstatic char *subtitle; /* Current subtitle */ 51977298Sobrienstatic unsigned int on_page; /* Number of lines printed on current page */ 52033965Sjdp 52133965Sjdpstatic void 522130561Sobrienlisting_page (list_info_type *list) 52333965Sjdp{ 52433965Sjdp /* Grope around, see if we can see a title or subtitle edict coming up 52577298Sobrien soon. (we look down 10 lines of the page and see if it's there) */ 52677298Sobrien if ((eject || (on_page >= (unsigned int) paper_height)) 52777298Sobrien && paper_height != 0) 52833965Sjdp { 52933965Sjdp unsigned int c = 10; 53033965Sjdp int had_title = 0; 53133965Sjdp int had_subtitle = 0; 53233965Sjdp 53333965Sjdp page++; 53433965Sjdp 53533965Sjdp while (c != 0 && list) 53633965Sjdp { 53733965Sjdp if (list->edict == EDICT_SBTTL && !had_subtitle) 53833965Sjdp { 53933965Sjdp had_subtitle = 1; 54033965Sjdp subtitle = list->edict_arg; 54133965Sjdp } 54233965Sjdp if (list->edict == EDICT_TITLE && !had_title) 54333965Sjdp { 54433965Sjdp had_title = 1; 54533965Sjdp title = list->edict_arg; 54633965Sjdp } 54733965Sjdp list = list->next; 54833965Sjdp c--; 54933965Sjdp } 55033965Sjdp 55133965Sjdp if (page > 1) 55233965Sjdp { 55333965Sjdp fprintf (list_file, "\f"); 55433965Sjdp } 55533965Sjdp 55633965Sjdp fprintf (list_file, "%s %s \t\t\tpage %d\n", LISTING_HEADER, fn, page); 55733965Sjdp fprintf (list_file, "%s\n", title); 55833965Sjdp fprintf (list_file, "%s\n", subtitle); 55933965Sjdp on_page = 3; 56033965Sjdp eject = 0; 56133965Sjdp } 56233965Sjdp} 56333965Sjdp 56433965Sjdpstatic unsigned int 565130561Sobriencalc_hex (list_info_type *list) 56633965Sjdp{ 56738889Sjdp int data_buffer_size; 56833965Sjdp list_info_type *first = list; 56977298Sobrien unsigned int address = ~(unsigned int) 0; 57033965Sjdp fragS *frag; 57133965Sjdp fragS *frag_ptr; 57260484Sobrien unsigned int octet_in_frag; 57333965Sjdp 57477298Sobrien /* Find first frag which says it belongs to this line. */ 57533965Sjdp frag = list->frag; 57633965Sjdp while (frag && frag->line != list) 57733965Sjdp frag = frag->fr_next; 57833965Sjdp 57933965Sjdp frag_ptr = frag; 58033965Sjdp 58133965Sjdp data_buffer_size = 0; 58233965Sjdp 58377298Sobrien /* Dump all the frags which belong to this line. */ 58433965Sjdp while (frag_ptr != (fragS *) NULL && frag_ptr->line == first) 58533965Sjdp { 58677298Sobrien /* Print as many bytes from the fixed part as is sensible. */ 58760484Sobrien octet_in_frag = 0; 58860484Sobrien while ((offsetT) octet_in_frag < frag_ptr->fr_fix 58938889Sjdp && data_buffer_size < MAX_BYTES - 3) 59033965Sjdp { 59177298Sobrien if (address == ~(unsigned int) 0) 592130561Sobrien address = frag_ptr->fr_address / OCTETS_PER_BYTE; 59333965Sjdp 59433965Sjdp sprintf (data_buffer + data_buffer_size, 59533965Sjdp "%02X", 59660484Sobrien (frag_ptr->fr_literal[octet_in_frag]) & 0xff); 59733965Sjdp data_buffer_size += 2; 59860484Sobrien octet_in_frag++; 59933965Sjdp } 600104834Sobrien if (frag_ptr->fr_type == rs_fill) 601104834Sobrien { 602104834Sobrien unsigned int var_rep_max = octet_in_frag; 603104834Sobrien unsigned int var_rep_idx = octet_in_frag; 60433965Sjdp 605104834Sobrien /* Print as many bytes from the variable part as is sensible. */ 606104834Sobrien while (((offsetT) octet_in_frag 607104834Sobrien < (frag_ptr->fr_fix + frag_ptr->fr_var * frag_ptr->fr_offset)) 608104834Sobrien && data_buffer_size < MAX_BYTES - 3) 609104834Sobrien { 610104834Sobrien if (address == ~(unsigned int) 0) 611130561Sobrien address = frag_ptr->fr_address / OCTETS_PER_BYTE; 612130561Sobrien 613104834Sobrien sprintf (data_buffer + data_buffer_size, 614104834Sobrien "%02X", 615104834Sobrien (frag_ptr->fr_literal[var_rep_idx]) & 0xff); 616104834Sobrien data_buffer_size += 2; 61733965Sjdp 618104834Sobrien var_rep_idx++; 619104834Sobrien octet_in_frag++; 62033965Sjdp 621104834Sobrien if ((offsetT) var_rep_idx >= frag_ptr->fr_fix + frag_ptr->fr_var) 622104834Sobrien var_rep_idx = var_rep_max; 623104834Sobrien } 624104834Sobrien } 62533965Sjdp 62633965Sjdp frag_ptr = frag_ptr->fr_next; 62733965Sjdp } 62838889Sjdp data_buffer[data_buffer_size] = '\0'; 62933965Sjdp return address; 63033965Sjdp} 63133965Sjdp 63233965Sjdpstatic void 633130561Sobrienprint_lines (list_info_type *list, unsigned int lineno, 634130561Sobrien char *string, unsigned int address) 63533965Sjdp{ 63633965Sjdp unsigned int idx; 63733965Sjdp unsigned int nchars; 63833965Sjdp unsigned int lines; 63960484Sobrien unsigned int octet_in_word = 0; 64033965Sjdp char *src = data_buffer; 64160484Sobrien int cur; 64233965Sjdp 64377298Sobrien /* Print the stuff on the first line. */ 64433965Sjdp listing_page (list); 64538889Sjdp nchars = (LISTING_WORD_SIZE * 2 + 1) * listing_lhs_width; 64677298Sobrien 64777298Sobrien /* Print the hex for the first line. */ 64877298Sobrien if (address == ~(unsigned int) 0) 64933965Sjdp { 65033965Sjdp fprintf (list_file, "% 4d ", lineno); 65133965Sjdp for (idx = 0; idx < nchars; idx++) 65233965Sjdp fprintf (list_file, " "); 65333965Sjdp 65433965Sjdp fprintf (list_file, "\t%s\n", string ? string : ""); 65577298Sobrien 65677298Sobrien on_page++; 65777298Sobrien 65833965Sjdp listing_page (0); 65933965Sjdp 66060484Sobrien return; 66133965Sjdp } 66260484Sobrien 66360484Sobrien if (had_errors ()) 66460484Sobrien fprintf (list_file, "% 4d ???? ", lineno); 66533965Sjdp else 66660484Sobrien fprintf (list_file, "% 4d %04x ", lineno, address); 66760484Sobrien 66877298Sobrien /* And the data to go along with it. */ 66960484Sobrien idx = 0; 67060484Sobrien cur = 0; 67160484Sobrien while (src[cur] && idx < nchars) 67233965Sjdp { 67360484Sobrien int offset; 67460484Sobrien offset = cur; 67577298Sobrien fprintf (list_file, "%c%c", src[offset], src[offset + 1]); 67660484Sobrien cur += 2; 67760484Sobrien octet_in_word++; 67877298Sobrien 67960484Sobrien if (octet_in_word == LISTING_WORD_SIZE) 68033965Sjdp { 68160484Sobrien fprintf (list_file, " "); 68260484Sobrien idx++; 68360484Sobrien octet_in_word = 0; 68433965Sjdp } 68577298Sobrien 68660484Sobrien idx += 2; 68760484Sobrien } 68877298Sobrien 68960484Sobrien for (; idx < nchars; idx++) 69060484Sobrien fprintf (list_file, " "); 69177298Sobrien 69260484Sobrien fprintf (list_file, "\t%s\n", string ? string : ""); 69360484Sobrien on_page++; 69460484Sobrien listing_page (list); 69577298Sobrien 69660484Sobrien if (list->message) 69760484Sobrien { 69860484Sobrien fprintf (list_file, "**** %s\n", list->message); 69960484Sobrien listing_page (list); 70060484Sobrien on_page++; 70160484Sobrien } 70277298Sobrien 70360484Sobrien for (lines = 0; 70460484Sobrien lines < (unsigned int) listing_lhs_cont_lines 70560484Sobrien && src[cur]; 70677298Sobrien lines++) 70760484Sobrien { 70877298Sobrien nchars = ((LISTING_WORD_SIZE * 2) + 1) * listing_lhs_width_second - 1; 70933965Sjdp idx = 0; 71077298Sobrien 71177298Sobrien /* Print any more lines of data, but more compactly. */ 71260484Sobrien fprintf (list_file, "% 4d ", lineno); 71377298Sobrien 71460484Sobrien while (src[cur] && idx < nchars) 71533965Sjdp { 71677298Sobrien int offset; 71777298Sobrien offset = cur; 71877298Sobrien fprintf (list_file, "%c%c", src[offset], src[offset + 1]); 71960484Sobrien cur += 2; 72060484Sobrien idx += 2; 72160484Sobrien octet_in_word++; 72277298Sobrien 72360484Sobrien if (octet_in_word == LISTING_WORD_SIZE) 72433965Sjdp { 72533965Sjdp fprintf (list_file, " "); 72633965Sjdp idx++; 72760484Sobrien octet_in_word = 0; 72833965Sjdp } 72933965Sjdp } 73077298Sobrien 73160484Sobrien fprintf (list_file, "\n"); 73277298Sobrien on_page++; 73333965Sjdp listing_page (list); 73433965Sjdp } 73533965Sjdp} 73633965Sjdp 73733965Sjdpstatic void 738130561Sobrienlist_symbol_table (void) 73933965Sjdp{ 74033965Sjdp extern symbolS *symbol_rootP; 74133965Sjdp int got_some = 0; 74233965Sjdp 74333965Sjdp symbolS *ptr; 74433965Sjdp eject = 1; 74533965Sjdp listing_page (0); 74633965Sjdp 74733965Sjdp for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr)) 74833965Sjdp { 74938889Sjdp if (SEG_NORMAL (S_GET_SEGMENT (ptr)) 75038889Sjdp || S_GET_SEGMENT (ptr) == absolute_section) 75133965Sjdp { 75238889Sjdp /* Don't report section symbols. They are not interesting. */ 75360484Sobrien if (symbol_section_p (ptr)) 75438889Sjdp continue; 755218822Sdim 75633965Sjdp if (S_GET_NAME (ptr)) 75733965Sjdp { 75833965Sjdp char buf[30], fmt[8]; 75933965Sjdp valueT val = S_GET_VALUE (ptr); 76033965Sjdp 76133965Sjdp /* @@ Note that this is dependent on the compilation options, 76233965Sjdp not solely on the target characteristics. */ 76333965Sjdp if (sizeof (val) == 4 && sizeof (int) == 4) 76433965Sjdp sprintf (buf, "%08lx", (unsigned long) val); 76533965Sjdp else if (sizeof (val) <= sizeof (unsigned long)) 76633965Sjdp { 76733965Sjdp sprintf (fmt, "%%0%lulx", 76833965Sjdp (unsigned long) (sizeof (val) * 2)); 76933965Sjdp sprintf (buf, fmt, (unsigned long) val); 77033965Sjdp } 77133965Sjdp#if defined (BFD64) 77233965Sjdp else if (sizeof (val) > 4) 77333965Sjdp sprintf_vma (buf, val); 77433965Sjdp#endif 77533965Sjdp else 77633965Sjdp abort (); 77733965Sjdp 77833965Sjdp if (!got_some) 77933965Sjdp { 78033965Sjdp fprintf (list_file, "DEFINED SYMBOLS\n"); 78133965Sjdp on_page++; 78233965Sjdp got_some = 1; 78333965Sjdp } 78433965Sjdp 78560484Sobrien if (symbol_get_frag (ptr) && symbol_get_frag (ptr)->line) 78638889Sjdp { 78738889Sjdp fprintf (list_file, "%20s:%-5d %s:%s %s\n", 78860484Sobrien symbol_get_frag (ptr)->line->file->filename, 78960484Sobrien symbol_get_frag (ptr)->line->line, 79038889Sjdp segment_name (S_GET_SEGMENT (ptr)), 79138889Sjdp buf, S_GET_NAME (ptr)); 79238889Sjdp } 79338889Sjdp else 79438889Sjdp { 79538889Sjdp fprintf (list_file, "%33s:%s %s\n", 79638889Sjdp segment_name (S_GET_SEGMENT (ptr)), 79738889Sjdp buf, S_GET_NAME (ptr)); 79838889Sjdp } 79933965Sjdp 80077298Sobrien on_page++; 80133965Sjdp listing_page (0); 80233965Sjdp } 80333965Sjdp } 80433965Sjdp 80533965Sjdp } 80633965Sjdp if (!got_some) 80733965Sjdp { 80833965Sjdp fprintf (list_file, "NO DEFINED SYMBOLS\n"); 80933965Sjdp on_page++; 81033965Sjdp } 81133965Sjdp fprintf (list_file, "\n"); 81233965Sjdp on_page++; 81333965Sjdp listing_page (0); 81433965Sjdp 81533965Sjdp got_some = 0; 81633965Sjdp 81733965Sjdp for (ptr = symbol_rootP; ptr != (symbolS *) NULL; ptr = symbol_next (ptr)) 81833965Sjdp { 81933965Sjdp if (S_GET_NAME (ptr) && strlen (S_GET_NAME (ptr)) != 0) 82033965Sjdp { 82138889Sjdp if (S_GET_SEGMENT (ptr) == undefined_section) 82233965Sjdp { 82333965Sjdp if (!got_some) 82433965Sjdp { 82533965Sjdp got_some = 1; 82633965Sjdp fprintf (list_file, "UNDEFINED SYMBOLS\n"); 82733965Sjdp on_page++; 82833965Sjdp listing_page (0); 82933965Sjdp } 83033965Sjdp fprintf (list_file, "%s\n", S_GET_NAME (ptr)); 83133965Sjdp on_page++; 83233965Sjdp listing_page (0); 83333965Sjdp } 83433965Sjdp } 83533965Sjdp } 83633965Sjdp if (!got_some) 83733965Sjdp { 83833965Sjdp fprintf (list_file, "NO UNDEFINED SYMBOLS\n"); 83933965Sjdp on_page++; 84033965Sjdp listing_page (0); 84133965Sjdp } 84233965Sjdp} 84333965Sjdp 84433965Sjdpstatic void 845130561Sobrienprint_source (file_info_type *current_file, list_info_type *list, 846130561Sobrien char *buffer, unsigned int width) 84733965Sjdp{ 84838889Sjdp if (!current_file->at_end) 84933965Sjdp { 85033965Sjdp while (current_file->linenum < list->hll_line 85133965Sjdp && !current_file->at_end) 85233965Sjdp { 85333965Sjdp char *p = buffer_line (current_file, buffer, width); 854130561Sobrien 85538889Sjdp fprintf (list_file, "%4u:%-13s **** %s\n", current_file->linenum, 85633965Sjdp current_file->filename, p); 85733965Sjdp on_page++; 85833965Sjdp listing_page (list); 85933965Sjdp } 86033965Sjdp } 86133965Sjdp} 86233965Sjdp 86333965Sjdp/* Sometimes the user doesn't want to be bothered by the debugging 86438889Sjdp records inserted by the compiler, see if the line is suspicious. */ 86533965Sjdp 86633965Sjdpstatic int 867130561Sobriendebugging_pseudo (list_info_type *list, const char *line) 86833965Sjdp{ 86938889Sjdp static int in_debug; 87038889Sjdp int was_debug; 87138889Sjdp 87238889Sjdp if (list->debugging) 87338889Sjdp { 87438889Sjdp in_debug = 1; 87538889Sjdp return 1; 87638889Sjdp } 87738889Sjdp 87838889Sjdp was_debug = in_debug; 87938889Sjdp in_debug = 0; 88038889Sjdp 88189857Sobrien while (ISSPACE (*line)) 88233965Sjdp line++; 88333965Sjdp 88433965Sjdp if (*line != '.') 88538889Sjdp { 88638889Sjdp#ifdef OBJ_ELF 88738889Sjdp /* The ELF compiler sometimes emits blank lines after switching 88838889Sjdp out of a debugging section. If the next line drops us back 88938889Sjdp into debugging information, then don't print the blank line. 89038889Sjdp This is a hack for a particular compiler behaviour, not a 89138889Sjdp general case. */ 89238889Sjdp if (was_debug 89338889Sjdp && *line == '\0' 89438889Sjdp && list->next != NULL 89538889Sjdp && list->next->debugging) 89638889Sjdp { 89738889Sjdp in_debug = 1; 89838889Sjdp return 1; 89938889Sjdp } 90038889Sjdp#endif 90133965Sjdp 90238889Sjdp return 0; 90338889Sjdp } 90438889Sjdp 90533965Sjdp line++; 90633965Sjdp 90733965Sjdp if (strncmp (line, "def", 3) == 0) 90833965Sjdp return 1; 90933965Sjdp if (strncmp (line, "val", 3) == 0) 91033965Sjdp return 1; 91133965Sjdp if (strncmp (line, "scl", 3) == 0) 91233965Sjdp return 1; 91333965Sjdp if (strncmp (line, "line", 4) == 0) 91433965Sjdp return 1; 91533965Sjdp if (strncmp (line, "endef", 5) == 0) 91633965Sjdp return 1; 91733965Sjdp if (strncmp (line, "ln", 2) == 0) 91833965Sjdp return 1; 91933965Sjdp if (strncmp (line, "type", 4) == 0) 92033965Sjdp return 1; 92133965Sjdp if (strncmp (line, "size", 4) == 0) 92233965Sjdp return 1; 92333965Sjdp if (strncmp (line, "dim", 3) == 0) 92433965Sjdp return 1; 92533965Sjdp if (strncmp (line, "tag", 3) == 0) 92633965Sjdp return 1; 92733965Sjdp if (strncmp (line, "stabs", 5) == 0) 92833965Sjdp return 1; 92933965Sjdp if (strncmp (line, "stabn", 5) == 0) 93033965Sjdp return 1; 93133965Sjdp 93233965Sjdp return 0; 93333965Sjdp} 93433965Sjdp 93533965Sjdpstatic void 936130561Sobrienlisting_listing (char *name ATTRIBUTE_UNUSED) 93733965Sjdp{ 93833965Sjdp list_info_type *list = head; 93933965Sjdp file_info_type *current_hll_file = (file_info_type *) NULL; 94033965Sjdp char *message; 94133965Sjdp char *buffer; 94233965Sjdp char *p; 94333965Sjdp int show_listing = 1; 94433965Sjdp unsigned int width; 94533965Sjdp 94638889Sjdp buffer = xmalloc (listing_rhs_width); 94738889Sjdp data_buffer = xmalloc (MAX_BYTES); 94833965Sjdp eject = 1; 94933965Sjdp list = head->next; 95033965Sjdp 95133965Sjdp while (list) 95233965Sjdp { 95360484Sobrien unsigned int list_line; 95460484Sobrien 95538889Sjdp width = listing_rhs_width > paper_width ? paper_width : 95638889Sjdp listing_rhs_width; 95733965Sjdp 95860484Sobrien list_line = list->line; 95933965Sjdp switch (list->edict) 96033965Sjdp { 96133965Sjdp case EDICT_LIST: 96260484Sobrien /* Skip all lines up to the current. */ 96360484Sobrien list_line--; 96433965Sjdp break; 96533965Sjdp case EDICT_NOLIST: 96633965Sjdp show_listing--; 96733965Sjdp break; 96833965Sjdp case EDICT_NOLIST_NEXT: 96977298Sobrien if (show_listing == 0) 97077298Sobrien list_line--; 97133965Sjdp break; 97233965Sjdp case EDICT_EJECT: 97333965Sjdp break; 97433965Sjdp case EDICT_NONE: 97533965Sjdp break; 97633965Sjdp case EDICT_TITLE: 97733965Sjdp title = list->edict_arg; 97833965Sjdp break; 97933965Sjdp case EDICT_SBTTL: 98033965Sjdp subtitle = list->edict_arg; 98133965Sjdp break; 98233965Sjdp default: 98333965Sjdp abort (); 98433965Sjdp } 98533965Sjdp 98660484Sobrien if (show_listing <= 0) 98760484Sobrien { 98860484Sobrien while (list->file->linenum < list_line 98960484Sobrien && !list->file->at_end) 99060484Sobrien p = buffer_line (list->file, buffer, width); 99160484Sobrien } 99260484Sobrien 99377298Sobrien if (list->edict == EDICT_LIST 99477298Sobrien || (list->edict == EDICT_NOLIST_NEXT && show_listing == 0)) 99560484Sobrien { 99660484Sobrien /* Enable listing for the single line that caused the enable. */ 99760484Sobrien list_line++; 99860484Sobrien show_listing++; 99960484Sobrien } 100060484Sobrien 100133965Sjdp if (show_listing > 0) 100233965Sjdp { 100333965Sjdp /* Scan down the list and print all the stuff which can be done 100433965Sjdp with this line (or lines). */ 100533965Sjdp message = 0; 100633965Sjdp 100733965Sjdp if (list->hll_file) 1008130561Sobrien current_hll_file = list->hll_file; 100933965Sjdp 101038889Sjdp if (current_hll_file && list->hll_line && (listing & LISTING_HLL)) 1011130561Sobrien print_source (current_hll_file, list, buffer, width); 101233965Sjdp 101338889Sjdp if (list->line_contents) 101433965Sjdp { 101538889Sjdp if (!((listing & LISTING_NODEBUG) 101638889Sjdp && debugging_pseudo (list, list->line_contents))) 1017130561Sobrien print_lines (list, 1018130561Sobrien list->file->linenum == 0 ? list->line : list->file->linenum, 1019130561Sobrien list->line_contents, calc_hex (list)); 1020130561Sobrien 102160484Sobrien free (list->line_contents); 102260484Sobrien list->line_contents = NULL; 102338889Sjdp } 102438889Sjdp else 102538889Sjdp { 102660484Sobrien while (list->file->linenum < list_line 102738889Sjdp && !list->file->at_end) 102838889Sjdp { 102938889Sjdp unsigned int address; 103033965Sjdp 103138889Sjdp p = buffer_line (list->file, buffer, width); 103233965Sjdp 103360484Sobrien if (list->file->linenum < list_line) 103477298Sobrien address = ~(unsigned int) 0; 103538889Sjdp else 103638889Sjdp address = calc_hex (list); 103733965Sjdp 103838889Sjdp if (!((listing & LISTING_NODEBUG) 103938889Sjdp && debugging_pseudo (list, p))) 104038889Sjdp print_lines (list, list->file->linenum, p, address); 104138889Sjdp } 104233965Sjdp } 104333965Sjdp 104433965Sjdp if (list->edict == EDICT_EJECT) 1045130561Sobrien eject = 1; 104633965Sjdp } 104733965Sjdp 104877298Sobrien if (list->edict == EDICT_NOLIST_NEXT && show_listing == 1) 104933965Sjdp --show_listing; 105033965Sjdp 105133965Sjdp list = list->next; 105233965Sjdp } 105338889Sjdp 105433965Sjdp free (buffer); 105538889Sjdp free (data_buffer); 105638889Sjdp data_buffer = NULL; 105733965Sjdp} 105833965Sjdp 105933965Sjdpvoid 1060130561Sobrienlisting_print (char *name) 106133965Sjdp{ 106233965Sjdp int using_stdout; 106377298Sobrien 106433965Sjdp title = ""; 106533965Sjdp subtitle = ""; 106633965Sjdp 106733965Sjdp if (name == NULL) 106833965Sjdp { 106933965Sjdp list_file = stdout; 107033965Sjdp using_stdout = 1; 107133965Sjdp } 107233965Sjdp else 107333965Sjdp { 107489857Sobrien list_file = fopen (name, FOPEN_WT); 107533965Sjdp if (list_file != NULL) 107633965Sjdp using_stdout = 0; 107733965Sjdp else 107833965Sjdp { 1079218822Sdim as_warn (_("can't open %s: %s"), name, xstrerror (errno)); 108033965Sjdp list_file = stdout; 108133965Sjdp using_stdout = 1; 108233965Sjdp } 108333965Sjdp } 108433965Sjdp 108533965Sjdp if (listing & LISTING_NOFORM) 1086130561Sobrien paper_height = 0; 108733965Sjdp 108833965Sjdp if (listing & LISTING_LISTING) 1089130561Sobrien listing_listing (name); 109033965Sjdp 109133965Sjdp if (listing & LISTING_SYMBOLS) 1092130561Sobrien list_symbol_table (); 109333965Sjdp 109433965Sjdp if (! using_stdout) 109533965Sjdp { 109633965Sjdp if (fclose (list_file) == EOF) 1097218822Sdim as_warn (_("can't close %s: %s"), name, xstrerror (errno)); 109833965Sjdp } 109933965Sjdp 110038889Sjdp if (last_open_file) 1101130561Sobrien fclose (last_open_file); 110233965Sjdp} 110333965Sjdp 110433965Sjdpvoid 1105130561Sobrienlisting_file (const char *name) 110633965Sjdp{ 110733965Sjdp fn = name; 110833965Sjdp} 110933965Sjdp 111033965Sjdpvoid 1111130561Sobrienlisting_eject (int ignore ATTRIBUTE_UNUSED) 111233965Sjdp{ 111333965Sjdp if (listing) 111433965Sjdp listing_tail->edict = EDICT_EJECT; 111533965Sjdp} 111633965Sjdp 111733965Sjdpvoid 1118130561Sobrienlisting_flags (int ignore ATTRIBUTE_UNUSED) 111933965Sjdp{ 112033965Sjdp while ((*input_line_pointer++) && (*input_line_pointer != '\n')) 112133965Sjdp input_line_pointer++; 112233965Sjdp 112333965Sjdp} 112433965Sjdp 112533965Sjdp/* Turn listing on or off. An argument of 0 means to turn off 112633965Sjdp listing. An argument of 1 means to turn on listing. An argument 112733965Sjdp of 2 means to turn off listing, but as of the next line; that is, 112833965Sjdp the current line should be listed, but the next line should not. */ 112933965Sjdp 113033965Sjdpvoid 1131130561Sobrienlisting_list (int on) 113233965Sjdp{ 113333965Sjdp if (listing) 113433965Sjdp { 113533965Sjdp switch (on) 113633965Sjdp { 113733965Sjdp case 0: 113833965Sjdp if (listing_tail->edict == EDICT_LIST) 113933965Sjdp listing_tail->edict = EDICT_NONE; 114033965Sjdp else 114133965Sjdp listing_tail->edict = EDICT_NOLIST; 114233965Sjdp break; 114333965Sjdp case 1: 114433965Sjdp if (listing_tail->edict == EDICT_NOLIST 114533965Sjdp || listing_tail->edict == EDICT_NOLIST_NEXT) 114633965Sjdp listing_tail->edict = EDICT_NONE; 114733965Sjdp else 114833965Sjdp listing_tail->edict = EDICT_LIST; 114933965Sjdp break; 115033965Sjdp case 2: 115133965Sjdp listing_tail->edict = EDICT_NOLIST_NEXT; 115233965Sjdp break; 115333965Sjdp default: 115433965Sjdp abort (); 115533965Sjdp } 115633965Sjdp } 115733965Sjdp} 115833965Sjdp 115933965Sjdpvoid 1160130561Sobrienlisting_psize (int width_only) 116133965Sjdp{ 116233965Sjdp if (! width_only) 116333965Sjdp { 116433965Sjdp paper_height = get_absolute_expression (); 116533965Sjdp 116633965Sjdp if (paper_height < 0 || paper_height > 1000) 116733965Sjdp { 116833965Sjdp paper_height = 0; 116960484Sobrien as_warn (_("strange paper height, set to no form")); 117033965Sjdp } 117133965Sjdp 117233965Sjdp if (*input_line_pointer != ',') 117333965Sjdp { 117433965Sjdp demand_empty_rest_of_line (); 117533965Sjdp return; 117633965Sjdp } 117733965Sjdp 117833965Sjdp ++input_line_pointer; 117933965Sjdp } 118033965Sjdp 118133965Sjdp paper_width = get_absolute_expression (); 118233965Sjdp 118333965Sjdp demand_empty_rest_of_line (); 118433965Sjdp} 118533965Sjdp 118633965Sjdpvoid 1187130561Sobrienlisting_nopage (int ignore ATTRIBUTE_UNUSED) 118833965Sjdp{ 118933965Sjdp paper_height = 0; 119033965Sjdp} 119133965Sjdp 119233965Sjdpvoid 1193130561Sobrienlisting_title (int depth) 119433965Sjdp{ 119533965Sjdp int quoted; 119633965Sjdp char *start; 119733965Sjdp char *ttl; 119833965Sjdp unsigned int length; 119933965Sjdp 120033965Sjdp SKIP_WHITESPACE (); 120133965Sjdp if (*input_line_pointer != '\"') 120233965Sjdp quoted = 0; 120333965Sjdp else 120433965Sjdp { 120533965Sjdp quoted = 1; 120633965Sjdp ++input_line_pointer; 120733965Sjdp } 120833965Sjdp 120933965Sjdp start = input_line_pointer; 121033965Sjdp 121133965Sjdp while (*input_line_pointer) 121233965Sjdp { 121333965Sjdp if (quoted 121433965Sjdp ? *input_line_pointer == '\"' 121533965Sjdp : is_end_of_line[(unsigned char) *input_line_pointer]) 121633965Sjdp { 121733965Sjdp if (listing) 121833965Sjdp { 121933965Sjdp length = input_line_pointer - start; 122033965Sjdp ttl = xmalloc (length + 1); 122133965Sjdp memcpy (ttl, start, length); 122233965Sjdp ttl[length] = 0; 122333965Sjdp listing_tail->edict = depth ? EDICT_SBTTL : EDICT_TITLE; 122433965Sjdp listing_tail->edict_arg = ttl; 122533965Sjdp } 122633965Sjdp if (quoted) 122733965Sjdp input_line_pointer++; 122833965Sjdp demand_empty_rest_of_line (); 122933965Sjdp return; 123033965Sjdp } 123133965Sjdp else if (*input_line_pointer == '\n') 123233965Sjdp { 123389857Sobrien as_bad (_("new line in title")); 123433965Sjdp demand_empty_rest_of_line (); 123533965Sjdp return; 123633965Sjdp } 123733965Sjdp else 123833965Sjdp { 123933965Sjdp input_line_pointer++; 124033965Sjdp } 124133965Sjdp } 124233965Sjdp} 124333965Sjdp 124433965Sjdpvoid 1245130561Sobrienlisting_source_line (unsigned int line) 124633965Sjdp{ 124733965Sjdp if (listing) 124833965Sjdp { 124933965Sjdp new_frag (); 125033965Sjdp listing_tail->hll_line = line; 125133965Sjdp new_frag (); 125233965Sjdp } 125333965Sjdp} 125433965Sjdp 125533965Sjdpvoid 1256130561Sobrienlisting_source_file (const char *file) 125733965Sjdp{ 125833965Sjdp if (listing) 125933965Sjdp listing_tail->hll_file = file_info (file); 126033965Sjdp} 126133965Sjdp 126233965Sjdp#else 126333965Sjdp 126477298Sobrien/* Dummy functions for when compiled without listing enabled. */ 126533965Sjdp 126633965Sjdpvoid 1267130561Sobrienlisting_flags (int ignore) 126833965Sjdp{ 126933965Sjdp s_ignore (0); 127033965Sjdp} 127133965Sjdp 127277298Sobrienvoid 1273130561Sobrienlisting_list (int on) 127433965Sjdp{ 127533965Sjdp s_ignore (0); 127633965Sjdp} 127733965Sjdp 127877298Sobrienvoid 1279130561Sobrienlisting_eject (int ignore) 128033965Sjdp{ 128133965Sjdp s_ignore (0); 128233965Sjdp} 128333965Sjdp 128477298Sobrienvoid 1285130561Sobrienlisting_psize (int ignore) 128633965Sjdp{ 128733965Sjdp s_ignore (0); 128833965Sjdp} 128933965Sjdp 129033965Sjdpvoid 1291130561Sobrienlisting_nopage (int ignore) 129233965Sjdp{ 129333965Sjdp s_ignore (0); 129433965Sjdp} 129533965Sjdp 129677298Sobrienvoid 1297130561Sobrienlisting_title (int depth) 129833965Sjdp{ 129933965Sjdp s_ignore (0); 130033965Sjdp} 130133965Sjdp 130233965Sjdpvoid 1303130561Sobrienlisting_file (const char *name) 130433965Sjdp{ 130533965Sjdp} 130633965Sjdp 130777298Sobrienvoid 1308130561Sobrienlisting_newline (char *name) 130933965Sjdp{ 131033965Sjdp} 131133965Sjdp 131277298Sobrienvoid 1313130561Sobrienlisting_source_line (unsigned int n) 131433965Sjdp{ 131533965Sjdp} 131677298Sobrien 131777298Sobrienvoid 1318130561Sobrienlisting_source_file (const char *n) 131933965Sjdp{ 132033965Sjdp} 132133965Sjdp 132233965Sjdp#endif 1323