MPEX: FLEXIBLE LISTFs and OTHER TRICKS by Brad Griffin, Computer Consultant; 1995. Telephone : 011 61 055 625436 Fax : 011 61 055 623163 I have finally gotten around to putting pen to paper (or more correctly, fingers to keyboard) to write this article on one of, what I believe is, the lesser known, but very powerful features of MPEX, that is FLEXIBLE LISTFs. MPEX is probably one of the most widely used pieces of 3rd party software in use on the HP3000 series of computers. MPEX (MPE eXtended) provides the ability to use all MPE commands with a very flexible fileset structure, unlike MPE, where you can only execute a command on a single file. While this is a very powerful reason to use such a program, MPEX also provides the user with the ability to write MPEX programs using its own very powerful command language. MPEX is a product of VESOFT Inc. In short a Flexible LISTF provides the ability, within MPEX, to be able to write your own LISTF programs as the following example demonstrates, also included is an example on how to write an MPEX EXPRESSION Program. FLEXIBLE LISTF PROGRAM I have known about the Flexible LISTF feature for some years, but it was not unt il I went out as a consultant that I had a need to make extensive use of this pa rticular feature of MPEX. In the past if a certain utility was required, we would sit down and write what ever was required in the programming language of our choice, sound familiar? But as a consultant, the time required to achieve this is never available, so there had to be a quicker way of providing IT departments with the ability to perform small, routine tasks with ease, enter MPEX's FLEXIBLE LISTFs. To create the code for your particular LISTF program, simply fire up your favour ite text editor and add the code into a standard MPE text file. The first time y ou try the program from within MPEX, MPEX will do a pseudo compile of the code and generate its own "compiled object" within the group that contains your source LISTF file. With most of the utilities and tips that will be described, they all could be do ne long hand, but with the power of MPEX behind them, all have provided signific ant time savings. ALLBASE: ISQL DROP/INSERT UTILITY In my current contract we have had to do a lot of development using HP's ALLBASE database package. While this in itself is not a problem, but the fact that the development is done on a development machine and the resulting code and ALLBASE code has to be migrated to other ALLBASE database Environments (DBEs)does cause some problems in that it then does become a time consuming and tedious task to maintain the various DBEs associated with the project. Probably a short explanation of what is required to move an ALLBASE developed ap plication is required here. Regardless of the languages being used to develop th e application, using ALLBASE requires a MODULE file to be built if the applicat ion is to be moved to other DBEs. Within this module file, there is a SECTION for each ALLBASE/SQL call. It is these Section's that have to be migrated to the remote DBEs to allow the ALLBASE optimizer to make the correct decisions on which access path to use. To update the sections in a DBE the ALLBASE utility ISQL needs to be invoked, and then a connection made to the DBE. Once this is done we need to DROP and INSTALL the SECTION, this is not so hard, but remembering the correct structure of the syntax can be confusing, as different languages seem to generate different structures. This is where a Flexible LISTF program comes in handy, see example 1. This program is run from MPEX using a simple MPEX command file, see example 2. This command file is invoked from MPEX as follows: %SQLFILES file_set Where the file_set is a standard MPEX file_set definition, and defines the GROUP where the required MODULE/SECTION files reside. The SQLFILES routine will create, in this case, 3 files: XFRSQL1 This is a list of filenames that can used as an indirect file in a STORE XFRSQL2 This file contains the CONNECT/DROP/INSTALL for DBE1 XFRSQL3 This file contains the CONNECT/DROP/INSTALL for DBE2 Obviously, any number of files could be generated, it would depend on the number of remote DBEs, and what Accounts the remote DBEs are in. In the case that this routine was developed, DBE2 had the same name as DBE1, but resided in a different account. All that is required now, is to fire up ISQL and invoke XFRSQL2 and XFRSQL2 so t hat the relevant DBEs are updated with the new Module/Sections: ISQL >start XFRSQL2; >start XFRSQL3; >exit; Example 1 SQLFILES LISTF PROGRAM NOTE: certain parts of the following example do contain ACCOUNT/SITE specific co de, but this code easily be changed to suit whatever ACCOUNT/SITE requirements a re needed. I have attempted to add comments highlighting the ACCOUNT/SITE specif ic areas. (* define the program variables here *) var current_user : STRING[8]; var module_user : STRING[8]; var current_account : STRING[8]; var module_source : STRING[8]; var current_module : STRING[8]; var source_type : STRING[8]; var source_group : STRING[8]; var module_group : STRING[8]; var pacer_module : STRING[8]; var pacer_quick : STRING[26]; var pacer_quiz : STRING[26]; var pacer_qtp : STRING[26]; for rfile in mpexfileset (* only select those module files that have a record count > 1 *) (* files with a record count <= 1 do not contain any Sections *) select eof > 1 first (* only do this bit once, at the beginning *) begin writeln("connect to 'DBE1';"); writeln("set owner DBE1;"); writeln("set echo on;"); writeln("debug noopt 160;"); end (* for each file within the nominated fileset do the *) (* following: *) do begin current_user:= svar("HPUSER"); current_account:= svar("HPACCOUNT"); if account <> "PACER" then (* PACER is an account in which we used Cognos's *) module_user:= current_user (* Powerhouse products for develo pment *) else module_user:="PACER"; source_type:="COBOL"; module_group:=group; (* because the accounting structure id different in each account, we *) (* have to determine were we are, and then where the module files reside *) (* a lot of the following code is also very account and application specific *) (* Most of the following LISTF code is designed for a specific environment, but *) (* the basic structure can be adapted for any account structure *) if current_account = "PACER" then begin (* because the ALLBASE module files reside in groups with different names *) (* we have to be very account specific here *) source_type:="PACER"; module_group:="mmsect"; (* GROUP where module files reside in the PACER account*) end; if current_account = "MINIMAT" then begin source_type:="MINIMAT"; module_group:="SECT"; (* GROUP where module files reside in MINIMAT account*) end; if source_type = "COBOL" then (* generate MODULE name. This is formatted by *) (* dropping the last character (M) from the *) (* filename. The (M) has been added by the COBOL/SQL pre-processor * ) begin NOTE: The internal MODULE filename for a COBOL generated module file takes its n ame from the source code PROGRAM-ID. current_module:= strrtrim(file,"M"); writeln("drop module ", current_user, "@", current_account, ".", current_module, ";") end; if source_type = "PACER" then (* generate MODULE name. This is formatted by *) (* inserting an _ between the file and the *) (* group name. *) begin pacer_module:="OBJ"; (* this is the default suffix of a section n ame *) pacer_quick:=" "; pacer_qtp :=" "; pacer_quiz :=" "; pacer_quick:=file + ".mmqkcmp.pacer"; (* Powerhouse QUICK obje cts *) pacer_quiz :=file + ".mmqzcmp.pacer"; (* Powerhouse QUIZ objec ts *) pacer_qtp :=file + ".mmqpcmp.pacer"; (* Powerhouse QTP object s *) if fexists(pacer_quick) then begin pacer_module:="mmqkcmp"; (* Powerhouse QUICK suffix *) end else if fexists(pacer_quiz) then begin pacer_module:="mmqzcmp"; (* Powerhouse QUIZ suffix *) end else if fexists(pacer_qtp) then begin pacer_module:="mmqpcmp"; (* Powerhouse QTP suffix *) end; (* output the syntax to DROP the old module/section *) writeln("drop module ", module_user, ".", file, "_", pacer_module, ";"); end; if source_type = "MINIMAT" then (* generate MODULE name. This is formatted by *) (* inserting an _ between the file and the *) (* group name. *) begin pacer_module:="OBJ"; pacer_quick:=" "; pacer_qtp :=" "; pacer_quiz :=" "; pacer_quick:=file + ".qkcmp.minimat"; (* Powerhouse QU ICK object *) pacer_quiz :=file + ".qzcmp.minimat"; (* Powerhouse QUIZ objec t *) pacer_qtp :=file + ".qpcmp.minimat"; (* Powerhouse QTP object *) if fexists(pacer_quick) then begin pacer_module:="qkcmp"; end else if fexists(pacer_quiz) then begin pacer_module:="qzcmp"; end else if fexists(pacer_qtp) then begin pacer_module:="qpcmp"; end; (* output the syntax to drop this module from the DBE *) writeln("drop module ", "pacer.", file, "_", pacer_module, ";"); end; (* output the syntax to install the new module *) writeln("install ", file, ".", module_group, ".", account, ";"); (* of course after each SQL call we must commit it * writeln("commit work;"); end; Example 2 SQLFILES COMMAND FILE NOTE: We have included all our LISTF programs in LISTF.VESOFT group and account, but have noted the disclaimer in the MPEX manual that VESOFT will not preserve non-VESOFT LISTFs in the VESOFT account in future releases. parm !fileset=@ setvar response "N" if finfo('sqlxfr1',0) then echo SQL script files currently exist in !hpgroup.!hpaccount setvar response "Y" input response;prompt=Purge them(Y/n)? if ups(response) = "Y" then purge sqlxfr#;yes endif endif if fexists('sqlxfr1') then file sqlxfr1=sqlxfr1,old;acc=append else file sqlxfr1;disc=5000;rec=-72,,f,ascii;save;nocctl endif if fexists('sqlxfr2') then file sqlxfr2=sqlxfr2,old;acc=append else file sqlxfr2;disc=10000;rec=-72,,f,ascii;save;nocctl endif if fexists('sqlxfr3') then file sqlxfr3=sqlxfr3,old;acc=append else file sqlxfr3;disc=10000;rec=-72,,f,ascii;save;nocctl endif echo Generating SQL transfer script files now ...... echo Generating a fully qualified list of file names listf !fileset,6;*sqlxfr1 echo Generating the ISQL DROP/INSTALL statements for DBE1 listf !fileset,xfrsql2;*sqlxfr2 echo Generating the ISQL DROP/INSTALL statements for DBE2 listf !fileset,xfrsql3;*sqlxfr3 echo SQL transfer script files have been generated !!!! deletevar response reset sqlxfr1 reset sqlxfr2 reset sqlxfr3 EXPRESSION PROGRAM The following code allows you to update multiple XL files in one pass using MPEX's powerful fileset ability. It was a routine that came in for a lot use several years ago when migrating from an old classic/3000 to a Native Mode 3000. parm !fileset=@.@.@ comment ******************************************* comment * comment * filename: XLUPDATE comment * comment * author: Brad Griffin comment * comment * date : 22 September 1992 comment * comment ******************************************* :input MODULE;prompt="Enter the MODULE name to be PURGED: " :setvar CONTINUE 0 while continue <> 1 :input OBJECT;prompt="Enter the OBJ filename: " :if NOT finfo('!OBJECT',0) echo ERROR **** !OBJECT does not exist **** else :if NOT finfo('!OBJECT',9) = "NMOBJ" echo ERROR **** !OBJECT is not a valid NMOBJ file else setvar CONTINUE 1 endif endif endwhile REPEAT echo -----Processing !mpexcurrentfile now run LINKEDIT.pub.sys;& input="xl !mpexcurrentfile";& input="purgexl module=!MODULE";& input="addxl !OBJECT";& input="cleanxl";& input="e" (* we only want valid XLs *) forfiles !fileset(code="NMXL") :deletevar CONTINUE :deletevar MODULE :deletevar OBJECT When executed from within MPEX as %XLUPDATE xl_fileset, you will be prompted for the section to be purged from the XL and then prompted for the object file that contains the new section to be linked into the XL, MPEX will then do its thing and update each XL in the nominated file-set. SUMMARY While these are only a small number of routines, they do demonstrate the power of the programming ability that is available within MPEX. Just these several rou tines have saved me, and the people that I have worked for a lot of time and eff ort. They have simplified many tedious process's into simple MPEX commands, mean ing that they can be invoked with the full power of MPEX file sets. I hate to th ink how many times I would have had to thank Eugene for his work in providing a tool that should have been what MPE should have been in the first place. Two oth er quick note of thanks are to Vladimir for his help and encouragement to write this article, and to Wayne Harris (Shell Refining Geelong (Australia)) for giving me the opportunity to continue my work in the HP environment.