input-scrub.c revision 60484
133965Sjdp/* input_scrub.c - Break up input buffers into whole numbers of lines.
233965Sjdp   Copyright (C) 1987, 90, 91, 92, 93, 94, 95, 96, 1997
333965Sjdp   Free Software Foundation, Inc.
433965Sjdp
533965Sjdp   This file is part of GAS, the GNU Assembler.
633965Sjdp
733965Sjdp   GAS is free software; you can redistribute it and/or modify
833965Sjdp   it under the terms of the GNU General Public License as published by
933965Sjdp   the Free Software Foundation; either version 2, or (at your option)
1033965Sjdp   any later version.
1133965Sjdp
1233965Sjdp   GAS is distributed in the hope that it will be useful,
1333965Sjdp   but WITHOUT ANY WARRANTY; without even the implied warranty of
1433965Sjdp   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1533965Sjdp   GNU General Public License for more details.
1633965Sjdp
1733965Sjdp   You should have received a copy of the GNU General Public License
1833965Sjdp   along with GAS; see the file COPYING.  If not, write to the Free
1933965Sjdp   Software Foundation, 59 Temple Place - Suite 330, Boston, MA
2033965Sjdp   02111-1307, USA. */
2133965Sjdp
2233965Sjdp#include <errno.h>		/* Need this to make errno declaration right */
2333965Sjdp#include "as.h"
2433965Sjdp#include "input-file.h"
2533965Sjdp#include "sb.h"
2660484Sobrien#include "listing.h"
2733965Sjdp
2833965Sjdp/*
2933965Sjdp * O/S independent module to supply buffers of sanitised source code
3033965Sjdp * to rest of assembler.  We get sanitised input data of arbitrary length.
3133965Sjdp * We break these buffers on line boundaries, recombine pieces that
3233965Sjdp * were broken across buffers, and return a buffer of full lines to
3333965Sjdp * the caller.
3433965Sjdp * The last partial line begins the next buffer we build and return to caller.
3533965Sjdp * The buffer returned to caller is preceeded by BEFORE_STRING and followed
3633965Sjdp * by AFTER_STRING, as sentinels. The last character before AFTER_STRING
3733965Sjdp * is a newline.
3833965Sjdp * Also looks after line numbers, for e.g. error messages.
3933965Sjdp */
4033965Sjdp
4133965Sjdp/*
4233965Sjdp * We don't care how filthy our buffers are, but our callers assume
4333965Sjdp * that the following sanitation has already been done.
4433965Sjdp *
4533965Sjdp * No comments, reduce a comment to a space.
4633965Sjdp * Reduce a tab to a space unless it is 1st char of line.
4733965Sjdp * All multiple tabs and spaces collapsed into 1 char. Tab only
4833965Sjdp *   legal if 1st char of line.
4933965Sjdp * # line file statements converted to .line x;.file y; statements.
5033965Sjdp * Escaped newlines at end of line: remove them but add as many newlines
5133965Sjdp *   to end of statement as you removed in the middle, to synch line numbers.
5233965Sjdp */
5333965Sjdp
5433965Sjdp#define BEFORE_STRING ("\n")
5533965Sjdp#define AFTER_STRING ("\0")	/* memcpy of 0 chars might choke. */
5633965Sjdp#define BEFORE_SIZE (1)
5733965Sjdp#define AFTER_SIZE  (1)
5833965Sjdp
5933965Sjdpstatic char *buffer_start;	/*->1st char of full buffer area. */
6033965Sjdpstatic char *partial_where;	/*->after last full line in buffer. */
6133965Sjdpstatic int partial_size;	/* >=0. Number of chars in partial line in buffer. */
6233965Sjdpstatic char save_source[AFTER_SIZE];
6333965Sjdp/* Because we need AFTER_STRING just after last */
6433965Sjdp/* full line, it clobbers 1st part of partial */
6533965Sjdp/* line. So we preserve 1st part of partial */
6633965Sjdp/* line here. */
6733965Sjdpstatic unsigned int buffer_length;	/* What is the largest size buffer that */
6833965Sjdp/* input_file_give_next_buffer() could */
6933965Sjdp/* return to us? */
7033965Sjdp
7133965Sjdp/* The index into an sb structure we are reading from.  -1 if none.  */
7233965Sjdpstatic int sb_index = -1;
7333965Sjdp
7433965Sjdp/* If we are reading from an sb structure, this is it.  */
7533965Sjdpstatic sb from_sb;
7633965Sjdp
7760484Sobrien/* Should we do a conditional check on from_sb? */
7860484Sobrienstatic int from_sb_is_expansion = 1;
7960484Sobrien
8033965Sjdp/* The number of nested sb structures we have included.  */
8133965Sjdpint macro_nest;
8233965Sjdp
8333965Sjdp/* We can have more than one source file open at once, though the info for all
8433965Sjdp   but the latest one are saved off in a struct input_save.  These files remain
8533965Sjdp   open, so we are limited by the number of open files allowed by the
8633965Sjdp   underlying OS. We may also sequentially read more than one source file in an
8733965Sjdp   assembly. */
8833965Sjdp
8933965Sjdp/* We must track the physical file and line number for error messages. We also
9033965Sjdp   track a "logical" file and line number corresponding to (C?)  compiler
9133965Sjdp   source line numbers.  Whenever we open a file we must fill in
9233965Sjdp   physical_input_file. So if it is NULL we have not opened any files yet. */
9333965Sjdp
9433965Sjdpstatic char *physical_input_file;
9533965Sjdpstatic char *logical_input_file;
9633965Sjdp
9733965Sjdptypedef unsigned int line_numberT;	/* 1-origin line number in a source file. */
9833965Sjdp/* A line ends in '\n' or eof. */
9933965Sjdp
10033965Sjdpstatic line_numberT physical_input_line;
10133965Sjdpstatic int logical_input_line;
10233965Sjdp
10333965Sjdp/* Struct used to save the state of the input handler during include files */
10433965Sjdpstruct input_save
10533965Sjdp  {
10633965Sjdp    char *buffer_start;
10733965Sjdp    char *partial_where;
10833965Sjdp    int partial_size;
10933965Sjdp    char save_source[AFTER_SIZE];
11033965Sjdp    unsigned int buffer_length;
11133965Sjdp    char *physical_input_file;
11233965Sjdp    char *logical_input_file;
11333965Sjdp    line_numberT physical_input_line;
11433965Sjdp    int logical_input_line;
11533965Sjdp    int sb_index;
11633965Sjdp    sb from_sb;
11760484Sobrien    int from_sb_is_expansion;       /* Should we do a conditional check? */
11833965Sjdp    struct input_save *next_saved_file;	/* Chain of input_saves */
11933965Sjdp    char *input_file_save;	/* Saved state of input routines */
12033965Sjdp    char *saved_position;	/* Caller's saved position in buf */
12133965Sjdp  };
12233965Sjdp
12333965Sjdpstatic struct input_save *input_scrub_push PARAMS ((char *saved_position));
12433965Sjdpstatic char *input_scrub_pop PARAMS ((struct input_save *arg));
12533965Sjdpstatic void as_1_char PARAMS ((unsigned int c, FILE * stream));
12633965Sjdp
12733965Sjdp/* Saved information about the file that .include'd this one.  When we hit EOF,
12833965Sjdp   we automatically pop to that file. */
12933965Sjdp
13033965Sjdpstatic struct input_save *next_saved_file;
13133965Sjdp
13233965Sjdp/* Push the state of input reading and scrubbing so that we can #include.
13333965Sjdp   The return value is a 'void *' (fudged for old compilers) to a save
13433965Sjdp   area, which can be restored by passing it to input_scrub_pop(). */
13533965Sjdpstatic struct input_save *
13633965Sjdpinput_scrub_push (saved_position)
13733965Sjdp     char *saved_position;
13833965Sjdp{
13933965Sjdp  register struct input_save *saved;
14033965Sjdp
14133965Sjdp  saved = (struct input_save *) xmalloc (sizeof *saved);
14233965Sjdp
14333965Sjdp  saved->saved_position = saved_position;
14433965Sjdp  saved->buffer_start = buffer_start;
14533965Sjdp  saved->partial_where = partial_where;
14633965Sjdp  saved->partial_size = partial_size;
14733965Sjdp  saved->buffer_length = buffer_length;
14833965Sjdp  saved->physical_input_file = physical_input_file;
14933965Sjdp  saved->logical_input_file = logical_input_file;
15033965Sjdp  saved->physical_input_line = physical_input_line;
15133965Sjdp  saved->logical_input_line = logical_input_line;
15233965Sjdp  saved->sb_index = sb_index;
15333965Sjdp  saved->from_sb = from_sb;
15460484Sobrien  saved->from_sb_is_expansion = from_sb_is_expansion;
15533965Sjdp  memcpy (saved->save_source, save_source, sizeof (save_source));
15633965Sjdp  saved->next_saved_file = next_saved_file;
15733965Sjdp  saved->input_file_save = input_file_push ();
15833965Sjdp
15933965Sjdp  input_file_begin ();		/* Reinitialize! */
16033965Sjdp  logical_input_line = -1;
16133965Sjdp  logical_input_file = (char *) NULL;
16233965Sjdp  buffer_length = input_file_buffer_size ();
16333965Sjdp  sb_index = -1;
16433965Sjdp
16533965Sjdp  buffer_start = xmalloc ((BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE));
16633965Sjdp  memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE);
16733965Sjdp
16833965Sjdp  return saved;
16933965Sjdp}				/* input_scrub_push() */
17033965Sjdp
17133965Sjdpstatic char *
17233965Sjdpinput_scrub_pop (saved)
17333965Sjdp     struct input_save *saved;
17433965Sjdp{
17533965Sjdp  char *saved_position;
17633965Sjdp
17733965Sjdp  input_scrub_end ();		/* Finish off old buffer */
17833965Sjdp
17933965Sjdp  input_file_pop (saved->input_file_save);
18033965Sjdp  saved_position = saved->saved_position;
18133965Sjdp  buffer_start = saved->buffer_start;
18233965Sjdp  buffer_length = saved->buffer_length;
18333965Sjdp  physical_input_file = saved->physical_input_file;
18433965Sjdp  logical_input_file = saved->logical_input_file;
18533965Sjdp  physical_input_line = saved->physical_input_line;
18633965Sjdp  logical_input_line = saved->logical_input_line;
18733965Sjdp  sb_index = saved->sb_index;
18833965Sjdp  from_sb = saved->from_sb;
18960484Sobrien  from_sb_is_expansion = saved->from_sb_is_expansion;
19033965Sjdp  partial_where = saved->partial_where;
19133965Sjdp  partial_size = saved->partial_size;
19233965Sjdp  next_saved_file = saved->next_saved_file;
19333965Sjdp  memcpy (save_source, saved->save_source, sizeof (save_source));
19433965Sjdp
19533965Sjdp  free (saved);
19633965Sjdp  return saved_position;
19733965Sjdp}
19833965Sjdp
19933965Sjdp
20033965Sjdpvoid
20133965Sjdpinput_scrub_begin ()
20233965Sjdp{
20333965Sjdp  know (strlen (BEFORE_STRING) == BEFORE_SIZE);
20433965Sjdp  know (strlen (AFTER_STRING) == AFTER_SIZE || (AFTER_STRING[0] == '\0' && AFTER_SIZE == 1));
20533965Sjdp
20633965Sjdp  input_file_begin ();
20733965Sjdp
20833965Sjdp  buffer_length = input_file_buffer_size ();
20933965Sjdp
21033965Sjdp  buffer_start = xmalloc ((BEFORE_SIZE + buffer_length + buffer_length + AFTER_SIZE));
21133965Sjdp  memcpy (buffer_start, BEFORE_STRING, (int) BEFORE_SIZE);
21233965Sjdp
21333965Sjdp  /* Line number things. */
21433965Sjdp  logical_input_line = -1;
21533965Sjdp  logical_input_file = (char *) NULL;
21633965Sjdp  physical_input_file = NULL;	/* No file read yet. */
21733965Sjdp  next_saved_file = NULL;	/* At EOF, don't pop to any other file */
21833965Sjdp  do_scrub_begin (flag_m68k_mri);
21933965Sjdp}
22033965Sjdp
22133965Sjdpvoid
22233965Sjdpinput_scrub_end ()
22333965Sjdp{
22433965Sjdp  if (buffer_start)
22533965Sjdp    {
22633965Sjdp      free (buffer_start);
22733965Sjdp      buffer_start = 0;
22833965Sjdp      input_file_end ();
22933965Sjdp    }
23033965Sjdp}
23133965Sjdp
23233965Sjdp/* Start reading input from a new file. */
23333965Sjdp
23433965Sjdpchar *				/* Return start of caller's part of buffer. */
23533965Sjdpinput_scrub_new_file (filename)
23633965Sjdp     char *filename;
23733965Sjdp{
23833965Sjdp  input_file_open (filename, !flag_no_comments);
23960484Sobrien  physical_input_file = filename[0] ? filename : _("{standard input}");
24033965Sjdp  physical_input_line = 0;
24133965Sjdp
24233965Sjdp  partial_size = 0;
24333965Sjdp  return (buffer_start + BEFORE_SIZE);
24433965Sjdp}
24533965Sjdp
24633965Sjdp
24733965Sjdp/* Include a file from the current file.  Save our state, cause it to
24833965Sjdp   be restored on EOF, and begin handling a new file.  Same result as
24933965Sjdp   input_scrub_new_file. */
25033965Sjdp
25133965Sjdpchar *
25233965Sjdpinput_scrub_include_file (filename, position)
25333965Sjdp     char *filename;
25433965Sjdp     char *position;
25533965Sjdp{
25633965Sjdp  next_saved_file = input_scrub_push (position);
25733965Sjdp  return input_scrub_new_file (filename);
25833965Sjdp}
25933965Sjdp
26033965Sjdp/* Start getting input from an sb structure.  This is used when
26133965Sjdp   expanding a macro.  */
26233965Sjdp
26333965Sjdpvoid
26460484Sobrieninput_scrub_include_sb (from, position, is_expansion)
26533965Sjdp     sb *from;
26633965Sjdp     char *position;
26760484Sobrien     int is_expansion;
26833965Sjdp{
26933965Sjdp  if (macro_nest > max_macro_nest)
27060484Sobrien    as_fatal (_("buffers nested too deeply"));
27133965Sjdp  ++macro_nest;
27233965Sjdp
27360484Sobrien#ifdef md_macro_start
27460484Sobrien  if (is_expansion)
27560484Sobrien    {
27660484Sobrien      md_macro_start ();
27760484Sobrien    }
27860484Sobrien#endif
27960484Sobrien
28033965Sjdp  next_saved_file = input_scrub_push (position);
28133965Sjdp
28233965Sjdp  sb_new (&from_sb);
28360484Sobrien  from_sb_is_expansion = is_expansion;
28438889Sjdp  if (from->len >= 1 && from->ptr[0] != '\n')
28538889Sjdp    {
28638889Sjdp      /* Add the sentinel required by read.c.  */
28738889Sjdp      sb_add_char (&from_sb, '\n');
28838889Sjdp    }
28933965Sjdp  sb_add_sb (&from_sb, from);
29033965Sjdp  sb_index = 1;
29133965Sjdp
29233965Sjdp  /* These variables are reset by input_scrub_push.  Restore them
29333965Sjdp     since we are, after all, still at the same point in the file.  */
29433965Sjdp  logical_input_line = next_saved_file->logical_input_line;
29533965Sjdp  logical_input_file = next_saved_file->logical_input_file;
29633965Sjdp}
29733965Sjdp
29833965Sjdpvoid
29933965Sjdpinput_scrub_close ()
30033965Sjdp{
30133965Sjdp  input_file_close ();
30233965Sjdp}
30333965Sjdp
30433965Sjdpchar *
30533965Sjdpinput_scrub_next_buffer (bufp)
30633965Sjdp     char **bufp;
30733965Sjdp{
30833965Sjdp  register char *limit;		/*->just after last char of buffer. */
30933965Sjdp
31033965Sjdp  if (sb_index >= 0)
31133965Sjdp    {
31233965Sjdp      if (sb_index >= from_sb.len)
31333965Sjdp	{
31433965Sjdp	  sb_kill (&from_sb);
31560484Sobrien          if (from_sb_is_expansion)
31660484Sobrien            {
31760484Sobrien              cond_finish_check (macro_nest);
31860484Sobrien#ifdef md_macro_end
31960484Sobrien              /* allow the target to clean up per-macro expansion data */
32060484Sobrien              md_macro_end ();
32160484Sobrien#endif
32260484Sobrien            }
32360484Sobrien          --macro_nest;
32433965Sjdp	  partial_where = NULL;
32533965Sjdp	  if (next_saved_file != NULL)
32633965Sjdp	    *bufp = input_scrub_pop (next_saved_file);
32733965Sjdp	  return partial_where;
32833965Sjdp	}
32933965Sjdp
33033965Sjdp      partial_where = from_sb.ptr + from_sb.len;
33133965Sjdp      partial_size = 0;
33233965Sjdp      *bufp = from_sb.ptr + sb_index;
33333965Sjdp      sb_index = from_sb.len;
33433965Sjdp      return partial_where;
33533965Sjdp    }
33633965Sjdp
33733965Sjdp  *bufp = buffer_start + BEFORE_SIZE;
33833965Sjdp
33933965Sjdp  if (partial_size)
34033965Sjdp    {
34133965Sjdp      memcpy (buffer_start + BEFORE_SIZE, partial_where,
34233965Sjdp	      (unsigned int) partial_size);
34333965Sjdp      memcpy (buffer_start + BEFORE_SIZE, save_source, AFTER_SIZE);
34433965Sjdp    }
34533965Sjdp  limit = input_file_give_next_buffer (buffer_start
34633965Sjdp				       + BEFORE_SIZE
34733965Sjdp				       + partial_size);
34833965Sjdp  if (limit)
34933965Sjdp    {
35033965Sjdp      register char *p;		/* Find last newline. */
35133965Sjdp
35233965Sjdp      for (p = limit - 1; *p != '\n'; --p)
35333965Sjdp	;
35433965Sjdp      ++p;
35533965Sjdp
35633965Sjdp      while (p <= buffer_start + BEFORE_SIZE)
35733965Sjdp	{
35833965Sjdp	  int limoff;
35933965Sjdp
36033965Sjdp	  limoff = limit - buffer_start;
36133965Sjdp	  buffer_length += input_file_buffer_size ();
36233965Sjdp	  buffer_start = xrealloc (buffer_start,
36333965Sjdp				   (BEFORE_SIZE
36433965Sjdp				    + 2 * buffer_length
36533965Sjdp				    + AFTER_SIZE));
36633965Sjdp	  *bufp = buffer_start + BEFORE_SIZE;
36733965Sjdp	  limit = input_file_give_next_buffer (buffer_start + limoff);
36833965Sjdp
36933965Sjdp	  if (limit == NULL)
37033965Sjdp	    {
37160484Sobrien	      as_warn (_("partial line at end of file ignored"));
37233965Sjdp	      partial_where = NULL;
37333965Sjdp	      if (next_saved_file)
37433965Sjdp		*bufp = input_scrub_pop (next_saved_file);
37533965Sjdp	      return NULL;
37633965Sjdp	    }
37733965Sjdp
37833965Sjdp	  for (p = limit - 1; *p != '\n'; --p)
37933965Sjdp	    ;
38033965Sjdp	  ++p;
38133965Sjdp	}
38233965Sjdp
38333965Sjdp      partial_where = p;
38433965Sjdp      partial_size = limit - p;
38533965Sjdp      memcpy (save_source, partial_where, (int) AFTER_SIZE);
38633965Sjdp      memcpy (partial_where, AFTER_STRING, (int) AFTER_SIZE);
38733965Sjdp    }
38833965Sjdp  else
38933965Sjdp    {
39033965Sjdp      partial_where = 0;
39133965Sjdp      if (partial_size > 0)
39233965Sjdp	{
39360484Sobrien	  as_warn (_("Partial line at end of file ignored"));
39433965Sjdp	}
39560484Sobrien
39660484Sobrien      /* Tell the listing we've finished the file.  */
39760484Sobrien      LISTING_EOF ();
39860484Sobrien
39933965Sjdp      /* If we should pop to another file at EOF, do it. */
40033965Sjdp      if (next_saved_file)
40133965Sjdp	{
40233965Sjdp	  *bufp = input_scrub_pop (next_saved_file);	/* Pop state */
40333965Sjdp	  /* partial_where is now correct to return, since we popped it. */
40433965Sjdp	}
40533965Sjdp    }
40633965Sjdp  return (partial_where);
40733965Sjdp}				/* input_scrub_next_buffer() */
40833965Sjdp
40933965Sjdp/*
41033965Sjdp * The remaining part of this file deals with line numbers, error
41133965Sjdp * messages and so on.
41233965Sjdp */
41333965Sjdp
41433965Sjdp
41533965Sjdpint
41633965Sjdpseen_at_least_1_file ()		/* TRUE if we opened any file. */
41733965Sjdp{
41833965Sjdp  return (physical_input_file != NULL);
41933965Sjdp}
42033965Sjdp
42133965Sjdpvoid
42233965Sjdpbump_line_counters ()
42333965Sjdp{
42433965Sjdp  if (sb_index < 0)
42533965Sjdp    {
42633965Sjdp      ++physical_input_line;
42733965Sjdp      if (logical_input_line >= 0)
42833965Sjdp	++logical_input_line;
42933965Sjdp    }
43033965Sjdp}
43133965Sjdp
43233965Sjdp/*
43333965Sjdp *			new_logical_line()
43433965Sjdp *
43533965Sjdp * Tells us what the new logical line number and file are.
43633965Sjdp * If the line_number is -1, we don't change the current logical line
43733965Sjdp * number.  If it is -2, we decrement the logical line number (this is
43833965Sjdp * to support the .appfile pseudo-op inserted into the stream by
43933965Sjdp * do_scrub_chars).
44033965Sjdp * If the fname is NULL, we don't change the current logical file name.
44138889Sjdp * Returns nonzero if the filename actually changes.
44233965Sjdp */
44338889Sjdpint
44433965Sjdpnew_logical_line (fname, line_number)
44533965Sjdp     char *fname;		/* DON'T destroy it! We point to it! */
44633965Sjdp     int line_number;
44733965Sjdp{
44833965Sjdp  if (line_number >= 0)
44933965Sjdp    logical_input_line = line_number;
45033965Sjdp  else if (line_number == -2 && logical_input_line > 0)
45133965Sjdp    --logical_input_line;
45238889Sjdp
45338889Sjdp  if (fname
45438889Sjdp      && (logical_input_file == NULL
45538889Sjdp	  || strcmp (logical_input_file, fname)))
45638889Sjdp    {
45738889Sjdp      logical_input_file = fname;
45838889Sjdp      return 1;
45938889Sjdp    }
46038889Sjdp  else
46138889Sjdp    return 0;
46233965Sjdp}				/* new_logical_line() */
46333965Sjdp
46433965Sjdp/*
46533965Sjdp *			a s _ w h e r e ()
46633965Sjdp *
46733965Sjdp * Return the current file name and line number.
46833965Sjdp * namep should be char * const *, but there are compilers which screw
46933965Sjdp * up declarations like that, and it's easier to avoid it.
47033965Sjdp */
47133965Sjdpvoid
47233965Sjdpas_where (namep, linep)
47333965Sjdp     char **namep;
47433965Sjdp     unsigned int *linep;
47533965Sjdp{
47633965Sjdp  if (logical_input_file != NULL
47733965Sjdp      && (linep == NULL || logical_input_line >= 0))
47833965Sjdp    {
47933965Sjdp      *namep = logical_input_file;
48033965Sjdp      if (linep != NULL)
48133965Sjdp	*linep = logical_input_line;
48233965Sjdp    }
48333965Sjdp  else if (physical_input_file != NULL)
48433965Sjdp    {
48533965Sjdp      *namep = physical_input_file;
48633965Sjdp      if (linep != NULL)
48733965Sjdp	*linep = physical_input_line;
48833965Sjdp    }
48933965Sjdp  else
49033965Sjdp    {
49133965Sjdp      *namep = 0;
49233965Sjdp      if (linep != NULL)
49333965Sjdp	*linep = 0;
49433965Sjdp    }
49533965Sjdp}				/* as_where() */
49633965Sjdp
49733965Sjdp
49833965Sjdp
49933965Sjdp
50033965Sjdp/*
50133965Sjdp *			a s _ h o w m u c h ()
50233965Sjdp *
50333965Sjdp * Output to given stream how much of line we have scanned so far.
50433965Sjdp * Assumes we have scanned up to and including input_line_pointer.
50533965Sjdp * No free '\n' at end of line.
50633965Sjdp */
50733965Sjdpvoid
50833965Sjdpas_howmuch (stream)
50933965Sjdp     FILE *stream;		/* Opened for write please. */
51033965Sjdp{
51133965Sjdp  register char *p;		/* Scan input line. */
51233965Sjdp  /* register char c; JF unused */
51333965Sjdp
51433965Sjdp  for (p = input_line_pointer - 1; *p != '\n'; --p)
51533965Sjdp    {
51633965Sjdp    }
51733965Sjdp  ++p;				/* p->1st char of line. */
51833965Sjdp  for (; p <= input_line_pointer; p++)
51933965Sjdp    {
52033965Sjdp      /* Assume ASCII. EBCDIC & other micro-computer char sets ignored. */
52133965Sjdp      as_1_char ((unsigned char) *p, stream);
52233965Sjdp    }
52333965Sjdp}
52433965Sjdp
52533965Sjdpstatic void
52633965Sjdpas_1_char (c, stream)
52733965Sjdp     unsigned int c;
52833965Sjdp     FILE *stream;
52933965Sjdp{
53033965Sjdp  if (c > 127)
53133965Sjdp    {
53233965Sjdp      (void) putc ('%', stream);
53333965Sjdp      c -= 128;
53433965Sjdp    }
53533965Sjdp  if (c < 32)
53633965Sjdp    {
53733965Sjdp      (void) putc ('^', stream);
53833965Sjdp      c += '@';
53933965Sjdp    }
54033965Sjdp  (void) putc (c, stream);
54133965Sjdp}
54233965Sjdp
54333965Sjdp/* end of input_scrub.c */
544