9fans - fans of the OS Plan 9 from Bell Labs
 help / color / mirror / Atom feed
From: smiley@zenzebra.mv.com (smiley at zenzebra.mv.com)
Subject: [9fans] Making read(1) an rc(1) builtin?
Date: Sun,  3 Apr 2011 22:30:56 +0000	[thread overview]
Message-ID: <86fwpz55nj.fsf@cmarib.ramside> (raw)

I'm in the process of writing some filters in rc(1).  One thing that has
come to concern me about rc(1) is that read(1) is not a "builtin"
command.  For example, with a loop like:

    while(message=`{read})
      switch($message) {
      case foo
        dofoo
      case bar
        dobar
      case *
        dodefault
      }

Each line that's read by the script causes it to fork a new process,
/bin/read, whose sole purpose is to read a single line and die.  That
means at least one fork for each line read and, if your input has many
lines, that means spawning many processes.  I wonder if it wouldn't make
sense to move read(1) into rc(1) and make it a "builtin" command.  A
wrapper script could then be created, at /bin/read, to call "rc -c 'eval
read $*'" with the appropriate arguments (or sed $n^q, etc.), for any
program that requires an actual /bin/read to exist.

A similar line of thought holds for /bin/test.  The string and numeric
tests (-n, -z, =, !=, <, >, -lt, -eq, -ne, etc.) can be very frequently
used, and can lead to spawning unnecessarily many processes.  For the
file test parameters (-e, -f, -d, -r, -x, -A, -L, -T, etc.), however,
this argument isn't as strong.  Since the file tests have to stat(2) a
path, they already require a call to the underlying file system, and an
additional fork wouldn't be that much more expensive.  I could see the
string and numeric tests being moved into rc(1) as a "test" builtin,
with the file tests residing at "/bin/ftest" (note the "f").  The "test"
builtin could scan its arguments and call "ftest" if needed.  A wrapper
script at /bin/test could provide compatibility for existing programs
which expect an executable named /bin/test to exist.

I understand the Unix/Plan 9 philosophy of connecting tools that do one
job and do it well.  But I don't think /bin/read and /bin/test are
places where that philosophy is practical (i.e., efficient).  After all,
reading input lines really is the perogative of any program that
processes line-oriented data (like rc(1) does).  In addition, /bin/read
represents a simple and fairly stable interface that's not likely to
change appreciably in the future.  Comparison of numeric and string
values is also a fairly stable operation that's not likely to change,
and is not likely to be needed outside of rc(1).  Most programming
languages (C, awk, etc.) have their own mechanisms for integer and
string comparison.  I suspect moving these operations into rc(1) (with
appropriate replacement scripts to ensure compatibility) could
appreciably increase the performance of shell scripts, with very little
cost in modularity or compatibility.

Any thoughts on this?

I'm also a bit stumped by the fact that rc(1) doesn't have anything
analogous to bash(1)'s string parsing operations: ${foo#bar},
${foo##bar}, ${foo%bar}, ${foo%%bar}, or ${foo/bar/baz}.  Is there any
way to extract substrings (or single characters) from a string in rc(1)
without having to fork a dd, awk, or sed?  I've tried setting ifs='' and
using foo=($"bar), but rc(1) always splits bar on spaces.  Perhaps, if
rc(1) used the first character of $ifs to split $"bar, $bar could be
split into individual characters when ifs=''.  Then, the characters of
$bar could be addressed without resort to dd and friends.

(As a side note, if anyone goes into rc(1)'s source to implement any of
this, please add a "--" option (or similar) to the "echo" builtin while
you're there.  Having to wrap echo in:

    # make 'myecho $foo' work even when $foo starts with '-n'
    fn myecho {
      if(~ $1 --) {
        shift
        if(~ $1 -n) {
          shift
          echo -n -n $*
          echo
        }
        if not echo $*
      }
      if not echo $*
    }

can be rather inconvenient.)

-- 
+---------------------------------------------------------------+
|E-Mail: smiley at zenzebra.mv.com             PGP key ID: BC549F8B|
|Fingerprint: 9329 DB4A 30F5 6EDA D2BA  3489 DAB7 555A BC54 9F8B|
+---------------------------------------------------------------+



             reply	other threads:[~2011-04-03 22:30 UTC|newest]

Thread overview: 47+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2011-04-03 22:30 smiley at zenzebra.mv.com [this message]
2011-04-03 23:22 ` pmarin
2011-04-03 23:41 ` Tristan Plumb
2011-04-04  2:02   ` Ethan Grammatikidis
2011-04-04  2:53   ` erik quanstrom
2011-04-04  7:54     ` Tristan Plumb
2011-04-04  9:26     ` roger peppe
2011-04-04 21:35       ` smiley
2011-04-04 21:46         ` Anthony Sorace
2011-04-04 22:03           ` erik quanstrom
2011-04-05  8:57           ` Balwinder S Dheeman
2011-04-04 22:00         ` Oleg Finkelshteyn
2011-04-04 22:33         ` erik quanstrom
2011-04-04 23:01         ` Lyndon Nerenberg
2011-04-05  8:58         ` yy
2011-04-05 19:54           ` Ethan Grammatikidis
2011-04-05 19:56             ` erik quanstrom
2011-04-05 20:54               ` Ethan Grammatikidis
2011-04-05 21:53                 ` andrey mirtchovski
2011-04-06 16:32                   ` Bakul Shah
2011-04-06 16:43                     ` roger peppe
2011-04-06 18:15                       ` erik quanstrom
2011-04-06 18:37                         ` Yaroslav
2011-04-07  8:45                           ` Greg Comeau
2011-04-06 18:18                     ` erik quanstrom
2011-04-07  8:45                     ` Greg Comeau
2011-04-05  9:10         ` roger peppe
2011-04-05 15:47           ` ron minnich
2011-04-05 15:52             ` Jacob Todd
2011-04-05 15:57               ` erik quanstrom
2011-04-05 16:04               ` Rudolf Sykora
2011-04-05 17:17                 ` ron minnich
2011-04-05 17:49             ` smiley
2011-04-05 18:01               ` erik quanstrom
2011-04-05 19:50               ` Yaroslav
2011-04-06 15:27                 ` smiley
2011-04-06 15:32                   ` Jacob Todd
2011-04-07  1:26                     ` [9fans] Busy mouse WAS: " smiley
2011-04-07 11:49                       ` erik quanstrom
2011-04-07 19:59                         ` smiley
2011-04-07 20:19                           ` erik quanstrom
2011-04-09 12:26                             ` smiley
2011-04-09 12:33                               ` erik quanstrom
2011-04-05 16:28         ` [9fans] " dexen deVries
2011-04-05 17:05         ` Bakul Shah
2011-04-03 23:51 ` Lyndon Nerenberg (VE6BBM/VE7TFX)
2011-04-04  3:01 ` erik quanstrom

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=86fwpz55nj.fsf@cmarib.ramside \
    --to=smiley@zenzebra.mv.com \
    /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).