Appendix E:  3GL External Procedure Calling

Introduction

External 3GL procedures may be called with the @CALL System Function for those occasions when it is expedient to perform a task outside of the ACCENT R environment.  VAX/OpenVMS systems and any language run-time libraries that conform to the VAX calling standard may be called from ACCENT R.  The @CALL System Function is especially useful for integrating with existing applications which rely on procedure libraries in order to perform calculations and field edits, calling special purpose libraries such as graphics and statistical function libraries, and calling OpenVMS run-time library routines.  The libraries that are linked can be protected with normal OpenVMS file security masks.  External 3GL procedures can be called from any level, module, or 4th Generation Tool of ACCENT R.  This section describes 3GL External Procedure calling for VAX/OpenVMS systems only.  This option is available as part of the ACCENT R Host Language Interface extra-cost option.

External procedures should only be used to augment application development and not to replace functions already provided in ACCENT R.  External procedure calling from ACCENT R is an extremely efficient means for interfacing with 3GL procedure libraries since the routines occupy the same memory and resources as the calling program.  In general, external routines which display text to the screen should be avoided since ACCENT R’s Window Development Language does not have any knowledge of the location of the text.  This section provides examples of calling 3GL routines from C, COBOL, and FORTRAN.

The @CALL System Function calls a separate program image in order to execute the procedure call.  The default name for the program image is ACCEXT.EXE, or another name can be specified.  This program can be built with the ACCEXT_BUILD command procedure.

If ACCENT R is installed with privileges, the ACCEXT.EXE program image must also be installed in memory.  ACCENT R can call routines linked in program images from any logical name or subdirectory, so system managers would be well advised to examine shareable images thoroughly before installing them in memory with privileges.

3rd Generation Language Integration Strategies

Applications which were previously developed in a 3GL can be tightly integrated with the ACCENT R environment.  Consider each of the following scenarios in order to gain an understanding of which strategy best supports your needs.

1.      ACCENT R and 3GL programs must access the same historical data base.

Recommendation:  Leave the existing programs intact to avoid rewriting applications.  Develop menu systems in ACCENT R with OSQL MENU and respond to enhancement requests with new modules in ACCENT R.  Use the ACCENT LINK command and the SMF Window Development Language to create a consistent end-user interface.  Avoid development in the 3GL.

2.     ACCENT R must support migration to the new data base structure.  ACCENT R and 3GL programs must access the same historical data base.

Recommendation:  Move existing data definitions into ACCENT R and make changes to reflect the current environment.  Use OSQL and the 4th Generation Tools to prototype the new system rapidly and gain feedback from the analysts and the user community.  Develop new modules in ACCENT R and evolve away from the old system.

3.    ACCENT R must support migration to the new data base structure.  ACCENT R must provide the ability to call existing 3GL libraries.

Recommendation:  Use ACCENT R as in scenario number 2 above.  Use the external calling capability of ACCENT R to set up 3GL triggers at any level within the application.  Use the 3GL to perform special purpose functions instead of rewriting these in the 4GL.

Data Sharing Within Shareable Libraries

If the 3GL compiler which you are using creates program sections, or PSECTs, which are writeable and shareable, the ACCEXT.EXE program image needs to be installed with shared write attributes.  However, there is the potential that this data may be overwritten by several processes which are calling routines in the ACCEXT image.

It is possible to prevent this problem by performing these steps:

1.     Examine the Program Section Synopsis of the map file and find those PSECT's with attributes listed as SHR and WRT.  If you do not want the data to be shared, record the name of that PSECT.

2.     Create a link options file with the file extension .OPT, or edit the default link options file, ACCEXT_WRK: ACCEXTOPT.OPT, if this is the second time you are executing ACCEXT_BUILD.  Add a line in the options file for each PSECT that you recorded in step 1 in the following form:

PSECT_ATTR=<psectname>,WRT,NOSHR

Each PSECT described in the link options file will have both the write and non-share attributes.

3.       Build the shareable image with ACCEXT_BUILD command procedure:

$ @NISUTL:ACCEXT_BUILD ACCEXTOPT.OPT/ACCOPTION

@CALL System Function for External Routine Calling

This System Function makes it possible to call 3rd Generation Language (3GL) routines from within all levels of ACCENT R.  You may call a 3GL from the SD, ID, DI, PM, CM, or CS objects.  A 3GL may also be called interactively from ACCENT R’s (Interactive Command Language).  Any number of shareable libraries may be called from the @CALL system function.  If you wish to call your own 3GL routines, see the following section on building shareable libraries from within ACCENT R.

SYNTAX

@CALL ('procedure_name', 'library_name', [\\argument_list\\]) TO status_flag

procedure_name

is the name of the 3GL routine you wish to call.  The routine must exist as an entry point into a shareable library in order to be called from ACCENT R.  The routine_name parameter must be enclosed with single or double quote marks.

library_name

is the name of the shareable library which contains the routine_name which you wish to call.  This library must be linked as a shareable image and must be installed in memory with the SYSLCK privilege along with ACCENT R.  If the shareable library does not reside in SYS$SHARE:, the name of the library must be preceded by a system-wide, executive mode logical name pointing to the location of the library.  The routine_name is located in library_name using the LIB$FIND_IMAGE_SYMBOL RTL service and is internally executed using the LIB$CALLG system service.  See the following topic entitled Linking Shareable Libraries for information about creating shareable libraries which are callable from ACCENT R.

argument_list

is the list of arguments, if any, which are to be passed to or returned from the routine which is being called.  If the called routine expects the arguments to be passed by descriptor, a valid descriptor must be described as an ACCENT R Group Field (see NOTES at the end of this topic).  If the called routine expects the arguments to be passed by reference, the address of the field containing the argument must be passed to the routine.  The address of the field being passed as an argument can be obtained with the @ADR System Function.

status_flag

the integer return status from the routine being called.  This return status contains diagnostic information about the procedure call just made if you are calling VAX/OpenVMS system library calls.  Normally this return flag is set to zero and will be returned as zero if the call was successful.

Examples

The following examples describe how to call a 3GL procedure from COBOL, FORTRAN, and C.  An additional example showing the calling procedure for VAX/OpenVMS system library routines is shown.  The final example demonstrates how to approach the solution in ACCENT R.  The text for these examples may be found in the DBL NISDATA:ACCEXM.

This Code Segment describes the screen which displays the results of the mortgage payment calculation for the examples which follow:

SEGMENT PAYMENT_SCN
LAYOUT SCREEN PAYMENT_SCN
/ FILL    11, 23, 8, 36, @SCN_NORMAL
/ SELECTION @SCN_UNDERLINE
/ BORDER @SCN_BOLD, "Mortgage Payment Calculation"
/ FIELD  1, 2, 40, @SCN_NORMAL, @PM_NAME, SHOW
/ PROMPT 3, 2, @SCN_NORMAL, "Number of Years:"
/ FIELD  3, 23, 8, @SCN_NORMAL, NYEARS:D, DEFAULT
/ PROMPT 4, 2, @SCN_NORMAL, "Principal:"
/ FIELD 4, 23, 8, @SCN_NORMAL, BAL:D, DEFAULT
/ PROMPT 5, 2, @SCN_NORMAL, "Interest Rate %:"
/ FIELD 5, 23, 8, @SCN_NORMAL, INTYR:D, DEFAULT
/ PROMPT 6, 2, @SCN_NORMAL, "Payment:"
/ FIELD 6, 23, 8, @SCN_NORMAL, PMT:D, SHOW
/ PROMPT 8, 2, @SCN_NORMAL, "Type CTRL-Z to Do, CTRL-G to Quit"
LAYOUT END
PAYMENT_SCN_ID, INT, MAX

  Mortgage Payment Calculation

   CALL_PAYMENT_COBOL

   Number of Years:          30

   Principal:            100000

   Interest Rate %:        12.5

   Payment:             1067.26

Type CTRL-Z to Do, CTRL-G to Quit

   Mortgage Payment Calculation Screen

VAX C Example

The ACCENT R program for calling the mortgage calculation procedure written in C is as follows:

! PM CALL_PAYMENT_C

DECLARE SECTION

 BAL,         FLOAT,       MAX,         2

 INTYR,       FLOAT,       MAX,         2

 PMT,         FLOAT,       MAX,         2

 NYEARS,      INT,         MAX

 INCLUDE PAYMENT_SCN FROM CS PAYMENT_SCN

DETAIL SECTION

 GENERATE PAYMENT_SCN:D TO PAYMENT_SCN_ID:D
 SCREEN PASTE_WINDOW USING PAYMENT_SCN_ID:D, 11, 23

 START
   FILL PAYMENT_SCN_ID:D FOR CHANGE
 LEAVE IF @FILL_ACTION = 'CANCEL'
   @CALL("PAYMENT_C", "ACCEXT_LIB:ACCEXT", @ADR INTYR:D, &
   @ADR NYEARS:D, @ADR BAL:D, @ADR PMT:D) TO @INTEGER
 REPEAT

 SCREEN UNPASTE_WINDOW USING PAYMENT_SCN_ID:D

This is the C procedure which performs the mortgage payment calculation.

/*
   Calling C from ACCENT R -- Calculate a mortgage payment
*/
#include math
payment_c (intyr, nyears, bal, pmt)
         double *intyr;
         int *nyears;
         double *bal;
         double *pmt;
         {
         double intmo;
         int npmts;
         intmo = *intyr / 12. / 100.;
         npmts = *nyears * 12;
         *pmt = *bal * (intmo/ (1. - pow(1. + intmo, - npmts)));
         }

VAX COBOL Example

The ACCENT R program for calling the mortgage calculation procedure written in COBOL is as follows:

!
DECLARE SECTION
BAL,         FLOAT,       MAX,         2
INTYR,       FLOAT,       MAX,         2
PMT,         FLOAT,       MAX,         2
NYEARS,      INT,         MAX
INCLUDE PAYMENT_SCN FROM CS PAYMENT_SCN
DETAIL SECTION
GENERATE PAYMENT_SCN:D TO PAYMENT_SCN_ID:D
SCREEN PASTE_WINDOW USING PAYMENT_SCN_ID:D, 11, 23
START
FILL PAYMENT_SCN_ID:D FOR CHANGE
LEAVE IF @FILL_ACTION = 'CANCEL'
@CALL("PAYMENT_COBOL", "ACCEXT_LIB:ACCEXT", @ADR INTYR:D, &
@ADR NYEARS:D, @ADR BAL:D, @ADR PMT:D) TO @INTEGER
REPEAT
SCREEN UNPASTE_WINDOW USING PAYMENT_SCN_ID:D

This is the COBOL procedure which performs the mortgage payment calculation.

*
*   Calling COBOL from ACCENT R -- Calculate a mortgage payment
*
IDENTIFICATION DIVISION.
PROGRAM-ID. PAYMENT_COBOL.
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 INTMO    COMP-2.
01 NPMTS    COMP-2.
LINKAGE SECTION.
01 INTYR    COMP-2.
01 NYEARS      PIC S9(8) COMP.
01 BAL      COMP-2.
01 PMT      COMP-2.
PROCEDURE DIVISION USING INTYR
             NYEARS
             BAL
             PMT.
A00.
   COMPUTE INTMO = ((INTYR / 12.00) / 100.00).
   COMPUTE NPMTS = (NYEARS * 12).
   COMPUTE PMT = (BAL * (INTMO / (1.00 - ((1.00 + INTMO) ** (- NPMTS))))).
   EXIT PROGRAM.

VAX FORTRAN Example

The ACCENT R program for calling the mortgage calculation procedure written in FORTRAN is as follows:

! PM CALL_PAYMENT_FORTRAN
DECLARE SECTION
BAL,         FLOAT,       MAX,         2
INTYR,       FLOAT,       MAX,         2
PMT,         FLOAT,       MAX,         2
NYEARS,      INT,         MAX
INCLUDE PAYMENT_SCN FROM CS PAYMENT_SCN
DETAIL SECTION
GENERATE PAYMENT_SCN:D TO PAYMENT_SCN_ID:D
SCREEN PASTE_WINDOW USING PAYMENT_SCN_ID:D, 11, 23
START
FILL PAYMENT_SCN_ID:D FOR CHANGE
LEAVE IF @FILL_ACTION = 'CANCEL'
@CALL("PAYMENT_FORTRAN", "ACCEXT_LIB:ACCEXT", @ADR INTYR:D, &
@ADR NYEARS:D, @ADR BAL:D, @ADR PMT:D) TO @INTEGER
REPEAT
SCREEN UNPASTE_WINDOW USING PAYMENT_SCN_ID:D

ACCENT R for VAX/OpenVMS Example

This is the FORTRAN procedure which performs the mortgage payment calculation.

C
C   Calling FORTRAN from ACCENT R -- Calculate a mortgage payment
C
PROCEDURE PAYMENT_FORTRAN (INTYR, NYEARS, BAL, PMT)
DOUBLE PRECISION INTYR, BAL, PMT, INTMO, NPMTS
INTEGER NYEARS
INTMO = ((INTYR / 12.00) / 100.00)
NPMTS = (NYEARS * 12)
PMT = (BAL * (INTMO / (1.00 - (( 1.00 + INTMO) ** ( - NPMTS)))))
RETURN
END

The ACCENT R program for calling the mortgage calculation procedure written in ACCENT R is as follows (please notice that the same payment calculation can be made without the use of a 3GL):

! PM CALL_PAYMENT_ACCENT
DECLARE SECTION
BAL,      FLOAT,    MAX,    2
INTYR,    FLOAT,    MAX,    2
PMT,      FLOAT,    MAX,    2
INTMO,    FLOAT,    MAX,    2
NPMTS,    FLOAT,    MAX,    2
NYEARS,   INT,      MAX
INCLUDE PAYMENT_SCN FROM CS PAYMENT_SCN
DETAIL SECTION
GENERATE PAYMENT_SCN:D TO PAYMENT_SCN_ID:D
SCREEN PASTE_WINDOW USING PAYMENT_SCN_ID:D, 11, 23
START
   FILL PAYMENT_SCN_ID:D FOR CHANGE
LEAVE IF @FILL_ACTION = 'CANCEL'
   ((INTYR:D / 12.00) / 100.00) TO INTMO:D
   (NYEARS:D * 12) TO NPMTS:D
   (BAL:D * (INTMO:D / (1.00 - ((1.00 + INTMO:D) ** (- NPMTS:D))))) TO PMT:D
REPEAT
SCREEN UNPASTE_WINDOW USING PAYMENT_SCN_ID:D

VAX/OpenVMS Run-time Library Example

The following example demonstrates how to call various system routines to obtain I/O statistics information:

! PM GET_IO_STATISTICS
!
! Example PM showing use of several VAX/OpenVMS LIB$ system calls.
! The system's statistics timer is initialized, followed by some CPU-churning
! code, then the accumulated statistics are gathered and the elapsed-time
! statistic is converted to an ASCII string.
!
!=================
DECLARE SECTION
!=================
        STATUS, I, MAX         ! returned status code of system calls
        CODE, I, MAX           ! code value of various statistics
        NUM, N, 7,2            ! value used in CPU-churning loop
        ANSWER, N, 7,2         ! result of CPU-churning loop
        QUADWORD, BB, 16, OCCURS 4       ! code = 1, quadword sys time format
        CPU.TIME, I, MAX                 ! code = 2, 10 mS increments
        BUFFERED.IO, I, MAX              ! code = 3
        DIRECT.IO, I, MAX                ! code = 4
        PAGE.FAULTS, I, MAX              ! code = 5
!       OpenVMS string descriptor to be used by LIB$SYS_ASCTIM for converting the
!       quadword system time value to an ASCII string.
!
      GROUP DESC OCCURS 1 TIMES
            W_LENGTH, BB, 16
            B_DTYPE, BB, 8
            B_CLASS, BB, 8
            A_POINTER, I, MAX
      GROUP END
               A_STRING, C, 45  ! resultant string converted by LIB$SYS_ASCTIM
               RLEN, I, MAX     ! resultant length; chars stored by LIB$SYS_ASCTIM
!=================
DETAIL SECTION
!=================
!      Initialize the statistics buffer
!
@CALL("lib$init_timer", "librtl") TO STATUS
!      Burn some CPU and elapsed time, and output some characters to
!      increase the buffered IO count
!
TYPE "Starting to burn some CPU time ..."
@SQRT(NUM) TO ANSWER FOR NUM = 1.0 TO 144. BY 0.01
TYPE "Burning no more CPU cycles ..."
!      Collect accumulated statistics from the system's buffers
1 TO CODE
@CALL("lib$stat_timer","librtl",@ADR CODE,@ADR QUADWORD(1)) TO STATUS
2 TO CODE
@CALL("lib$stat_timer","librtl",@ADR CODE,@ADR CPU.TIME) TO STATUS
3 TO CODE
@CALL("lib$stat_timer","librtl",@ADR CODE,@ADR BUFFERED.IO) TO STATUS
4 TO CODE
@CALL("lib$stat_timer","librtl",@ADR CODE,@ADR DIRECT.IO)TO STATUS
5 TO CODE
@CALL("lib$stat_timer","librtl",@ADR CODE,@ADR PAGE.FAULTS)TO STATUS
!Convert VAX-quadword elapsed time to an ASCII string
!
! DSC$K_DTYPE_T
14 TO B_DTYPE(1)
! K_CLASS_S
1 TO B_CLASS(1)
! max length that CAN be stored
45 TO W_LENGTH(1)
@ADR A_STRING TO A_POINTER(1)
@CALL("lib$sys_asctim", "librtl", @ADR RLEN, @ADR W_LENGTH(1), &
@ADR QUADWORD(1)) TO STATUS
!      Display results
!
TYPE "    elapsed:", A_STRING       @ "", " (rlen = ", RLEN@'', ")"
TYPE "   cpu time:", CPU.TIME * .01 @ "5-.ddd", " secs"
TYPE "buffered io:", BUFFERED.IO    @ "5-"
TYPE "  direct io:", DIRECT.IO      @ "5-"
TYPE "page faults:", PAGE.FAULTS    @ "5-"

When executed, this PM produces the following:

            *use pm GET_IO_STATISTICS
            Starting to burn some CPU time...
            Burning no more CPU cycles...
               elapsed:             0 00:00:03.66 (rlen = 16)
               cpu time:            3.320 secs
            buffered io:            4
               direct io:           0
            page faults:            8
            *

VAX C Example with Transfer Vectors

This second example calls several "C" subroutines in a private library.  The subroutines are compiled and linked per the following DCL script:

$ assign/system/executive_mode sys$login accext_lib
$ cc/optimize=noinvariant/nolist clib.c
$ macro/nolist clibvec.mar
$ link/share=accext_lib:clib clibvec,clib
$ install :== install/command_mode
$ install
remove accext_lib:accext.exe
create/open/shared/header_resident/privilege=syslck/writeable accext_lib:clib.exe
exit
    The "C" subroutines are in the file clib.c, which contains:
/*         clib.c
 *
 *         Examples illustrating external subroutines called from ACCENT R
 *
 *         SYNOPSIS
 *
 *         integer_result = doublefunct(integer_value)
 *
 *         integer_result will be the doubling of the input integer_value
 *
 *         integer_status = doall(&integer, &real, &number)
 *
 * integer_status will be a zero indicating the following
 *       operations succeeded:
 * integer is the address of an "I" value that will be squared
 * real is the address of an "R" value that will be cubed
 * number is the address of an "N" value whose square root
 *       will be taken.
 */
long doublefunct(ival)
   long   ival;
{return(ival + ival);}
long doall(integer, real, number)
   long   *integer;
   float   *real;
   double*number;
{extern double sqrt();
   *integer = (*integer) * (*integer);
   *real    = (*real) * (*real) * (*real);
   *number  = sqrt(*number);
   return(0L);}

The Macro file with the transfer vectors contains:

.TITLE         CLIBVEC
.IDENT         /EXAMPLE/
.PSECT         $$XFRVECTORS,EXE,NOWRT
.TRANSFER      DOUBLEFUNCT
.MASK          DOUBLEFUNCT
JMP            L^DOUBLEFUNCT+2
.TRANSFER      DOALL
.MASK          DOALL
JMP            L^DOALL+2
.END

And the ACCENT R PM is:

! PM CLIB
!
! Simple demonstration of calling external C language routines from ACCENT R.
!
DECLARE
         cstatus, c, 20
         istatus, i,      max
         ival, i,         max, pp=""
         rval, r,         max, pp=""
         nval, n,         max, pp=""
DETAIL
      ! This first example calls a C routine named "doublefunct" which has been
      ! linked into the image named CLIB.EXE residing in the current directory.
      ! The routine accepts the input argument BY VALUE, doubles it, and returns
      ! the doubled value as the integer status value of @CALL.
      !
      type "The doubled value of 3 is ", @call("doublefunct", "accext_lib:clib",3)
      ! This final example sets values to three arguments in memory and calls
      ! a routine named "doall" which accepts the arguments BY REFERENCE and
      ! processes them returning the results into the original variables.
      !
      17 to ival
      23 to rval
      99 to nval
      !
      @call("doall","accext_lib:clib", @adr ival, @adr rval, @adr nval) to istatus
      !
      type "The square of 17 is ", ival
      type "The cube of 23 is ", rval
      type "The root of 99 is ", nval

When the CLIB.EXE is built and the PM is saved, its execution produces:

      *use pm clib
      The doubled value of 3 is 6
      The square of 17 is 289
      The cube   of 23 is 12167
      The root   of 99 is 9.9498744
      *

NOTES:  The external routines you wish to call must reside in a shareable library which is installed in memory in order to be available for calling from ACCENT R.  This requirement makes it necessary for you to communicate with the system manager of your system in order make your 3GL routines available for use.  OpenVMS Access Control Lists and File Protection schemes may be used to protect your routines or any third-party routines from unauthorized use.

Because the installation of the shared library in memory is required, your external routines cannot be debugged with the normal debugging facility of your 3GL.  These routines must be debugged before they are linked into the shareable image.

Remember, any system-wide, executive mode logical names associated with shareable libraries must be assigned before using the @CALL system function.

There will exist the potential for access violations, reserved operand faults, etc., when interfacing with 3GL subroutines.  ACCENT R is unable to verify the number of and the data types of the arguments required by external 3GL routines; argument correspondence between ACCENT R and the 3GL subroutines is the responsibility of the application developer.

It is important that the arguments be passed to the called routine exactly as it is expecting them.  Arguments are traditionally passed “by value” or “by reference”.  For VAX/OpenVMS systems, a third argument form, “by descriptor can be constructed using ACCENT R’s GROUP capability.  It may be necessary for you to construct descriptors of your own.

Usage “by reference” simply means the value of a constant or the contents of a scalar or array occurrence.  Such usage implies the argument is an INPUT argument only.  For example:

1, 3.45, COST_FIELD, MONTHLY_SALES(5)

Usage “by reference” means the location of the data field in memory is passed to the external subroutine, and thus it can be used as an INPUT and/or as an OUTPUT argument “pointer.”  The address pointer to any argument is available using the @ADR System Function.  This System Function, which returns the address of a data structure, is actually a unary operator, even though it syntactically resembles a System Field or System Function.  Note that the @ADR System Function does not allow parentheses.  An example of the use of @ADR is:

@ADR COST_FIELD, @ADR MONTHLY_SALES(7)

An argument passed “by descriptor” for systems such as VAX/OpenVMS can be effected by passing the address pointer to a GROUP or a GROUP occurrence representing the “by descriptor” format.  For example, the C language definition of the standard OpenVMS argument descriptor is:

struct dsc$descriptor
{
            unsigned short        dsc$w_length;
            unsigned char         dsc$b_dtype;
            unsigned char         dsc$b_class;
            char                  *dsc$a_pointer;
}

The equivalent expression in ACCENT R is the following:

GROUP DSC_DESCRIPTOR OCCURS 1
               W_LENGTH,                 BINARY BIT, 16
               B_DTYPE,                  BINARY BIT, 8
               B_CLASS,                  BINARY BIT, 8
               A_POINTER,                INT, MAX
GROUP END

Values can be placed in the GROUP per:

<expression> TO W_LENGTH
<datatype.val> TO B_DTYPE
<class.val> TO B_CLASS
@ADR fieldname to A_POINTER

The GROUP is passed as an argument “by reference” using the address of the first field of the group or the address of the first occurrence of the first field of a repeating GROUP.  For example, the following would be used to identify the above group as an argument to a function expecting a VAX/OpenVMS descriptor:

@ADR W_LENGTH

Please note that using 3GL subroutine calls will reduce the portability of your application to other hardware platforms.  This is due to the fact that ACCENT R-based applications can be ported to other platforms more easily if the developer is not required to port the 3GL routines as well.

NIS:ACCEXT_BUILD.COM - Linking Shareable Libraries

Purpose:  In order to call 3GL subroutines from ACCENT R, you must first link them together into a shareable library.  ACCENT R provides a simple and efficient way of building shareable libraries with the DCL procedure NIS:ACCEXT_BUILD.COM.

ACCEXT_BUILD will build a shareable library which contains all of the object files (.OBJ extension) in the directory ACCEXT_OBJ:.  ACCEXT_BUILD will assume that the name of the .OBJ files is the name of the routine as it will be called from the shareable library.  These object modules must first be compiled via a 3GL compiler such as COBOL, FORTRAN, C or any language that uses the VAX calling standard.  If you are using MMS, a shareable library can be linked by using that process whenever the underlying source files are changed.

Syntax

$ @NIS:ACCEXT_BUILD.COM

[transfer_vector_file_name/ACCMACRO]

[additional_object_library_file_name/ACCLIBRARY]

[options_file_name/ACCOPTION]

[shareable_image_file_name/ACCSHARE]

transfer_vector_file_name/ACCMACRO

specifies the name of the VAX MACRO file name to be used as the calling module for each of the routines in the library.  If this option is not specified, ACCENT R will create a VAX MACRO transfer vector file containing the name of each object file in the directory pointed to by the logical name ACCEXT_OBJ:.

additional_object_library_file_name/ACCLIBRARY

specifies the name of an object library which should be searched when linking the shareable image.  If no additional library is specified, the DCL LINK command will search the object libraries which are specified by default and those pointed to by the logicals LNK$LIBRARY only.

options_file_name/ACCOPTION

specifies the name of the options file to be used instead of the options file which is created automatically.  If this clause is not specified, ACCEXT_BUILD will link the shareable image in accordance with the object files which are found in the directory pointed to by the logical name ACCEXT_OBJ:.

shareable_image_file_name/ACCSHARE

specifies the name of the shareable other than ACCEXT.EXE, which is the default.  This clause is useful for creating your own shareable images.

Example

$ ASSIGN [] ACCEXT_OBJ:
$ ASSIGN [] ACCEXT_WRK:
$ ASSIGN SYS$LIBRARY: ACCEXT_LIB:
$ @NIS:ACCEXT_BUILD PAYLIB.EXE/ACCSHARE

In this example, ACCEXT_BUILD will build the shareable image from the objects residing in ACCEXT_OBJ:.  ACCEXT_BUILD will use ACCEXT_WRK:: for the creation of any work files.  The shareable image named PAYLIB.EXE will be linked and placed in the system directory SYS$LIBRARY;:.

Notes:  ACCEXT_BUILD requires that you assign the following logicals before starting the process of building the shareable image:

ACCEXT_LIB    (Where the shareable image will reside)

ACCEXT_WRK  (A work directory for ACCEXT_BUILD)

ACCEXT_OBJ   (Where the object files to be linked reside)

The shareable libraries that are created with @NIS:ACCEXT_BUILD procedure must be installed in memory with privileges exactly as ACCENT R is installed in memory.  The following commands should be placed in the system start-up command files and used to install your shareable library in memory for use with ACCENT R:

$ INSTALL :== INSTALL/COMMAND_MODE
$ INSTALL
$ DECK
REMOVE ACCEXT_LIB:ACCEXT.EXE
CREATE/OPEN/SHARED/HEADER_RESIDENT/PRIVILEGE=
SYSLCK/WRITEABLE - ACCEXT_LIB:ACCEXT.EXE
$ EOD
$ EXIT

If the shareable library does not exist in SYS$SHARE:, a system-wide, executive mode logical must point to the directory where the library resides.  For example, the logical ACCEXT_LIB: can be properly defined for this function as follows:

$ ASSIGN/SYSTEM/EXECUTIVE_MODE SYS$USER1:
[WAGNER.ACCENT.3GL] - ACCEXT_LIB

If other than a system-wide, executive mode logical is assigned, processes accessing the shareable library will encounter the following OpenVMS error message:

%LIB-E-ACTIMAGE, error activating image
ACCEXT_LIB:[WAGNER.ACCENT.3GL]ACCEXT.EXE;
%RMS-F-DEV, error in device name or inappropriate device type for operation

If for some reason a new version of the shareable image is placed in the appropriate directory and the appropriate logical name is assigned, but the new version of the shareable image is not installed in memory, the following OpenVMS error message is encountered:

%LIB-W-ILLRECLEN, illegal record length (0)
%LIB-E-KEYNOTFOU, key not found in tree.