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