Natural ISPF Macros: An Alternative to Code CONSTRUCTion

CAUCUS in The Natural State
April 1994

Kathryn Cantrell
Computing Services
University of Arkansas, Fayetteville


Table of Contents

Introduction
What is the UAF Program Generator?
How Does It Work?
Template Components
Generate the Program
The Generated Program
Regeneration
Behind the Scenes and Techniques Used
Conclusion


Introduction

Like most universities and businesses, the University of Arkansas is interested in ways to decrease development time and increase productivity. With the advent of an internal rewrite of our financial and human resources systems, this interest became a pressing need. Since 1988, the University had had in place a successful architecture for its online Natural systems - the Natural Secured Menus Architecture (NSM). In 1991, we investigated Software AG's CONSTRUCT. CONSTRUCT is a complex product, and the recommendation was made that if this product were purchased, much internal training would be required. In addition, since we already had a successful architecture in place, we would be required to learn how to make our own models for CONSTRUCT.

Natural ISPF was purchased in 1991, and a subsequent version contained the macro facility. In early 1992, along with the planned enhancements to our architecture for the upcoming rewrite of the financial and human resources systems, we decided that a code generator might be developed using these macros. New models for the architecture were already planned, and macros could be written to generate the code for those models.

Initial experimentation with the macros yielded a few problems. We wanted a way to save the variables used to generate the code, and that would require an additional file. Also, if we used copycode for the common code that should not be altered by the programmer, we would have to keep numerous versions of the copycode so that older programs not using the updated copycode would still compile.

In response to these concerns, we examined edit macros. Edit macros, like regular macros, generate text, in this case Natural code. But an edit macro provides a means of saving the variables and their values for future regeneration. This ability, therefore, eliminates the need for an external file. Furthermore, the lines of code generated by the edit macro are protected from entry in the ISPF Natural Editor, thereby abolishing the necessity of maintaining separate versions of copycode that would be necessary as the models evolved. This ability also means that the generated program code conforms to our architecture standards. With edit macros, the program need only be regenerated in order to be updated with the latest model code. For these reasons, we chose to develop our internal code generator with Natural ISPF Edit Macros.

The generator developed using edit macros is one that the programmer can learn easily, as this paper will show. Very little training is required, and even a novice Natural programmer in a relatively short period of time can generate sophisticated, full-featured online function modules.


What is the UAF Program Generator?

The UAF Program Generator is a collection of Natural ISPF edit macros designed to generate programs that conform to University of Arkansas, Fayetteville standards. The macros create the specified program from a tested and de-bugged model (contained within the macros) utilizing variables input by the programmer. These variables are used to customize the code by replacing a macro variable (e.g. #DESCRIPTOR) with the value the user supplies (e.g. APPLICATION-ID). In this way, the programs are standard, and yet are regenerable at any time to use the most up-to-date models.

The program generator actually has two components: the 'driver' edit macro that is used by the programmer to generate the program, and template components - local data areas and maps - for each model. The 'driver' edit macro presents the screen that contains the required variables for that particular model's program generation process. The template components are Natural objects that cannot be generated but are required for a model. The shell for the component is provided as a starting point for the creation of the supporting object.

Because the lines generated by the edit macro are protected, modifiable blocks of code are included in the generated output. These allow the programmer control over code that may need to be customized and locations where code may need to be added. Program statements contained inside the user-edited blocks are not altered in the regeneration process.


How Does It Work?

The first step in the generation process is the determination of the correct model to use. Currently, the University has developed edit macros for online programs only; batch models are planned for the future. These online programs include four utility models, six file maintenance models, and four list models to list data for browsing. If, for instance, the program is to perform file maintenance, then the programmer must determine which of the file maintenance models to use. The program generator documentation details all models and describes their use.


Template Components

Once the programmer determines the appropriate model, the next step is to develop the required component parts using the templates provided. Templates are stored on the SYSTEM library and are copied by the programmer into the specific library where the program is to be developed. Our naming convention makes it easy for the programmer to determine the appropriate template. All edit macros begin with 'pgz', which stands for program generator and type z (macro), and ends with the model name (e.g. pgzmsf is the driver edit macro for the Multi-Screen Function model); all template components begin with 'xxt', where the 'xx' indicates that it is a template component and the 't' is the type of template: 'L' for local data area, "G' for global data area, or 'M' for map. Thus, if the programmer is using the MSF model, the driver edit macro he needs is PGZMSF, the template local data area is XXLMSF, and the template map is XXMMSF.

There are two types of templates: data areas and maps. For an online program, the programmer should create the required local data area prior to the map since many fields from the lda must be brought in from that object and placed on the map due to the heavy use of data structures (see Behind The Scenes on page 11 for more details). Figure 1 shows the template local data area used for the "regular" file maintenance model, which is called a Multi-Screen Function (MSF).

Figure 1. Template Local Data Area for Multi-Screen Function


Local     XXLMSF    Library SYSTEM                             DBID   1 FNR
Command
>
I T L Name                             F Leng Index/Init/EM/Name/Comment
Top - -------------------------------- - ---- --------------------------------
  *   Template local data area for
  *   Multi-Screen Function Module            /* MSF - NSM V2
  *
  *   Modifiable Screen Elements
    1 MSE                                     /* DON'T include keys here
    2 field-name
  *   Data Base View
  V 1 DBV                                     view-name
  *   HistoGram View fields
  V 1 HGV                                     view-name
    2 key-field
  R 2 key-field                               /* REDEF. BEGIN : key-field
    3 HIST-SEARCH-KEY                         /* Format must match Search Key
  *   Search Key Structure
    1 SKS
    2 major-key
    2 minor-key
  R 1 SKS                                     /* REDEF. BEGIN : SKS
    2 #SEARCH-KEY                             /* Search Value for Find
  *   Display Key Structure
    1 DKS
    2 major-key                               /* If keys are not specified
    2 DKS-FILLER-1                     A    1 /* here, #DISPLAY-KEY must be
    2 minor-key                               /* level 2 field (no redef.)
  R 1 DKS                                     /* REDEF. BEGIN : DKS
    2 #DISPLAY-KEY                     A
  *   DeCode Fields
    1 DCF
    2 field-name
  *   Local variables & other
  *     data base views
Template objects are designed so that the programmer knows what to replace and what is required. Lower case words indicate the replacement by the programmer with the proper field names. Upper case signifies that the structure name (e.g. MSE for Modifiable Screen Elements) is a required name for that structure. In this case, the programmer would place the appropriate fields in the MSE structure, bring in (via the .V command) the database fields needed for the DBV structure and the proper key for the HGV (HistoGram View) structure, and place the key field names in the SKS (Search Key Structure) and DKS (Display Key Structure). The DCF, DeCode Fields, structure is optional. The last comment indicates the area where other local variables and database views should be placed, if needed.

Though the local data area is not required for program generation of virtually all the models, its completion prior to generating the program helps the programmer ascertain the needs of the program and aids in the determination of the correct values of the macro variables required by the program generator. For this same reason, the function's map should also be created prior to the generation of the program.

Like template local data areas, template maps are skeleton maps that contain required elements, such as PF-Key processing rules and other fields and parameter fields, and also aid the programmer in the determination of required fields by means of upper and lower case text. Figure 2 shows the template map for the Multi Screen Function module.

Figure 2. Template map for Multi Screen Function model


+XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX+MMMMMMMM+MMMMM
  Command:&XXXX ?Action:&X ?BKF.key:&XXXXXXXX
 
 -------------------------------------------------------------------------------
   Action:(X  SKS.key:(XXXXXXXX
   Screen&9 of(9
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 Off screen elements: +X +X +X +X +X +X +X +9 +X +X
This first line of the map contains two standard fields required on all of our online maps, as well as the system date and time. Because the programmer copies the template map, these fields are already there and need no alteration. Command and Action also identify fields that are required and needn't be changed. The remaining fields in our 'banner' are key fields used in the online program. These are defined in the global data area for the application and are always under the structure BKF, Banner Key Fields. The programmer must include all the necessary Banner Key Fields by bringing them in from the global data area. This requirement is identified by the 'BKF.key' tag and its associated field BKF.KEY on the second line of the map. Again, the lower case 'key' tells the programmer to replace the field with the appropriate key field from the required structure BKF in the global data area. The 'SKS.key' works the same way; from the lda the programmer just created he brings in the appropriate field from the SKS structure and places it on the map.

Standard PF-Key processing rules that are required by our architecture and by the specific model are also included on the template map. Those PF-Key processing rules that will not be altered by the programmer are stored as Free Rules in Predict and are protected from modification within the map by the programmer. Figure 3 shows the listing of all PF-Key processing rules included on the Multi-Screen Function model template map.

Figure 3. PF-Key Processing Rules on a Multi-Screen Function template map


 13:19:41               Select a processing rule by rank
04/13/94
 
 Rk Typ Field Name / Rule Name / Source Code
 -- --- ------------------------------------------------------------------------
  0 Fre NS-PFKEY-KEY-VALIDATION
  1 Fre NS-PFKEY-FM-RANK1
  2 Inl * Determine if new keys have been entered in the banner
        *
        IF BKF.#ACTION-REQUESTED NE CFF.#ACTION-IN-PROCESS OR
  3 Fre NS-PFKEY-FM-RANK3
 50 Fre NS-PFKEY-FM-RANK50
 99 Fre NS-VALID-SCREEN
 
 
 
 
 
 
 
 
 
 
 __ Select rank
The only inline rule on this list is the rank 2 rule. This rule, included on all of our maps, determines if new keys have been entered in the banner area, and it must be modified by the programmer. Like the template local data area, the inline processing rule contains lower case text to tell the programmer what to modify. The programmer will also encounter this technique in the generated program. Figure 4 displays this inline rule.

Figure 4. Inline Rank 2 PF-Key Processing Rule of Multi-Screen Function Map


Rule ________________________________       *PF-KEY RULE
 >                                      > + Rank 2     S 6   L 1
Struct Mode
 ALL
 ...+....10...+....+....+....30...+....+....+....50...+....+....+....70.
   0010 * Determine if new keys have been entered in the banner
   0020 *
   0030 IF BKF.#ACTION-REQUESTED NE CFF.#ACTION-IN-PROCESS OR
   0040    BKF.key-field NE SKS.key-field
   0050   ASSIGN CFF.#NEW-KEYS = TRUE
   0060 END-IF
   0070
   0080
   0090
   0100
   0110
   0120
   0130
   0140
   0150
   0160
   0170
   0180
 Enter-PF1---PF2---PF3---PF4---PF5---PF6---PF7---PF8---PF9---PF10--PF11-
-PF12---
       Help  Mset  Exit  Test        --    -     +     Split Sc=Let
As this figure shows, the programmer need only supply the proper key field name for 'key-field'. If there are multiple keys that should be checked, then the programmer simply inserts another 'OR' statement.

Generate the Program

Once the local data area and map are completed, the programmer may generate the program. This is the easiest step of all! To generate a new program, the programmer must initiate the command from ISPF. Three elements are required: the Library in which the generated program is to be saved, the program name, and the driver edit macro for the appropriate model. Figure 5 shows an example of using the ISPF Natural Editor to accomplish this process.

Figure 5. Generation Command Input on ISPF Natural Editor Menu


--------------------- NATURAL OBJECTS - ENTRY PANEL -------------------------
COMMAND ===>
 
 
   Library       ===> nsm-ms
   Member        ===> nsou
   Type          ===>                         (Blank,P,S,N,C,M,G,L,A,H,T,Z )
   Status        ===>                         ( Blank,S,C,OS,OC)
   Scan for      ===>
   Edit macro    ===> pgzmsf
   Set number    ===>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
There is also a direct command that may be issued from the Command line on any Natural ISPF screen in the form Edit NAT library(pgmname) MACRO=macro-name. An example of this method is E NAT NSM-MS(NSOU) MACRO=PGZMSF.

Once this command has been issued, a screen is presented on which required macro variable values are entered. Figure 6 shows the screen presented for the Multi-Screen Function model and its macro variables.

Figure 6. Program Generator Screen for Multi-Screen Function


Enter program generation parameters and press ENTER to validate MSF
04/13/94 13:24
 
               Fields for Multi-Screen Function Modules
 
 
   NSM Application Id: NS-DEVL       Command-Id:
   Number of Screens: 1              Screens valid for decode:
   Valid Actions: VAUCD              Additional LDAs?  N (Y/N)
   Descriptor:
   Superdescriptor?  N (Y/N)
 
   Key Field Position:               Action Field Position:
   Entry Field Position:
 
 
   Remarks:
 
 
 
 
 
 Enter-PF1---PF2---PF3---PF4---PF5---PF6---PF7---PF8---PF9---PF10--PF11--PF12---
                   Quit                                      Save  Cmts
This screen presents the macro variables needed for this model's generation process. Some of the fields may be initialized, as is the case of Application ID, Number of Screens, and Valid Actions, but the programmer may change these values. There are also edits on this map to validate input before generation of the program can continue.

Our architecture designates PF10 as the 'Save' key: no changes are made to the database until PF10 is pressed. To remain consistent with this philosophy, PF10 is also the 'Save' key for the program generator. When PF10 is pressed, the program will actually be generated and placed in the ISPF Natural editor.

Another PF-Key that was a later addition is PF11 (Cmts). When PF11 is pressed, comments concerning modifications made to the model are displayed in a window. These update comments are stored on the driver edit macro and follow a standard format: 'Updated: mm/dd/yy initials of programmer and a description of the modification made.' The comments are displayed beginning with the last date of generation (or regeneration). If this is a new program generation, all update comments are listed.

These comments can be particularly helpful to the programmer who is regenerating and wants to know how and why the model changed. Because regeneration does not alter the modifiable blocks, the programmer must determine if code in these blocks needs to be modified to correspond with those changes. Figure 7 is an example of the PF11 function.

Figure 7. Update Comments Window for Multi-Screen Function model.


Enter program generation parameters and press ENTER to validate MSF
04/13/94 13:24
 
 +----------------------Update Comments for MSF Model----------------------+
 | Press ENTER or PF8 to view more comments                                |
 |                                                                         |
 |  Updated: 08-04-92 KC - changed Decide on PFKey and added mod. block    |
 |    for post-pfkey processing.                                           |
 |  Updated: 09-01-92 KC - changed DB-ACCESS routine to move SKS instead   |
 |    of BKF to DBV if key not exist                                       |
 |  Updated: 11-02-92 kc - reversed order of DB-ACCESS & VALIDATE-ACTION   |
 |    subroutines, modified VALIDATE-ACTION to use #EFFECTIVE-ACTION,      |
 |    and added ck of db-keys after a suspend.                             |
 |  Updated: 12-17-92 kc; took Reset DCF out of mod. block.                |
 |  Updated: 01-28-93 kc; moved assignment of #PS-PF-KEY to directly       |
 |    after Input of map and before mod. block.                            |
 |  Updated: 02-24-93 kc; added #ADDITIONAL-LDAS and code for it.          |
 |  Updated: 04-20-93 KC; added INCLUDE xxCSETAE commented out in          |
 |    pre-map mod. block; Enhanced Invalid Action message to include       |
 |    #FM-ACTIONS.                                                         |
 |  Updated: 05-24-93 KC; Added #APPARENT-ACTION and code for it; also     |
 |                                                                         |
 |      PF3=Quit  PF5=RStrt  PF6=CDate  PF8=Forwd                          |
 +-------------------------------------------------------------------------+
PF8 can be used to page forward through the comments, and PF5 will perform a Restart and begin the list at the first 'page' of comments. PF6 may be used to change the beginning date of the displayed comments.

The Generated Program

When PF10 is pressed, the generated program is placed in ISPF's Natural Editor. The programmer may then modify the code in the modifiable blocks and stow the program. Figure 8 shows a portion of a generated Multi-Screen Function module.

Figure 8: Portion of the Generated Multi-Screen Function module


EDIT-NAT:NSM-MS(NSOU)-Program->Struct-Free-27K ------------- Columns 001 072
  COMMAND===>
SCROLL===> CSR
 ****** ****************************** top of data*****************************
 =p0010 ***M     GENERATED USING;PGZMSF
 =p0020
**********************************************************************
 =p0030 *  Program:     NSOU
 =p0040 *  Generated:   04/13/94 by Kathryn Cantrell using MSF
 =p0050 *  Regenerated:
 =p0060 *
 =p0070 *  Remarks:   This program performs User maintenance.
 =p0080 *
 =p0090 *
 =p0100 ***MBB UPDINFO
 000110 * OPTIONAL: Additional remarks and update information
 000120 *  Updated:   mm/dd/yy, name & change description
 =p0130 ***MBE
 =p0140
**********************************************************************
 =p0150 *
 =p0160 DEFINE DATA
 =p0170 GLOBAL USING NSGLOBAL
 =p0180 LOCAL USING NSLMSF
 =p0190 LOCAL USING NSLU
 =p0200 END-DEFINE
 =p0210 *
 =p0220 * Initialization
 =p0230 *
 =p0240 RESET #COMMAND-ID-ISSUED #PS-PF-KEY
 =p0250 ASSIGN #CURRENT-MENU-COMMAND-ID = #PREVIOUS-MENU-COMMAND-ID
 =p0260 ASSIGN #NEW-KEYS = TRUE
 =p0270 ASSIGN #CMD-NOT-PF2-AND-WARNED = FALSE
 =p0280 ASSIGN #CURRENT-PROGRAM = *PROGRAM
 =p0290 ASSIGN #TAC-CMD-ID = #CURRENT-COMMAND
 =p0300 ASSIGN #CURRENT-LEVEL = *LEVEL
 =p0310 ASSIGN #CURRENT-TITLE = #GDA-TITLE
 =p0320 ASSIGN #CURRENT-SECURITY-LEVEL = #GDA-SECURITY-LEVEL
 =p0330 *
 =p0340 ASSIGN #MAX-SCREEN = 2
 =p0350 ASSIGN #KEY-FIELD-POSITION = 3
 =p0360 ASSIGN #ACTION-FIELD-POSITION = 2
 =p0370 ASSIGN #ENTRY-FIELD-POSITION = 5
 =p0380 ASSIGN #FM-ACTIONS = 'VAUCD'  /* Actions permitted
 =p0390 ASSIGN #PF4-VALID(1) = TRUE
 =p0400 ***MBB INIT
 000410 * OPTIONAL: Initialize additional fields
 =p0420 ***MBE
 =p0430 *

As Figure 8 shows, an '=p' in the prefix area indicates that these lines are protected from entry in this editor. The modifiable blocks are identified by '***MBB' followed by a name (e.g. INIT), and the end of the block is referenced with '***MBE'. Each modifiable block begins with a tag; either 'REQUIRED' or 'OPTIONAL'. Those blocks that are required for entry by the programmer are identified by the tag 'REQUIRED', while the optional blocks, or sections of blocks, are labelled 'OPTIONAL'. In both cases, a description of the code desired follows the label. The user supplied code is not limited by these descriptions, and, in the case of the optional code, serves as a guideline to the programmer. Skeleton blocks of code may also be generated within the modifiable blocks to aid the programmer in customizing the code. If these skeleton blocks are used, modifications to them are generally indicated by words in lower case, while the upper case data should remain untouched.

After making the appropriate code changes and/or additions, now all the programmer must do is stow and test the program.


Regeneration

Regeneration is simply the method of rebuilding an existing program that was previously generated using a specific edit macro. Regeneration can be done at any time but is only useful when the model has changed or the program is to be generated with different user input. For instance, the programmer may change the value of a macro variable at the time of regeneration. Regeneration will automatically recreate all write-protected lines of code; modifiable blocks are merely copied from the original version of the program.

Regeneration is accomplished either by the same method used to generate a new program, or the REGENERATE command can be issued while editing the program in the ISPF Natural Editor.


Behind the Scenes and Techniques Used

Each model actually is contained within multiple edit macros due to size constraints that exist for edit macros. The driver edit macro not only presents the screen with the required macro variables, but it also does a fetch return to other edit macros to build the entire program. These macros contain the code that will become the generated program. The driver edit macro also saves the variables and their values at the end of the program, and, on regeneration, reads in these values and presents them on the map. Each driver edit macro has a local data area that contains the variables that need to be saved. Figure 9 shows the driver edit macro for the Multi-Screen Function model.

Figure 9: Driver Edit Macro for the Multi-Screen Function model.

000010 @**********************************************************************
000020 @ * Macro  : PGZMSF - macro driver for Multi-Screen Function modules
000030 @ * Author : Kathryn Cantrell
000040 @ * Written: 07-22-92
000050 @ *
000060 @ * Model modifications:
000070 @ * Updated: 08-04-92 KC - changed Decide on PFKey and added mod. block
000080 @ *   for post-pfkey processing.
000090 @ * Updated: 09-01-92 KC - changed DB-ACCESS routine to move SKS instead
000100 @ *   of BKF to DBV if key not exist
000110 @ * Updated: 11-02-92 kc - reversed order of DB-ACCESS & VALIDATE-ACTION
000120 @ *   subroutines, modified VALIDATE-ACTION to use #EFFECTIVE-ACTION,
000130 @ *   and added ck of db-keys after a suspend.
000140 @ * Updated: 12-17-92 kc; took Reset DCF out of mod. block.
000150 @ * Updated: 01-28-93 kc; moved assignment of #PS-PF-KEY to directly
000160 @ *   after Input of map and before mod. block.
000170 @ * Updated: 02-24-93 kc; added #ADDITIONAL-LDAS and code for it.
000180 @ * Updated: 04-20-93 KC; added INCLUDE xxCSETAE commented out in
000190 @ *   pre-map mod. block; Enhanced Invalid Action message to include
000200 @ *   #FM-ACTIONS.
000210 @ * Updated: 05-24-93 KC; Added #APPARENT-ACTION and code for it; also
000220 @ *   added assignment of #APPARENT-ACTION = V in processing loop
000230 @ *   if any key error; moved PERFORM INITIALIZE-VALUES outside of
000240 @ *   IF statement so that it is always executed on new keys;
000250 @ *   added error msg. for invalid action resulting from a Copy;
000260 @ *   deleted line that assigned MSE.TIME-STAMP (field was moved from
000270 @ *   MSE to CFF); moved INCLUDE xxCSETAE from PREMAP to NKRESET; and
000280 @ *   modified to use *PF-NAME variable.
000290 @ * Updated: 08-31-93 KC; Modified PROCESS-COMMAND so that PF2 is not
000300 @ *   allowed to a UA function (LOG, FIN, CDCD).
000310 @ * Updated: 10-14-93 KC; added #PS-PF-NAME & code for it.
000320 @ * Updated: 10-19-93 KC; modified DECIDE ON to use #PS-PF-NAME.
000330 @ *
000340 @ * Remarks: This macro invokes other macros as necessary to generate
000350 @ *          the online Multi-Screen Function Module program.
000360 @ *
000370 @ * MACRO modifications:
000380 @ * Updated: 12-07-92 KC; added SET CONTROL 'L' to allow
000390 @ *   mixed case on entry.
000400 @ * Updated: 02-01-93 KC; corrected input parms for PGZMSF3.
000410 @ * Updated: 03-29-93 kc; added #DECODE-VALID-FOR-SCREENS(*) to #4
000420 @ * Updated: 10-15-93 kc; removed #VALID-PF-KEYS; new rule uses *PF-NAME
000430 @ * Updated: 10-28-93 kc; revised macros to be used with TARGET MSF.
000440 @ * Updated: 11-02-93 kc; added PF11 (Cmts) to show update comments.
000450 @
**********************************************************************
000460 @ *
000470 @ DEFINE DATA
000480 @ LOCAL USING PGLMSF
000490 @ LOCAL
000500 @ 1 #LOCALS
000510 @  2 #APPLICATION-PREFIX (A2)
000520 @  2 #BY                 (A2)
000530 @  2 #USER               (A8)  /* user's id
000540 @  2 #AUTHOR             (A32) /* user's name returned from subprogram
000550 @  2 #MODEL              (A8) INIT<'MSF'>
000560 @  2 #WARNED             (L)   /* only used for TARGET MSF
000570 @  2 #DATE-PARM          (D)
000580 @  2 #PROMPT             (A65)
000590 @ END-DEFINE
000600 @ *
000610 @ SET CONTROL 'L'    /* allow mixed case on input
000620 @ *
000630 @ GET-DATA
000640 @   USING PGLMSF
000650 @ END-GET
000660 @ *
000670 @ IF #NSM-APPLICATION-ID = ' '
000680 @   ASSIGN #NSM-APPLICATION-ID = *APPLIC-ID
000690 @ END-IF
000700 @ *
000710 @ #PROMPT := 'Enter program generation parameters and press ENTER'-
000720 @  ' to validate'
000730 @ *
000740 @ INPUT-LOOP.
000750 @ REPEAT
000760 @ INCLUDE UACPFKEY
000770 @ SET KEY PF10 NAMED 'Save'
000780 @ SET KEY PF3 NAMED 'Quit'
000790 @ SET KEY PF11 NAMED 'Cmts'
000800 @ *
000810 @ INPUT WITH TEXT #PROMPT
000820 @   USING MAP 'PGMMSF'
000830 @ *
000840 @ DECIDE ON FIRST VALUE OF *PF-KEY
000850 @  VALUE 'PF3'
000860 @    ESCAPE ROUTINE   /* must force it to quit out of generation
000870 @  VALUE 'PF10'
000880 @    ESCAPE BOTTOM (INPUT-LOOP.)
000890 @  VALUE 'PF11'
000900 @ * determine the date last generated or re-generated
000910 @    IF #REGEN-BY-USER = ' '  /* hasn't been regenerated yet
000920 @      #DATE-PARM := #DATE-GENERATED
000930 @    ELSE
000940 @      #DATE-PARM := #DATE-REGEN
000950 @    END-IF
000960 @    CALLNAT 'PGNRDCMT' 'PGZMSF  ' #DATE-PARM
000970 @    #PROMPT := 'Comments displayed; press PF10 to generate '-
000980 @      'your program'
000990 @  NONE       /* must be Enter
001000 @     #PROMPT :=
001010 @       'All entries are valid; press PF10 to generate your program'
001020 @ END-DECIDE
001030 @ END-REPEAT
001040 @ *
001050 @ * Lookup the application and get the prefix
001060 @ *
001070 @ FIND (1) APPLICATION WITH APPLICATION-ID = #NSM-APPLICATION-ID
001080 @   ASSIGN #APPLICATION-PREFIX = APPLICATION-PREFIX
001090 @ END-FIND
001100 @ *
001110 @ ASSIGN #USER = *USER
001120 @ CALLNAT 'NSNREADU' #USER #AUTHOR
001130 @ *
001140 @ IF #GEN-BY-USER = ' '
001150 @   ASSIGN #GEN-BY-USER = #AUTHOR
001160 @   ASSIGN #DATE-GENERATED = *DATX
001170 @ ELSE
001180 @   ASSIGN #DATE-REGEN = *DATX
001190 @   ASSIGN #REGEN-BY-USER = #AUTHOR
001200 @   ASSIGN #BY = 'by'
001210 @ END-IF
001220 @ *
001230 @ FETCH RETURN 'PGZBANR' #APPLICATION-PREFIX #COMMAND-ID #REMARKS(*)
001240 @   #MODEL #DATE-GENERATED #GEN-BY-USER #DATE-REGEN #REGEN-BY-USER #BY
001250 @ FETCH RETURN 'PGZMSF1' #APPLICATION-PREFIX #COMMAND-ID
001260 @   #ADDITIONAL-LDAS #NO-OF-SCREENS #KEY-FIELD-POSITION
001270 @   #ACTION-FIELD-POSITION #ENTRY-FIELD-POSITION
001280 @   #VALID-ACTIONS #SCREENS-VALID-FOR-DECODE(*)
001290 @ FETCH RETURN 'PGZMSF2' #APPLICATION-PREFIX #DESCRIPTOR
001300 @   #SCREENS-VALID-FOR-DECODE(*) #COMMAND-ID #NO-OF-SCREENS #MODEL
001310 @ FETCH RETURN 'PGZMSF3' #DESCRIPTOR #SUPERDESCRIPTOR-FLAG
001320 @   #NO-OF-SCREENS #MODEL
001330 @ FETCH RETURN 'PGZMSF4' #COMMAND-ID #NO-OF-SCREENS
001340 @   #DESCRIPTOR #SCREENS-VALID-FOR-DECODE(*) #MODEL #DECODE
001350 @ *
001360 @ SAVE-DATA ALL
001370 @ * Must generate last line of pgm so that edit macro saves the last
001380 @ *  variable
001390 END

As the figure shows, the screen that is presented by the driver edit macro upon generation is a Natural map. Macro variables can be easily added, and processing rules on the fields help prevent inaccurate data entry.

The statements used to retrieve and save the values of these macro variables are the GET-DATA USING PGLMSF statement and the SAVE-DATA ALL, respectively. Macros are fetched using the FETCH RETURN statement so that control is passed back to the driver macro for completion of the code generation. There are a few edit macros that generate common code and which are included in multiple driver edit macros. For example, PGZBANR generates our comment area (name of program, author, date written, and update information) for each program. This macro is always the first one fetched by the model's driver edit macro.

For closely related models, we have used edit macros for multiple models, though each has its own separate driver edit macro. For example, the MSF macros PGZMSF2, PGZMSF3, and PGZMSF4 are used for three separate models: the Multi-Screen Function, the TARGET Multi-Screen Function (contains electronic forms processing capabilities), and the TARGET PE Group Maintenance (Periodic Group maintenance with electronic forms processing). This minimizes the number of edit macros that must be maintained, but it also significantly complicates the edit macro code.

We have employed several techniques to decrease the need for customization by the programmer of the generated code -- and therefore reduce also the number of modifiable blocks needed in the program. Heavy use is made of structures; the local data area supplies the required structure names (e.g. MSE, DBV, SKS), and MOVE BY NAME statements in the program accomplish the assignment of values to the appropriate variables. For example, the MSE, Modifiable Screen Elements, contains the fields displayed on the online map that are modifiable by the user. The DBV, DataBase View, contains the needed fields from the view of the primary file. If the requested key exists, a MOVE BY NAME DBV TO MSE assigns the proper values to each of the fields in the MSE so the user may update the data. When the user presses PF10 to save his changes to the database, another MOVE BY NAME MSE TO DBV assigns the modifiable values to the fields in the database. This results in less customization of the code since the actual field names are located in the lda, and yet the MOVE BY NAME statements make the desired assignments. Fields within structures can also be reset with the RESET statement (e.g. RESET DCF resets all fields under the DeCode Field structure).

In a similar manner, redefinitions of whole structures in the local data area are employed. The Search Key Structure, SKS, defines the key field(s) used for the database access. The entire structure is then redefined into #SEARCH-KEY. The database access statement then uses #SEARCH-KEY to find or read the record. For instance, this statement in the MSF model program is FIND (1) RECORD IN FILE DBV WITH USER-ID = #SEARCH-KEY.

We have also made extensive use of standard variables. Each model has a separate local data area in which these standard variables are defined, and the lda is stored on SYSTEM. For instance, the inline rank 2 on the map sets a logical variable, #NEW-KEYS, to true when the banner key fields have been modified (see Figure 4 on page 6).

It is the external components - the local data area and the map - that define the unique characteristics of a function. The use of these components, instead of coding these attributes directly into the program, reduces both the standard and customized code in the program. Within the framework of the program generator, this significantly reduces the number of modifiable blocks.

Though our intention was to eliminate the maintenance of various versions of copycode, copycode still plays an important role in optimizing the code generator. Common code that is stable and highly unlikely to change is stored in a copycode member that is then included in the protected lines of the generated program. NSCVCSV is a copycode that calls a subprogram that validates the command entered by the user. This code is included in every model.

The macros themselves are also written so that programmer customization is kept to a minimum. Particular code can be generated based upon the value of a macro variable. For example, if the programmer says that there will be a decode function, then the necessary SET KEY statement for PF4 is generated. A modifiable block may also be conditionally generated. All models provide, via a macro logical variable, the ability to code an additional LOCAL USING statement in the DEFINE DATA. If this variable is true, then a modifiable block labelled 'ADDLDA' is placed in the code. If the program is later regenerated and the logical is changed to false, the entire modifiable block is eliminated.


Conclusion

The University of Arkansas, Fayetteville's program generator has accomplished our goals. It provides the most recent version of standard models, a simple way to construct programs using model-dependent variables, and modifiable blocks of code within the generated program that enable the programmer to customize the resulting program to fit the individual needs of the function. Because the edit macros allow for user input variables to be saved within each generated program, there is no need to store the generation parameters externally.

The program generator saves development time because the difficult work of creating and testing a model has been accomplished. The programmer does not have to code and test common PF-Keys, for example. This capacity also means that the programmer can concentrate on the unique aspects of his program. For many applications, online programs can be developed faster and the code will be efficient. Even novice Natural programmers can develop, test and place in production online modules within a relatively short period of time. In-depth knowledge of Natural and the models is not a requirement for simple online programs. Perhaps most important, the code generator enforces architecture standards.

At the present time, six University analysts use the program generator for development of the new financial and human resources systems. With increased use of the models, needs were discovered that the models did not address or did not properly address. In some cases, modifiable blocks were added. This we expected, and in most cases the programmers merely regenerated to update their programs. The program generator has reduced development time, while at the same time producing quality, tested, and complex online programs. That is a mark of success.