* This code is derived from software copyrighted by the Free Software
* Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
static char sccsid
[] = "@(#)input-scrub.c 6.4 (Berkeley) %G%";
/* input_scrub.c - layer between app and the rest of the world
Copyright (C) 1987 Free Software Foundation, Inc.
This file is part of GAS, the GNU Assembler.
GAS is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 1, or (at your option)
GAS is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
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, 675 Mass Ave, Cambridge, MA 02139, USA. */
* O/S independent module to supply buffers of sanitised source code
* to rest of assembler. We get raw input data of some length.
* Also looks after line numbers, for e.g. error messages.
* This module used to do the sanitising, but now a pre-processor program
* (app) does that job so this module is degenerate.
* Now input is pre-sanitised, so we only worry about finding the
* last partial line. A buffer of full lines is returned to caller.
* The last partial line begins the next buffer we build and return to caller.
* The buffer returned to caller is preceeded by BEFORE_STRING and followed
* by AFTER_STRING. The last character before AFTER_STRING is a newline.
* We expect the following sanitation has already been done.
* No comments, reduce a comment to a space.
* Reduce a tab to a space unless it is 1st char of line.
* All multiple tabs and spaces collapsed into 1 char. Tab only
* legal if 1st char of line.
* # line file statements converted to .line x;.file y; statements.
* Escaped newlines at end of line: remove them but add as many newlines
* to end of statement as you removed in the middle, to synch line numbers.
#define BEFORE_STRING ("\n")
#define AFTER_STRING ("\0") /* bcopy of 0 chars might choke. */
static char * buffer_start
; /* -> 1st char of full buffer area. */
static char * partial_where
; /* -> after last full line in buffer. */
static int partial_size
; /* >=0. Number of chars in partial line in buffer. */
static char save_source
[AFTER_SIZE
];
/* Because we need AFTER_STRING just after last */
/* full line, it clobbers 1st part of partial */
/* line. So we preserve 1st part of partial */
static int buffer_length
; /* What is the largest size buffer that */
/* input_file_give_next_buffer() could */
static void as_1_char ();
We never have more than one source file open at once.
We may, however, read more than 1 source file in an assembly.
NULL means we have no file open right now.
We must track the physical file and line number for error messages.
We also track a "logical" file and line number corresponding to (C?)
compiler source line numbers.
Whenever we open a file we must fill in physical_input_file. So if it is NULL
we have not opened any files yet.
char * physical_input_file
,
typedef unsigned int line_numberT
; /* 1-origin line number in a source file. */
/* A line ends in '\n' or eof. */
line_numberT physical_input_line
,
know( strlen(BEFORE_STRING
) == BEFORE_SIZE
);
know( strlen( AFTER_STRING
) == AFTER_SIZE
);
buffer_length
= input_file_buffer_size ();
buffer_start
= xmalloc ((long)(BEFORE_SIZE
+ buffer_length
+ buffer_length
+ AFTER_SIZE
));
bcopy (BEFORE_STRING
, buffer_start
, (int)BEFORE_SIZE
);
/* Line number things. */
logical_input_file
= (char *)NULL
;
physical_input_file
= NULL
; /* No file read yet. */
char * /* Return start of caller's part of buffer. */
input_scrub_new_file (filename
)
input_file_open (filename
, !flagseen
['f']);
physical_input_file
= filename
[0] ? filename
: "{standard input}";
return (buffer_start
+ BEFORE_SIZE
);
input_scrub_next_buffer (bufp
)
register char * limit
; /* -> just after last char of buffer. */
limit
= input_file_give_next_buffer(buffer_start
+BEFORE_SIZE
);
as_warn("Partial line at end of file ignored");
bcopy(save_source
, partial_where
,(int)AFTER_SIZE
);
do_scrub(partial_where
,partial_size
,buffer_start
+BEFORE_SIZE
,limit
-(buffer_start
+BEFORE_SIZE
),&out_string
,&out_length
);
limit
=out_string
+ out_length
;
if(p
<=buffer_start
+BEFORE_SIZE
)
as_fatal("Source line too long. Please change file '%s' and re-make the assembler.",__FILE__
);
bcopy(partial_where
, save_source
,(int)AFTER_SIZE
);
bcopy(AFTER_STRING
, partial_where
, (int)AFTER_SIZE
);
/* We're not preprocessing. Do the right thing */
bcopy (partial_where
, buffer_start
+ BEFORE_SIZE
, (int)partial_size
);
bcopy (save_source
, buffer_start
+ BEFORE_SIZE
, (int)AFTER_SIZE
);
limit
= input_file_give_next_buffer (buffer_start
+ BEFORE_SIZE
+ partial_size
);
register char * p
; /* Find last newline. */
for (p
= limit
; * -- p
!= '\n'; )
if (p
<= buffer_start
+ BEFORE_SIZE
)
as_fatal ("Source line too long. Please change file %s then rebuild assembler.", __FILE__
);
partial_size
= limit
- p
;
bcopy (partial_where
, save_source
, (int)AFTER_SIZE
);
bcopy (AFTER_STRING
, partial_where
, (int)AFTER_SIZE
);
as_warn( "Partial line at end of file ignored" );
* The remaining part of this file deals with line numbers, error
seen_at_least_1_file () /* TRUE if we opened any file. */
return (physical_input_file
!= NULL
);
* Tells us what the new logical line number and file are.
* If the line_number is <0, we don't change the current logical line number.
* If the fname is NULL, we don't change the current logical file name.
new_logical_line (fname
, line_number
)
char * fname
; /* DON'T destroy it! We point to it! */
logical_input_file
= fname
;
logical_input_line
= line_number
;
* Write a line to stderr locating where we are in reading
* As a sop to the debugger of AS, pretty-print the offending line.
{ /* we tried to read SOME source */
if (input_file_is_open())
{ /* we can still read lines from source */
fprintf (stderr
," @ physical line %ld., file \"%s\"",
(long) physical_input_line
, physical_input_file
);
fprintf (stderr
," @ logical line %ld., file \"%s\"\n",
(long) logical_input_line
, logical_input_file
);
(void)putc('\n', stderr
);
p
= logical_input_file
? logical_input_file
: physical_input_file
;
line
= logical_input_line
? logical_input_line
: physical_input_line
;
fprintf(stderr
,"%s:%u:", p
, line
);
fprintf (stderr
," After reading source.\n");
p
= logical_input_file
? logical_input_file
: physical_input_file
;
line
= logical_input_line
? logical_input_line
: physical_input_line
;
fprintf (stderr
,"%s:unknown:", p
);
fprintf (stderr
," Before reading source.\n");
* Support for source file debugging. These functions handle
* logical lines and logical files.
static line_numberT saved_line
;
if (!physical_input_file
||
file
= logical_input_file
? logical_input_file
: physical_input_file
;
if (saved_file
== 0 || strcmp(file
, saved_file
) != 0)
saved_file
= xmalloc(len
);
saved_file
= xrealloc(saved_file
, len
);
memcpy(saved_file
, file
, len
);
strcpy(saved_file
, file
);
line
= logical_input_line
? logical_input_line
: physical_input_line
;
if (saved_line
== 0 || line
!= saved_line
)
* a s _ h o w m u c h ( )
* Output to given stream how much of line we have scanned so far.
* Assumes we have scanned up to and including input_line_pointer.
* No free '\n' at end of line.
FILE * stream
; /* Opened for write please. */
register char * p
; /* Scan input line. */
/* register char c; JF unused */
for (p
= input_line_pointer
- 1; * p
!= '\n'; --p
)
++ p
; /* p -> 1st char of line. */
for (; p
<= input_line_pointer
; p
++)
/* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */
/* c = *p & 0xFF; JF unused */
(void)putc( '%', stream
);
(void)putc( '^', stream
);