-- File [Ivy]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: "<<>>"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.