After all the recent discussion about builtin read, it is starting to sound like something that will happen, at the very least as a common addon. Given this, it's time to examine the design options and try to come up with something reasonable. After a bit of thought I came up with the following: To keep things in the spirit of rc, simplicity should be our guiding principle. This shapes most of the design decisions discussed below. 1) One string rather than IFS seperation of fields - simplicity - preserves information, such as runs of blanks - field splitting can always be done later with backquote: read x;x=(`{echo -- $x}) 2) Single variable rather than multiple variables - simplicity - you can always split the fields as above and use subscripts 3) Good behaviour on EOF. - return 1 on EOF, 0 otherwise - save any text on the line before EOF 4) Should strip the newline - This makes "read x;echo -- $x" work right. 5) Doesn't honor \ at EOL for continuation - simplicity 6) If interactive and compiled with readline, use that to get input. - consistency Aside from the last item, Alan Watson has already presented what looks like a reasonable implementation way back on May 17th of this year. (It could be packaged a bit better to fit in with the current addon scheme and be easier to install.) The case for a builtin read could be much better evaluated if some folks would try his version and report back on their experiances. Tom PS - with Alan's permission I'll repackage his read routine as a proper patch so it's easier to try. Alan?
[ Tom Culliton x2278 wrote: ] To keep things in the spirit of rc, simplicity should be our guiding principle. This shapes most of the design decisions discussed below. I always thought useability was the point .. 1) One string rather than IFS seperation of fields - simplicity - preserves information, such as runs of blanks - field splitting can always be done later with backquote: read x;x=(`{echo -- $x}) ... 4) Should strip the newline - This makes "read x;echo -- $x" work right. 5) Doesn't honor \ at EOL for continuation - simplicity This is an inconsistency. I'd very much prefer the usual "x = `read" or "x = `` ( $some_ifs_list ) { read }" Malte
If rc's read becomes a builtin version of line, I think we need some optimization of forks in rc, since currently x = `BUILTIN results in rc forking. - cks
> This is an inconsistency. I'd very much prefer the usual
> "x = `read"
> or "x = `` ( $some_ifs_list ) { read }"
Please explain how you would write a "read until EOF loop".
Don't confuse EOF with blank lines.
I think Tom's list is right-on.
/r$
[ rsalz@osf.org wrote ]: > This is an inconsistency. I'd very much prefer the usual > "x = `read" > or "x = `` ( $some_ifs_list ) { read }" Please explain how you would write a "read until EOF loop". Don't confuse EOF with blank lines. Well, let me put it this way: I always wanted $status to reflect the exit status of the backquote command, not the assignment. To give another example of my "disgustingly bad taste", this will allow "while( x = `{ ... } ) ..." to work, too. Malte
>Well, let me put it this way: I always wanted $status to reflect
>the exit status of the backquote command, not the assignment.
Let me make sure I understand. You want to be able to write this:
x=`read
I understand the consistency argument. Since most uses of read will be
in a "read until EOF loop," however, you would require that other changes
be made to rc. I think this is enough to kill your idea.
Anyhow, let's take a look at your idea. That is,
x=`foobar
should set $status to the exit value of foobar. What should
x=foobar
set $status to? Leave it unchanged? What about
x=*
if the directory is empty? And if it isn't? What about
x=/foo/*
when /foo doesn't exist?
You are making a simple shell very complicated, don't you think?
/r$
>This is an inconsistency. I'd very much prefer the usual
> "x = `read"
> or "x = `` ( $some_ifs_list ) { read }"
Something along the lines of:
fn read {
if (builtin read LINE) {
echo $LINE
return 0
} else {
echo $LINE
return 1
}
}
I would not mind Malte's suggestion as the primitive -- it seems fairly
easy to convert one to the other with a simple function.
Oh, where to start.... Rich is right about the patch for nalloc.c, his version is better style. For Malte, simplicity is often the same as usability, it takes a lot fewer brain cells to remember and correctly use something simple vs. something complex. Maybe I'm just getting old, but I find myself running low on brain cells pretty regularly these days. What really convinced me that rc's read should be simple was looking at the one in ksh. What a monstrosity! 8-P The other idea that Malte mentioned, having read act like line, does have a certain appeal. It's may even be cleaner because it doesn't add another way of setting variables. And as Alan points out, a simple function can easily convert one form to the other. The only problem is that you always need a `{} and thus an extra fork to do anything with it. For Chris, if you don't care about setting a different ifs, you can split the line without a fork by using eval: read x;eval 'x=('$x')' Of course if you want to split up the fields of /etc/passwd on ':' you'll still need to fork. Producing your own version of read, that splits the input line using ifs, should be easy if you generalize the backquote code in glom.c. Go for it! ;-) Finally, Alan has given me the go ahead to repost his version of read as a patch. The current version doesn't support readline yet, so maybe I'll try to hack that in after lunch. Tom
[ rsalz@osf.org wrote ]: Anyhow, let's take a look at your idea. That is, x=`foobar hould set $status to the exit value of foobar. What should x=foobar set $status to? Leave it unchanged? What about x=* if the directory is empty? And if it isn't? What about x=/foo/* when /foo doesn't exist? Yes, an assignment leaves the status unchanged. Your file name expansion examples are just a shorthand for x = `{ glob /foo/* } # glob == echo Currently, neither "x=*" nor "x=`{ glob *}" sets $status to some reasonable value, it is just 0 -- always! You are making a simple shell very complicated, don't you think? Complicated is your word for it, I'd rather call it more usable. I have frequently had the problem to distinguish between a failed backquote command and a command producing no output. There may be better solutions then this x = `{ foo || echo '!@#$%^&*()' } if( ~ $x '!@#$%^&*()' ) ... but it seems to me to be a FAQ. The person who started this thread had just this problem. I don't mean to offend anybody, but I have the impression that because Tom Duff invented this shell there can't be anything wrong. But if one takes a closer look, one sees quite a few sh'isms still in it, e.g shift. I think rc in its original form and in its current form is an excellent point to start a shell project. This is why I post all this to this list and have it discussed instead of just implementing it for myself. Be assured though, that I very much appreciate different opinions. Back to the read problem: Currently there is no builtin which assigns a value to a variable ( except for the special variables of course ). There's been a discussion on shift shifting arbitrary lists with the proposed syntax being "shift x 2" probably because "x = `{ shift x 2 }" isn't too elegant. If this makes its way into rc, I don't mind if read expects a variable as a command line parameter. But since I don't care if some functionality is built into the shell, I'd prefer the backquote substitution solution. Malte
cks:
> If rc's read becomes a builtin version of line, I think we need some
>optimization of forks in rc, since currently
> x = `BUILTIN
>results in rc forking.
I don't see how this could be avoided unless you define a whole
new i/o model internal to rc just for builtins and the backquote
splitter to use.
It looks like that would involve reinventing the OS inside rc, so it
would lead me to suggest that Unix fork is just broken (i.e., it should
be faster) but this is not a very productive avenue to pursue.
It's a shame when you can't use the Unix style when programming in
Unix. Is it time to move onto something else?
IMHO this is thus an argument against read as a backquote operator, since one strong reason to put it into the shell in the first place is for efficiency reasons. I'm not particularly eager to see someone have to change rc's perfectly fine and working i/o system for backquote operators. - cks
[Malte wrote:] |[ rsalz@osf.org wrote ]: | set $status to? Leave it unchanged? What about | x=* | if the directory is empty? And if it isn't? What about This sets x to '*', no error whatsoever. | x=/foo/* | when /foo doesn't exist? This sets x to '/foo/*', again no error. |Yes, an assignment leaves the status unchanged. Your file name expansion |examples are just a shorthand for | x = `{ glob /foo/* } # glob == echo I agree on this, It would be nice if the status reflects the result of the evaluation of the right-hand side, not that of the assignment itself. If you 'redefine' $status this way, it is also possible to save and restore its value, something you currently can't (see my earlier mail on the problems with $status and the prompt function). The only problem here may be the following: ; a=(b c) ; $a="foo" multi-word variable name ; echo $status 1 However, an rc-script aborts if you try this, so you can't check $status anyway. |There's been a discussion on shift shifting arbitrary lists with the |proposed syntax being "shift x 2" probably because "x = `{ shift x 2 }" |isn't too elegant. If this makes its way into rc, I don't mind if read |expects a variable as a command line parameter. As Chris said, a `BUILTIN currently always forks, which is a disadvantage of an implementation like "x=`{shift x 2}" or "x=`{read a; echo $a}" in order to get a set of words in 'x'. And since the $$<var-name> construction already allows a function like 'append x (a b c)' in order to modify the variable 'x', a 'read x' or 'shift x 2' is not introducing something new. Personally, I think that s = shift 2 $s s = shift 2 (what ever list) l = read l2 = read [1=3] # would this read from descriptor 3 ? would also be quite elegant, avoiding the builtins taking variable names. But as mentioned above, this causes problems with the current implementation of $status. Gert-Jan --------------------------------------------------- J.G. Vons E-Mail: vons@cesar.crbca1.sinet.slb.com
> Is it time to move onto something else?
It has been for some time, now. Why do you think Plan 9 was invented?
Alas, the commercial world is just now discovering Unix, and the universities
(at least around here) just want to Get The Next Paper Written using frame
or whatever. Heaven forbid they should actually *use* an experimental, but
state of the art distributed system.
"Unix is dead, and not only that, it's starting to smell pretty bad too."
-- Rob Pike
I don't believe in The Gospel According to Pike for everything, but a lot
of the time he's right...
Just spouting off steam,
Arnold
Malte brings up the desire for shift to shift things besides $*. This has been thoroughly beaten to death in the mailing list; see my message <91Sep11.132925edt.2708@hawkwind.utcs.toronto.edu>, which has a supershift function which involves no backquotes and no risk of carefully quoted variables 'escaping'. You can find it in the first mailing list archive on archone.tamu.edu, /pub/rc/rc-list.1991.Z. I highly recommend reading the mailing list archives; many issues have been discussed and summarized there. - cks [to save people's time, here's the function again: # 'supershift' function for rc. # usage: # sshift varname # sshift varname number # shifts the list varname by number (default 1) positions. fn sshift { if (~ $#* 1 ) { _sshift $1 1 $$1 } else { _sshift $1 $2 $$1 } } # this function does most of the work. # _sshift NAME COUNT LISTELEMS # shift LISTELEMS COUNT items left, and assign the result to NAME. fn _sshift { _vn=() { _vn=$1; shift; shift $1; shift; $_vn=$* } } ]
>Alas, the commercial world is just now discovering Unix, and the universities
>(at least around here) just want to Get The Next Paper Written using frame
>or whatever. Heaven forbid they should actually *use* an experimental, but
>state of the art distributed system.
Why would anyone who wants to write a paper want to use a research system?
/r4
> >Alas, the commercial world is just now discovering Unix, and the universities
> >(at least around here) just want to Get The Next Paper Written using frame
> >or whatever. Heaven forbid they should actually *use* an experimental, but
> >state of the art distributed system.
>
> Why would anyone who wants to write a paper want to use a research system?
It is my contention that much of the usability/success of Unix came from the
fact that it was *used*, and not just built and then mined for research
results, the way most university os's are.
I think if people put Plan 9 into production for day to day use,
including grungy things like writing papers, they might end up with
more productive environments for themselves. (This would be true of other
os's as well, eg Clouds here at GT.)
Maybe I'm wrong. But the attitude of "I just want to get my job done, I don't
care about elegance/non-elegance of my environment" just leads us to
DOS, Novell, and Windows NT. Yuck.
Arnold
> I think if people put Plan 9 into production for day to day use, > including grungy things like writing papers, they might end up with > more productive environments for themselves. (This would be true of other > os's as well, eg Clouds here at GT.) maybe. depends on whether they had access to other machines, too. at minster.york.ac.uk, the students use a plan 9-like os running on 386 boxes, but last i saw, i hadn't seen any students doing anything more than running a load of remote shells onto the file server (which happens to run AIX). me, i'd play with the local os, and have fun, but generally it doesn't look that different from unix anyway (the shared environment and lack of links are the main places where you see the join) - it's only when you get into the programming that you see where the kludges have been removed. > Maybe I'm wrong. But the attitude of "I just want to get my job done, I don't > care about elegance/non-elegance of my environment" just leads us to > DOS, Novell, and Windows NT. Yuck. kinda, but inertia was the main thing for dos, and pretty icons is the big mover for nt, i reckon. it's a sad world. still, this is off the track of rc. 9fans might be better, but i doubt it. steve