TAA Tools
CRTCLPINS       CREATE CLP INSERT                      TAACLRI

The Create CLP  Insert command creates  CL source for use  in inserting
data  from variables  declared  from a  data  base file  into  a record
buffer.    The  CRTCLPDCL  command  may  be  used  to  create  the  DCL
commands.    CRTCLPINS simplifies  the  use  of  an  UPDDBR  or  WRTDBR
command from  the CLPDBR  tool.  See  also the CRTCLPEXT  command which
performs the inverse function.

Note  that as  of V5R4,  the CL  Compiler allows  a data  structure and
eliminates the need for CRTCLPINS.  See the CRTCLPDCL command.

CRTCLPINS is intended primarily for  use with the CLPDBR tool to  allow
writing  and  updating  of  data  base   records  from  a  CL  program.
CRTCLPEXT  works from  a data  base file definition.   The  command may
also be helpful when a  record buffer must be passed  from CL to a  HLL
program or  an externally described  data structure  is processed in  a
CL program.

Steps used with CRTCLPINS
-------------------------

The typical  use of CRTCLPINS is  to create the CL needed  to work with
the  WRTDBR and/or UPDDBR commands of the CLPDBR  tool.  If you are not
familiar  with  CRTCLPINS,  go   thru  the  sample  described   in  the
following section.

The CRTCLPINS steps are summarized here:

  **   Create a  source member and write  CL code such as  described in
       the sample.

  **   Use  CRTCLPDCL  to  declare  the  variables  for the  externally
       described file.

  **   Use a  source  editor to  move the  DCL  statements to  the  DCL
       section of the program.

  **   Use CRTCLPINS to  create the code needed to  perform the insert.

  **   Use  a source editor  to 1) Move  the DCL statements  to the DCL
       section of  the program  2) Move  the linkage  code  immediately
       before the  WRTDBR or UPDDBR  statement and  3) Move the  INSERT
       subroutine after a RETURN and before a ENDPGM statement.

Sample use of CRTCLPINS
-----------------------

The  best  method  of  understanding  CRTCLPINS  is  to  use  a  simple
example.    You must  be familiar  with the  CLPDBR tool  to understand
this example.

Assume you want  a program  that will write  a new  record to the  data
base.

Assume the file is named FILEA and is defined as:

     A          R FILEARCD
     A            KEY            5
     A            FLD1          10
     A            FLD2           3  0
     A            FLD3           7  2
     A          K KEY

To use the  sample, you need to  enter the DDS for a  physical file and
use CRTPF for FILEA.

To  use CRTCLPINS,  you would  create a CL  source member  (WRTFILEA is
used in this example) in  a QCLSRC file with  the code you need.   Note
that  the file  name (FILEA)  must be  entered into  the DBRCTLx  files
with WRKDBRCTL to use OPNDBR.


             PGM
             OPNDBR     FILE(xxx/FILEA) OPNTYPE(*OUT) DBRCTLLIB(yyy)
                        /* Move data to variables for a new record */
             CHGVAR     &KEY 'BBBBB'
             CHGVAR     &FLD1 'BANANAS'
             CHGVAR     &FLD2 '987'
             CHGVAR     &FLD3 '12345.67'
                        /* Write a new record                      */
             WRTDBR     RCD(&RCD)
             CLSDBR
             RETURN
             ENDPGM

This  is  the  only  code  you need  to  write.    Other  code will  be
generated for you by use of TAA commands.

The CLPDBR tool's WRTDBR  command requires a variable  that is 5000  or
less bytes.   The WRTDBR RCD  parameter is named  &RCD to allow  you to
use the  default name on CRTCLPINS.   The variable will  be declared as
*CHAR LEN(5000) by the use of CRTCLPINS.

The  program will write  one record to  FILEA.  The  data is created by
using CHGVAR  commands for  the variables  declared for  the data  base
fields.

The  next step  is to  use  CRTCLPDCL to  create the  DCLs that  define
variables for the fields in FILEA.

             CRTCLPDCL     FILE(FILEA) SRCMBR(WRTFILEA)

CRTCLPDCL  generates DCL statements  for each field  in the  file.  The
source  statements are  added  at  the  end  of  the  specified  source
member.   Using a source  editor, move the DCLs  to the DCL  section of
the program.  Your source would look like:


             PGM
                        /* Defined from FILEA in xxx                */
                        /*  Start CRTCLPDCL definitions - 09/07/09  */
             DCL        VAR(&KEY) TYPE(*CHAR) LEN(5)
             DCL        VAR(&FLD1) TYPE(*CHAR) LEN(10)
             DCL        VAR(&FLD2) TYPE(*DEC) LEN(3 0)
             DCL        VAR(&FLD3) TYPE(*DEC) LEN(7 2)
                        /* End of CRTCLPDCL definitions             */
             OPNDBR     FILE(xxx/FILEA) OPNTYPE(*OUT) DBRCTLLIB(yyy)
                        /* Move data to variables for a new record */
             CHGVAR     &KEY 'BBBBB'
             CHGVAR     &FLD1 'BANANAS'
             CHGVAR     &FLD2 '987'
             CHGVAR     &FLD3 '12345.67'
                        /* Write a new record                      */
             WRTDBR     RCD(&RCD)
             CLSDBR
             RETURN
             ENDPGM

When WRTDBR  occurs, the data must  be in the &RCD  variable.  To cause
this, you would have to move  the data from the variables declared  for
the data base  fields to the  &RCD variable using CL  substring (%SST).
This can be a tedious and error prone requirement.

To avoid  this coding of substring,  the CRTCLPINS tool can  be used to
generate the code that will do it for you.

CRTCLPINS  will generate source statements at  the end of your existing
source member:

             CRTCLPINS     FILE(FILEA) SRCMBR(WRTFILEA)

The source that is generated has 3 sections:

  **   DCL statements  that must  be moved to  the DCL  section of  the
       source.

  **   Linkage code  that is  needed to link  to a supplied  section of
       code   labeled  the  INSERT   routine  (described   in  a  later
       section).   Move  the  statements (beginning  with  the  comment
       'INSERT subroutine  linkage' to  the appropriate  place in  your
       program which  in this case is immediately  before WRTDBR.  Part
       of the linkage code  is to do CHGVAR  from &RCD to the  variable
       declared as the  record format name  (FILEARCD) of the  file you
       specified.

  **   The  third section is  the INSERT  routine which  uses substring
       functions  to  move data  from  the variables  declared  for the
       data base fields to  the variable used for the  format variable.
       Decimal fields  within the buffer require  special handling (see
       later  discussion).  This  subroutine like  function is intended
       to be placed after your RETURN statement.

The added code looks like:

                        /* Defined from FILEA in xxx                */
                        /*  Start CRTCLPINS definitions - 09/07/09  */
             DCL        VAR(&RCD) TYPE(*CHAR) LEN(5000)
             DCL        VAR(&FILEARCD) TYPE(*CHAR) LEN(21)
             DCL        VAR(&INSRTN) TYPE(*CHAR) LEN(8)
             DCL        VAR(&INSCHR8) TYPE(*CHAR) LEN(8)
             DCL        VAR(&INSDEC15) TYPE(*DEC) LEN(15 0)
                        /*  End CRTCLPINS definitions               */


/*   Move immediately before a command such as UPDDBR or WRTDRB */
                        /*   INSERT subroutine linkage              */
             CHGVAR     VAR(&INSRTN) VALUE('INSERT1')
             GOTO       CMDLBL(INSERT)
 INSERT1:               /*   Return from INSERT subroutine          */
             CHGVAR     VAR(&RCD) VALUE(&FILEARCD)

/*  Move after a RETURN and before ENDPGM  */
             SNDESCMSG  MSG('Your code has fallen into the +
                          INSERT subr')
                        /********************************************/
                        /*                                          */
 INSERT:                /* CRTCLPINS for FILEA in xxx               */
                        /*   Retrieved by CRTCLPINS on 09/07/09     */
                        /*                                          */
                        /********************************************/
             CHGVAR     VAR(%SST(&FILEARCD 1 5)) VALUE(&KEY)
             CHGVAR     VAR(%SST(&FILEARCD 6 10)) VALUE(&FLD1)

             CHGVAR     VAR(&INSDEC15) VALUE(&FLD2)
             MOVDECCHR  CHROUT(&INSCHR8) DECINP(&INSDEC15)
             CHGVAR     VAR(%SST(&FILEARCD 16 2)) +
                          VALUE(%SST(&INSCHR8 7 2))
             CHGVAR     VAR(&INSDEC15) VALUE(&FLD3 * 100)
             MOVDECCHR  CHROUT(&INSCHR8) DECINP(&INSDEC15)
             CHGVAR     VAR(%SST(&FILEARCD 18 4)) +
                          VALUE(%SST(&INSCHR8 5 4))
                        /*    Return GOTOs.  Modify as required     */
             IF         COND(&INSRTN *EQ 'INSERT1') +
                          THEN(GOTO CMDLBL(INSERT1))
             SNDESCMSG  MSG('Bad return in INSERT routine of '  +
                        *CAT &INSRTN)
                        /********************************************/
                        /*                                          */
                        /*     End of INSERT subroutine             */
                        /*                                          */
                        /********************************************/

Using a source editor, you then:

  **   Move the DCLs to the DCL section of the program.

  **   Move the linkage code immediately before WRTDBR.

  **   Move the INSERT subroutine after  the RETURN command and  before
       the ENDPGM statement.

  **   Delete  the   excess  blank  separator  lines   and  information
       comments.

The final code would look like:

             PGM
                        /* Defined from FILEA in xxx                */
                        /*  Start CRTCLPDCL definitions - 09/07/09  */
             DCL        VAR(&KEY) TYPE(*CHAR) LEN(5)
             DCL        VAR(&FLD1) TYPE(*CHAR) LEN(10)
             DCL        VAR(&FLD2) TYPE(*DEC) LEN(3 0)
             DCL        VAR(&FLD3) TYPE(*DEC) LEN(7 2)
                        /* End of CRTCLPDCL definitions             */
                        /* Defined from FILEA in xxx                */
                        /*  Start CRTCLPINS definitions - 09/07/09  */
             DCL        VAR(&RCD) TYPE(*CHAR) LEN(5000)
             DCL        VAR(&FILEARCD) TYPE(*CHAR) LEN(21)
             DCL        VAR(&INSRTN) TYPE(*CHAR) LEN(8)
             DCL        VAR(&INSCHR8) TYPE(*CHAR) LEN(8)
             DCL        VAR(&INSDEC15) TYPE(*DEC) LEN(15 0)
                        /*  End CRTCLPINS definitions               */
             OPNDBR     FILE(xxx/FILEA) OPNTYPE(*OUT) DBRCTLLIB(yyy)
                        /* Move data to variables for a new record */

             CHGVAR     &KEY 'BBBBB'
             CHGVAR     &FLD1 'BANANAS'
             CHGVAR     &FLD2 '987'
             CHGVAR     &FLD3 '12345.67'
                        /* Write a new record                      */
                        /*   INSERT subroutine linkage              */
             CHGVAR     VAR(&INSRTN) VALUE('INSERT1')
             GOTO       CMDLBL(INSERT)
 INSERT1:               /*   Return from INSERT subroutine          */
             CHGVAR     VAR(&RCD) VALUE(&FILEARCD)
             WRTDBR     RCD(&RCD)
             CLSDBR
             RETURN
             SNDESCMSG  MSG('Your code has fallen into the +
                          INSERT subr')
                        /********************************************/
                        /*                                          */
 INSERT:                /* CRTCLPINS for FILEA in xxx               */
                        /*   Retrieved by CRTCLPINS on 09/07/09     */
                        /*                                          */
                        /********************************************/
             CHGVAR     VAR(%SST(&FILEARCD 1 5)) VALUE(&KEY)
             CHGVAR     VAR(%SST(&FILEARCD 6 10)) VALUE(&FLD1)
             CHGVAR     VAR(&INSDEC15) VALUE(&FLD2)
             MOVDECCHR  CHROUT(&INSCHR8) DECINP(&INSDEC15)
             CHGVAR     VAR(%SST(&FILEARCD 16 2)) +
                          VALUE(%SST(&INSCHR8 7 2))
             CHGVAR     VAR(&INSDEC15) VALUE(&FLD3 * 100)
             MOVDECCHR  CHROUT(&INSCHR8) DECINP(&INSDEC15)
             CHGVAR     VAR(%SST(&FILEARCD 18 4)) +
                          VALUE(%SST(&INSCHR8 5 4))
                        /*    Return GOTOs.  Modify as required     */
             IF         COND(&INSRTN *EQ 'INSERT1') +
                          THEN(GOTO CMDLBL(INSERT1))
             SNDESCMSG  MSG('Bad return in INSERT routine of '  +
                        *CAT &INSRTN)
                        /********************************************/
                        /*                                          */
                        /*     End of INSERT subroutine             */
                        /*                                          */
                        /********************************************/
             ENDPGM

You are  now ready to create the WRTFILEA CL  program and call it.  The
program will write one record to the FILEA file.

Use of CLPDBR RCLDBR
--------------------

When  you  begin  to  use  CLPDBR  functions  along  with  the   INSERT
subroutine, it  is typical to  make mistakes which  cause the file  you
were  operating on  to remain  open.   If you  correct the  program and
call  it again, you will  receive an error saying  the OPNID is already
in use or open.

To correct the problem  you need to use  the RCLDBR command which  will
delete  all of the  data areas  created by  OPNDBR commands,  close any
files  that are open, and reclaim the  activation group that the CLPDBR
functions run in.

Then try your program again.

The Linkage code
----------------

The linkage  code changes  the value  of &INSRTN  to  a name  (INSERT1)
that will be  used later in an  IF test.  A  GOTO is used to  branch to
the  INSERT subroutine.  The  next statement uses a  label of INSERT as
the return point  from the  subroutine.  The  &FILEARCD variable  which
now contains the record buffer is then moved to the &RCD variable.

The INSERT subroutine
---------------------

The INSERT  subroutine uses substring  (%SST) to  insert the data  from
the  variables  declared  for the  data  base  fields  into the  record
buffer.

The  first  statement  generated  is the  SNDESCMSG  TAA  command which
states that your code  has fallen into the subroutine.   The subroutine
is intended  to be branched  to with a  GOTO, so the  SNDESCMSG command
protects your program logic.

Character data is moved by using substring positions.

Packed  and Zoned decimal  data require specific  handling as described
in the next section.

At the  end  of the  subroutine is  an  IF statement,  that  determines
where the code should branch to.

If you have  one place in your  program where you need  the subroutine,
the linkage  code and ending GOTO appear  overly complex.  However, the
code is  designed  to allow  multiple  uses  of the  subroutine  as  is
described in a later section.

The last  statement is  another SNDESCMSG  TAA command which  describes
the problem  where you have branched to the  INSERT routine, but do not
have a valid value in &INSRTN.

Handling of decimal fields
--------------------------

Packed  decimal fields require  some specific handling  because CL does
not  allow a  packed  value  in  a  *DEC  variable to  be  moved  to  a
character  variable  as  packed  data  (CHGVAR would  unpack  the  data
before  attempting to move  it).   For example, if  you have  a 3 digit
*DEC variable in  CL, the value might  be X'123F'.   If you use  CHGDTA
to a  *DEC field,  the data  would be unpacked  to a  value of  123 and
cannot  be moved to a  2 byte *CHAR  variable.  You  would receiver the
error message  CPF0819 (Variable  or  substring to  small to  hold  the
result).

The  TAA  MOVDECCHR tool  is  used  to  handle  the move  from  a  *DEC
variable  to  a *CHAR  variable  without unpacking  the  data.   Before
using  MOVCHRDEC, CHGVAR is  used to move  the data to  a standard *DEC
variable (&INSDEC15) which is declared as LEN(15 0).

If  the  field  has  more  than  0  decimal   positions,  the  data  is
multiplied so that  a whole number would exist.   For example, &FLD3 in
the example  is declared as *DEC LEN(7 2).   The value is multiplied by
100 to make  a whole number.   The MOVDECCHR TAA  command is then  used
to move the decimal  value to the &INSCHR8 variable  as a packed value.
The value  is right adjusted in the variable.   If the value was 123.45
in  a  *DEC  LEN(7  2)  variable,   the  data  in  &INSCHR8  would   be
X'000000000012345F' The data is  then moved using CHGVAR to  the proper
positions within  the variable that is used for  the format name.  Thus
each packed field takes 3 statements in the subroutine.

CL  does not  support a  zoned decimal  type of  variable.  If  a zoned
decimal field  exists in the  data base  file, the DCL  would define  a
*DEC type  which is  treated as packed  decimal within the  CL program.
Zoned  decimal fields are  processed in the subroutine  by first moving
the data to the  &EXTDEC15 field and creating  a whole number (same  as
described for packed  fields).  The RTVSGNPOS TAA command  is then used
which does  two things 1) It  returns the low order  digit of the field
as a zoned  decimal field and  2) It  returns a positive  value if  the
original value was negative.

The positive value is  then moved to &INSCHAR15 which is  declared as a
*CHAR  LEN(15) variable.   Since  a positive  whole number  exists, the
character  variable will  not contain  a decimal  point nor  minus sign
within the  data.  The  value is then  moved to  the variable name  for
the  record buffer  using substring  for both  values.   The  low order
digit  which  was retrieved  by  RTVSGNPOS is  then placed  in  the low
order position of the field in the record buffer.

Two additional DCL  statements (&INSCHR1  and &INSCHR15) are  generated
if any zoned decimal fields exist in the file.

Binary fields are declared  and moved to *CHAR variables.   If you have
binary  fields in the  data base, you  must code a  CHGVAR statement to
convert the data to a decimal variable such as:

             CHGVAR    VAR(%BIN(&BINFLD 1 4) 1000

Multiple use of the INSERT subroutine for the same file
-------------------------------------------------------

The INSERT  subroutine  is  designed  to allow  you  to  have  multiple
points within  your program  where you  need to write  and/or update  a
record  in the  same file.   Before  each WRTDBR  or UPDDBR,  you would
need  to insert  the required  values into  the variables  declared for
the data  base fields and  then use  the INSERT routine.   The  linkage
code must be modified for each subsequent use.

The following steps would be needed for each subsequent use:

  **   Duplicate the linkage code which appears as:

                        /*   INSERT Subroutine linkage            */
             CHGVAR     VAR(&INSRTN) VALUE('INSERT1')
             GOTO       CMDLBL(INSERT)
 INSERT1:               /*   Return from INSERT subroutine          */
             CHGVAR     VAR(&RCD) VALUE(&FILEARCD)

  **   Change the  INSERT1 constant in the  CHGVAR and the  name of the
       label.   'INSERT2'  would be the  typical choice  for the second
       usage.

  **   The last statement in the INSERT subroutine is:

             IF         COND(&EXTRTN *EQ 'INSERT1') +
                          THEN(GOTO CMDLBL(INSERT1))

Duplicate this code to  the next line  and change the 'INTSERT1'  value
on the IF and the THEN to the name you chose previously such as:

             IF         COND(&EXTRTN *EQ 'INSERT2') +
                          THEN(GOTO CMDLBL(INSERT2))

Using both CRTCLPINS and CRTCLPEXT in the same program
------------------------------------------------------

The  CRTCLPEXT  tool  provides   the  inverse  function  of  CRTCLPINS.
CRTCLPEXT  provides a subroutine like  function to extract  data from a
record to the variables declared for the data base fields.

You would  use CRTCLPEXT  if you  were using  a command  like RDDBR  to
read a record from the data base.

If you  are using  both RDDBR  and UPDDBR/WRTDBR in  the same  program,
then  both  subroutines  are   needed.    Just  follow  the  steps  for
CRTCLPEXT  in  addition  to  CRTCLPINS.    You  only  need  to  use the
CRTCLPDCL function  once to  declare the  variables for  the fields  in
the file.

Use of INSERT for different files
----------------------------------

You  can use  CRTCLPINS for  different files  within your  program, but
you  must use a different name  for each subsequent use.   Use a source
editor to change  the name INSERT and  the corresponding linkage  code.

Conversion of field types
-------------------------

Character fields in the data base are extracted to *CHAR variables.

Packed and zoned fields  are extracted to *DEC variables.   The size of
the field cannot exceed 15 digits or 9 decimal positions.

Binary fields are extracted to *CHAR variables.

Any other field types are extracted to *CHAR variables.

CRTCLPINS escape messages you can monitor for
---------------------------------------------

None.  Escape messages from based on functions will be re-sent.

Command parameters                                    *CMD
------------------

   FILE          The  externally described  file to  use to  create the
                 insert information for.  The  file may be either a  PF
                 or LF, but may only contain a single format.

                 The library  defaults to  *LIBL.   A specific  library
                 or *CURLIB may be entered.

   SRCMBR        The  member of the  source file to  be added to.   The
                 member  must  exist.   The  statements  will  be added
                 after  the  last  existing  record  (if  any)  in  the
                 source member.

   SRCFILE       The name  of the source file containing  the member to
                 be  added  to.    The  source  file  name defaults  to
                 QCLSRC.  The library qualifier  defaults to *LIBL.   A
                 specific library or *CURLIB may be entered.

   RCDVAR        The name  of the variable  that contains the  data for
                 a  function like  WRTDBR or  UPDDBR.   The  default is
                 &RCD.   While  both WRTDBR  and  UPDDBR will  allow  a
                 variable to be  less than 5000 bytes, the  variable is
                 declared  as *CHAR LEN(5000)  by CRTCLPINS.   The name
                 is   used  in  a  single   CHGVAR  statement  that  is
                 generated in  the linkage  code created by  CRTCLPINS.

Restrictions
------------

Packed or  zoned decimal  data base  fields must be  15 digits  or less
and the number of decimal positions must be 9 or less.

All  other  field  types  (including  binary)  are  converted to  *CHAR
variables.

Because a record buffer is used to  pass data to the data base, no  DDS
validity checking will occur.

  **   The source file must be at least 92 bytes in length.

Prerequisites
-------------

The following TAA Tools must be on your system:

     HLRMVMSG        HLL Remove message
     RTVDBFA         Retrieve data base file attributes
     RTVFMT          Retrieve format
     RTVSYSVAL3      Retrieve system value 3
     SNDCOMPMSG      Send completion message
     SNDDIAGMSG      Send diagnostic message
     SNDESCINF       Send escape information
     SNDESCMSG       Send escape message

Implementation
--------------

None, the tool is ready to use.

Objects used by the tool
------------------------

   Object        Type    Attribute      Src member    Src file
   ------        ----    ---------      ----------    ----------

   CRTCLPINS     *CMD                   TAACLRI       QATTCMD
   TAACLRIC      *PGM       CLP         TAACLRIC      QATTCL
   TAACLRIR      *PGM       RPG         TAACLRIR      QATTRPG
					

Added to TAA Productivity tools December 1, 2004


Home Page Up to Top