# Input/Output and Control Options

Using Embedded IO |

Embedded IO procedures allow the developer to intercept file Input and Output operations on a PxPlus KEYED data file. A user-defined program is logically PERFORMed during any OPEN, READ, WRITE, REMOVE and CLOSE operation. Optionally, with PxPlus 2014, you can specify an Object to handle the embedded IO processing.

The program to be PERFORMed and/or Object to use must be specified in the Data Dictionary Maintenance function in NOMADS to enable this feature.

The Embedded IO program/object must exist and be accessible using the standard PREFIX search rules in order to open the data file. If the program does not exist, then an Error #121: Invalid program format is reported.

(Use of objects to handle embedded IO was added in PxPlus 2014.)

## How It Works

Whenever a keyed file is opened (VLR or EFF), its file header is checked to see if an embedded IO program in specified.

If a program is specified, the system will then load and issue a PERFORM to various pre-defined entry points within the program in accordance to the file IO operation being executed. For example, when a REMOVE is executed, the system will look for, and if found, issue a PERFORM to the label PRE_REMOVE.

If an Object is specified (the embedded IO specification starts with OBJ=), then the object will be instantiated and the method POST_OPEN will be invoked.

The developer only needs to define those entry points/methods he/she needs to use. For example, if the logic does not need to intercept the READ directive, then the PRE_READ and/or POST_READ entry points do not need to be defined.

## Calling Parameters

Most entry points are passed four arguments that can be accessed by an ENTER directive (no parameters are sent to OPEN/CLOSE).

> LOCAL ACCESS_MODE, KEY$, INDEX, VALUE$, FLAG, KNO (See Note below)
> ENTER ACCESS_MODE, KEY$, INDEX, VALUE$, FLAG, KNO

Where:

ACCESS_MODE | Type of access being performed: 0 - Next, 1 - KEY=, 2 - IND=, 3 - RNO=
KEY$ | Value in KEY$ or NULL
INDEX | IND or RNO value
VALUE$ | Record contents being written or standard value from FIB/FID/FIN #### Note: When using embedded IO with an Extended Record Size VLR file, only the first segment will be passed in VALUE$ to the embedded IO program.
FLAG | A flag word indicating which IO options were present on the directive: 0x0001 - DOM= 0x0002 - END= 0x0004 - NUL= 0x0008 - BSY= 0x0010 - Directive is a FIND as opposed to a READ 0x0020 - Directive is an EXTRACT as opposed to a READ 0x0040 - Directive included a LOCK clause (added in PxPlus 2014)
KNO | KNO currently being used

In addition to the parameters passed to the embedded IO program, the program can return values to the file system to change the normal IO behaviour by altering the record contents, etc.

## Entry Point/Parameter Information (Performed Program)

The following is a table of pre-defined entry points that will be logically PERFORMed, the value passed in the fourth argument, and what return value can be sent back, if desired:

Directive | When 'Performed' | Entry Point | Input VALUE$ | Return Value
OPEN | After file is opened | <none> 1 |  |
CLOSE | Before file is actually closed | PRE_CLOSE |  |
READ / FIND | Before the file is read | PRE_READ |  | Returned value is considered the data record and is passed back to the application. Physical read not done.
| After the file is read | POST_READ | Record as read from the file | Returned value is considered the data record and is passed back to the application.
EXTRACT | Before the file is read | PRE_EXTRACT 2 |  | Returned value is considered the data record and is passed back to the application. Physical read not done.
| After the file is read | POST_EXTRACT 2 | Record as read from the file | Returned value is considered the data record and is passed back to the application.
WRITE / UPDATE / INSERT | Before the file is updated | PRE_WRITE | Record as output by program and will/should be written to the file | A 'RETURN 0' will bypass the actual write to the file.
| After the file is updated | POST_WRITE | Record as it was written to the file |
REMOVE | Before the file is updated | PRE_REMOVE |  |
| After the file is updated | POST_REMOVE |  |
LOCK | Before the file is locked | PRE_LOCK |  |
| After the file is locked | POST_LOCK |  |
UNLOCK | Before the file is unlocked | PRE_UNLOCK |  |
| After the file is unlocked | POST_UNLOCK |  |
PURGE | Before the file is purged | PRE_PURGE |  |
| After the file is purged | POST_PURGE |  |
Function | When 'Performed' | Entry Point | Input VALUE$ | Return Value
FIB( ) | After result from FIB function | POST_FIB | Original FIB value | Revised FIB value
FID( ) | After result from FIB function | POST_FID | Original FID value | Revised FID value
FIN( ) | After result from FIB function | POST_FIN | Original FIN value | Revised FIN value
IND( ) | Before function called | PRE_IND |  | IND return value
KEC( ) | Before function called | PRE_KEC |  | KEC return value
KEF( ) | Before function called | PRE_KEF |  | KEF return value
KEL( ) | Before function called | PRE_KEL |  | KEL return value
KEN( ) | Before function called N/A | PRE_KEN |  | KEN return value
KEP( ) | Before function called | PRE_KEP |  | KEP return value
KEY( ) | Before function called N/A | PRE_KEY |  | KEY return value
RNO( ) | Before function called N/A | PRE_RNO |  | RNO return value

1 There is no line label entry point used when a file is OPENed as the program is simply PERFORMed.
2 The PRE/POST extract routines are called if present; otherwise, an Extract will also attempt PRE/POST read.

#### Note:
As the embedded IO program is performed, care must be taken that NO variables are changed within the code. All variables used should be declared as LOCAL or the routine can issue a CALL to insulate the mainline program from the IO routine. The advantage of the PERFORM is that other variables that may exist in the application will still be accessible to the logic. In particular, you should always LOCALize the entry parameters as shown above.

## Methods Invoked (Embedded IO Object)

When using an object to handle embedded IO, each IO operation is invoked as a method within the object. The method names used are the same as the Entry Points found in column three of the preceding table. For example, instead of the system performing the Entry point PRE_READ in an embedded IO program, it will invoke the method PRE_READ(..), passing it the same parameters.

The only difference being that when the file is OPENed, the method POST_OPEN( ) is invoked, passing in the original pathname as specified in the program (string), channel number (numeric) and the full pathname to the file (string).

Example:

> 0010 ! ENCRYPT - Embedded IO Procedure to encrypt data
> 0100 ! ^100
> 0110 OPEN:
> 0120 LOCAL P$
> 0130 IF %PASSWORD$="OK" THEN GOTO 0190
> 0140 PRINT 'WINDOW'(10,10,50,6,"Password?",'MODE'($000F$)+'CS'),
> 0150 OBTAIN (0,ERR=0160)@(0,1),"Please enter the password? ",P$
> 0160 PRINT (0,ERR=*NEXT)'POP',
> 0170 IF UCS(P$)<>"PASSWORD" OR CTL<>0 THEN EXIT 52
> 0180 %PASSWORD$="OK"
> 0190 EXIT
> 0200 ! ^100
> 0210 POST_READ: LOCAL VALUE$,ACCESS_MODE,KEY$,INDEX,V$
> 0220 ENTER ACCESS_MODE,KEY$,INDEX,V$
> 0230 VALUE$=V$; GOSUB ENCRYPT_IT; RETURN VALUE$
> 0240 END
> 0300 ! ^100
> 0310 PRE_WRITE: LOCAL VALUE$,ACCESS_MODE,KEY$,INDEX,V$
> 0320 ENTER ACCESS_MODE,KEY$,INDEX,V$
> 0330 VALUE$=V$; GOSUB ENCRYPT_IT; RETURN VALUE$
> 0340 END
> 1000 ! ^1000
> 1010 ENCRYPT_IT:
> 1020 LOCAL ENCRYPT_STRING$
> 1030 IF VALUE$="" THEN RETURN
> 1040 ENCRYPT_STRING$="Use this string to randomize the data"
> 1050 ENCRYPT_STRING$=DIM(LEN(VALUE$),ENCRYPT_STRING$)
> 1060 VALUE$=XOR(VALUE$,ENCRYPT_STRING$)
> 1070 RETURN