rc-list - mailing list for the rc(1) shell
 help / color / mirror / Atom feed
From: Alan Watson <alan@oldp.astro.wisc.edu>
To: rc@hawkwind.utcs.toronto.edu
Subject: Re: read
Date: Mon, 17 May 1993 22:13:30 -0400	[thread overview]
Message-ID: <9305180213.AA18944@oldp.astro.wisc.edu> (raw)

Gosh, this stuff is tricky, isn't it?  Here are both external and
built-in implementations of read, following v7 semantics on EOF
(i.e., set the variable to '' and return 1), and a corrected trip.read.
None of the other reads in the list or the examples get this right
(including my previous offerings).

Of course, all of this will be made redundant by bqstatus.

I take it by the silence that no one objects to a built-in read by
default ("yeah, right").

Alan.

; cat addon/read.c
/* 
 b_reads -- read a single line, terminated by \n or EOF, from the standard
 input, and assign the line without the terminator to av[1].
 */

static int
readchar (int fd)
{
   unsigned char c;

   if (read (fd, &c, 1) == 1)
      return c;
   else
      return EOF;
}

void
b_read (char **av)
{
   char *name;
   int c;
   char *line;
   SIZE_T len;
   SIZE_T max_len;
   SIZE_T max_len_quantum;

   /* check usage is "read name" */
   if (av[1] == NULL)
      rc_error ("missing variable name");
   if (av[2] != NULL)
      rc_error ("too many arguments to read");
   name = av[1];

   /* read a single line from stdin */
   line = NULL;
   len = 0;
   max_len = 0;
   max_len_quantum = 256;
   do {
      c = readchar (0);
      if (len == max_len) 
	 line = erealloc (line, max_len += max_len_quantum);
      if (c == '\n' || c == EOF)
	 line[len] = 0;
      else
	 line[len] = c;
      len++;
   } while (c != '\n' && c != EOF);

   /* assign whatever we read to the variable */
   assign (word (name, NULL), word (line, NULL), FALSE);
   efree (line);

   /* return TRUE if we terminated with a \n, otherwise FALSE */
   set (c == '\n');

   return;
}
; cat read.fn
fn read {
	switch ( $#* ) {
	case 0
		echo >[1=2] missing variable
		return 1
	case 1
	case *
		echo >[1=2] too many arguments to read
		return 1
	}
	lines = () {
		ifs = $nl { lines = `{ line ; echo $status } }
		if ( ~ $#lines 1 ) {
			$1 = ''
			return $lines
		} else {
			$1 = $lines(1)
			return $lines(2)
		}
	}
}
; cat trip.read
# trip.read -- check a read implementation performs like a true v7 sh read

fn check {
   echo $1 $2
   ./rc -c $2
   if ( ! ~ $status $1 ) {
      echo failed: $2
   }
}

check 0 true
check 1 false

nl = '
'
ifs = $nl

file = /etc/passwd
first = `{ cat $file }
first = $first(1)

echo 'start of trip.read'

# check read X and read '*' return 0
check 0 'exec <$file ; read X'
check 0 'exec <$file ; read ''*'''

# check read, read 1, read '=', and read '' return 1
check 1 'exec <$file ; read'
check 1 'exec <$file ; read 1'
check 1 'exec <$file ; read ''='''
check 1 'exec <$file ; read '''''

# check read X correctly reads first line
check 0 'exec <$file; read X ; ~ $X $first'
check 0 'echo -n $first | { read X ; ~ $X $first }'

# check read '*' correctly reads first line, preserves $0
check 0 'exec <$file ; old0 = $0 ; read ''*'' ; ~ $0 $old0 && ~ $1 $first && ~ $#* 1'

# check read returns 1 on EOF and I/O error
check 1 'exec </dev/null ; read X'
check 1 'exec <[0=]      ; read X'

# check read sets variable to '' when line is empty and on EOF and I/O error.
check 0 '{ X = X ; echo | { read X ; ~ $X '''' } }'
check 0 '{ exec </dev/null ; X = X ; read X ; ~ $X '''' }'
check 0 '{ exec <[0=]      ; X = X ; read X ; ~ $X '''' }'

echo 'end of trip.read'

# end-of-file


             reply	other threads:[~1993-05-18  2:13 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1993-05-18  2:13 Alan Watson [this message]
  -- strict thread matches above, loose matches on Subject: below --
1993-05-16  7:51 read Alan Watson
1993-05-16  6:49 read Alan Watson
1993-05-16  7:12 ` read Chris Siebenmann
1993-05-15  4:14 read Alan Watson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=9305180213.AA18944@oldp.astro.wisc.edu \
    --to=alan@oldp.astro.wisc.edu \
    --cc=rc@hawkwind.utcs.toronto.edu \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).