| Front Page | News Headlines | Technical Headlines | Planning Features | Advanced Search |
Adager graphic Adager Sponsor Message

     

Expression Programming

By Shawn M. Gordon

Inside VESOFT covers tips and techniques you can use with VESOFT’s products, especially MPEX. As always, I am totally open to getting input from you users of MPEX, Security/3000 or VEAudit/3000 — it helps me learn, too. Send me your tricks, and we’ll get a “3000 for 2000” cap out to you as our thanks.

Some of the more fascinating aspects of the VESOFT products are the expression programs that implement almost all of the functionality of the product. The appendix of the manual goes on in pretty good detail on how to use expression programs for command files and custom LISTF modes, so I won’t go into a huge amount of detail about it here.

But how about a little history on it first? Eugene Volokh (the E in VESOFT) set about rewriting MPEX some 12 or so years ago, and as legend has it, he ended up writing a general purpose compiler. The language looks a lot like Pascal in places, but over the years has implemented some bits from the C language as well. It’s like an object-oriented, arbitrary expression parser. It is really incredibly powerful and versatile, and almost completely undocumented. If you go and look at any of the command files in CMD22.VESOFT that have a file code of 171, you will notice all sorts of nifty commands. But if you then try to say “HELP command,” for these commands, nothing will come up.

VESOFT only documents the things they are going to basically guarantee will continue to work. They reserve the right to change anything that is undocumented as much as they want. So while you might be able to figure out how to use something, it is not suggested that you rely on it to continue to work as time goes by. I think this is perfectly acceptable, and the rule is clearly described in the manual.

The functions that you see inside the command files in CMD22.VESOFT are implemented in the AA files in EXP22.VESOFT. When I first looked at these files, I assumed they were encrypted somehow, but it turns out that they aren’t — this is what they are supposed to look like. Here is a short example:

~0 [* SEC ~C ~V 70 DEL=, TERM=] SEC
:iiD iINDEXNB
:bbD iINDEXNB
:ddD |kkD |rrD |ttD dINDEX
~0 [^ ~C ~V 70 TERM=] DEL=: SEC
:SiDD ISUBSTR
:SSDD SSUBSTRFIX
~0 ASL ~C ~V 60 :DDD DASL
~0 ASR ~C ~V 60 :DDD DASR

Now both the expression programs and the AA files get pseudo compiled into other files with a file code of 176 and 8 appended to the name (this is different under CM). When the VESOFT software is installed they go through and precompile as much as possible. Basically these things get dynamically compiled when you use them if they have changed since the last compilation. It’s very convenient, but also means that the first run is a bit slower. This will pertain more often to your own expression programs.

What is really interesting is that all the VESOFT products use the same engine in the background, but their expression programs go into different groups. It was really an elegant solution for a pretty large and complex question. On the surface, there is very little relation to MPEX, Security and VEAUDIT. It takes some serious abstraction to follow the motivation, but once you get there, it makes perfect sense.

Okay, I’ve gone on long enough about the background — how about a little sample?

Many moons ago when I worked at VESOFT, one of the other tech support guys wanted to know what was in an SD (Self Describing) save file from Query. I happened to remember reading an article on it in the SCRUG Newsletter about a year before. Since no publication ever gets thrown away at VESOFT, we browsed till we found it. I decided to use the information to write an expression program that would read the file label of an SD file and extract the data and format it. See Figure 1 below for the code example.

Figure 1




PRINT SDREAD.CMD

VAR SD_LABEL     :STRING[256];
VAR FULL_NAME    :STRING[26];
VAR OUT_TYPE     :STRING[1];
VAR ITEM_NAME    :STRING[16];
VAR ITEM_TYPE    :SHORTINT;
VAR ITEM_OFFSET  :SHORTINT;
VAR ITEM_LENGTH  :SHORTINT;
VAR FNUM         :INTEGER;
VAR NUM_LABEL    :INTEGER;
VAR LOOP         :INTEGER;
VAR S            :INTEGER;
VAR I            :INTEGER;

SUBROUTINE SETTYPE;
BEGIN
   if ITEM_TYPE = 1 then OUT_TYPE := 'X';
   if ITEM_TYPE = 3 then OUT_TYPE := 'I';
   if ITEM_TYPE = 4 then OUT_TYPE := 'R';
   if ITEM_TYPE = 5 then OUT_TYPE := 'P';
   if ITEM_TYPE = 6 then OUT_TYPE := 'J';
   if ITEM_TYPE = 7 then OUT_TYPE := 'K';
   if ITEM_TYPE = 8 then OUT_TYPE := 'Z';
   if ITEM_TYPE = 10 then OUT_TYPE := 'C';
END;

FULL_NAME := vefinfo(VEPARMS).fullname;
FNUM      := vefopen(FULL_NAME+',OLD;ACC=IN');
NUM_LABEL := vefinfo(FULL_NAME).labeleof;
LOOP      := NUM_LABEL - 2;

writeln('Data Item':18, 'Image':9, 'Length':10, 'Starts':6);
writeln('                  Type    in Bytes   at Pos');
writeln(43*'-');
while LOOP > 9 do begin
    SD_LABEL := vefreadlabel(FNUM,LOOP);
    I := 0;
    S := 0;
(* writeln('Label: ', LOOP, ' ', SD_LABEL:'GARBAGE'); *)
    while I < 8 do begin
       ITEM_NAME    := SD_LABEL[S:15];
       ITEM_TYPE    := INTEGER(SD_LABEL[(S+16):2]);
       ITEM_OFFSET  := INTEGER(SD_LABEL[(S+18):2]);
       ITEM_LENGTH  := INTEGER(SD_LABEL[(S+20):2]);
       SETTYPE;
       writeln(ITEM_NAME:20,OUT_TYPE:4,ITEM_LENGTH:6,ITEM_OFFSET+1:10);
       I := I + 1;
       S := S + 30;
       if I < 8 then ITEM_TYPE := INTEGER(SD_LABEL[(S+16):2]);
       if ITEM_TYPE < 1 then I := 10;
     end;
     LOOP := LOOP - 1;
end;
Vefclose(FNUM);

Much of this should be obvious, even if you don’t know Pascal. Expression programs don’t support record structures like COBOL, so you have to parse out the data based on position. I’m also using an unsupported construct, the SUBROUTINE directive (don’t use it at home). VEPARMS is a predefined variable that will contain what is passed on the command line. In this case it is a simple file name with no parameters, so we can just use it to get the file name and the file label information.

The funny thing about SD files is that the data is stored in the file label in reverse order, so you have to read through it backward. I don’t have the original article anymore, so I always have to read through this expression program to figure out what went where. I don’t remember what is in the first eight records anymore, or the last two. I’ll leave it as an exercise for the reader.

Below, Figure 2 shows the original command file, and the compiled file that was generated by MPEX. Figure 3 shows an example of the output from executing the expression program.

Figure 2



                                        Figure 2

ACCOUNT=  SMGA        GROUP=  CMD

FILENAME  CODE  ------------LOGICAL RECORD-----------  ----SPACE----   --DAYS--
                   SIZE  TYP        EOF      LIMIT R/B  SECTORS #X MX   ACC  MOD

SDREAD    171      72B  FA          53         53  16       16  1  5         59
SDREAD8   176     128W  FB          10       1023   1       16  1  *

GROUP     TOTAL:     2 FILES                                32 SECTORS

Figure 3



%SDREAD X2
Data Item         Image    Length    Starts
                   Type    in Bytes   at Pos
-------------------------------------------
MAIL-NAME           X       12         1
TERMINAL-NO         J        2        13
PRINTER             X        8        15
PHONE-EXT           J        2        23
DEPT                X       26        25
NODE                X        8        51
FLAGS               X       16        59
USER-PASS           J        2        75
USER-NAME           X       30        77
TIME-ON             J        4       107
DATE-ON             J        2       111
FLAGS2              X       80       113

I hope you’ve enjoyed this little history lesson and tiny foray into expression programming. I’ll cover it more in the future for various types of uses. Make sure to send in your tips, too.

Shawn Gordon, whose S.M. Gordon & Associates firm supplies HP 3000 utilities, has worked with 3000s since 1983.
 


Copyright The 3000 NewsWire. All rights reserved.