Spires allows system variables in any commands that are parsed by a / or are contained in the following commands:
IF, LET, WHILE, UNTIL, EVAL, SHOW EVAL
UPROC of USERPROC and Formats are another place where variables can occur. The same basic set of commands is involved, with SHOW EVAL replaced by SET VALUE.
System variables are recognized by their starting $ character, followed by a name or a name in apostrophies. For example:
if $cap($cginame) = 'CGI-BIN' then /* $cginame /find name $select let myvar = $date || ' ' || $time /wdse x$'date'd.$'time't
Note: in the wdse above, the output might appear as: x11/02/05d.12:15:25t
The nature of each $variable is determined by where the variable's name is found in the element-list of the .$1VAR record-type of the $DATA file. In other words, variables are organized into structures within that record-type, and which structure they are in determines how they are obtained, and usually what 'type' they return. In the list below, the 'type' is given first, then possibly a brief description, and then an example.
Record .$1VAR of GG.SPI.DATA $01 FLAG (0=true), $NOECHO $02 FLAG (1=true), $ECHO $03 INT (2-byte), $LENGTH $04 STRING, $SELECT $05 STRING, $ASK $06 LINE, $DELTA $07 CHAR, $ACCT $08 Variable type - dynamically determined, $DATE $09 INT, Formats, $ULEN $10 STRING, Formats, $UVAL $11 FLAG, Formats, $FREC $12 FLAG, Formats, $VIAPTR $13 FLAG, Formats, $FLUSH $14 FLAG, Formats, $CHANGED $15 INT (1-byte), $FORTYPE $16 STRING, $FORMAT $17 FLAG (byte), $ELSE $18 FLAG (bit), $DEBUG $19 STRING, USERPROC, $VELEM $20 INT (4-byte), $RESULT $21 STRING, Site Dependent, $MACHINE $22 HEX, $GETXPATH $23 STRING, Prism, $PRISMID $24 STRING, $PROGRAM
Type CHAR is a fixed-length STRING, and may be returned with trailing blanks. Conversion to STRING will delete those blanks. Except for $08, all variables declared in a particular structure are stored in the same manner within the system, and return the same type. But $08 can return different types because all of these variables are dynamically constructed. The Structure/Element number is what identifies each variable, and determines how it should be retrieved.
As you can see above, there are several INT, STRING and FLAG groups. That's because each group contains variables all stored the same way. For example, STRING variables can be stored as follows:
1. INTEGER pointer -> one-byte length, followed by the string. 2. INTEGER pointer -> halfword length, followed by the string. 3. One-byte length, and INTEGER pointer -> string. 4. Halfword length, and INTEGER pointer -> string.
In all of the examples above, anything before the arrow (->) is within a DSECT at a known location. A pointer can point anywhere.
You can see a complete list of system variables by doing the following:
-> select system variables -> show elements
Yes, it is that simple. The SYSTEM VARIABLES subfile is .$1VAR of $DATA. By the way, record-names that begin with a dot are pseudo-record-types. If any records are added to such record-types, they exist in the DEFQ only.
SPIRES Variables are implemented as follows. Start by determining how the variable will be set, where that setting will be stored, and how it will be retrieved. You have to SELECT FILEDEF, TRANSFER $DATA, and add your new $variable name at the end of one of the structures in .$1VAR's record definition. You can add alternate spelling for your variable using the ALIAS statement. You then update the file definition and recompile it, and then dump characteristics:
-> master -> select filedef -> transfer $DATA -> ..edit <--- you add your variable name as described below. -> update -> /recompile $key -> select system variables -> dump char to VARS.OBJ rep entry VARSTABS build
It is simplest to implement Prism variables ($23 structure). They can be set using their ELEM name, which must appear in the PRISMVAR table in COMSPI.TXT as a one-byte length followed by a quoted name, like "CGINAME" shown below.
% diff old.DATA.FDEF DATA.FDEF 424a425 ; $23 appendage > ELEM = CGINAME;
% diff old.COMSPI.TXT COMSPI.TXT 1226c1226 ; PRISMLEN change < 64,36,0,0,0,0,0,0); --- > 64,36,16,0,0,0,0,0); 1241c1241 ; PRISMNAM change < 0); |-- Add here & in $DATA ST23 --| --- > 7, "CGINAME", 0); |-- Add here & in $DATA ST23 --|
PRISMLEN contains the maximum length of the STRING, and PRISMNAM has the variable name's length followed by the quoted variable's name. You can set such variables with a SET command in SPIRES, or with an EVAL $SET(...) function call. You can reference any $variable by its ELEM or ALIAS name.
-> set cginame = 'CGI-BIN' -> eval $set(cginame, $syseval('ENV:REQUEST_URI'))
SET only allows a simple string, while EVAL $SET allows an expression.
The next simplest to define are the $08 variables that are dynamically constructed. You should look at PARSEM.TXT near the 'ST8:' label to see what has been done already. Examples of dynamically constructed variables include $DATE, $TIME, $UDATE, $UTIME, etc.
FLAG variables are the next simplest, if there already is some BYTE somewhere with an available bit, and you need a FLAG variable. You can use $18 and modify V18 in PARSEM.TXT giving the address of the byte and what bit position to test. Again, it is best to examine other V18 bit-flags to see where they are located and how they are set. You may have to make SPIRES.BNF changes to define the commands for re/setting your bit-flag.
Almost anything else will require extensive modification and recompilation. Adding anything to R11DSECT.TXT to hold new items has a ripple effect. Both R11DSECT.TXT and "r11dsect.h" must be kept in sync, and that's very difficult to accomplish because a new SPIRES needs a new Emulator, at the same time. All source code that refers to either R11DSECT.TXT (pl360) or "r11dsect.h" (c) must be recompiled and relinked. Unfortunately, old TRAP-versions of SPIRES/SPIBILD won't work with a new Emulator, or vice-versa.
GETVAR in PARSEM.TXT is where $variables are retrieved. Variables can return different types. There are INT, HEX, PACK, FLAG, REAL, LINE, CHAR and STRING types. CHAR is a fixed-length string, which may be blank padded. There are special types infrequently used. They involve TRIPLES, and $ANY is an example.
Variables always return a 'type' in R3, an 'address' or 'value' in R2, and a 'length' in R1. INT and LINE types return a 'value' in R2, not an 'address'. STRING, CHAR, HEX, PACK and FLAG return an 'address' in R2. There are no REAL $variables, but if there were, they would return a REAL value in F01, and R2 would be meaningless.
SPIRES Variables are installed into SPIRES/SPIBILD as follows. You've already created the VARS.OBJ when you dumped characteristics from .$1VAR of the $DATA file. If you created your variable in COMSPI.TXT as a Prism Variable, then you must recompile both SPIRES and SPIBILD to get object decks. If you created your variable within PARSEM.TXT, then you must compile PARSEM to get all remaining object decks.
In SPIRES, you should do the following:
-> set xeq spiproto -> ..compall pl360.parsem -> ..compall pl360.spires -> ..compall pl360.spibild
You must now move your VARS.OBJ, from where it was stored when it was created by the dump char command, into the "obj" directory used for linking new versions of SPIRES/SPIBILD. An old version of VARS.OBJ should already be in your spisrc/obj directory. Your new VARS.OBJ should be in the spisys directory, the same place all GG.SPI files are located. Replace the old with the new as follows (Mac OSX example):
$ cd $ mv spisys/VARS.OBJ spisrc/obj/.
In SPIRES, you should now do the following:
-> set xeq spiproto -> ..emlink
This should move any object decks created by compiling PL360 code, and then link all versions of SPIRES and SPIBILD. The new versions will be in the spisrc/obj directory.
WARNING: Be sure you know where things are located. GG.SPI files are along some path that usually leads to spisys. GQ.DOC files are SPIKE files, and are usually some other place. MA.INT is where "spisrc/pl360" and "spisrc/obj" are located, although these paths can all be differently named.
Be sure your .empath file defines /paths for these accounts. Also be sure you have "link...." files in spisrc/obj, such as "link.spiresx". You need link files for: spibildh, spibildx, spiresh, spiresx.
And be sure you have "compall" and "emlink" in spiproto.
You must document your variable. There are several places where such documentation exists. First is within .$1VAR of the $DATA file. Second is within PARSEM.TXT or COMSPI.TXT, and possibly more.
You should update the FILEDEF.BI text file in spisrc/bi to reflect the ELEM (and ALIAS) statements you added to the $DATA file. FILEDEF.BI is a seed file used to build $DATA from scratch.
You should then create a new record in the PROTOCOLS MANUAL subfile. For Prism variables, update the PRISM APPLICATIONS MANUAL subfile. These are SPIKE-files, and are easiest to work with using the ..spike protocol defined in both SPIPROTO and SPIKE PROTOCOLS. If you have SET XEQ to either SPIPROTO or SPIKE PROTOCOLS, then you can use ..spike to select a SPIKE-file. There is a SPIKE.INDEX in the GQ.DOC directory that lists all the SPIKE-files accessible using the ..spike protocol. For our purposes, this is enough:
-> set xeq spike protocols -> ..spike proto . . or . . -> ..spike prism app
All currently defined variables are documented in these SPIKE-files. You see this when you EXPLAIN any existing variable. The header of the explanation indicates which section of the PROTOCOLS MANUAL or the PRISM APPLICATIONS MANUAL contains the documentation.
You should use the WRITE format to alter SPIKE-file records. You can TRANSFER an existing section to get an idea of how they are constructed. In fact, you can use an existing record as a model for a new record. Be sure to come up with a unique section number.
The -XP and -KT lines define the explainable terms. Usually, the first -XP phrase is the key phrase. All aliases follow, with semi-colon separations.
Once you have created a new section in the PROTOCOLS MANUAL documenting your variable, you must cause the EXPLAIN subfile to get updated. This is done with the ..spiexp protocol, which takes the same argument as the ..spike protocol.
-> set xeq spike protocols -> ..spikexp proto
At this point you create a result or stack of sections to be output to the EXPLAIN subfile, or use Global-For to create a display of records. [See 2.4.]
When CGINAME was added as a Prism variable, section 17 of PRISM APPLICATIONS MANUAL was updated adding this variable to the existing list.
Once you've created SPIRES/SPIBILD by linking VARS.OBJ and any object decks associated with variables defined by PL360 code, you have a complete implementation. You simply copy all versions of SPIRES/SPIBILD to other sites.
You do NOT have to migrate the $DATA file definition unless you want the other site(s) to have a $DATA file. If no one is going to SELECT SYSTEM VARIABLES, you don't need $DATA. Of course you need it at the site where you created the variable.
You should also copy the explanations added or updated in the EXPLAIN subfile. The best way to do that is by creating a LOAD file from the DEFQ of the EXPLAIN subfile after doing the ..upd.exp protocol within the ..spikexp process. You then INPUT LOAD loadfile UPDATE at each site that has an EXPLAIN subfile.