[comp.sys.amiga.tech] !.rexx

lrg7030@uxa.cso.uiuc.edu (Loren Rittle) (12/10/90)

OK, a few people have asked about !.rexx.  It is still rough,
I mean it works great for me, but there is no documentation yet
and all the system dependencies have been removed yet! (Most
of the more major ones are listed in a new section of the
ARexx comment at the top of !.rexx.)
I will add the CSH-style history in a few weeks and repost.
Any user submitted changes will be incorporated at that point.
(Sorry, but my sig will be attached to the bottom of this, I
don't know how to override that action!)

Here it is:
/*
 *  !.rexx ... processes '?', '[]', '*', '.', '..', '~', '/', '!*'
 *  and `backtick` evaluation.
 *  Does filename globbing, minimal UNIX file system emulation and
 *  CSH-style history management (soon).
 *  Requires WShell v1.2, ConMan v1.3c, ARexx v1.1, RexxArpLib, and
 *  ARP (possibly more!)
 *  Started: LJR 9/4/89
 *  Updates: LJR 10/22/89 1/9/90 2/20/90
 *  Last update: LJR Sun Dec 09 10:13:09 1990
 *  Version 5.0
 *  Copyright (C) 1990  Loren J. Rittle
 *  
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 5.0, or (at your option)
 *  any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  I can be reached at the following address:
 *  Loren J. Rittle
 *  lrg7030@uxa.cso.uiuc.edu
 */
/*
 *  READ ALL OF THIS BEFORE USING, PLEASE!
 *  You may delete this comment from the version you run from.
 *  You must keep it intact (or updated) on versions you give out.
 *
 *  I *want* as much user feedback on this as possible, send me
 *  mail if you love it or hate it.  Tell me how it crashes your
 *  machine (Yea, it's ARexx, but during the process of building
 *  this thing, I found a few ARexx bugs (all reported to WSH of
 *  course!) that *crashed* the machine!) SEND ANY UPDATES YOU
 *  MAKE TO THIS THING SO I CAN USE THEM IN NEW VERSIONS!
 *  This thing has many system dependencies,
 *  some of the more important ones are listed below:
 *  1)  There *MUST* be a logical device root: assigned!
 *  2)  FindTask returns, via stdout, the ID of the WShell process, I don't
 *  think that this can be found within ARexx, thus you need FindTask
 *  (a quick little program I wrote) in your path, given below
 *  in source form:
 *  --> FindTask.c  <--
 *  #include <proto/all.h>
 *
 *  void main(void)
 *  {
 *	char buffer[32];
 *	sprintf(buffer, "%08x", FindTask(NULL));
 *	puts(buffer);
 *  }
 *  --> END OF INSERTED FILE <--
 *  3)  I assume that you have local env's, the way I kludge it under
 *  1.3 AmigaOS is to make a directory for each user WShell.  It is
 *  located in env: with a name of the form env:004b0d48, where
 *  004b0d48 is the process ID of the WShell, found with the above
 *  program.  Local env, HOME, is the only one looked at in !.rexx.
 *  I have a login program that sets all this up: env:????????/HOME
 *  and env:????????/USER are the only two local env's I set (other
 *  programs need USER, RCS to name one).  When !.rexx notices
 *  eof while it is trying to read a line it closes the WShell (ala
 *  csh) and deletes all local env's.
 *  I believe that local env's are supported under 2.0, so
 *  this will be fixed up, some day in the future when I have 2.0.
 *  4)  Some things will work a bit differently than you would expect
 *  under a plain AmigaOS system:
 *  a)  / now refers to root: (so, echo /c/dir will print root:c/dir)
 *  b)  . refers to the current directory
 *  c)  .. refers to the parent directory
 *  d)  ~ refers to your home directory as set in local env USER.
 *  If none of this makes sense to you, then you (most likely)
 *  don't use UNIX and should (unless you want to learn a bit)
 *  stay away from this package, it will only confuse the hell
 *  out of you! :-) :-) :-)
 *  5) Unlike UNIX we don't pattern match directories.
 *  There are some good reasons for this, I just can't remember
 *  them right at the moment :-).
 *
 * Put the following line into your s:startup-wshell file:
 *  prompt "R(%3%r%1);T(%3%E%1)> %[!.rexx]"
 * Put FindTask in your c: directory (after making it!)
 * Put !.rexx in your Rexx: directory
 *
 * A bit of history, this thing is named !.rexx because WSH had
 * an example called $.rexx that did `backtick` evaluation.
 */
signal on BREAK_C
signal on ERROR
signal on SYNTAX

parse pull comm

if eof(stdin) then do
    arexxid = pragma('id')
    'findtask >t:'||arexxid
    'execio <t:'arexxid||' for 1 var id'
    'delete t:'arexxid
    'delete env:'||id||' all >nil:'
    queue "endcli <nil: >nil:"
    exit
  end

curdotpos = 0
do forever
    curdotpos=pos('/',comm, curdotpos+1)
    if curdotpos == 0 then break
    if curdotpos == 1 then
        comm = 'root:'||substr(comm, 2)
    if curdotpos == 1 then
        iterate
    if substr(comm, curdotpos-1, 1) == ' ' then do
        comm = substr(comm, 1, curdotpos-1)||'root:'||substr(comm, curdotpos+1)
      end
  end

do forever
    parse var comm first "~" last
    if first == comm then break
    arexxid = pragma('id')
    'findtask >t:'||arexxid
    'execio <t:'arexxid||' for 1 var id'
    'delete t:'arexxid
    home = getenv(id || '/' || home)
    if home == "" then 
      home = "root:"
    comm = first||home||last
  end

do forever
    parse var comm first ".." last
    if first == comm then break
    lastspace=lastpos(' ',first)
    second = substr(first,lastspace+1)
    first = left(first,lastspace)
    if second == "" then
      second = pragma(Directory)
say second
    curdir = pragma('Directory', second)
    second = pragma('Directory', curdir)
    lastslash=lastpos('/',second)
    if lastslash=0 then
      lastslash=lastpos(':',second)
    path=left(second,lastslash)
    if substr(last, 1, 1) == "/" then
      last = substr(last, 2)
    comm = first||path||last
  end 

curdotpos = 0
do forever
    curdotpos=pos('.',comm, curdotpos+1)
    if curdotpos == 0 then break
    if curdotpos == 1 then
        comm = pragma(Directory)||substr(comm, 2)
    if curdotpos == 1 then
        iterate
    if substr(comm, curdotpos-1, 1) == ' ' then do
        if substr(comm, curdotpos+1, 1) == ' ' then
          comm = substr(comm, 1, curdotpos-1)||pragma(Directory)||substr(comm, curdotpos+1)
        if substr(comm, curdotpos+1, 1) == '/' then
          comm = substr(comm, 1, curdotpos-1)||pragma(Directory)||substr(comm, curdotpos+1)
      end
  end

do i = words(comm) to 2 by -1
    ithsubword = subword(comm, i, 1)
    count = 0
    bracketcount = 0
    curpos = 0
    do forever
        curpos=pos('*',ithsubword, curpos+1)
        if curpos == 0 then break
	count = count + 1
      end
    do forever
        curpos=pos('?',ithsubword, curpos+1)
        if curpos == 0 then break
	count = count + 1
      end
    do forever
        curpos=pos('\*',ithsubword, curpos+1)
        if curpos == 0 then break
	count = count - 1
      end
    do forever
        curpos=pos('\?',ithsubword, curpos+1)
        if curpos == 0 then break
	count = count - 1
      end
    do forever
        curpos=pos('[',ithsubword, curpos+1)
        if curpos == 0 then break
	bracketcount = bracketcount + 1
      end
    do forever
        curpos=pos(']',ithsubword, curpos+1)
        if curpos == 0 then break
	bracketcount = bracketcount + 1
      end
    do forever
        curpos=pos('\[',ithsubword, curpos+1)
        if curpos == 0 then break
	bracketcount = bracketcount - 1
      end
    do forever
        curpos=pos('\]',ithsubword, curpos+1)
        if curpos == 0 then break
	bracketcount = bracketcount - 1
      end
    if (count == 0 & bracketcount == 0) then do
        do forever
            curpos=pos('\*',ithsubword, curpos+1)
            if curpos == 0 then break
            ithsubword = substr(ithsubword, 1, curpos-1)||substr(ithsubword, curpos+1)
          end
        do forever
            curpos=pos('\?',ithsubword, curpos+1)
            if curpos == 0 then break
            ithsubword = substr(ithsubword, 1, curpos-1)||substr(ithsubword, curpos+1)
          end
        do forever
            curpos=pos('\[',ithsubword, curpos+1)
            if curpos == 0 then break
            ithsubword = substr(ithsubword, 1, curpos-1)||substr(ithsubword, curpos+1)
          end
        do forever
            curpos=pos('\]',ithsubword, curpos+1)
            if curpos == 0 then break
            ithsubword = substr(ithsubword, 1, curpos-1)||substr(ithsubword, curpos+1)
          end
        comm = subword(comm, 1, i-1) ithsubword subword(comm, i+1)
        iterate i
      end
    temp = subword(comm, 1, i-1)
    if filelist(ithsubword, myfilelist, 'F') == 0 then do
        call open(stderr, '*', 'Write')
        call writeln(stderr, 'No match.')
        call close(stderr)
        queue ' '
        exit (5)
      end
    do j = 1 to myfilelist.0
        temp = temp myfilelist.j
      end
    comm = temp subword(comm, i+1)
  end

parse var comm first "`" middle "`" last
rc = 0
if middle ~= "" then do
    middle '| execio stem middle.'
    middle = ""
    do j = 1 to middle.0
      middle = middle middle.j
    end
    if rc = 0 then
      comm = first middle last
    else
      exit rc
  end

queue comm
exit

BREAK_C: 
call open(stderr, '*', 'Write')
call writeln(stderr, '!.rexx: Break')
call close(stderr)
queue ' '
exit (5)

ERROR:
call open(stderr, '*', 'Write')
call writeln(stderr, '!.rexx: External error' RC 'on line' SIGL)
call close(stderr)
queue ' '
exit (5)

SYNTAX:
call open(stderr, '*', 'Write')
call writeln(stderr, '!.rexx: ARexx error' RC 'on line' SIGL)
call close(stderr)
queue ' '
exit (5)

--
``In short, this is the absolute coolest computer device ever invented!''
                   -Tom Denbo speaking about The VideoToaster by NewTek
``Think about NewTek's VideoToaster!  Now think about the Amiga!''
Loren J. Rittle lrg7030@uxa.cso.uiuc.edu

lrg7030@uxa.cso.uiuc.edu (Loren Rittle) (12/10/90)

A quick correction:
*  5) Unlike UNIX we don't pattern match directories.         
*  There are some good reasons for this, I just can't remember
*  them right at the moment :-).

Should say:
*  5) Unlike UNIX we don't allow patterns to match directories.
*  E.g.  work:adventure/advent.f is a valid file on our system.
*  echo work:ad*re/ad*f  would print work:adventure/advent.f,
*  whereas, echo work:ad*re would print (!.rexx would print, BTW)
*  No match.
*  There are some good reasons for this, I just can't remember
*  them right at the moment :-).

--
``In short, this is the absolute coolest computer device ever invented!''
                   -Tom Denbo speaking about The VideoToaster by NewTek
``Think about NewTek's VideoToaster!  Now think about the Amiga!''
Loren J. Rittle lrg7030@uxa.cso.uiuc.edu