***********************************************************************
*                         Perl for GUARDIAN                           *
***********************************************************************

Welcome to Perl for Guardian.

This file contains information you will need to:

     * Run Perl on your Guardian NSK system
     * Compile Perl on your Guardian NSK system (should that be necessary)
     * Install Perl on your Guardian NSK system (jump to end of document)

This port has only been running on a D35 version of Guardian and has been
tested on G00 (using the D44 C compiler).  If the executable file doesn’t
run on your system, try recompiling (using the supplied instructions).  If
it still doesn’t run, give me a call and maybe I can help you figure out
what to do next.

This document contains the following sections:

     * INTRODUCTION

       Some remarks on why I tried to do this port (_why_ indeed?)

     * HOW TO USE PERL ON GUARDIAN

       An explanation of the command line

     * FILE ORGANIZATION

       How the Perl subdirectories got mapped into Guardian file names

     * LIBRARIES

       How libraries work under Guardian

     * STUFF THAT APPEARS TO WORK

       A discussion of what works

     * STUFF THAT WON'T WORK

       A discussion of what doesn't (or can't ever) work.

     * PERFORMANCE

       A brief remark on performance.

     * TEST SUITE RESULTS

       A discussion of what happened when I ran the validation suite

     * COMPILATION INSTRUCTIONS

       Some tools for recompiling and re-binding Perl for Guardian

     * TACL SUPPORT

       An explanation of the TACL macros

     * LICENSING

       This describes the LICENSE (it points you at the LICENSE file).

     * INSTALLATION INSTRUCTIONS

       How to install this beast.

     * README DOCUMENT CHANGE HISTORY

       A list of changes made to this document over time.  If you
       make any changes to the software which change it's behvaior
       please update this document to reflect them.

First, a caveat:  I'm not a UNIX person and only a moderately experienced C
programmer (most of my work has been in TAL).  So the choices I made about
what to get working and the approach I took for getting it working may seem
odd or idiosyncratic or even just plain wrong.  So, I am very open to
suggestions about how to improve this port.  Please feel free to call or
write with any ideas or thoughts you might have.

Enjoy!

Carl Adler
IDX, Systems Corp.
Seattle, Washington
(206) 689-1479
carl_adler@idx.com


INTRODUCTION
------------

Perl was built to help people do interesting work on UNIX platforms,
primarily related to system managment.  It is a lot more than that now and
it has been successfully ported to a number of other platforms which resemble
UNIX in several important aspects:

     *  The file system is tree structured

     *  Process creation is not a capital crime

     *  Most of the UNIX utilities or something like them have
        already been ported.

Guardian does not resemble UNIX in any of these aspects.  So what did we
hope to gain by trying to do this port?

     *  TACL doesn't do regular expressions; Perl does.

     *  Many people know Perl; not many know TACL.

     *  There are books you can buy to help you learn Perl.  There
        are no books on TACL that I'm aware of.

     *  For people who know C, Perl is probably easier to learn
        than TACL.

     *  With a little luck, any Perl scripts generated for our use
        on Guardian, will be useful on other platforms and vice versa.
        It's a cinch that our TACL macros won't be useful on another
        platform.



HOW TO USE PERL ON GUARDIAN
---------------------------

Before trying to execute a Perl script you must load the TACL wrapper:

      LOAD/KEEP 1/<perlvolsubvol>.PERLMAC

where <perlvolsubvol> is volume and subvolume where the Perl executeable
file is.

If you set up your #PMSEARCHLIST to include <volsubvol> you don't have
to explicitly load PERLMAC.  The PERL "bootstrap" macro will do it for
you the first time you execute a Perl script.

Use normal Perl command line syntax.  For example:

      > PERL -W PSCRIPT ARG1 ARG2

File name "globing" doesn't work inside perl so the TACL wrapper will
attempt to expand file name templates.  For example you can say:

      > PERL -W PSCRIPT STUFF.*

What the script actually sees when it runs is a space separated list of
all of the files in the STUFF subvolume.  NOTE:  there is a limit on
how long a TACL command line can be so if the STUFF.* expands to too many
names, the MACRO will croak.  If you know your script wants to deal
with multiple files, it's best to use OPENDIR with wild cards.

If you need to pass a file name template into the script, put it in
quotes.  As in:

      > PERL -W PSCRIPT "STUFF.*"

The Guardian way to do I/O redirection is inside the "/" characters
following the program name.  This works here as well.  For example:

      > PERL/OUT FOOBAR/ -W PSCRIPT ARG1

will redirect STDOUT to a file called FOOBAR.  If FOOBAR doesn't exist
it will be created.  If it does, output will be appended to it.  You
can also say:

      > PERL/IN BARFOO/ ARG1

which will redirect STDIN to a file called BARFOO.

However, the TACL wrapper supports ">" and ">>" for redirection (to try
to make regular Perl users feel a little more at home).  So the above
command would look like this:

      > PERL -W PSCRIPT ARG1 >>FOOBAR

To cause FOOBAR TO be emptied prior to the getting new output, you do
this:

      > PERL -W PSCRIPT ARG1 >FOOBAR



FILE ORGANIZATION
-----------------

On tree structured file systems, Perl is usually in something like:

      /usr/perl/...

and there is a tree under this with "bin", "lib", etc.

Here's what we did:

For our system PERL is currently installed on volume $SYS2 and resides in
a set of subvols, each of whose names is prefixed with "PERL":

     PERL       PERLO executeable, TACL library, PERLLOCL (config &
                init) PERL bootstrap macro and this file.

     PERLMNT    Perl Maintanence macros

     PERLSRC    Source code (program and header files)

     PERLOBJ    Object code (one per ".c" source compile)

     PERLL01 - PERLL09 Library directories (see the AAREADME file in
                each subvol for it's original UNIX name).

     PERLT01 - PERLT07 /t directories (see the README file in each
                subvol for it's orignal UNIX name).


LIBRARIES
---------

As you can probably tell from the above list, we had to figure out
a way of mapping the normal PERL library structure on to Guardian's
flat organization.  We did this by way of a kluge:  when PERL figures
out that it has to open a library (say, file::find), it tries to open
a file called:

     ./file/find.pm

that is a file called "find.pm" in the directory called "file" which
is contained within the current directory (presumably, "perl").  As
you can imagine, Guardian wouldn't know what to do with this.  So,
in the "file open" code we say:  if guardian can't open the file
verbatum then translate this into the define:

     =perl_filefindpm

that is, we squish out all of the illegal filename characters and
prefix the result with "=perl_".

The TACL we have wrapped around Perl assumes the existance of two
TACL macro files:  PERLLOCL (in the same subvolume that the Perl
executable is in) and PERLCSTM (in your own default subvolume).

When you invoke Perl (which, as you will see, is actually a TACL
macro), it will invoke both PERLLOCL and, if it exists, PERLCSTM.

PERLLOCL contains all of the defines necessary to reference libraries
which are available to all users.  PERLCSTM contains defines necessary
to reference your own individual libraries.  PERLCSTM may not exist.

Thus, if you want to write and then use your own PERL library file, you
must add a define to a file called PERLCSTM in your default subvolume.
You can use either the TACL "ADD DEFINE" or, if you have a lot of them,
you can use the following syntax (which is very fast):

    [#if [#definesetattr class map]]
    [#if [#definesetattr file <your library file>]]
    [#if [#defineadd =PERL_<unqualified file>PM]]

where:  <your library file> is a real Tandem file name (you
        probably should keep all of your Perl library scripts in a
        single subvol).

        <unqualified file> is the unqualified file name of <your
        library file>.

note:   the "=PERL_" prefix and the "PM" suffix is required.

And to reference this library script in a Perl program, you do
this:

        use <unqualified file>;

So, for example, suppose you wanted to build a library script that
did something interesting for you and suppose you would call it
GEEWIZ.  In the Perl program you would say:

        use GEEWIZ;

And then add the following defines to your PERLCSTM macro:

    [#if [#definesetattr class map]]
    [#if [#definesetattr file <$D1.YOURLIB.GEEWIZ>]]
    [#if [#defineadd =PERL_GEEWIZPM]]



STUFF THAT APPEARS TO WORK
--------------------------

In general anything that operates on variables and does no I/O
or system calls appears to work.

The following I/O and system calls work:

1.  Basic "line oriented" file I/O uses the underlying C runtime routines
    "getc" and "putc" (getc has been doctored a wee bit to get performance).
    As such, EDIT files and UNSTRUCTURED files can be read or written.
    If an output file doesn't exist it will default to an EDIT file.
    You can write to a pre-existing UNSTRUCTURED file as long as you
    use the ">>" suffix when opening the file.

    A mechanism exists for reading and writing ENSCRIBE structured files
    (see 1.3 below).

    1.1  Perl can read and write UNSTRUCTURED files.  This means
         for example, that, a file of binary data that has been
         FTP'd to the Tandem can be processed by a Perl script.

         PAY ATTENTION TO THIS:

               UNSTRUCTURED files must have ODDUNSTR flag set
               in order for Perl to be able to write to them.
               Otherwise you will get the following error:

                     "Not a C file"

         You can use either <FILE> or "read" to read UNSTRUCTURED files.
         However, suppose $D1.FOO.BAR is a an UNSTRUCTURED file
         containing binary (i.e. non-displayable) information.  The
         following script:

              $foo = "\$D1.FOO.BAR";
              open F,$foo;
              $d = <F>;

         will read all of the information from the file $D1.FOO.BAR
         into the variable $d until either EOF or until a "\n"
         character is found.  That is, for "line oriented" files the
         <FILE> will read one line and a line is alway terminated with
         the "\n" character.  NOTE: the "\n" character will be
         included in the information in $d.  If there is no "\n"
         character in a file, <FILE> will read the entire file into
         memory.  So far we have not seen a limit on how large the file
         can be in this case.

    1.2  Perl scripts can know what kind of file you are using.
         The following script demonstrates this:

            stat($ARGV[0]);                   # get "status" of file
            if (!defined -e _) {              # does not exist if undefinded
               print "$ARGV[0] doesn't exist\n";
               exit 0;
            }

            print "Directory\n" if -d _;      # if file was <template>
            print "Block Special\n" if -b _;  # if file was ENSCRIBE
            print "File\n" if -f _;           # if file was line oriented
            print "Text\n" if -T _;           # if content is displayable
            print "Binary\n" if -B _;         # if content isn't

         That is:

            -d returns true if the filename is actually a template
               (see item #2, below for more on "directories").
            -b returns true if the file is an ENSCRIBE file
            -f returns true if the file is a line oriented file
            -T returns true if the first 512 bytes or the first
               ENSCRIBE record contains only displayable data.
            -B returns true if the first 512 bytes or the first
               ENSCRIBE record contains non-displayable data.

         and, if the result of any of these tests is !defined then
         the file you are testing doesn't exist.

    1.3  Perl can read and write ENSCRIBE files but only through the use
         of the following commands:

            - sysopen
            - sysread
            - syswrite

         If you try to use "open" on an ENSCRIBE file you'll get an
         error (in $!):

               "Not a C file"

         If you are reading ENSCRIBE files you must specify a length
         that is >= the record length of the file or you will truncate
         your data.  For example:

               $file = "\$CUST15.HHDATA.ACCT";
               sysopen (ACCT, $file, 0);
               $status = sysread (ACCT, $rec, 4000);

         The "sysread" will return up to 4000 bytes from an ACCT record.

         Also, $rec will contain RAW data.  That is, if the record
         had binary data in it, then $rec will have it as well.
         You must write your scripts knowing the record layout.

         To write to ENSCRIBE files use "syswrite".  The length
         of the string you writing must make sense in terms of the
         record length of the file.  For example, if the record length
         of the ENSCRIBE record was 127, then the variable that you
         write should be 127 bytes long.

         When writing to ENSCRIBE files, DO NOT include "\n" character
         at the end of the string.  ENSCRIBE files are record oriented
         (1 syswrite = 1 record) and the "\n" will be included in the
         data which you probably don't want.

         When writing to KEY SEQUENCED files you must make sure that
         the primary key is unique.  For example, suppose you were
         writing to a KEY SEQUENCED file with KEYOFF = 0, KEYLEN = 10.
         The first 10 bytes of every variable you write will be the
         primary key.

         When writing to RELATIVE RECORD files, if you write out a zero
         length string, there will not be a record written.  That is
         if you have say:  $foo = "" and then do:

              syswrite (OUTFILE, $foo, length($foo));

         No record will be writeN if OUTFILE is RELATIVE RECORD.

         EOF doesn't work on ENSCRIBE files (it always returnes TRUE).
         For sysread you can always use "defined" to test the result
         of the read (I've doctored up sysread so that even Perl
         files return !defined at end of file).  Read on for more.

         And, if the result of sysread or syswrite is !defined then
         an error has occured.  $! in a numeric context returns the
         error code.  $! in a string context returns an error message.
         The message is usually somethine like:  "Guardian or user
         define error <num>".  In particular, you should quit your
         read/write loops when the result of system is !defined.  For
         example:

              while (defined sysread (FILE, $var, $rdlen)) {
                  ...process $var...
              }

              if ($! != 1) {
                 print "Error on FILE: $!\n";
              }

         Writing is similar.

         Errors are the usual Guardian suspects:

              21   number of bytes is longer than record
              45   file full
              43   disk file
               1   end of file
              etc.

2.  OPENDIR/CLOSEDIR/READDIR works but it has some funny Guardian
    quirks.  Here are some examples that work (that is, READDIR
    will actually give you a file name)

         a.    opendir DIR, $CUST20.F5OBEY

               Each readdir will return a file in this directory.

         b.    opendir DIR, $CUST20.F5OBEY.A*

               The mask is expanded and readdir will return an
               item from this list.

         c.    opendir DIR, $CUST20.FAOBEY.A

               same as b.

     The rule is this:  OPENDIR will take whatever you pass it and
     try to turn it into a template which is then passed to the
     FILE_FINDFIRST_ Guardian procedure call.  If you pass something
     that doesn't have any wild cards (as in example "a", above),
     OPENDIR will append a ".*" to the end of it.  OPENDIR will
     take "b" verbatum because it has wild cards in it.  Example "c"
     may look like a file name but OPENDIR needs to pass a template
     so it converts "c" into "b".  if "A" were really a file name
     OPENDIR will still work, but READDIR will return all of the
     files in FAOBEY that begin with the letter "A".

     NOTE:  the PERL run command in the TACL library will expand
     templates before running the Perl executable unless the
     template is surrounded by quotes.  For exmample, suppose
     the subvolume $D1.FOO had three files in it:  BAR, DRAT, & ZOT.
     And, further suppose you entered the following command (REMEMBER,
     YOU MUST RUN PERL VIA THE PERLMAC MACRO):

               PERL -W SCRIPT FOO.*

     The command that actually gets executed is:

               PERL -W SCRIPT BAR DRAT ZOT

     In particular, note that SCRIPT will never see the reference
     to "FOO.*".

     You can get a template passed to a PERL script by surrounding it
     with double quotes.  For example, if you wanted FOO.* to be
     seen by SCRIPT, you would enter the command like:

               PERL -W SCRIPT "FOO.*"

     SCRIPT can access this template as $ARGV[0].


3.   SYSTEM works.  What you do with it is execute TACL commands.
     The C Runtime starts up a TACL the first time you use it and
     this TACL is yours and yours only.  This means you can do
     things like:

               system ('#push #out');
               system ('#set #out $s.#junk');
               system ('fileinfo $d1.junk.*');

     The fileinfo will generate a list of the files in $d1.junk to
     the spooler location mentioned.  Note the use of single quotes
     to prevent PERL from treating $s and $d1 as variables.

4.   CHDIR seems to work (see PERLL02.FIND).

5.   While(<>) seems to work as long as you don't try to pass it
     any templates (this is why PERL command line expands templates
     before running the PERL program).

6.   Command switches that seem to work:

         -w    will display warnings
         -h    will display help
         -V    will display configuration (not that it tells you much)
         -e    but be careful because the command line parsing isn't
               intutively obvious.  Here's an example, this doesn't work
               as you'd expect:

                   perl -e"$a=~1"; -e"print ""$a\n""";

               but this version of the same thing does:

                   perl -e"$a = ~1"; -e"print ""$a\n""";


7.   Requester/Server scripts.  Perl scripts can act as either servers
     or requesters.

     A Perl script acting as a server accepts messages on $RECEIVE,
     does something, and the replies.  A perl script acting as a
     requester, "prompts" a server for some work and accepts its reply
     all in a single read request (Guardian WRITEREAD).

     To "enable" reqeuster/server behavior, a script must open $RECEIVE
     or a process using "sysopen" with "MODE=3".

     The following is a simple server:

        sysopen (R, "\$RECEIVE", 3);
        while (defined sysread (R, $s, 200)){
             print "Request:  $s\n";
             $s = "Ok";
             syswrite (R, $s, length($s));
        }
        print "$!\n";

     It opens $RECEIVE with mode = 3.  Then until an error occurs
     (which isn't likely) the script reads $RECEIVE, prints what it
     received, and then responds with "Ok".  This script will run
     forever until you stop the PERL processor.

     IMPORTANT NOTE:  When you want Perl to execute a server script
     Perl must itself be running as a named process.  That is:

        TACL > perl/name $ptzzz/smplsvr

     This is so that requesters know where to send their messages.

     The following is a simple requester:

        sysopen (S, "\$PTZZZ", 3);
        $s = ">";
        sysread (S, $s, 200);
        print $s;

     This script opens a process named $PTZZZ (e.g. the Perl processor
     running the server script above).  It then sends a ">" as a prompt
     to the process, gets back it's response, prints the response and
     then terminates.  Note that when "mode = 3" "sysread" works like
     the COBOL verb:  READ WITH PROMPT with the contents of buffer
     containing the prompt and being replaced with the response.

     Perl scripts can also do "simplex" (i.e. one-way) output to
     processes and can do "simplex" (i.e. one-way) reads on $RECEIVE.
     In this case, you use SYSOPEN with mode = 0 (for read) or 1
     (for write).

     [ed note:  someday, when we're bored, we might try to implement
     PATHSENDS, but don't hold your breath].

8.   Perl can directly access the following Guardian system calls:

           Perl Call                    System Call
           ---------                    -----------
           GUARDEXT::aborttmf           ABORTTRANSACTION
           GUARDEXT::begintmf           BEGINTRANSACTION
           GUARDEXT::endtmf             ENDTRANSACTION
           GUARDEXT::control            CONTROL
           GUARDEXT::setmode            SETMODE
           GUARDEXT::position           POSITITION
           GUARDEXT::keypos             KEYPOSITIONX

      In every case the parameters and return values are as
      described in the Guardian Procedure Calls Manual.  The following
      script illustrates how to use the keypos routine to position
      within a KEYSEQUENCED file before reading.

        1       sysopen  (HTLOG, "\$CUST15.HHDATA.HTLOG", 0)
                         or die "Couldn't open HTLOG: $!\n";
        2       $fnum = fileno(HTLOG);
        3       $keyval = "9802230800";
        4       $keyspec = "\x00\x00";
        5       $len = length $keyval;
        6       $len = ($len << 8) | $len;
        7       $pmode = 0;
        8       $status = GUARDEXT::keypos($fnum, $keyval, $keyspec, $len,
                         $pmode);
        9       print "$status\n";
       10       sysread (HTLOG, $logrec, 300);
       11       print "$logrec\n";

      Line 1 opens an HTLOG file using sysopen (On our system an HTLOG file
             is a log file keyed by date/time).
      line 2 gets the file number for that file
      line 3 sets the date/time to start at
      line 4 sets the key to "primary key"
      line 5 & 6 sets up the length word (left half = righ half) as
        described in the Procedure calls manual.
      line 7 sets the positioning mode to approximate.
      line 8 does the keypos
      line 9 prints the status (1 = Okay, anything else is failure)
      line 10 reads the first record at or after the one that has the
        the date/time specified
      line 11 prints out the record.



STUFF THAT WON'T WORK
---------------------

This list isn't completely enumerated yet.  Please tell me if you try
something and it doesn't work.

In general, anything that appears to be a UNIX kind of command
like fork(), exec(), mkdir(), etc., won't work.

seek() Doesn't work.

PIPES don't work.

TCP/IP stuff doesn't work (although we could, in principle, make
them work).

File name globbing doesn't work (e.g. while(<FOO.*>)

File tests that ask questions about ownership, executability and
other OS dependent stuff don't work (see the discussion above
about file I/O for a list of the file tests that do work).

The @{<expression>} construct causes perl to crash.  I don't know why
yet.

You can redirect STDOUT and STDERR to a disk file inside a perl
perl program but once you do, you can't switch back.

Printing arrays directly does not give you the results that you'd expect.
For example if @a contains 3 elements: "EL1", "EL2", and "EL3".  Then
print @a generates "EL1EL2EL3" with maybe some garbage characters
interspersed.  In general when you print arrays, you should do it from
within a foreach loop.

Command line switches that don't work:

     -d  A bunch of errors suggesting that perl is doing very
         UNIXy kind of stuff

See below for details on the results from the suite of tests.


PERFORMANCE
-----------

Input seems acceptable.  I was able to load a 13,300 line file into a
variable in about 4 + or - 1 seconds using:

      undef $/;
      $d = <INFILE>;
      $/ = '\n';

I haven't done anything to optimize Output so it's a little slow.

Regular expression evaluation looks like it's about 25% to 50%
slower than on DOS.

Also, I've asked our operations folks to let me know when and if they
notice a system performance problem at the same time that Perl is running.
So far (after 6 months or so) they haven't said anything so, for the
moment, anyway, I'm assuming that the use of Perl on the system is not
causing any grief.  As you can guess, however, Perl, operating on a bunch
of stuff in memory is going to be compute bound.  You'll need to configure
your CMON accordingly.

If you notice anything else, let me know.


TEST SUITE RESULTS
------------------

The following summarizes the results of running the programs in
the /perl/t/... directories.

In general, they support my supposition that anything that perl does
internally works and only a few things that it does with the
outside world work.  It turns out, that Perl is crashing either
during compilation or execution of 17 of the many dozens of test.
It also turns out that many of the tests fail because of hard coded
UNIX syntax file names.  Sometimes (I only tried a few) by modifying
the names to GUARDIAN syntax I could get the scripts to run.  If
I had to modify hard coded file names and, after doing so, the script
ran, I called it successful.

The other thing the test suite does, a lot, is add a hard coded
library reference to @INC.  I had to eliminate those assignments
to get many of the scripts to run.  This suggests that any scripts
that depend on being able to look in multiple places for a file
will fail.

The following is the "directory" listing for all of the test scripts.
You'll notice some of the names have been munged to 8 characters:


perl5.004/t/README
perl5.004/t/TEST
perl5.004/t/base/cond.t
perl5.004/t/base/if.t
perl5.004/t/base/lex.t
perl5.004/t/base/pat.t
perl5.004/t/base/term.t
perl5.004/t/cmd/elsif.t
perl5.004/t/cmd/for.t
perl5.004/t/cmd/mod.t
perl5.004/t/cmd/subval.t
perl5.004/t/cmd/switch.t
perl5.004/t/cmd/while.t
perl5.004/t/comp/cmdopt.t
perl5.004/t/comp/colon.t
perl5.004/t/comp/cpp.aux
perl5.004/t/comp/cpp.t
perl5.004/t/comp/decl.t
perl5.004/t/comp/multiline.t
perl5.004/t/comp/package.t
perl5.004/t/comp/proto.t
perl5.004/t/comp/redef.t
perl5.004/t/comp/script.t
perl5.004/t/comp/term.t
perl5.004/t/comp/use.t
perl5.004/t/harness
perl5.004/t/io/argv.t
perl5.004/t/io/dup.t
perl5.004/t/io/fs.t
perl5.004/t/io/inplace.t
perl5.004/t/io/pipe.t
perl5.004/t/io/print.t
perl5.004/t/io/read.t
perl5.004/t/io/tell.t
perl5.004/t/lib/abbrev.t
perl5.004/t/lib/anydbm.t
perl5.004/t/lib/autoloader.t
perl5.004/t/lib/basename.t
perl5.004/t/lib/bigint.t
perl5.004/t/lib/bigintpm.t
perl5.004/t/lib/checktree.t
perl5.004/t/lib/complex.t
perl5.004/t/lib/db-btree.t
perl5.004/t/lib/db-hash.t
perl5.004/t/lib/db-recno.t
perl5.004/t/lib/dirhand.t
perl5.004/t/lib/english.t
perl5.004/t/lib/env.t
perl5.004/t/lib/filecache.t
perl5.004/t/lib/filecopy.t
perl5.004/t/lib/filefind.t
perl5.004/t/lib/filehand.t
perl5.004/t/lib/filepath.t
perl5.004/t/lib/findbin.t
perl5.004/t/lib/gdbm.t
perl5.004/t/lib/getopt.t
perl5.004/t/lib/hostname.t
perl5.004/t/lib/io_dup.t
perl5.004/t/lib/io_pipe.t
perl5.004/t/lib/io_sel.t
perl5.004/t/lib/io_sock.t
perl5.004/t/lib/io_taint.t
perl5.004/t/lib/io_tell.t
perl5.004/t/lib/io_udp.t
perl5.004/t/lib/io_xs.t
perl5.004/t/lib/ndbm.t
perl5.004/t/lib/odbm.t
perl5.004/t/lib/opcode.t
perl5.004/t/lib/open2.t
perl5.004/t/lib/open3.t
perl5.004/t/lib/ops.t
perl5.004/t/lib/parsewords.t
perl5.004/t/lib/posix.t
perl5.004/t/lib/safe1.t
perl5.004/t/lib/safe2.t
perl5.004/t/lib/sdbm.t
perl5.004/t/lib/searchdict.t
perl5.004/t/lib/selectsaver.t
perl5.004/t/lib/socket.t
perl5.004/t/lib/soundex.t
perl5.004/t/lib/symbol.t
perl5.004/t/lib/texttabs.t
perl5.004/t/lib/textwrap.t
perl5.004/t/lib/timelocal.t
perl5.004/t/lib/trig.t
perl5.004/t/op/append.t
perl5.004/t/op/arith.t
perl5.004/t/op/array.t
perl5.004/t/op/assignwarn.t
perl5.004/t/op/auto.t
perl5.004/t/op/bop.t
perl5.004/t/op/chop.t
perl5.004/t/op/closure.t
perl5.004/t/op/cmp.t
perl5.004/t/op/cond.t
perl5.004/t/op/delete.t
perl5.004/t/op/do.t
perl5.004/t/op/each.t
perl5.004/t/op/eval.t
perl5.004/t/op/exec.t
perl5.004/t/op/exp.t
perl5.004/t/op/flip.t
perl5.004/t/op/fork.t
perl5.004/t/op/glob.t
perl5.004/t/op/goto.t
perl5.004/t/op/groups.t
perl5.004/t/op/gv.t
perl5.004/t/op/inc.t
perl5.004/t/op/index.t
perl5.004/t/op/int.t
perl5.004/t/op/join.t
perl5.004/t/op/list.t
perl5.004/t/op/local.t
perl5.004/t/op/magic.t
perl5.004/t/op/method.t
perl5.004/t/op/misc.t
perl5.004/t/op/mkdir.t
perl5.004/t/op/my.t
perl5.004/t/op/oct.t
perl5.004/t/op/ord.t
perl5.004/t/op/pack.t
perl5.004/t/op/pat.t
perl5.004/t/op/push.t
perl5.004/t/op/quotemeta.t
perl5.004/t/op/rand.t
perl5.004/t/op/range.t
perl5.004/t/op/re_tests
perl5.004/t/op/read.t
perl5.004/t/op/readdir.t
perl5.004/t/op/recurse.t
perl5.004/t/op/ref.t
perl5.004/t/op/regexp.t
perl5.004/t/op/repeat.t
perl5.004/t/op/runlevel.t
perl5.004/t/op/sleep.t
perl5.004/t/op/sort.t
perl5.004/t/op/split.t
perl5.004/t/op/sprintf.t
perl5.004/t/op/stat.t
perl5.004/t/op/study.t
perl5.004/t/op/subst.t
perl5.004/t/op/substr.t
perl5.004/t/op/sysio.t
perl5.004/t/op/taint.t
perl5.004/t/op/tie.t
perl5.004/t/op/time.t
perl5.004/t/op/undef.t
perl5.004/t/op/universal.t
perl5.004/t/op/unshift.t
perl5.004/t/op/vec.t
perl5.004/t/op/write.t
perl5.004/t/pragma/constant.t
perl5.004/t/pragma/locale.t
perl5.004/t/pragma/overload.t
perl5.004/t/pragma/strict-refs
perl5.004/t/pragma/strict-subs
perl5.004/t/pragma/strict-vars
perl5.004/t/pragma/strict.t
perl5.004/t/pragma/subs.t
perl5.004/t/pragma/warn-1global
perl5.004/t/pragma/warning.t


The following is a summary of the results of each of the above tests
An "*" means there is additional information available following the
summary.


/perl/t/base - PERLT01

     cond.t      passed
     if.t        passed
    *lex.t       passed (Fixed 15SEP1997 - see note #4)
     pat.t       passed
     term.t      Failed (too much dependence on UNIX)

                                                                               .
/perl/t/cmd  - PERLT02

     elsif.t     passed
     for.t       passed
     mod.t       passed
     subval.t    passed
     while.t     passed


/perl/t/comp - PERLT03

     cmdopt.t    passed
     colon.t     passed
     cppaux.t    Failed (Can't emulate -P on #! line at perlt03.cppaux line 1)
     decl.t      passed
     multili.t   Failed (backtick)
     package.t   passed
     proto.t     passed
     redef.t     passed
     script.t    Failed (backtick)
     term.t      passed
     use.t       Failed (eval "use lib 1.01" & similar statements)

/perl/t/io   -  PERLT04

     argv.t      Failed (backtick)
     dup.t       Failed (open '>&xxx')
     fs.t        Failed (backtick, link, chmod, stat, rmdir, mkdir)
     inplace.t   Failed (backtick, inplace edits)
     pipe.t      Failed (fork not implemented)
     read.t      Failed (open '+>xxx' and seek)
     tell.t      Failed (seek, maybe tell)

/perl/t/lib   - PERLT05

     abbrev.t    passed
     anydbm.t    Failed (DBM package not installed)
     autoloa.t   Failed (mkdir required, might work otherwise)
     basenam.t   passed
     bigintp.t   Failed (40 of 287 tests failed)
     checktr.t   Failed (depends on UNIX or UNIX like file system)
    *complex.t   passed (fixed 19SEP1997, see note #6)
     dbbtree.t   Failed (ext/ not installed)
     dbhash.t    Failed (ext/ not installed)
     dbrecno.t   Failed (ext/ not installed)
     dirhand.t   Failed (object creation)
     filepat.t   Failed (mkdir not supported)
     findbin.t   Failed (Cannot chdir to $D1.ADLERPT/ -- file name spec)
     gdbm.t      Failed (ext/ not installed)
    *getopt.t    passed (fixed 24SEP1997, see note #7)
     hostnam.t   Failed (hostname not implemented)
     iodup.t     Failed (/ext not installed)
     iopipe.t    Failed (/ext not installed)
     iosel.t     Failed (/ext not installed)
     iosock.t    Failed (/ext not installed)
     iotaint.t   Failed (/ext not installed)
     iotell.t    Failed (/ext not installed)
     ioudp.t     Failed (/ext not installed)
     ioxs.t      Failed (/ext not installed)
     ndbm.t      Failed (/ext not installed)
     odbm.t      Failed (/ext not installed)
     opcode.t    Failed (/ext not installed)
     open2.t     Failed (fork not implemented, /ext not installed)
     open3.t     Failed (fork not implemented, /ext not installed)
     ops.t       Failed (/ext not installed)
     parsewo.t   Failed (thinks subroutine name is a script name)
     posix.t     Failed (/ext not installed)
     safe1.t     Failed (/ext not installed)
     safe2.t     Failed (/ext not installed)
     sdbm.t      Failed (/ext not installed)
     searchd.t   Failed (tries to create file w/illegal Guardian name)
     selects.t   Failed (tries to create file w/illegal Guardian name)
     socket.t    Failed (TCP/IP not implemented)
     soundex.t   passed
     symbol.t    passed
     texttab.t   passed
     textwra.t   passed
     timeloc.t   passed (sort of:  there's a wierd library deal going on)
    *trig.t      passed (Fixed 19SEP1997 see note #6)

/perl/t/op/*.* - PERLT06

     append.t    passed
     arith.t     passed
     array.t     passed (Fixed 19SEP1997 - see note #6)
     assignw.t   passed
     auto.t      passed
     bop.t       passed (Fixed 19SEP1997 - see note #6)
     chop.t      passed
     closure.t   Failed (closeure.t looks like it goes into a loop)
     cmp.t       passed
     cond.t      passed
     delete.t    passed
     do.t        passed
     each.t      passed
     eval.t      passed
     exec.t      Failed (exec not supported)
     exp.t       passed
     flip.t      passed
     fork.t      Failed (fork not supported)
     glob.t      Failed (file globbing not supported)
     goto.t      Failed (backtick not supported)
     groups.t    Failed (Security stuff not implemented)
     gv.t        passed
     inc.t       passed (Fixed 19SEP1997 - see note #6)
     index.t     passed
     int.t       passed
     join.t      passed
     list.t      passed
     local.t     passed (Fixed 19SEP1997 - see note #6)
     magic.t     Failed (Use of uninitialized value at perlt06.magict line 28)
     method.t    passed (this is odd: OO stuff had a problem above)
     misc.t      Failed (probably, but I'm not sure what real result is)
     mkdir.t     Failed (mkdir not supported)
     my.t        passed (Fixed 19SEP1997 - see note #6)
     oct.t       passed (fixed 18SEP1997 - was crashing during compilation)
     ord.t       passed
     pack.t      Failed (some tests failed)
     pat.t       passed
     push.t      passed (Fixed 19SEP1997 - see note #6)
     quotme.t    passed
     rand.t      passed (it seems, anyway)
     range.t     passed
     readdir.t   Failed (19SEP1997 - 1 passed, 2 failed, 3 no output)
     read.t      Failed (1 test of 4 failed)
     recurse.t   Failed (some functions never terminate in my lifetime)
     ref.t       passed
     regexp.t    Failed (Reg exp work, so I don't know what's going on here)
     repeat.t    passed
     runleve.t   Failed (tests failed)
     sleep.t     Failed (sleep returned incorrect value)
     sort.t      passed (Fixed 19SEP1997 - see note #6)
     split.t     passed
     sprintf.t   passed
     stat.t      Failed (stat not fully supported)
     study.t     passed
     substr.t    passed
     subst.t     Failed (3 out of 60 tests failed)
     sysio.t     Failed (50% of the tests failed)
     taint.t     Failed (Too late for "-T" option at perlt06.taintt line 1.)
     tie.t       Failed (tests failed)
     time.t      Failed (times not implemented at perlt06.timet line 8.)
     undef.t     passed
     univers.t   passed
     unshift.t   passed
     vec.t       passed
     write.t     Failed (backtick not implemented)

/perl/t/pragma/*.* - PERLT07

     constan.t   passed (Fixed 19SEP1997 - see note #6)
     locale.t    Failed (Too late for "-T" option at perlt07.localet line 1.)
     overloa.t   Failed (4 out of 115 tests failed)
     strict.t    Failed (no output)
     subs.t      Failed (Tests failed)
     warning.t   Failed (no output)



NOTES on tests:

1.  /perl/t/base/lex.t                            (01SEP1997)

    This failed when PERL tried parse a 10 digit number.  The crash
    resulted from an arithmetic overflow.  Evidently, other C runtimes
    will allow this to occur without any disasters.

    So, if you get an arithmetic overflow with any of your scripts, it's
    probably because a value has exceeded the largest value possible for
    a 32 bit integer.  For example, this will fail:

            $foo = int ($bar);      # where $bar is a float > 2147483647.0


2.  /perl/t/lib/complex.t                               (03SEP1997)
    /perl/t/lib/trig.t

    Perl crashes during compilation when it tries to compile one or another
    of the following:

            use constant pi => 4 * atan2(1, 1);
            use constant log10inv => 1 / log(10);

    The failure is an arithmetic overflow in sv_upgrade.  The double

            4294967293.

    is being cast into a 32 bit integer which C can't do because the
    maximum integer value is 2147483647.  We don't know where this
    number comes from.

    This means that you can't use the trig or complex number functions
    from the library.

3.  /perl/t/lib/getopt.t                              (03SEP1997)

    This is similar to #2 above.  The crash is an arithmetic overflow
    during a cast from double to int.  The location in the code is the
    exact same place as #2 and the number that is being dealt with is
    almost the same:

            4294965757.


    instead of:

            4294967293.

    Both of these numbers, when cast as (long long) end up looking like
    negative 32 bit integers.  In the first case it's FFFFF9FD or -1539
    and in the second it looks like FFFFFFFD or -3.

    This suggests that some arithmetic is going wrong somewhere or maybe
    an ABS function.  Too soon to speculate.


4.  More on #2 and #3 above:                           (15SEP1997)

    Here's a reliable case that causes the exact same crash

          # t23 - complement test
          #
          #
          $b = 17;
          $b &= ~1;
          print "$a, $b\n";

    Evidently, Perl is treating ~1 as ULONG_MAX - 1 instead of -2.  And
    because ULONG_MAX is > LONG_MAX Perl converts this thing to a double.
    Well that's okay until it has to convert it back to a long.  That's
    when we get into trouble.  We can't convert directly from double to
    long.  We have to convert from double to unsigned long to long.

    This has been fixed by changing the macros:  I_32 and I_V as follows:

         #ifdef CASTI32
         #   ifndef _GUARDIAN_TARGET
         #      define I_32(what) ((I32)(what))
         #      define I_V(what) ((IV)(what))
         #   else
         #      define I_32(what)   ((I32)(UV)(what))
         #      define I_V(what) ((IV)(UV)(what))
         #   endif
         #else
         #   etc. etc.

    That is, instead of going directly from double to long we cast
    to unsigned long first.

5.  /perl/t/lib/complex.t                         (18SEP1997)
    /perl/t/lib/trig.t
    /perl/t/lib/getopt.t

    See note #4 before reading this one.

    After fixing the problem with "~" (complement), Perl is not crashing
    during execution with the following error in both tests.

      \PHAMIS.$:5:242:411332716 - Invalid function parameter
      \PHAMIS.$:5:242:411332716 - From Perl_pp_padav + %246, UC.01


6.  /perl/t/op/array.t                            (18SEP1997)

    See note #3 before reading this one.

    After fixing the arithmetic overflow problem, we are now able to
    start executing the test.  But now, Perl crashes during execution.

            *** Run-time Error 040 ***
            Invalid function parameter
            From Perl_pp_rv2av + %1052, UC.02
            Perl_runops + %143, UC.02
            perl_run + %546, UC.00
            main + %57, UC.00
            _MAIN + %33, UC.00

    There are two things to pay attention to here:  first, this error is
    occured in the following bit of script:

            @foo = ();
            $r = join(',', $#foo, @foo);

    And went away when I added:

            @foo = (1, 2, 3);

    as the first statement.  Then the test passed completely.  Then,
    secondly, when I removed the first line from the script, it worked
    perfectly.

    Go figure.

    In the debugger the problem was occuring in the following
    C statement:

             Copy(AvARRAY(av), SP+1, maxarg, SV*);

    which invokes the macro:

             (void)memcpy((char*)(d),(char*)(s), (n) * sizeof(t))

    AvARRAY(sv) is equal to 0, which is why memcpy is complaining.

    When I tried this same code in the WIN32 version, there wasn't any
    problem.

    So, here's what I suspect:

    Perl doesn't know that the array it's moving is empty and it doesn't
    know that the destination doesn't really exist yet.  So it happily
    goes off to move 0 bytes into outerspace.  Evidently in the
    Guardian C compiler if outerspace is NULL then we get a run-time
    error.

    I think the fix is to change the Copy MACRO so that if the length
    is zero, it doesn't try to execute memcpy.

    Postscript to #6:  I implmented the change to the copy MACRO and
    that eliminated every single one of the crash.  A new symptom
    showed up that is related to how I tortered the GETS routine
    into performing.


7.  /perl/t/lib/getopt.t                          (19SEP1997)

    The test ran to completion, but when the script tried to close a
    file:

              *** Run-time Error 034 ***
              Released space not allocated
              From GUARDIAN_FCLOSE + %21, UC.03
              PerlIO_close + %5, UC.01
              Perl_io_close + %175, UC.00
              Perl_do_close + %176, UC.00
              Perl_pp_close + %63, UC.02
              Perl_runops + %143, UC.02
              perl_run + %546, UC.00
              main + %57, UC.00
              _MAIN + %33, UC.00

    Perl is trying to close STDERR twice.  It's the second time through
    that is causing the error.  Oddly, the the first time STDERR is
    closed is during execution of pp_open.

    The way we redirect STDERR in GUARDIAN C is to use an ASSIGN.  I
    think what's going on might have something to do with the special
    status of STDERR in UNIX.

    (21SEP1997)

    The runtime library routine, fileno, returns 0, 1, 2 for stdin, stdout
    and stderr respectively.  these aren't good numbers.  So, when perl
    starts messing around with STDERR, it tries to do some stuff with
    file number 2 and gets into trouble.

    MAXSYSFD is a variable that controls (I think) which numbers are
    defined as system files (i.e. stdin, stdout and sterr).

    So, if we are to support the following construct:

         open STDERR, ">foo" or die "stderr: $!\n";
         print STDERR "this is an error?\n";
         close STDERR;

    and have something actually show up in foo, we're going to have to
    allow open, close, etc. to work on these wierd files.

    (24SEP1997)

    Turns out the WIN32 version of perl doesn't quit work here either.
    We'll make the GUARDIAN version work like WIN32.

    Once you open STDERR (or STDOUT) with a different file, you can't
    switch back to where STDERR was originally pointing.

    So the above script will work but if you then try to print to
    STDERR after the close, you'll get a "write on unopened file"
    warning.


COMPILATION
-----------

Unless you start messing the source code or if the executable provided
in this distribution doesn't work on your system, you shouldn't have
to re-compile the source.  But that's the programmer's kiss of death so
here is what you do if you have to recompile:

A) Complete Recompilation

There is a cheesy little MAKE macro that will recompile and rebind Perl.
To use it:

     1.  VOLUME PERLMNT
     2.  RUN MAKE MKPERL
     3.  GO TO COFFEE (I live in Seattle so that's obligatory)

It will do what you'd expect a cheesy little MAKE macro to do and either
generates an executable or quits when something goes wrong.

The executable that gets generated is called PERLUX (meaning PERL
unaccellerated).  Unless you're using a NATIVE compiler you should
probably accellerate the code:

     > AXCEL PERLUX PERLO

If you are using a NATIVE compiler or if you don't want to run an
accellerated version, all you have to do is rename the file.

     > RENAME PERLUX,PERLO

In any case, the executable has to be named:  PERLO because that's what
the TACL wrapper wants (and whatever TACL wants, TACL gets :)

B)  Partial Recompilation

In some cases, after you know how the pieces fit together, you can recompile
individual files and just rebind (even though MAKE would recompile more
or even the whole thing).

There is a macro called COMP that compiles one source file.

     > VOLUME PERLMNT
     > RUN COMP <file>

where <file> is the name of the source code file without the C suffix.

Then when your ready to rebind everything you can do:

     > RUN BIND

This does the same bind that the MAKE does.

Again, partial recompilations are not recommended unless you kind of
know what you're doing.  Particularly if you're making header file
changes.


TACL SUPPORT
------------

As alluded to above, in many places, we've added a bunch of TACL to
make the use of Perl on Guardian a little more natural than it would
otherwise be.

Aside from the source code maintanence macros mentioned in the previous
section the following TACL macros and libraries are distributed:

     PERLLOCL

     This is a file which creates all of the defines necessary for Perl
     to find its libraries.  It uses the TACL builtins ("#" commands)
     instead of the ADD DEFINE commands and, as a result, it is very
     fast (you can't tell that it exeutes).

     PERLLOCL is executed under two different circumstances:

     1)  when the timestamp changes (i.e. when its been modified)
     2)  when a "signal" define is missing (i.e. when the defines have
         never been loaded).


     PERLMAC

     This is a TACL library containing, among other things, the PERL
     command that runs the PERLO executable.  It is responsible for
     keeping tabs on the current state of PERLLOCL and, if present
     PERLCSTM (which is your own personal PERL wrapper).

     When PERLMAC has been loaded, and you enter, for example:

          > perl foo bar > outfile

     the routines in PERLMAC build a new set of commands:

          > SINK [#PURGE OUTFILE]
          > PERL/OUT OUTFILE/FOO BAR

     As we mentioned previously, these routines will also expand file name
     template parameters into a space separated list.


     PERL

     This is a "bootstrap" macro.  It's only job in life is to load PERLMAC
     and then re-run the command you used.  So, if your #PMSEARCHLIST
     inclues the volume and subvolume that contains PERLMAC (and PERLO) the
     PERL macro will first load PERLMAC and then re-execute exactly the
     same thing you typed.  Once the PERLMAC library has been loaded, the
     only way you can execute this macro again is by fully qualifying it
     because "PERL" is now a variable and variables take precendence over
     file names.


LICENSING
---------

Please read the LICENSE file in this subvol.  I have attempted to
be complient with all provisions.  If I did not it was through my
inability to deal with the legalese and not through any malice.

1.  All of the source code that makes up this port is contained in
    the PERLSRC sub-volume.

2.  If you want a copy of this source code, just ask via the phone numbers
    or email addresses listed above.

3.  NO WARRENTY:  QUOTED FROM THE LICENSE.

  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
REPAIR OR CORRECTION.

  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
POSSIBILITY OF SUCH DAMAGES.



INSTALL INSTRUCTIONS
--------------------

The following install instructions assume you are installing from the
ZIP file and it is on your PC.  Also note that I don't talk about security
here at all.  Once the Perl distribution is on the Tandem you'll need
to secure the files so that only authorized people can access them.

The archiver/de-archiver referenced in the following discussion is a
couple of programs we wrote to be able to package a bunch of stuff
together and treat it as a single file.  The only piece you'll need
is the de-archiver program but the rest is included in case you
stumble across a software error that I didn't catch.

Step 1:  Expand the ZIP file (using PKUNZIP or WINZIP or whatever).

     PKUNZIP gperl.zip

What you'll end up with are the following files (Codes listed so you
can do the FUP ALTER commands):

     File        Code    What
     ---------   ----    -------------------------------------
     ARCHC       101     The source to the archiver program
     ARCHDDL     101     The DDL for the archive file headers
     ARCHDDLH    101     The header file created from the ARCHDDL
     ARCHH       101     The archiver/dearchiver header file
     ARCHHLP     101     The help file for archiver/decarchiver
     ARCHO       100     The archiver executable (code 100)
     DARCHC      101     The source to the de-archiver program
     DARCHO      100     The de-archiver executable (code 100)
     PERLARCH    180     The archive file containing Perl for Guardian
     PERLINP     101     The input file used to archive Perl for Guardian

Step 2:  Upload to Tandem.

Upload all of the files IN BINARY!.  The only ones you actually need
are PERLARCH and DARCHO (the archive file and the de-archiver) but it's
probably easier to just do the whole shootin' match.

All of the files in the zip file were downloaded to my PC in "binary".
Thus, they should all be uploaded in binary.  Caution:  PERLARCH is
about 10 megabytes.


Step 3:  FUP ALTER file codes.

You need to do this because all files were originally downloaded in Binary.

DARCHO and ARCHO are executables (CODE 100).

PERLARCH is a CODE 180 ("C" File)

All of the rest are CODE 101 files (Edit).


Step 4:  De-archive the perl files.

Take a look at the ARCHHLP file just to make sure you know what's going
on.  Here's the command:

     run darcho -cv<your disk> perlarch

what's supposed to happen is all of the files in the archive file will
get writen out to:

     <your disk>.perl*.*

So for example, suppose you were installing on $disk1.  You would enter
the command:

     run darcho -cv$disk1 perlarch

The de-archiver will print out messages saying that it's dearchiving
stuff.  If any errors occur, the de-archiver will stop.  If there
are any files the dearchiver is about to overwrite it will prompt you
first.  The best thing to do is to answer "N" to the question and then
figure out what's going on.

NOTE:  PERL, ARCHO, and DARCHO were all compiled here on a D38 OS using
D30 C and Binder.  You may need to recompile if your environment is
earlier than this.


Step 5:  Run the INSTALL macro.

Once you get all of the files that belong to PERL onto the disk, you
need to run the INSTALL macro.

The volume and prefix are hard coded in a couple of places.  The
INSTALL macro figures out what the volume and prefix is and fixes up
those places where it's been hard coded.

Don't freak-out.  The hard coding is not any of the actual PERL software.
We hard code the volume and prefix in the PERLMAC TACL library which has
to know where everything is and can't figure it out on the fly (because
it's a library) and we also store the volume and prefix in a file called

    PERLPFIX

This file is read by PERLLOCL to figure out where all of the PERL library
scripts are stored (see the section above on libraries).

To run the INSTALL macro, make sure you're logged on as someone who can
modify the files in the main PERL subvolume (where the executable is).
Then from whereever you happen to be enter at the TACL prompt:

    RUN <vol>.<prefix>.INSTALL

Answer the question (Continue?  Y/N) and that's it.


ADDITIONAL INSTALLATION NOTES:

PERL must physically reside on a single VOLUME (you can always fuss with
the files if you don't want this to be true, but we recommend you don't
mess around with anything until you've had some experience with this port).

The subvolume names PERL uses are all prefixed with a string 5 chracters
or less.  For purposes of this explanation we will assume you are installing
PERL on $SYSTEM and you are using the suggested prefix of "PERL".

PERL consists of the following subvolumes:

    $SYSTEM.PERL
    $SYSTEM.PERLL01
    $SYSTEM.PERLL02
    $SYSTEM.PERLL03
    $SYSTEM.PERLL04
    $SYSTEM.PERLL05
    $SYSTEM.PERLL06
    $SYSTEM.PERLL07
    $SYSTEM.PERLL08
    $SYSTEM.PERLL09
    $SYSTEM.PERLMNT
    $SYSTEM.PERLSRC
    $SYSTEM.PERLT01
    $SYSTEM.PERLT02
    $SYSTEM.PERLT03
    $SYSTEM.PERLT04
    $SYSTEM.PERLT05
    $SYSTEM.PERLT06
    $SYSTEM.PERLT07

Again, the volume you choose may be different as might be the prefix.



README DOCUMENT CHANGE HISTORY
------------------------------

Date         Who    What
---------    ---    ---------------------------------------------------
27Jan1998    CDA    Added info about ARRAYS not printing directly via
                    print @array;
30Jan1998    CDA    It is possible to read Type U files files and to
                    ask Perl whether a file is an edit file or not
                    <see below for a change>
08Feb1998    CDA    It is no longer possible for a script to tell
                    whether a file is an EDIT file or an UNSTRUCTURED
                    file.  It doesn't need to because both kinds of files
                    are treated the same way:  as "line oriented".
                    It is now possible to read and write ENSCRIBE files.
                    A script can ask weather the file is an Enscribe
                    file or not.  Perl can read any kind of
                    unstructured file but can write to only ODDUNSTR
                    files.
24Feb1998    CDA    Perl scripts can be written as servers or requesters.
                    Perl scripts have access to the following Guardian
                    routines:  ABORTTRANSACTION, BEGINTRANSACTION,
                    ENDTRANSACTION, KEYPOSITION, POSITION, CONTROL AND
                    SETMODE.
24Mar1998    FLC    No longer need to load perl.perlmac prior to
                    running perl.  Perlmac will be loaded via the PERL
                    bootstrap macro if it had not already been loaded
                    via a previous PERL command in the session.  The
                    PERL.PERL 100 file has been renamed to
                    PERL.PERLO.
10Apr1998    CDA    Fixed it up for the upload to CPAN.




