1*49403Sbostic /*-
2*49403Sbostic * This code is derived from software copyrighted by the Free Software
3*49403Sbostic * Foundation.
4*49403Sbostic *
5*49403Sbostic * Modified 1991 by Donn Seeley at UUNET Technologies, Inc.
6*49403Sbostic */
747443Sdonn
8*49403Sbostic #ifndef lint
9*49403Sbostic static char sccsid[] = "@(#)input-scrub.c 6.4 (Berkeley) 05/08/91";
10*49403Sbostic #endif /* not lint */
1147443Sdonn
1247405Sdonn /* input_scrub.c - layer between app and the rest of the world
1347405Sdonn Copyright (C) 1987 Free Software Foundation, Inc.
1447405Sdonn
1547405Sdonn This file is part of GAS, the GNU Assembler.
1647405Sdonn
1747405Sdonn GAS is free software; you can redistribute it and/or modify
1847405Sdonn it under the terms of the GNU General Public License as published by
1947405Sdonn the Free Software Foundation; either version 1, or (at your option)
2047405Sdonn any later version.
2147405Sdonn
2247405Sdonn GAS is distributed in the hope that it will be useful,
2347405Sdonn but WITHOUT ANY WARRANTY; without even the implied warranty of
2447405Sdonn MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2547405Sdonn GNU General Public License for more details.
2647405Sdonn
2747405Sdonn You should have received a copy of the GNU General Public License
2847405Sdonn along with GAS; see the file COPYING. If not, write to
2947405Sdonn the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
3047405Sdonn
3147405Sdonn #include "as.h"
3247405Sdonn #include "read.h"
3347405Sdonn #include "input-file.h"
3447405Sdonn
3547405Sdonn /*
3647405Sdonn * O/S independent module to supply buffers of sanitised source code
3747405Sdonn * to rest of assembler. We get raw input data of some length.
3847405Sdonn * Also looks after line numbers, for e.g. error messages.
3947405Sdonn * This module used to do the sanitising, but now a pre-processor program
4047405Sdonn * (app) does that job so this module is degenerate.
4147405Sdonn * Now input is pre-sanitised, so we only worry about finding the
4247405Sdonn * last partial line. A buffer of full lines is returned to caller.
4347405Sdonn * The last partial line begins the next buffer we build and return to caller.
4447405Sdonn * The buffer returned to caller is preceeded by BEFORE_STRING and followed
4547405Sdonn * by AFTER_STRING. The last character before AFTER_STRING is a newline.
4647405Sdonn */
4747405Sdonn
4847405Sdonn /*
4947405Sdonn * We expect the following sanitation has already been done.
5047405Sdonn *
5147405Sdonn * No comments, reduce a comment to a space.
5247405Sdonn * Reduce a tab to a space unless it is 1st char of line.
5347405Sdonn * All multiple tabs and spaces collapsed into 1 char. Tab only
5447405Sdonn * legal if 1st char of line.
5547405Sdonn * # line file statements converted to .line x;.file y; statements.
5647405Sdonn * Escaped newlines at end of line: remove them but add as many newlines
5747405Sdonn * to end of statement as you removed in the middle, to synch line numbers.
5847405Sdonn */
5947405Sdonn
6047405Sdonn #define BEFORE_STRING ("\n")
6147405Sdonn #define AFTER_STRING ("\0") /* bcopy of 0 chars might choke. */
6247405Sdonn #define BEFORE_SIZE (1)
6347405Sdonn #define AFTER_SIZE (1)
6447405Sdonn
6547405Sdonn static char * buffer_start; /* -> 1st char of full buffer area. */
6647405Sdonn static char * partial_where; /* -> after last full line in buffer. */
6747405Sdonn static int partial_size; /* >=0. Number of chars in partial line in buffer. */
6847405Sdonn static char save_source [AFTER_SIZE];
6947405Sdonn /* Because we need AFTER_STRING just after last */
7047405Sdonn /* full line, it clobbers 1st part of partial */
7147405Sdonn /* line. So we preserve 1st part of partial */
7247405Sdonn /* line here. */
7347405Sdonn static int buffer_length; /* What is the largest size buffer that */
7447405Sdonn /* input_file_give_next_buffer() could */
7547405Sdonn /* return to us? */
7647405Sdonn
7747405Sdonn static void as_1_char ();
7847405Sdonn
7947405Sdonn /*
8047405Sdonn We never have more than one source file open at once.
8147405Sdonn We may, however, read more than 1 source file in an assembly.
8247405Sdonn NULL means we have no file open right now.
8347405Sdonn */
8447405Sdonn
8547405Sdonn
8647405Sdonn /*
8747405Sdonn We must track the physical file and line number for error messages.
8847405Sdonn We also track a "logical" file and line number corresponding to (C?)
8947405Sdonn compiler source line numbers.
9047405Sdonn Whenever we open a file we must fill in physical_input_file. So if it is NULL
9147405Sdonn we have not opened any files yet.
9247405Sdonn */
9347405Sdonn
9447405Sdonn static
9547405Sdonn char * physical_input_file,
9647405Sdonn * logical_input_file;
9747405Sdonn
9847405Sdonn
9947405Sdonn
10047405Sdonn typedef unsigned int line_numberT; /* 1-origin line number in a source file. */
10147405Sdonn /* A line ends in '\n' or eof. */
10247405Sdonn
10347405Sdonn static
10447405Sdonn line_numberT physical_input_line,
10547405Sdonn logical_input_line;
10647405Sdonn
10747405Sdonn void
input_scrub_begin()10847405Sdonn input_scrub_begin ()
10947405Sdonn {
11047405Sdonn know( strlen(BEFORE_STRING) == BEFORE_SIZE );
11147405Sdonn know( strlen( AFTER_STRING) == AFTER_SIZE );
11247405Sdonn
11347405Sdonn input_file_begin ();
11447405Sdonn
11547405Sdonn buffer_length = input_file_buffer_size ();
11647405Sdonn
11747405Sdonn buffer_start = xmalloc ((long)(BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE));
11847405Sdonn bcopy (BEFORE_STRING, buffer_start, (int)BEFORE_SIZE);
11947405Sdonn
12047405Sdonn /* Line number things. */
12147405Sdonn logical_input_line = 0;
12247405Sdonn logical_input_file = (char *)NULL;
12347405Sdonn physical_input_file = NULL; /* No file read yet. */
12447405Sdonn do_scrub_begin();
12547405Sdonn }
12647405Sdonn
12747405Sdonn void
input_scrub_end()12847405Sdonn input_scrub_end ()
12947405Sdonn {
13047405Sdonn input_file_end ();
13147405Sdonn }
13247405Sdonn
13347405Sdonn char * /* Return start of caller's part of buffer. */
input_scrub_new_file(filename)13447405Sdonn input_scrub_new_file (filename)
13547405Sdonn char * filename;
13647405Sdonn {
13747405Sdonn input_file_open (filename, !flagseen['f']);
13847405Sdonn physical_input_file = filename[0] ? filename : "{standard input}";
13947405Sdonn physical_input_line = 0;
14047405Sdonn
14147405Sdonn partial_size = 0;
14247405Sdonn return (buffer_start + BEFORE_SIZE);
14347405Sdonn }
14447405Sdonn
14547405Sdonn char *
input_scrub_next_buffer(bufp)14647405Sdonn input_scrub_next_buffer (bufp)
14747405Sdonn char **bufp;
14847405Sdonn {
14947405Sdonn register char * limit; /* -> just after last char of buffer. */
15047405Sdonn
15147405Sdonn #ifdef DONTDEF
15247405Sdonn if(preprocess) {
15347405Sdonn if(save_buffer) {
15447405Sdonn *bufp = save_buffer;
15547405Sdonn save_buffer = 0;
15647405Sdonn }
15747405Sdonn limit = input_file_give_next_buffer(buffer_start+BEFORE_SIZE);
15847405Sdonn if (!limit) {
15947405Sdonn partial_where = 0;
16047405Sdonn if(partial_size)
16147405Sdonn as_warn("Partial line at end of file ignored");
16247405Sdonn return partial_where;
16347405Sdonn }
16447405Sdonn
16547405Sdonn if(partial_size)
16647405Sdonn bcopy(save_source, partial_where,(int)AFTER_SIZE);
16747405Sdonn do_scrub(partial_where,partial_size,buffer_start+BEFORE_SIZE,limit-(buffer_start+BEFORE_SIZE),&out_string,&out_length);
16847405Sdonn limit=out_string + out_length;
16947405Sdonn for(p=limit;*--p!='\n';)
17047405Sdonn ;
17147405Sdonn p++;
17247405Sdonn if(p<=buffer_start+BEFORE_SIZE)
17347405Sdonn as_fatal("Source line too long. Please change file '%s' and re-make the assembler.",__FILE__);
17447405Sdonn
17547405Sdonn partial_where = p;
17647405Sdonn partial_size = limit-p;
17747405Sdonn bcopy(partial_where, save_source,(int)AFTER_SIZE);
17847405Sdonn bcopy(AFTER_STRING, partial_where, (int)AFTER_SIZE);
17947405Sdonn
18047405Sdonn save_buffer = *bufp;
18147405Sdonn *bufp = out_string;
18247405Sdonn
18347405Sdonn return partial_where;
18447405Sdonn }
18547405Sdonn
18647405Sdonn /* We're not preprocessing. Do the right thing */
18747405Sdonn #endif
18847405Sdonn if (partial_size)
18947405Sdonn {
19047405Sdonn bcopy (partial_where, buffer_start + BEFORE_SIZE, (int)partial_size);
19147405Sdonn bcopy (save_source, buffer_start + BEFORE_SIZE, (int)AFTER_SIZE);
19247405Sdonn }
19347405Sdonn limit = input_file_give_next_buffer (buffer_start + BEFORE_SIZE + partial_size);
19447405Sdonn if (limit)
19547405Sdonn {
19647405Sdonn register char * p; /* Find last newline. */
19747405Sdonn
19847405Sdonn for (p = limit; * -- p != '\n'; )
19947405Sdonn {
20047405Sdonn }
20147405Sdonn ++ p;
20247405Sdonn if (p <= buffer_start + BEFORE_SIZE)
20347405Sdonn {
20447405Sdonn as_fatal ("Source line too long. Please change file %s then rebuild assembler.", __FILE__);
20547405Sdonn }
20647405Sdonn partial_where = p;
20747405Sdonn partial_size = limit - p;
20847405Sdonn bcopy (partial_where, save_source, (int)AFTER_SIZE);
20947405Sdonn bcopy (AFTER_STRING, partial_where, (int)AFTER_SIZE);
21047405Sdonn }
21147405Sdonn else
21247405Sdonn {
21347405Sdonn partial_where = 0;
21447405Sdonn if (partial_size > 0)
21547405Sdonn {
21647405Sdonn as_warn( "Partial line at end of file ignored" );
21747405Sdonn }
21847405Sdonn }
21947405Sdonn return (partial_where);
22047405Sdonn }
22147405Sdonn
22247405Sdonn /*
22347405Sdonn * The remaining part of this file deals with line numbers, error
22447405Sdonn * messages and so on.
22547405Sdonn */
22647405Sdonn
22747405Sdonn
22847405Sdonn int
seen_at_least_1_file()22947405Sdonn seen_at_least_1_file () /* TRUE if we opened any file. */
23047405Sdonn {
23147405Sdonn return (physical_input_file != NULL);
23247405Sdonn }
23347405Sdonn
23447405Sdonn void
bump_line_counters()23547405Sdonn bump_line_counters ()
23647405Sdonn {
23747405Sdonn ++ physical_input_line;
23847405Sdonn ++ logical_input_line;
23947405Sdonn }
24047405Sdonn
24147405Sdonn /*
24247405Sdonn * new_logical_line()
24347405Sdonn *
24447405Sdonn * Tells us what the new logical line number and file are.
24547405Sdonn * If the line_number is <0, we don't change the current logical line number.
24647405Sdonn * If the fname is NULL, we don't change the current logical file name.
24747405Sdonn */
24847405Sdonn void
new_logical_line(fname,line_number)24947405Sdonn new_logical_line (fname, line_number)
25047405Sdonn char * fname; /* DON'T destroy it! We point to it! */
25147405Sdonn int line_number;
25247405Sdonn {
25347405Sdonn if ( fname )
25447405Sdonn {
25547405Sdonn logical_input_file = fname;
25647405Sdonn }
25747405Sdonn if ( line_number >= 0 )
25847405Sdonn {
25947405Sdonn logical_input_line = line_number;
26047405Sdonn }
26147405Sdonn }
26247405Sdonn
26347405Sdonn /*
26447405Sdonn * a s _ w h e r e ( )
26547405Sdonn *
26647405Sdonn * Write a line to stderr locating where we are in reading
26747405Sdonn * input source files.
26847405Sdonn * As a sop to the debugger of AS, pretty-print the offending line.
26947405Sdonn */
27047405Sdonn void
as_where()27147405Sdonn as_where()
27247405Sdonn {
27347405Sdonn char *p;
27447405Sdonn line_numberT line;
27547405Sdonn
27647405Sdonn if (physical_input_file)
27747405Sdonn { /* we tried to read SOME source */
27847405Sdonn if (input_file_is_open())
27947405Sdonn { /* we can still read lines from source */
28047405Sdonn #ifdef DONTDEF
28147405Sdonn fprintf (stderr," @ physical line %ld., file \"%s\"",
28247405Sdonn (long) physical_input_line, physical_input_file);
28347405Sdonn fprintf (stderr," @ logical line %ld., file \"%s\"\n",
28447405Sdonn (long) logical_input_line, logical_input_file);
28547405Sdonn (void)putc(' ', stderr);
28647405Sdonn as_howmuch (stderr);
28747405Sdonn (void)putc('\n', stderr);
28847405Sdonn #else
28947405Sdonn p = logical_input_file ? logical_input_file : physical_input_file;
29047405Sdonn line = logical_input_line ? logical_input_line : physical_input_line;
29147405Sdonn fprintf(stderr,"%s:%u:", p, line);
29247405Sdonn #endif
29347405Sdonn }
29447405Sdonn else
29547405Sdonn {
29647405Sdonn #ifdef DONTDEF
29747405Sdonn fprintf (stderr," After reading source.\n");
29847405Sdonn #else
29947405Sdonn p = logical_input_file ? logical_input_file : physical_input_file;
30047405Sdonn line = logical_input_line ? logical_input_line : physical_input_line;
30147405Sdonn fprintf (stderr,"%s:unknown:", p);
30247405Sdonn #endif
30347405Sdonn }
30447405Sdonn }
30547405Sdonn else
30647405Sdonn {
30747405Sdonn #ifdef DONTDEF
30847405Sdonn fprintf (stderr," Before reading source.\n");
30947405Sdonn #else
31047405Sdonn #endif
31147405Sdonn }
31247405Sdonn }
31347443Sdonn
31447443Sdonn /*
31547447Sdonn * Support for source file debugging. These functions handle
31647447Sdonn * logical lines and logical files.
31747443Sdonn */
31847447Sdonn static char *saved_file;
31947447Sdonn static int saved_len;
32047447Sdonn static line_numberT saved_line;
32147447Sdonn
32247443Sdonn void
filestab()32347447Sdonn filestab()
32447443Sdonn {
32547443Sdonn char *file;
32647443Sdonn int len;
32747405Sdonn
32847447Sdonn if (!physical_input_file ||
32947447Sdonn !input_file_is_open())
33047443Sdonn return;
33147405Sdonn
33247443Sdonn file = logical_input_file ? logical_input_file : physical_input_file;
33347405Sdonn
33447443Sdonn if (saved_file == 0 || strcmp(file, saved_file) != 0)
33547443Sdonn {
33647443Sdonn stabs(file);
33747443Sdonn len = strlen(file) + 1;
33847443Sdonn if (len > saved_len)
33947443Sdonn {
34047443Sdonn if (saved_file == 0)
34147443Sdonn saved_file = xmalloc(len);
34247443Sdonn else
34347443Sdonn saved_file = xrealloc(saved_file, len);
34447443Sdonn memcpy(saved_file, file, len);
34547443Sdonn saved_len = len;
34647443Sdonn }
34747443Sdonn else
34847443Sdonn strcpy(saved_file, file);
34947443Sdonn saved_line = 0;
35047443Sdonn }
35147447Sdonn }
35247443Sdonn
35347447Sdonn void
funcstab(func)35447447Sdonn funcstab(func)
35547447Sdonn char *func;
35647447Sdonn {
35747447Sdonn if (now_seg != SEG_TEXT)
35847447Sdonn return;
35947447Sdonn
36047447Sdonn filestab();
36147447Sdonn stabf(func);
36247447Sdonn }
36347447Sdonn
36447447Sdonn void
linestab()36547447Sdonn linestab()
36647447Sdonn {
36747447Sdonn line_numberT line;
36847447Sdonn
36947447Sdonn if (now_seg != SEG_TEXT)
37047447Sdonn return;
37147447Sdonn
37247447Sdonn filestab();
37347447Sdonn
37447447Sdonn line = logical_input_line ? logical_input_line : physical_input_line;
37547447Sdonn
37647443Sdonn if (saved_line == 0 || line != saved_line)
37747443Sdonn {
37847443Sdonn stabd(line);
37947443Sdonn saved_line = line;
38047443Sdonn }
38147443Sdonn }
38247405Sdonn
38347405Sdonn /*
38447405Sdonn * a s _ h o w m u c h ( )
38547405Sdonn *
38647405Sdonn * Output to given stream how much of line we have scanned so far.
38747405Sdonn * Assumes we have scanned up to and including input_line_pointer.
38847405Sdonn * No free '\n' at end of line.
38947405Sdonn */
39047405Sdonn void
as_howmuch(stream)39147405Sdonn as_howmuch (stream)
39247405Sdonn FILE * stream; /* Opened for write please. */
39347405Sdonn {
39447405Sdonn register char * p; /* Scan input line. */
39547405Sdonn /* register char c; JF unused */
39647405Sdonn
39747405Sdonn for (p = input_line_pointer - 1; * p != '\n'; --p)
39847405Sdonn {
39947405Sdonn }
40047405Sdonn ++ p; /* p -> 1st char of line. */
40147405Sdonn for (; p <= input_line_pointer; p++)
40247405Sdonn {
40347405Sdonn /* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */
40447405Sdonn /* c = *p & 0xFF; JF unused */
40547405Sdonn as_1_char (*p, stream);
40647405Sdonn }
40747405Sdonn }
40847405Sdonn
40947405Sdonn static void
as_1_char(c,stream)41047405Sdonn as_1_char (c,stream)
41147405Sdonn unsigned char c;
41247405Sdonn FILE * stream;
41347405Sdonn {
41447405Sdonn if ( c > 127 )
41547405Sdonn {
41647405Sdonn (void)putc( '%', stream);
41747405Sdonn c -= 128;
41847405Sdonn }
41947405Sdonn if ( c < 32 )
42047405Sdonn {
42147405Sdonn (void)putc( '^', stream);
42247405Sdonn c += '@';
42347405Sdonn }
42447405Sdonn (void)putc( c, stream);
42547405Sdonn }
42647405Sdonn
42747405Sdonn /* end: input_scrub.c */
428