Special Considerations and Restrictions [ Switch Programming User's Guide ] MPE/iX 5.0 Documentation
Switch Programming User's Guide
Special Considerations and Restrictions
There are certain considerations to bear in mind when you use Switch.
General
General considerations apply no matter what the direction of the
mixed-mode call:
* Mixed-mode procedure calls require an increased level of programming
complexity.
* The overhead of Switch can be significant.
* Because Switch does no probing on addresses passed by the caller,
data memory protection faults are likely when you pass in bad
parameter addresses or lengths.
* Since Switch does no parameter type or alignment checking, the target
procedure must make the necessary checks.
The following considerations apply to a particular direction of
mixed-mode call.
NM--> CM
When making mixed-mode procedure calls in the direction NM--> CM, the
following considerations apply:
* Any CM procedure called from NM code must reside in a CM SL. The SL
containing the procedure must be accessible via the LOADPROC or
HPLOADCMPROCEDURE intrinsic. This may be the system library, a group
library, or a user library.
* Unlike other MPE XL intrinsics, the Switch intrinsics do not promote
their privilege level. If your user code calls Switch to access a
non-Privileged target procedure, the execution level remains
unchanged. On the other hand, if your user code calls Switch to
access a Privileged target, the execution level becomes Privileged
after the target is accessed.
* HP Pascal/XL does not support the equivalent of SPL's option
variable, and HPSWITCHTOCM knows nothing about such procedures.
Option variable procedures are implemented in Compatibility Mode by
pushing a 16- or 32-bit mask on the CM stack immediately before
calling the procedure.
You can use the HPSWITCHTOCM intrinsic to call an option variable
procedure, but it is your responsibility to construct the mask (refer
to the SPL Reference Manual (30000-90024) for more information on the
OPTION VARIABLE option) and to describe it to HPSWITCHTOCM as the
first parameter. See Example 3-11 for an illustration of the use of
HPSWITCHTOCM to call an option variable procedure.
Example 3-11. Stub for Option Variable Target Procedure
$subprogram$
$standard_level 'ext_modcal'$
$tables off$
$code_offsets off$
$xref off$
$type_coercion 'representation'$
PROGRAM XAMPL311(input, output);
CONST
Pidt_Known = 0; { By number }
Pidt_Name = 1; { By name }
Pidt_Plabel = 2; { By PLABEL }
System_Sl = 0;
Logon_Pub_Sl = 1;
Logon_Group_Sl = 2;
Pub_Sl = 3;
Group_Sl = 4;
Method_Normal = 0; { Not callable from split stack}
Method_Split = 1; { Callable in split stack mode }
Method_No_Copy = 2; { No-copy method }
Parm_Type_Value = 0; { value parameter }
Parm_Type_Word_Ref = 1; { reference parm, word addr }
Parm_Type_Byte_Ref = 2; { reference parm, byte addr }
Ccg = 0; { condition code greater (>) }
Ccl = 1; { condition code less (<) }
Cce = 2; { condition code equal (=) }
All_Ok = 0; { Used in status check }
TYPE
BIT8 = 0..255;
BIT16 = 0..65535;
BIT8_A1 = $ALIGNMENT 1$ BIT8;
BIT16_A1 = $ALIGNMENT 1$ BIT16;
CM_PROC_NAME = PACKED ARRAY [1..16] OF CHAR;
GENERIC_BUFFER = PACKED ARRAY [1..65535] OF CHAR;
SCM_PROCEDURE =
PACKED RECORD
CASE p_proc_id_type : BIT8 OF
Pidt_Known: (p_fill : BIT8_A1;
p_proc_id : BIT16_A1);
Pidt_Name: (p_lib : BIT8_A1;
p_proc_name : CM_PROC_NAME);
Pidt_Plabel: (p_plabel : BIT16_A1);
END; { record }
Example 3-11. Stub for Option Variable Target Procedure, continued
SCM_IO_TYPE = SET OF (input_parm, output_parm);
PARM_DESC =
PACKED RECORD
pd_parmptr : GLOBALANYPTR;
pd_parmlen : BIT16;
pd_parm_type : BIT16;
pd_io_type : SCM_IO_TYPE;
END;
SCM_PARM_DESC_ARRAY = ARRAY [0..31] OF PARM_DESC;
CCODE_TYPE = shortint;
XLSTATUS =
RECORD
CASE INTEGER OF
0: (all : INTEGER);
1: (info : SHORTINT;
subsys : SHORTINT);
END; { record }
PROCEDURE HPSWITCHTOCM; INTRINSIC;
PROCEDURE HPSETCCODE; INTRINSIC;
PROCEDURE QUIT; INTRINSIC;
{ End of OUTER BLOCK GLOBAL declarations }
PROCEDURE FCHECK $ALIAS 'FCHECK'$
(
FILENUM : SHORTINT;
VAR ERRORCODE : SHORTINT;
VAR TLOG : SHORTINT;
VAR BLKNUM : INTEGER;
VAR NUMRECS : SHORTINT
);
VAR
proc : SCM_PROCEDURE;
parms : SCM_PARM_DESC_ARRAY;
method : INTEGER;
nparms : INTEGER;
funclen : INTEGER;
funcptr : INTEGER;
byte_len_of_parm : BIT16;
cond_code : CCODE_TYPE;
status : XLSTATUS;
mask : BIT16;
Example 3-11 Stub for Option Variable Target Procedure, continued
VAR loc_FILENUM : SHORTINT;
begin { STUB procedure FCHECK }
{ Initialization }
{ Setup procedure information--name, lib, etc. }
proc.p_proc_id_type := Pidt_Name; { By name }
proc.p_lib := System_Sl; { Library }
proc.p_proc_name := 'FCHECK ';
{ Setup misc. variables }
mask := 0;
method := Method_Normal; { Split stack? }
nparms := 6; { 5 + mask }
{ Setup length/pointers for functional return if this }
{ is a FUNCTION. Set length to zero, pointer to NIL }
{ if this is not a FUNCTION. }
funclen := 0; { Not a function }
funcptr := 0;
{ Make a local copy of all VALUE parameters }
loc_FILENUM := FILENUM;
{ Build parameter descriptor array to describe each }
{ parameter. }
{ FILENUM -- Input Only by VALUE }
byte_len_of_parm := 2;
mask := binary('10000');
parms[0].pd_parmptr := ADDR(loc_FILENUM);
parms[0].pd_parmlen := byte_len_of_parm;
parms[0].pd_parm_type := Parm_Type_Value;
parms[0].pd_io_type := [Input_Parm];
{ ERRORCODE -- Output Only by REFERENCE }
byte_len_of_parm := 2;
mask := ior16(mask, binary('01000'));
parms[1].pd_parmptr := ADDR(ERRORCODE);
parms[1].pd_parmlen := byte_len_of_parm;
parms[1].pd_parm_type := Parm_Type_Word_Ref;
parms[1].pd_io_type := [Output_Parm];
Example 3-11. Stub for Option Variable Target Procedure, continued
{ TLOG -- Output Only by REFERENCE }
byte_len_of_parm := 2;
mask := ior16(mask, binary('00100'));
parms[2].pd_parmptr := ADDR(TLOG);
parms[2].pd_parmlen := byte_len_of_parm;
parms[2].pd_parm_type := Parm_Type_Word_Ref;
parms[2].pd_io_type := [Output_Parm];
{ BLKNUM -- Output Only by REFERENCE }
byte_len_of_parm := 4;
mask := ior16(mask, binary('00010'));
parms[3].pd_parmptr := ADDR(BLKNUM);
parms[3].pd_parmlen := byte_len_of_parm;
parms[3].pd_parm_type := Parm_Type_Word_Ref;
parms[3].pd_io_type := [Output_Parm];
{ NUMRECS -- Output Only by REFERENCE }
byte_len_of_parm := 2;
mask := ior16(mask, binary('00001'));
parms[4].pd_parmptr := ADDR(NUMRECS);
parms[4].pd_parmlen := byte_len_of_parm;
parms[4].pd_parm_type := Parm_Type_Word_Ref;
parms[4].pd_io_type := [Output_Parm];
{ mask parameter }
parms[5].pd_parmptr := ADDR(mask);
parms[5].pd_parmlen := byte_len_of_parm;
parms[5].pd_parm_type := parm_type_value;
parms[5].pd_io_type := [Input_Parm];
{ Do the actual SWITCH call }
HPSWITCHTOCM(proc, { Procedure info }
method, { Split stack ? }
nparms, { Number of parameters }
parms, { Parm descriptor array }
funclen, { func ret value length }
funcptr, { Addr of func return }
cond_code, { cond. code return }
status); { SWITCH status code }
if (status.all <> all_ok) then
BEGIN { SWITCH subsystem error }
QUIT(status.info);
END; { SWITCH subsystem error }
Example 3-11. Stub for Option Variable Target Procedure, continued
HPSETCCODE(cond_code);
end; { STUB procedure FCHECK }
BEGIN { Program Outer block code }
END. { Program Outer block code }
{end Example 3-11}
MPE/iX 5.0 Documentation