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.

Go to Adager's index of technical papers