CAUCUS in The Natural State
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.
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.
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.
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
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
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
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
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 ===>
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
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 | +-------------------------------------------------------------------------+
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 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.
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.
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.