-- File [Ivy]<Nelson>Lupine>LupineDeclareStubsImpl.mesa.
-- Last edited by BZM on 14-May-82 13:06:34.
-- This module cooperates with LupineDeclare*Impl to export LupineDeclare.
DIRECTORY
CWF USING [SWF1, WF1],
LongString USING [EqualStrings],
LupineDeclare USING [
DispatcherType, PktSite,
TransferDeclaration, TransferName, TransferSite,
WriteParameterName, WriteTypeName ],
LupineDeclarePrivate USING [DispatcherName, GetString],
LupineManagerPrivate USING [
AllocString, Indent, IsNull, MaxIdentifierLength,
Nest, Options, String, StringNIL,
WFL, WFL1, WFLL, WFS, WFS1, WFSL ],
LupineMarshal USING [
BeginAllocation, EndAllocation,
EnumerateParams, FieldInfo, FreeParamInfo, FromPacket,
MakeParamInfo, ParamProcedure, ParamInfo, ParamIndex, ParamLocation,
ToPacket, VariableNames, Words ],
LupineSymbolTable USING [
GetTypeInfo, IsAnonymous, SymbolHandle,
TransferTypes, TypeHandle, TypeInfo ];
LupineDeclareStubsImpl: PROGRAM
IMPORTS
CWF, Declare: LupineDeclare, LongString, LupineManagerPrivate,
Marshal: LupineMarshal, Private: LupineDeclarePrivate,
ST: LupineSymbolTable
EXPORTS LupineDeclare
= BEGIN OPEN LupineManagerPrivate, LupineDeclare;
ParamInfo: TYPE = Marshal.ParamInfo;
ParamLocation: TYPE = Marshal.ParamLocation;
TransferInfo: TYPE = Transfer ST.TypeInfo;
-- Public code generation routines.
ProcedureStub: PUBLIC PROCEDURE [
transfer: ST.SymbolHandle,
transferType: ST.TypeHandle,
transferDeclaration: TransferDeclaration,
signalDispatcherType: DispatcherType,
options: Options,
nest: Nest ] =
BEGIN
nameString: AllocString = [MaxIdentifierLength];
procName: String = Declare.TransferName[transfer, nameString];
transferInfo: TransferInfo = GetTransferInfo[transferType];
argInfo, resultInfo: ParamInfo;
[argInfo, resultInfo] ← GetArgResultInfo[
transferInfo: transferInfo,
transferDeclaration: transferDeclaration,
transferSite: caller, pktSite: stubFrame,
options: options ];
BEGIN ENABLE UNWIND => FreeArgResultInfo[argInfo, resultInfo];
WFS1["*N"L];
TransferHeader[ nest: nest,
transferName: procName,
transferInfo: transferInfo,
argInfo: argInfo, resultInfo: resultInfo,
public: transferDeclaration=inInterface ];
WFS1[" =*N"L];
CallingStubBody[ nest: nest+1,
transferName: procName, blockName: procName,
transferInfo: transferInfo,
signalDispatcher: Private.DispatcherName[signalDispatcherType],
argInfo: argInfo, resultInfo: resultInfo];
END; -- ENABLE UNWIND.
FreeArgResultInfo[argInfo, resultInfo];
END;
DispatcherStubArm: PUBLIC PROCEDURE [
transfer: ST.SymbolHandle,
transferType: ST.TypeHandle,
transferDeclaration: TransferDeclaration,
options: Options,
nest: Nest ] =
BEGIN
nameString: AllocString = [MaxIdentifierLength];
transferName: String = Declare.TransferName[transfer, nameString];
WFSL[ Indent[nest], transferName, " => RETURN[*N"L,
Indent[nest+1], transferName, "Stub["L,
Private.GetString[dispatcherArgs], "]];*N"L ];
END;
DispatcherStubBody: PUBLIC PROCEDURE [
transfer: ST.SymbolHandle,
transferType: ST.TypeHandle,
transferDeclaration: TransferDeclaration,
inlineBody: BOOLEAN,
options: Options,
nest: Nest ] =
BEGIN
nameString: AllocString = [MaxIdentifierLength];
transferName: String = Declare.TransferName[transfer, nameString];
transferInfo: TransferInfo = GetTransferInfo[transferType];
argInfo, resultInfo: ParamInfo;
stubName: AllocString = [MaxIdentifierLength];
CWF.SWF1[stubName, "%LSStub"L, transferName];
-- The stubName here must agree with that used in DispatcherStubArm.
[argInfo, resultInfo] ← GetArgResultInfo[
transferInfo: transferInfo,
transferDeclaration: transferDeclaration,
transferSite: callee, pktSite: rpcRuntime,
options: options ];
BEGIN ENABLE UNWIND => FreeArgResultInfo[argInfo, resultInfo];
WFSL["*N"L, Indent[nest], stubName, ": "L];
TransferType[ nest: nest,
transferInfo: transferInfo,
argInfo: argInfo, resultInfo: resultInfo,
printAsComment: TRUE ];
WFS1[" RpcPrivate.Dispatcher =*N"L];
CalledStubBody[ nest: nest+1,
transferName: transferName, blockName: stubName,
transferInfo: transferInfo,
inlineBody: inlineBody,
argInfo: argInfo, resultInfo: resultInfo ];
END; -- ENABLE UNWIND.
FreeArgResultInfo[argInfo, resultInfo];
END;
SignalCode: PUBLIC PROCEDURE [
transfer: ST.SymbolHandle,
transferType: ST.TypeHandle,
transferDeclaration: TransferDeclaration,
options: Options,
nest: Nest ] =
BEGIN
nameString: AllocString = [MaxIdentifierLength];
transferInfo: TransferInfo = GetTransferInfo[transferType];
argInfo, resultInfo: ParamInfo;
[argInfo, resultInfo] ← GetArgResultInfo[
transferInfo: transferInfo,
transferDeclaration: transferDeclaration,
transferSite: caller, pktSite: stubFrame,
options: options ];
BEGIN ENABLE UNWIND => FreeArgResultInfo[argInfo, resultInfo];
WFS1["*N"L];
TransferHeader[ nest: nest,
transferName: Declare.TransferName[transfer, nameString],
transferInfo: transferInfo,
argInfo: argInfo, resultInfo: resultInfo,
public: transferDeclaration=inInterface ];
WFS1[" = CODE;*N"L];
END; -- ENABLE UNWIND.
FreeArgResultInfo[argInfo, resultInfo];
END; -- SignalCode.
SignalCatchStub: PUBLIC PROCEDURE [
transfer: ST.SymbolHandle,
transferType: ST.TypeHandle,
transferDeclaration: TransferDeclaration,
signalDispatcherType: DispatcherType ← none,
options: Options,
nest: Nest ] =
BEGIN
nameString: AllocString = [MaxIdentifierLength];
signalName: String = Declare.TransferName[transfer, nameString];
transferInfo: TransferInfo = GetTransferInfo[transferType];
argInfo, resultInfo: ParamInfo;
[argInfo, resultInfo] ← GetArgResultInfo[
transferInfo: transferInfo,
transferDeclaration: transferDeclaration,
transferSite: caller, pktSite: rpcRuntime,
options: options ];
BEGIN ENABLE UNWIND => FreeArgResultInfo[argInfo, resultInfo];
WFSL["*N"L, Indent[nest], signalName, " "L];
TransferType[ nest: nest,
printAsComment: TRUE,
transferInfo: transferInfo,
argInfo: argInfo, resultInfo: resultInfo ];
WFS1[" =>*N"L];
CallingStubBody[ nest: nest+1,
transferName: signalName, blockName: signalName,
transferInfo: transferInfo,
signalDispatcher: Private.DispatcherName[signalDispatcherType],
argInfo: argInfo, resultInfo: resultInfo ];
END; -- ENABLE UNWIND.
FreeArgResultInfo[argInfo, resultInfo];
END;
-- Detailed code generation utilities.
TransferHeader: PROCEDURE [
transferName: String,
transferInfo: TransferInfo,
argInfo, resultInfo: ParamInfo,
public: BOOLEAN,
nest: Nest ] =
BEGIN
WFSL[Indent[nest], transferName,
(IF public THEN ": PUBLIC "L ELSE ": "L),
(IF transferInfo.safe THEN "SAFE "L ELSE ""L) ];
TransferType[nest: nest,
transferInfo: transferInfo, argInfo: argInfo, resultInfo: resultInfo];
END;
TransferType: PROCEDURE [
transferInfo: TransferInfo,
argInfo, resultInfo: ParamInfo,
printAsComment: BOOLEAN←FALSE,
nest: Nest ] =
BEGIN
TransferTypeName: ARRAY ST.TransferTypes OF STRING = [
Procedure: "PROCEDURE"L, Error: "ERROR"L, Signal: "SIGNAL"L,
Port: "PORT"L, Program: "PROGRAM"L, Process: "PROCESS"L,
Other: "<<<ERROR>>>"L ];
WFS[ (IF printAsComment THEN "--"L ELSE ""L),
TransferTypeName[transferInfo.kind],
(IF argInfo.paramCount>0 OR resultInfo.paramCount>0 THEN " "L ELSE ""L)];
FullParameterList[ nest: nest,
argInfo: argInfo, resultInfo: resultInfo,
printingComment: printAsComment ];
IF printAsComment THEN WFS1["--"L];
END;
-- Generate Client procedure stubs and Server catch-phrase stubs.
CallingStubBody: PROCEDURE [
transferName, blockName: String,
transferInfo: TransferInfo,
signalDispatcher: String,
argInfo, resultInfo: ParamInfo,
nest: Nest ] =
BEGIN
CallPkt: String = "pkt"L; -- For signal stubs, this must be = Dispatcher's pkt.
ReturnPkt: String = "pkt"L; -- For signal stubs, ...
CallLength: String = "pktLength"L;
ReturnLength: String --must equal-- = CallLength;
ReturnLimit: String = "returnLimit"L; -- Not used at this time.
LastPkt: String = "lastPkt"L;
ArgPtr: String = "argPkt"L;
ResultPtr: String = "resPkt"L;
CallVars: Marshal.VariableNames = [
pkt: CallPkt, overlayPtr: ArgPtr,
pktLength: CallLength, pktLimit: ""L,
lastPkt: LastPkt ];
ReturnVars: Marshal.VariableNames = [
pkt: ReturnPkt, overlayPtr: ResultPtr,
pktLength: ReturnLength, pktLimit: ReturnLimit,
lastPkt: LastPkt ];
WFL[nest, (IF transferInfo.safe THEN "TRUSTED "L ELSE ""L), "BEGIN"L];
SELECT transferInfo.kind FROM
Signal, Error =>
BEGIN
--ParamsAsLocalVars[paramInfo: argInfo, ...];
-- Anonymous signal arguments are impossible to handle,
-- the compiler will complain.
ParamsAsLocalVars [ nest: nest,
paramInfo: resultInfo, doOnlyAnonymousParams: TRUE ];
-- Declare locals corresponding to anon. AC result parameters.
END;
Procedure =>
BEGIN
--ParamsAsLocalVars[paramInfo: argInfo, ...];
-- All argument declarations already performed in the PROC header.
ParamsAsLocalVars [ nest: nest,
paramInfo: resultInfo, doOnlyAddressParams: TRUE ];
-- AC results are not declared in the PROC header when there are
-- any static results (this saves space). Declare them now.
END;
ENDCASE => ERROR;
OverlayRecord[
paramInfo: argInfo, transferIndexName: transferName, nest: nest ];
OverlayRecord[paramInfo: resultInfo, nest: nest];
SELECT transferInfo.kind FROM
Signal, Error =>
-- These reuse the Dispatcher's call pkt.
IF ~LongString.EqualStrings[CallPkt, Private.GetString[dispatcherPkt]]
THEN ERROR;
ENDCASE =>
-- Procedures (and the rest) use a freshly declared pkt.
LocalPacket[ nest: nest,
pktName: CallPkt,
size: MAX[argInfo.sizeOf.pktToAllocate, resultInfo.sizeOf.pktToAllocate] ];
IF ~LongString.EqualStrings[CallPkt, ReturnPkt]
THEN WFLL[nest, ReturnPkt, ": RpcPrivate.StubPkt = "L, CallPkt, ";"L];
OverlayPointer[ nest: nest,
paramInfo: argInfo,
pktName: CallPkt, overlayPtrName: ArgPtr,
do: both ];
OverlayPointer[ nest: nest,
paramInfo: resultInfo,
pktName: ReturnPkt, overlayPtrName: ResultPtr,
do: both ];
PacketLength[ nest: nest,
paramInfo: argInfo,
pktLengthName: CallLength,
declare: yes, assign: yes ];
WFL[nest, LastPkt, ": BOOLEAN;"L];
SELECT transferInfo.kind FROM
Procedure =>
BEGIN
WFSL[Indent[nest], "RpcPrivate.StartCall[callPkt: "L, CallPkt,
", interface: myInterface"L ];
IF argInfo.hasConversation THEN DoConversationArg[argInfo];
WFS1["];*N"L];
END;
Signal, Error =>
WFL[nest, "RpcPrivate.StartSignal[signalPkt: "L, CallPkt, "];"L];
ENDCASE => ERROR;
IF ~argInfo.hasOverlayParams
THEN WFLL[nest, ArgPtr, ".transferIndex ← "L, transferName, ";"L];
Marshal.ToPacket[ nest: nest,
paramInfo: argInfo,
overlayHandling: [static: copyToPkt],
varNames: CallVars ];
WFSL[Indent[nest],
"[returnLength: , lastPkt: "L, LastPkt,
"] ←*N"L, Indent[nest+1],
"RpcPrivate.Call[ pkt: "L, CallPkt, ", callLength: "L, CallLength,
",*BmaxReturnLength: "L];
CWF.WF1["%LD"L, @resultInfo.sizeOf.pktToAllocate];
IF ~IsNull[signalDispatcher]
THEN WFS[", signalHandler: "L, signalDispatcher];
WFS1["];*N"L];
PacketLength[ nest: nest,
paramInfo: resultInfo,
pktLengthName: ReturnLength,
declare: no, assign: ifNeeded ];
SELECT TRUE FROM
resultInfo.transferType=Error =>
WFL1[nest, "Lupine.RuntimeError; -- Impossible to RESUME an ERROR."L];
resultInfo.alwaysOnePkt =>
BEGIN
Marshal.FromPacket[ nest: nest,
paramInfo: resultInfo,
overlayHandling: [static: leaveInPkt],
varNames: ReturnVars ];
ReturnStmt[ nest: nest,
type: transferInfo.kind,
resultInfo: resultInfo,
resultOverlayPtr: ResultPtr,
staticResults: inPktOverlay ];
END; -- alwaysOnePkt.
resultInfo.alwaysMultiplePkts =>
BEGIN
Marshal.FromPacket[ nest: nest,
paramInfo: resultInfo,
overlayHandling: [static: copyToFrame],
varNames: ReturnVars ];
ReturnStmt[ nest: nest,
type: transferInfo.kind,
resultInfo: resultInfo,
resultOverlayPtr: ResultPtr,
staticResults: inFrame ];
END; -- alwaysMultiplePkt.
~resultInfo.hasOverlayParamType[static] =>
BEGIN
-- Could be multiple packets, no statics.
Marshal.FromPacket[ nest: nest,
paramInfo: resultInfo,
overlayHandling: [static: leaveInPkt],
varNames: ReturnVars ];
ReturnStmt[ nest: nest,
type: transferInfo.kind,
resultInfo: resultInfo,
resultOverlayPtr: ResultPtr,
staticResults: inFrame ];
END; -- One or more packets, no statics.
ENDCASE => -- Could be one or more packets, some statics.
BEGIN
WFL1[nest, "BEGIN -- OnePkt."L];
WFL[nest, "onePkt: BOOLEAN = "L, LastPkt, ";"L];
WFL1[nest, "IF ~onePkt THEN BEGIN -- Must move statics from pkt now."L];
Marshal.FromPacket[ nest: nest+1,
paramInfo: resultInfo,
overlayHandling: [static: justCopyToFrame],
varNames: ReturnVars ];
WFL1[nest+1, "END;"L];
Marshal.FromPacket[ nest: nest,
paramInfo: resultInfo,
overlayHandling: [static: leaveInPkt],
varNames: ReturnVars ];
WFL1[nest, "IF onePkt"L];
WFS[Indent[nest+1], "THEN "L];
Return[
type: transferInfo.kind,
resultInfo: resultInfo,
resultOverlayPtr: ResultPtr,
staticResults: inPktOverlay ];
WFS["*N"L, Indent[nest+1], "ELSE "L];
Return[
type: transferInfo.kind,
resultInfo: resultInfo,
resultOverlayPtr: ResultPtr,
staticResults: inFrame ];
WFS1[";*N"L];
WFL1[nest, "END; -- OnePkt."L];
END; -- One or more packets.
WFL[nest, "END; -- "L, blockName, "."L];
END; -- CallingStubBody.
DoConversationArg: PROCEDURE [argInfo: ParamInfo] =
BEGIN
conversationFound: BOOLEAN ← FALSE;
PrintConversationName: Marshal.ParamProcedure =
BEGIN
IF paramFieldInfo.location = inConversation
THEN BEGIN
Declare.WriteParameterName[paramName, paramIndex];
RETURN[stop: (conversationFound ← TRUE)];
END;
END;
WFS1[", localConversation: "L];
Marshal.EnumerateParams[paramInfo: argInfo, paramProc: PrintConversationName];
IF ~conversationFound THEN ERROR;
END;
-- Generate Server procedure stubs and Client signal-raising stubs.
CalledStubBody: PROCEDURE [
transferName, blockName: String,
transferInfo: TransferInfo,
inlineBody: BOOLEAN,
argInfo, resultInfo: ParamInfo,
nest: Nest ] =
BEGIN
CallPkt: String = "pkt"L; -- Must be identical to Dispatcher's pkt.
ReturnPkt: String = CallPkt; -- ... pkt.
CallLength: String = "pktLength"L;
ReturnLength: String --must equal-- = CallLength;
CallLimit: String = "callLimit"L; -- Not used at this time.
LastPkt: String = "lastPkt"L; -- Must be identical to Dispatcher's lastPkt.
ArgPtr: String = "argPkt"L;
ResultPtr: String = "resPkt"L;
CallVars: Marshal.VariableNames = [
pkt: CallPkt, overlayPtr: ArgPtr,
pktLength: CallLength, pktLimit: CallLimit,
lastPkt: LastPkt ];
ReturnVars: Marshal.VariableNames = [
pkt: ReturnPkt, overlayPtr: ResultPtr,
pktLength: ReturnLength, pktLimit: ""L,
lastPkt: LastPkt ];
WFL[nest, (IF inlineBody THEN "INLINE "L ELSE ""L), "BEGIN"L];
ParamsAsLocalVars[nest: nest, paramInfo: argInfo];
ParamsAsLocalVars[nest: nest, paramInfo: resultInfo];
OverlayRecord[paramInfo: argInfo, nest: nest];
OverlayRecord[paramInfo: resultInfo, nest: nest];
IF ~LongString.EqualStrings[CallPkt, Private.GetString[dispatcherPkt]] THEN ERROR;
--IF ~LongString.EqualStrings[CallPkt, ReturnPkt] THEN ERROR;
OverlayPointer[ nest: nest,
paramInfo: argInfo,
pktName: CallPkt, overlayPtrName: ArgPtr,
do: both ];
OverlayPointer[ nest: nest,
paramInfo: resultInfo,
pktName: ReturnPkt, overlayPtrName: ResultPtr,
do: IF argInfo.alwaysOnePkt THEN both ELSE declare ];
PacketLength[ nest: nest,
paramInfo: argInfo,
pktLengthName: CallLength,
declare: IF argInfo.transferType=Error THEN ifNeeded ELSE yes,
assign: ifNeeded ];
nest ← Marshal.BeginAllocation[paramInfo: argInfo, nest: nest];
SELECT TRUE FROM
argInfo.alwaysOnePkt =>
BEGIN
Marshal.FromPacket[ nest: nest,
paramInfo: argInfo,
overlayHandling: [static: leaveInPkt],
varNames: CallVars ];
--OverlayPointer[ nest: nest,
--paramInfo: resultInfo,
--pktName: ReturnPkt, overlayPtrName: ResultPtr,
--do: argInfo.alwaysOnePkt => assigned above ];
CallStmt[ nest: nest,
transferName: transferName,
type: transferInfo.kind,
argInfo: argInfo, resultInfo: resultInfo,
staticArgs: inPktOverlay, staticResults: inPktOverlay,
argOverlayPtr: ArgPtr, resultOverlayPtr: ResultPtr ];
END; -- alwaysOnePkt.
argInfo.alwaysMultiplePkts =>
BEGIN
Marshal.FromPacket[ nest: nest,
paramInfo: argInfo,
overlayHandling: [static: copyToFrame],
varNames: CallVars ];
OverlayPointer[ nest: nest,
paramInfo: resultInfo,
pktName: ReturnPkt, overlayPtrName: ResultPtr,
do: assign ];
CallStmt[ nest: nest,
transferName: transferName,
type: transferInfo.kind,
argInfo: argInfo, resultInfo: resultInfo,
staticArgs: inFrame, staticResults: inPktOverlay,
argOverlayPtr: ArgPtr, resultOverlayPtr: ResultPtr ];
END; -- alwaysMultiplePkt.
~argInfo.hasOverlayParamType[static] =>
BEGIN
-- Could be multiple packets, no statics.
Marshal.FromPacket[ nest: nest,
paramInfo: argInfo,
overlayHandling: [static: leaveInPkt],
varNames: CallVars ];
OverlayPointer[ nest: nest,
paramInfo: resultInfo,
pktName: ReturnPkt, overlayPtrName: ResultPtr,
do: assign ];
CallStmt[ nest: nest,
transferName: transferName,
type: transferInfo.kind,
argInfo: argInfo, resultInfo: resultInfo,
staticArgs: inFrame, staticResults: inPktOverlay,
argOverlayPtr: ArgPtr, resultOverlayPtr: ResultPtr ];
END; -- One or more packets, no statics.
ENDCASE => -- Could be one or more packets, some statics.
BEGIN
WFL1[nest, "BEGIN -- OnePkt."L];
WFL[nest, "onePkt: BOOLEAN = "L, LastPkt, ";"L];
WFL1[nest, "IF ~onePkt THEN BEGIN -- Must move statics from pkt now."L];
Marshal.FromPacket[ nest: nest+1,
paramInfo: argInfo,
overlayHandling: [static: justCopyToFrame],
varNames: CallVars ];
WFL1[nest+1, "END;"L];
Marshal.FromPacket[ nest: nest,
paramInfo: argInfo,
overlayHandling: [static: leaveInPkt],
varNames: CallVars ];
OverlayPointer[ nest: nest,
paramInfo: resultInfo,
pktName: ReturnPkt, overlayPtrName: ResultPtr,
do: assign ];
WFL1[nest, "IF onePkt"L];
WFS[Indent[nest+1], "THEN "L];
Call[ nest: nest+2,
transferName: transferName,
type: transferInfo.kind,
argInfo: argInfo, resultInfo: resultInfo,
staticArgs: inPktOverlay, staticResults: inPktOverlay,
argOverlayPtr: ArgPtr, resultOverlayPtr: ResultPtr ];
WFS["*N"L, Indent[nest+1], "ELSE "L];
Call[ nest: nest+2,
transferName: transferName,
type: transferInfo.kind,
argInfo: argInfo, resultInfo: resultInfo,
staticArgs: inFrame, staticResults: inPktOverlay,
argOverlayPtr: ArgPtr, resultOverlayPtr: ResultPtr ];
WFS1[";*N"L];
WFL1[nest, "END; -- OnePkt."L];
END; -- One or more packets.
PacketLength[ nest: nest,
paramInfo: resultInfo,
pktLengthName: ReturnLength,
declare: no,
assign: IF argInfo.transferType=Error THEN no ELSE yes ];
Marshal.ToPacket[ nest: nest,
paramInfo: resultInfo,
overlayHandling: [static: alreadyInPkt],
varNames: ReturnVars ];
nest ← Marshal.EndAllocation[ nest: nest,
paramInfo: argInfo,
justCloseBlocks: argInfo.transferType=Error ];
IF argInfo.transferType # Error -- Nothing can follow an ERROR.
THEN BEGIN
WFSL[Indent[nest],
"RETURN["L, Private.GetString[dispatcherReturnLength],
": "L, ReturnLength, "];*N"L ];
END;
WFL[nest, "END; -- "L, blockName, "."L];
END; -- CalledStubBody.
-- Call, return, and parameter record routines.
CallStmt: PROCEDURE [
transferName: String,
type: ST.TransferTypes,
argInfo, resultInfo: ParamInfo,
staticArgs, staticResults: ParamLocation,
argOverlayPtr, resultOverlayPtr: String,
nest: Nest ] =
BEGIN
WFS1[Indent[nest]];
Call[transferName, type, argInfo, resultInfo,
staticArgs, staticResults, argOverlayPtr, resultOverlayPtr, nest];
WFS1[";*N"L];
END;
Call: PROCEDURE [
transferName: String,
type: ST.TransferTypes,
argInfo, resultInfo: ParamInfo,
staticArgs, staticResults: ParamLocation,
argOverlayPtr, resultOverlayPtr: String,
nest: Nest ] =
BEGIN
CallName: ARRAY ST.TransferTypes OF String = [
Procedure: ""L, Error: "ERROR "L, Signal: "SIGNAL "L,
Port: ""L, Program: "START "L, Process: "FORK "L, Other: ""L ];
IF resultInfo.paramCount > 0
THEN BEGIN
ParameterConstructor[
paramInfo: resultInfo,
overlayPtrName: resultOverlayPtr,
statics: staticResults ];
IF resultInfo.paramCount < 2
THEN WFS1[" ← "L] ELSE WFS[" ←*N"L, Indent[nest+1]];
END;
WFS[CallName[type], --ModuleName[interface], "."L,-- transferName];
ParameterConstructor[
paramInfo: argInfo, overlayPtrName: argOverlayPtr, statics: staticArgs];
END;
ReturnStmt: PROCEDURE [
type: ST.TransferTypes,
resultInfo: ParamInfo,
resultOverlayPtr: String,
staticResults: ParamLocation,
nest: Nest ] =
BEGIN
WFS1[Indent[nest]];
Return[type, resultInfo, resultOverlayPtr, staticResults];
WFS1[";*N"L];
END;
Return: PROCEDURE [
type: ST.TransferTypes,
resultInfo: ParamInfo,
resultOverlayPtr: String,
staticResults: ParamLocation ] =
BEGIN
ReturnName: ARRAY ST.TransferTypes OF String = [
Procedure: "RETURN"L, Error: "RESUME"L, Signal: "RESUME"L,
Port: ""L, Program: "STOP"L, Process: ""L, Other: ""L ];
WFS1[ReturnName[type]];
ParameterConstructor[
paramInfo: resultInfo,
overlayPtrName: resultOverlayPtr,
statics: staticResults ];
END;
ParameterConstructor: PROCEDURE [
paramInfo: ParamInfo,
overlayPtrName: String,
statics: ParamLocation ] =
BEGIN
DoField: Marshal.ParamProcedure =
BEGIN
IF paramIndex > 1 THEN WFS1[", "L];
SELECT paramFieldInfo.location FROM
inConversation => WFS1[Private.GetString[dispatcherConversation]];
inPktOverlay => {
IF statics=inPktOverlay THEN WFS[overlayPtrName, "."L];
Declare.WriteParameterName[paramName, paramIndex] };
inFrame, inFrameAndOverlay =>
Declare.WriteParameterName[paramName, paramIndex];
ENDCASE => ERROR;
END; -- DoField.
WFS1["["L];
Marshal.EnumerateParams[paramInfo, DoField];
WFS1["]"L];
END;
FullParameterList: PROCEDURE [
argInfo, resultInfo: ParamInfo,
printingComment: BOOLEAN,
nest: Nest ] =
BEGIN
IF argInfo.paramCount > 0
THEN BEGIN
ArgNameTypeList: Marshal.ParamProcedure =
BEGIN
IF paramIndex > 1 THEN WFS1[", "L];
Declare.WriteParameterName[paramName, paramIndex];
WFS1[": "L]; Declare.WriteTypeName[paramType];
END; -- ArgNameTypeList.
WFS1["["L];
Marshal.EnumerateParams[argInfo, ArgNameTypeList];
WFS1["]"L];
END;
IF resultInfo.paramCount > 0
THEN BEGIN
keywordComments: BOOLEAN =
~printingComment AND OverlayStaticsStayInPkt[resultInfo];
-- If the overlay never moves, do not allocate needless space for
-- results by assigning keywords. This means that nonstatics
-- will have no keywords and be undeclared too. Their needed
-- declarations are handled separately by ParamsAsLocalVars.
ResultNameTypeList: Marshal.ParamProcedure =
BEGIN
IF paramIndex > 1 THEN WFS1[", "L];
IF keywordComments THEN WFS1["--"L];
Declare.WriteParameterName[paramName, paramIndex];
WFS1[IF keywordComments THEN ":-- "L ELSE ": "L];
Declare.WriteTypeName[paramType];
END; -- ResultNameTypeList.
SELECT argInfo.paramCount FROM
0 => NULL;
IN [1..2] => WFS1[" "L];
>2 =>
WFS["*N"L, Indent[nest+1], (IF printingComment THEN "-- "L ELSE ""L)];
ENDCASE => NULL;
WFS1["RETURNS ["L];
Marshal.EnumerateParams[resultInfo, ResultNameTypeList];
WFS1["]"L];
END;
END;
ParamsAsLocalVars: PROCEDURE [
paramInfo: ParamInfo,
doOnlyAnonymousParams: BOOLEAN←FALSE,
doOnlyAddressParams: BOOLEAN←FALSE,
nest: Nest ] =
BEGIN
DeclareLocalVar: Marshal.ParamProcedure =
BEGIN
IF doOnlyAnonymousParams AND ~ST.IsAnonymous[paramName] THEN RETURN;
IF doOnlyAddressParams AND ~OverlayStaticsStayInPkt[paramInfo] THEN RETURN;
IF ParamStaysInPkt[paramInfo, paramFieldInfo] THEN RETURN;
SELECT paramFieldInfo.location FROM
inFrame, inPktOverlay, inFrameAndOverlay =>
BEGIN
WFS1[Indent[nest]];
Declare.WriteParameterName[paramName, paramIndex];
WFS1[": "L];
Declare.WriteTypeName[paramType];
WFS1[";*N"L];
END;
ENDCASE => NULL; -- Skip others (eg, conversation, stream).
END; -- DeclareLocalVar.
Marshal.EnumerateParams[paramInfo, DeclareLocalVar];
END;
ParamStaysInPkt: PROCEDURE [
paramInfo: ParamInfo, fieldInfo: Marshal.FieldInfo ]
RETURNS [--yes:-- BOOLEAN] =
INLINE BEGIN OPEN info: paramInfo;
RETURN[
fieldInfo.location = inPktOverlay AND
( info.alwaysOnePkt OR
info.transferSite=caller AND info.paramRecordKind=argument OR
info.transferSite=callee AND info.paramRecordKind=result ) ];
END;
OverlayStaticsStayInPkt: PROCEDURE [paramInfo: ParamInfo]
RETURNS [--yes:-- BOOLEAN] =
INLINE BEGIN
RETURN[ paramInfo.hasOverlayParamType[static] AND paramInfo.alwaysOnePkt ];
END;
-- Overlay record, overlay pointer, and packet length routines.
OverlayRecord: PROCEDURE [
paramInfo: ParamInfo,
transferIndexName: String←StringNIL,
nest: Nest] =
BEGIN
overlayIndex: Marshal.Words ← paramInfo.sizeOf.overlayHeader;
printedOne: BOOLEAN ← FALSE;
DeclareField: Marshal.ParamProcedure =
BEGIN
SELECT paramFieldInfo.location FROM
inPktOverlay, inFrameAndOverlay =>
BEGIN
IF printedOne THEN WFS1[", "L] ELSE printedOne ← TRUE;
Declare.WriteParameterName[paramName, paramIndex];
CWF.WF1[" (%D): "L, @overlayIndex];
overlayIndex ← overlayIndex + paramFieldInfo.size;
Declare.WriteTypeName[paramType];
END;
ENDCASE => NULL;
END; -- DeclareField.
SELECT paramInfo.paramRecordKind FROM
argument =>
IF paramInfo.hasOverlayParams OR paramInfo.transferSite=caller
THEN BEGIN
WFSL[Indent[nest],
"ArgumentOverlay: TYPE = MACHINE DEPENDENT RECORD [*B"L,
"transferIndex (0): RpcControl."L,
(SELECT paramInfo.transferType FROM
Procedure => Private.GetString[procedureIndex],
Signal, Error => Private.GetString[signalIndex],
ENDCASE => ERROR) ];
IF ~IsNull[transferIndexName] THEN WFS[" ← "L, transferIndexName];
SELECT paramInfo.transferDeclaration FROM
inRoutine => WFS1[", callback (1): RpcPrivate.Dispatcher"L];
ENDCASE => NULL;
printedOne ← TRUE;
Marshal.EnumerateParams[paramInfo, DeclareField];
WFS1["];*N"L];
END;
result =>
IF paramInfo.hasOverlayParams
THEN BEGIN
WFS[ Indent[nest],
"ResultOverlay: TYPE = MACHINE DEPENDENT RECORD [*B"L ];
Marshal.EnumerateParams[
paramInfo: paramInfo, paramProc: DeclareField,
includeRESULTs: TRUE ];
WFS1["];*N"L];
END;
ENDCASE => ERROR;
IF overlayIndex # paramInfo.sizeOf.overlayParamRecord THEN ERROR;
END;
OverlayPointer: PROCEDURE [
paramInfo: ParamInfo,
pktName, overlayPtrName: String,
do: {declare, assign, both},
nest: Nest ] =
BEGIN
IF NOT ( paramInfo.hasOverlayParams OR
(paramInfo.paramRecordKind=argument AND paramInfo.transferSite=caller) )
THEN RETURN;
WFS[Indent[nest], overlayPtrName];
SELECT do FROM
declare, both =>
WFSL[
(SELECT paramInfo.pktSite FROM
rpcRuntime => ": LONG "L, stubFrame => ": "L, ENDCASE => ERROR),
"POINTER TO "L,
(SELECT paramInfo.paramRecordKind FROM
argument => "Argument"L, result => "Result"L, ENDCASE => ERROR),
"Overlay"L];
ENDCASE => NULL;
SELECT do FROM assign => WFS1[" ← "L]; both => WFS1[" = "L]; ENDCASE => NULL;
SELECT do FROM
assign, both => WFS["@"L, pktName, ".data[0]"L];
ENDCASE => NULL;
WFS1[";*N"L];
END;
LocalPacket: PROCEDURE [pktName: String, size: Marshal.Words, nest: Nest] =
BEGIN
WFS[Indent[nest], pktName, "Buffer: ARRAY [1..RpcPrivate.pktOverhead"L];
CWF.WF1["+%LD] OF WORD;*N"L, @size];
WFLL[nest, pktName, ": RpcPrivate.StubPkt = RpcPrivate.GetStubPkt[space: @"L,
pktName, "Buffer];"L];
END;
PacketLength: PROCEDURE [
paramInfo: ParamInfo,
pktLengthName: String,
declare, assign: {yes, ifNeeded, no},
nest: Nest ] =
BEGIN
HasInFrameParams: PROC [paramInfo: ParamInfo] RETURNS [BOOLEAN] =
INLINE {RETURN[
paramInfo.adrInfo.hasAddresses OR
paramInfo.adrInfo.hasDynamics OR
~paramInfo.alwaysOnePkt ]};
declareNeeded: BOOLEAN = SELECT declare FROM
yes => TRUE, no => FALSE, ifNeeded => HasInFrameParams[paramInfo],
ENDCASE => ERROR;
assignNeeded: BOOLEAN = SELECT assign FROM
yes => TRUE, no => FALSE, ifNeeded => HasInFrameParams[paramInfo],
ENDCASE => ERROR;
IF declareNeeded OR assignNeeded THEN WFS[Indent[nest], pktLengthName];
IF declareNeeded THEN WFS1[": RpcPrivate.DataLength"L];
IF assignNeeded
THEN CWF.WF1[" ← %LD"L, @paramInfo.sizeOf.overlayParamRecord];
IF declareNeeded OR assignNeeded THEN WFS1[";*N"L];
END;
-- ParamInfo veneer.
GetArgResultInfo: PROCEDURE [
transferInfo: TransferInfo,
transferDeclaration: TransferDeclaration,
transferSite: TransferSite,
pktSite: PktSite,
options: Options ]
RETURNS [argInfo, resultInfo: ParamInfo] =
BEGIN
argInfo ← Marshal.MakeParamInfo[
paramRecord: transferInfo.argumentType,
paramRecordKind: argument,
transferType: transferInfo.kind,
transferDeclaration: transferDeclaration,
transferSite: transferSite,
pktSite: pktSite,
options: options ];
resultInfo ← Marshal.MakeParamInfo[
paramRecord: transferInfo.resultType,
paramRecordKind: result,
RESULTsParamInfo: argInfo,
transferType: transferInfo.kind,
transferDeclaration: transferDeclaration,
transferSite: transferSite,
pktSite: pktSite,
options: options
! UNWIND => Marshal.FreeParamInfo[argInfo] ];
END;
FreeArgResultInfo: PROCEDURE [argInfo, resultInfo: ParamInfo] =
INLINE BEGIN
Marshal.FreeParamInfo[argInfo];
Marshal.FreeParamInfo[resultInfo];
END;
GetTransferInfo: PROCEDURE [typeHandle: ST.TypeHandle]
RETURNS[--transferInfo:-- TransferInfo] =
INLINE BEGIN
typeInfo: ST.TypeInfo = ST.GetTypeInfo[type: typeHandle];
WITH typeInfo: typeInfo SELECT FROM
Transfer => RETURN[typeInfo];
ENDCASE => RETURN[ERROR];
END;
END. -- LupineDeclareStubsImpl.