*********************************************************************** * 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/.PERLMAC where is volume and subvolume where the Perl executeable file is. If you set up your #PMSEARCHLIST to include 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 ]] [#if [#defineadd =PERL_PM]] where: is a real Tandem file name (you probably should keep all of your Perl library scripts in a single subvol). is the unqualified file name of . note: the "=PERL_" prefix and the "PM" suffix is required. And to reference this library script in a Perl program, you do this: use ; 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 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 = ; 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 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, 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