|
Expression
Programming Inside VESOFT covers
tips and techniques you can use with VESOFTs 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 well get a 3000 for
2000 cap out to you as our thanks. 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. Its 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 arent this is what they are supposed to look like. Here is a short example: ~0 [* SEC ~C ~V 70 DEL=,
TERM=] SEC 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. Its 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, Ive 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 dont know Pascal. Expression programs dont support record structures like COBOL, so you have to parse out the data based on position. Im also using an unsupported construct, the SUBROUTINE directive (dont 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 dont have the original article anymore, so I always have to read through this expression program to figure out what went where. I dont remember what is in the first eight records anymore, or the last two. Ill 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
youve enjoyed this little history lesson and tiny foray into
expression programming. Ill cover it more in the future for
various types of uses. Make sure to send in your tips, too. Copyright The 3000 NewsWire. All rights reserved. |