-- File [Ivy]Lupine>LupineMarshalTypeConstructorImpl.mesa. -- Last edited by BZM on March 18, 1982 11:18 AM. -- This module cooperates with LupineMarshal*Impl to export LupineMarshal. DIRECTORY CWF USING [SWF1, SWF2], LupineDeclare USING [WriteSymbolName, WriteTypeName], LupineManagerPrivate USING [ AllocString, Indent, MaxIdentifierLength, Nest, ParamPassingMethod, String, StringNIL, WFS, WFS1, WFSL, WFL, WFL1, WFLL ], LupineMarshal USING [FieldInfo, ParamInfo, ParamRecordKind], LupineMarshalPrivate USING [ ContainsRefs, ContainsSequences, ContainsStatics, CopyOne, CopyTwo, CopyType, Direction, Error, HasEmptyIndex, MarshalInfo, MarshalType, MaxGeneratedIdLength, MaxPointerDepth, NeedsMarshaling, NeedsOperationProc, OperationProc, ParentInfo, Passing, SubStrings, UniqueName, VerifyPassingMethods, WriteNEW ], LupineSymbolTable USING [ ComponentProcedure, EnumerateRecord, EnumerateVariants, GetTypeInfo, IsAnonymous, SymbolHandle, SymbolName, TypeHandle, TypeInfo, Types, VariantProcedure ]; LupineMarshalTypeConstructorImpl: PROGRAM IMPORTS CWF, Declare: LupineDeclare, LupineManagerPrivate, Private: LupineMarshalPrivate, ST: LupineSymbolTable EXPORTS LupineMarshalPrivate = BEGIN OPEN LupineManagerPrivate, LupineMarshal; -- Types from the internal LupineManagerPrivate interface. ParentInfo: TYPE = Private.ParentInfo; MarshalInfo: TYPE = Private.MarshalInfo; NeedsOperationProc: TYPE = Private.NeedsOperationProc; OperationProc: TYPE = Private.OperationProc; SubStrings: TYPE = Private.SubStrings; MaxGeneratedIdLength: CARDINAL = Private.MaxGeneratedIdLength; -- NOTE: -- The string constants in recursively-callable routines within this -- this module have intentionally been put into the global frame. This -- is necessary because putting the literals into the local frames gives -- them sizes in the 100-600 word range, which causes the deep calls -- to get frame faults. When the amount of frame space increases, just -- substitute "L for "-'-L-'-. -- Marshaling routines for type constructors (i.e., nonbuiltin types). MarshalTransfer: PUBLIC PROCEDURE [ name: String, transferInfo: Transfer ST.TypeInfo, parentInfo: ParentInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN Private.VerifyPassingMethods[value: TRUE, handle: TRUE, marshalInfo: marshalInfo]; Private.Error[code: TransferParameter, type: transferInfo.self]; END; MarshalRecord: PUBLIC PROCEDURE [ name: String, recInfo: Record ST.TypeInfo, parentInfo: ParentInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN Private.VerifyPassingMethods[value: TRUE, marshalInfo: marshalInfo]; IF recInfo.hasSequences THEN MarshalSequenceRecord[ nest: nest, recName: name, recInfo: recInfo, parentInfo: parentInfo, marshalInfo: marshalInfo ] ELSE MarshalFixedRecord[ nest: nest, recName: name, recInfo: recInfo, parentInfo: parentInfo, marshalInfo: marshalInfo ]; END; MarshalFixedRecord: PROCEDURE [ recName: String, recInfo: Record ST.TypeInfo, parentInfo: ParentInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN -- MarshalFixedRecord needs storage for the record to already be allocated. -- Thus, sequence containing records are separately handled by -- MarshalSequenceRecord, which calls us to do some work. IF (SELECT parentInfo.typeInfo.type FROM Record, VariantPart => FALSE, ENDCASE => TRUE) AND Private.ContainsStatics[recInfo.self] THEN BEGIN Private.CopyType[ nest: nest, variableName: recName, variableInfo: recInfo, parentInfo: parentInfo, marshalInfo: marshalInfo ]; -- After a blind copy, always reset any Refs to NIL immediately. -- This consistency-making must be done atomically, ie, there -- must be no possibility of a fault (UNWIND) between the copying -- and the NIL-making. MakeRefsNil[ nest: nest, name: recName, type: recInfo.self, parentInfo: parentInfo, marshalInfo: marshalInfo ]; END; DoRecordOperation[ nest: nest, opProc: Private.MarshalType, needsOpProc: Private.NeedsMarshaling, recName: recName, recInfo: recInfo, marshalInfo: marshalInfo ]; END; MarshalSequenceRecord: PROCEDURE [ recName: String, recInfo: Record ST.TypeInfo, parentInfo: ParentInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN IF ~recInfo.hasSequences OR (SELECT parentInfo.typeInfo.type FROM Pointer, Ref => FALSE, ENDCASE => TRUE) THEN ERROR; SELECT marshalInfo.direction FROM toPkt => BEGIN Private.CopyOne[ nest: nest, wordsNeeded: 3, value: [parentInfo.name, "=NIL"--L--], marshalInfo: marshalInfo ]; WFL[nest, "IF "--L--, parentInfo.name, " # NIL THEN BEGIN"--L--]; WFL1[nest+1, "-- Record has a sequence, put its length up front."--L--]; Private.CopyTwo[ nest: nest+1, wordsNeeded: 0, value: SubStrings["LENGTH[DESCRIPTOR["--L--, recName, "]]"--L--], marshalInfo: marshalInfo ]; IF Private.Passing[Result, argument, marshalInfo] THEN WFL1[nest+1, "NULL; -- Call by result, don't send record."--L--] ELSE MarshalFixedRecord[ nest: nest+1, recName: recName, recInfo: recInfo, parentInfo: parentInfo, marshalInfo: marshalInfo ]; WFL[nest+1, "END; -- IF "--L--, parentInfo.name, " # NIL."--L--]; END; fromPkt => BEGIN WFL1[nest, "recordIsNIL: Lupine.NilHeader;"--L--]; Private.CopyOne[ nest: nest, wordsNeeded: 3, value: ["recordIsNIL"--L--], marshalInfo: marshalInfo ]; IF Private.Passing[Result, result, marshalInfo] OR Private.Passing[Var, result, marshalInfo] THEN WFL[nest, "IF recordIsNIL # ("--L--, parentInfo.name, "=NIL) THEN Lupine.UnmarshalingError;"--L--]; WFL1[nest, "IF recordIsNIL"--L--]; WFL[nest+1, "THEN "--L--, parentInfo.name, " _ NIL"--L--]; WFL1[nest+1, "ELSE BEGIN"--L--]; WFL1[nest+2, "seqLength: Lupine.SequenceHeader;"--L--]; Private.CopyTwo[ nest: nest+2, wordsNeeded: 0, value: ["seqLength"--L--], marshalInfo: marshalInfo ]; IF Private.Passing[Result, result, marshalInfo] OR Private.Passing[Var, result, marshalInfo] THEN BEGIN WFL[nest+2, "IF seqLength # LENGTH[DESCRIPTOR["--L--, recName, "]] THEN Lupine.UnmarshalingError;"--L-- ]; WFL1[nest+2, "NULL; -- Call by var or result, use existing record."--L--]; END ELSE BEGIN WFS[Indent[nest+2], parentInfo.name, " _ ("--L--]; Private.WriteNEW[ ptrInfo: parentInfo.typeInfo, marshalInfo: marshalInfo ]; WFS1["["--L--]; Declare.WriteTypeName[recInfo.self]; WFS1["[Lupine.SHORT[seqLength]]]);*N"--L--]; END; IF Private.Passing[Result, argument, marshalInfo] THEN WFL1[nest+2, "NULL; -- Call by result, use uninitialized record."--L--] ELSE MarshalFixedRecord[ nest: nest+2, recName: recName, recInfo: recInfo, parentInfo: parentInfo, marshalInfo: marshalInfo ]; WFL[nest+2, "END; -- IF recordIsNIL."--L--]; END; ENDCASE => ERROR; END; DoRecordOperation: PROCEDURE [ opProc: OperationProc, needsOpProc: NeedsOperationProc, recName: String, recInfo: Record ST.TypeInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN MarshalField: ST.ComponentProcedure = BEGIN fieldString: AllocString = [MaxIdentifierLength]; IF ~needsOpProc[componentType] THEN RETURN; -- Monitored records will be caught because of the LOCK field. opProc[ nest: nest, name: FieldName[ fieldSymbol: component, fieldString: fieldString, recordType: recInfo.self, anonOk: -- Single component variant records don't need names. componentIndex = 1 AND recInfo.hasVariants AND ST.GetTypeInfo[componentType].type = VariantPart ], type: componentType, parentInfo: [recName, recInfo], marshalInfo: marshalInfo ]; END; IF needsOpProc[recInfo.self] THEN BEGIN WFL[nest, "BEGIN OPEN record: "--L--, recName, ";"--L--]; [] _ ST.EnumerateRecord[recordType: recInfo.self, proc: MarshalField]; WFL[nest, "END; -- OPEN record: "--L--, recName, "."--L--]; END; END; MarshalVariantPart: PUBLIC PROCEDURE [ name: String, varInfo: VariantPart ST.TypeInfo, parentInfo: ParentInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN Private.VerifyPassingMethods[value: TRUE, marshalInfo: marshalInfo]; IF Private.ContainsSequences[varInfo.self] THEN Private.Error[code: SequenceInsideVariant, type: varInfo.self] ELSE DoVariantOperation[ nest: nest, opProc: Private.MarshalType, needsOpProc: Private.NeedsMarshaling, varName: name, varInfo: varInfo, marshalInfo: marshalInfo ]; END; DoVariantOperation: PROCEDURE [ opProc: OperationProc, needsOpProc: NeedsOperationProc, varName: String, varInfo: VariantPart ST.TypeInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN MarshalVariant: ST.VariantProcedure = BEGIN IF ~needsOpProc[variantRecordType] THEN RETURN; WFS1[Indent[nest+1]]; Declare.WriteSymbolName[variantTag]; WFS1[" =>*N"--L--]; opProc[ nest: nest+2, name: "variant"--L--, type: variantRecordType, parentInfo: [varName, varInfo], marshalInfo: marshalInfo ]; END; -- MarshalVariant. SELECT TRUE FROM ~needsOpProc[varInfo.self] => NULL; varInfo.kind = Computed => Private.Error[code: ComputedVariant, type: varInfo.self]; ENDCASE => BEGIN WFL1[nest, "WITH variant: record SELECT FROM"--L--]; [] _ ST.EnumerateVariants[ variantPartType: varInfo.self, proc: MarshalVariant]; WFL1[nest+1, "ENDCASE => NULL; -- WITH variant: record."--L--]; END; END; MarshalPointer: PUBLIC PROCEDURE [ name: String, pointerInfo: Pointer ST.TypeInfo, parentInfo: ParentInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN MarshalPointerTypes[ nest: nest, ptrName: name, ptrInfo: pointerInfo, referentType: pointerInfo.referentType, parentInfo: parentInfo, marshalInfo: marshalInfo ]; END; MarshalRef: PUBLIC PROCEDURE [ name: String, refInfo: Ref ST.TypeInfo, parentInfo: ParentInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN MarshalPointerTypes[ nest: nest, ptrName: name, ptrInfo: refInfo, referentType: refInfo.referentType, parentInfo: parentInfo, marshalInfo: marshalInfo ]; END; MarshalPointerTypes: PROCEDURE [ ptrName: String, ptrInfo: ST.TypeInfo, referentType: ST.TypeHandle, parentInfo: ParentInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN referentInfo: ST.TypeInfo = ST.GetTypeInfo[referentType]; referentName: AllocString = [MaxIdentifierLength]; Private.VerifyPassingMethods[all: TRUE, marshalInfo: marshalInfo]; CWF.SWF1[referentName, "%LS^"--L--, ptrName]; marshalInfo.ptrDepth _ marshalInfo.ptrDepth + 1; SELECT TRUE FROM marshalInfo.ptrDepth > Private.MaxPointerDepth => Private.Error[code: ProbablePointerRecursion, type: ptrInfo.self]; (WITH refInfo: referentInfo SELECT FROM Basic => SELECT refInfo.kind FROM Unspecified, Other => TRUE, ENDCASE => FALSE, Any => TRUE, Opaque => ~refInfo.lengthKnown, ENDCASE => FALSE) => Private.Error[code: InvalidHandle, type: ptrInfo.self]; (WITH refInfo: referentInfo SELECT FROM Text, StringBody => TRUE, Record => refInfo.hasSequences, ENDCASE => FALSE) => Private.MarshalType[ nest: nest, name: referentName, type: referentType, parentInfo: [ptrName, ptrInfo], marshalInfo: marshalInfo ]; ENDCASE => MarshalFixedReferent[ nest: nest, ptrName: ptrName, ptrInfo: ptrInfo, referentName: referentName, referentInfo: referentInfo, parentInfo: parentInfo, marshalInfo: marshalInfo ]; marshalInfo.ptrDepth _ marshalInfo.ptrDepth - 1; END; MarshalFixedReferent: PROCEDURE [ ptrName: String, ptrInfo: ST.TypeInfo, referentName: String, referentInfo: ST.TypeInfo, parentInfo: ParentInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN -- This routine expects that the referentType has a fixed, -- nondynamic length. MarshalPointerTypes should have screened this. SELECT marshalInfo.direction FROM toPkt => BEGIN Private.CopyOne[ nest: nest, wordsNeeded: 1, value: [ptrName, "=NIL"--L--], marshalInfo: marshalInfo ]; WFL[nest, "IF "--L--, ptrName, " # NIL THEN"--L--]; IF Private.Passing[Result, argument, marshalInfo] THEN WFL1[nest+1, "NULL; -- Call by result, send nothing."--L--] ELSE Private.MarshalType[ nest: nest+1, name: referentName, type: referentInfo.self, parentInfo: [ptrName, ptrInfo], marshalInfo: marshalInfo ]; END; fromPkt => BEGIN WFL1[nest, "isNIL: Lupine.NilHeader;"--L--]; Private.CopyOne[ nest: nest, wordsNeeded: 1, value: ["isNIL"--L--], marshalInfo: marshalInfo ]; IF Private.Passing[Result, result, marshalInfo] OR Private.Passing[Var,result,marshalInfo] THEN BEGIN WFL[nest, "IF isNIL # ("--L--, ptrName, "=NIL) THEN Lupine.UnmarshalingError;"--L--]; WFL1[nest, "IF ~isNIL THEN"--L--]; WFL1[nest+1, "-- Call by var or result, use existing referent."--L--]; Private.MarshalType[ nest: nest+1, name: referentName, type: referentInfo.self, parentInfo: [ptrName, ptrInfo], marshalInfo: marshalInfo ]; END ELSE BEGIN WFL1[nest, "IF isNIL"--L--]; WFL[nest+1, "THEN "--L--, ptrName, " _ NIL"--L--]; WFL1[nest+1, "ELSE BEGIN"--L--]; WFS[Indent[nest+2], ptrName, " _ ("--L--]; Private.WriteNEW[ptrInfo: ptrInfo, marshalInfo: marshalInfo]; WFS1["["--L--]; Declare.WriteTypeName[referentInfo.self]; WFS1["]);*N"--L--]; IF Private.Passing[Result, argument, marshalInfo] THEN WFL1[nest+2, "NULL; -- Call by result, use uninitialized referent."--L--] ELSE Private.MarshalType[ nest: nest+2, name: referentName, type: referentInfo.self, parentInfo: [ptrName, ptrInfo], marshalInfo: marshalInfo ]; WFL1[nest+2, "END; -- IF isNIL."--L--]; END; END; ENDCASE => ERROR; END; MarshalList: PUBLIC PROCEDURE [ name: String, listInfo: List ST.TypeInfo, parentInfo: ParentInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN Private.VerifyPassingMethods[value: TRUE, handle: TRUE, marshalInfo: marshalInfo]; DoListOperation[ nest: nest, opProc: Private.MarshalType, needsOpProc: Private.NeedsMarshaling, listName: name, listInfo: listInfo, marshalInfo: marshalInfo ]; END; DoListOperation: PROCEDURE [ opProc: OperationProc, needsOpProc: NeedsOperationProc, listName: String, listInfo: List ST.TypeInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN thisNode: AllocString = [MaxGeneratedIdLength]; thisNodeFirst: AllocString = [MaxGeneratedIdLength]; IF opProc # Private.MarshalType THEN ERROR; -- DoListOperation does only marshaling correctly for now. Private.UniqueName[ root: "thisNode"--L--, nameString: thisNode, marshalInfo: marshalInfo ]; Private.UniqueName[ root: "thisNode"--L--, suffix: ".first"--L--, nameString: thisNodeFirst, marshalInfo: marshalInfo ]; SELECT marshalInfo.direction FROM toPkt => BEGIN WFS[Indent[nest], thisNode, ": "--L--]; Declare.WriteTypeName[type: listInfo.self, includeReadonly: FALSE]; WFS1[";*N"--L--]; WFL1[nest, "listLength: Lupine.ListHeader _ 0;"--L--]; WFSL[ Indent[nest], "FOR "--L--, thisNode, " _ "--L--, listName, ", "--L--, thisNode, ".rest UNTIL "--L--, thisNode, " = NIL DO*N"--L--]; WFL1[nest+1, "listLength _ listLength + 1; ENDLOOP;"--L--]; Private.CopyTwo[ nest: nest, wordsNeeded: 2, value: SubStrings["listLength"--L--], marshalInfo: marshalInfo ]; WFSL[ Indent[nest], "FOR "--L--, thisNode, " _ "--L--, listName, ", "--L--, thisNode, ".rest UNTIL "--L--, thisNode, " = NIL DO*N"--L--]; opProc[ nest: nest+1, name: thisNodeFirst, type: listInfo.firstType, parentInfo: [listName, listInfo], marshalInfo: marshalInfo ]; WFL[nest+1, "ENDLOOP; -- FOR "--L--, thisNode, "."--L--]; END; fromPkt => BEGIN --lastNode: AllocString = [MaxGeneratedIdLength]; --UniqueName[ -- root: "lastNode"L, -- nameString: lastNode, marshalInfo: marshalInfo ]; WFS[Indent[nest], "lastNode: "--L--]; Declare.WriteTypeName[type: listInfo.self, includeReadonly: FALSE]; WFS[" _ ("--L--, listName, " _ NIL);*N"--L--]; WFL1[nest, "listLength: Lupine.ListHeader;"--L--]; Private.CopyTwo[ nest: nest, wordsNeeded: 2, value: SubStrings["listLength"--L--], marshalInfo: marshalInfo ]; WFL1[nest, "WHILE listLength > 0 DO"--L--]; WFS[Indent[nest+1], thisNode, ": "--L--]; Declare.WriteTypeName[type: listInfo.self, includeReadonly: FALSE]; WFS1[" = "--L--]; Private.WriteNEW[ allocOp: cons, ptrInfo: listInfo, marshalInfo: marshalInfo]; WFS1["[--DefaultValue--,NIL];*N"--L--]; opProc[ nest: nest+1, name: thisNodeFirst, type: listInfo.firstType, parentInfo: [listName, listInfo], marshalInfo: marshalInfo ]; WFL1[nest+1, "IF lastNode # NIL"--L--]; WFSL[ Indent[nest+2], "THEN lastNode _ (lastNode.rest _ "--L--, thisNode, ")*N"--L--, Indent[nest+2], "ELSE lastNode _ ("--L--, listName, " _ "--L--, thisNode, ");*N"--L-- ]; WFL1[nest+1, "listLength _ listLength - 1;"--L--]; WFL1[nest+1, "ENDLOOP; -- WHILE listLength > 0."--L--]; END; ENDCASE => ERROR; END; MarshalArray: PUBLIC PROCEDURE [ name: String, arrayInfo: Array ST.TypeInfo, parentInfo: ParentInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN Private.VerifyPassingMethods[value: TRUE, marshalInfo: marshalInfo]; IF Private.HasEmptyIndex[index: arrayInfo.indexType] THEN Private.Error[code: EmptyArray, type: arrayInfo.self] ELSE MarshalVector[ nest: nest, vectorName: name, vectorInfo: arrayInfo, indexType: arrayInfo.indexType, elementType: arrayInfo.elementType, parentInfo: parentInfo, marshalInfo: marshalInfo ]; END; MarshalDescriptor: PUBLIC PROCEDURE [ name: String, descInfo: Descriptor ST.TypeInfo, parentInfo: ParentInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN lengthString: AllocString = [2*MaxIdentifierLength]; Private.VerifyPassingMethods[all: TRUE, marshalInfo: marshalInfo]; CWF.SWF2[ lengthString, "(IF BASE[%LS]=NIL THEN 0 ELSE LENGTH[%LS])"--L--, name, name ]; SELECT marshalInfo.direction FROM toPkt => BEGIN Private.CopyTwo[ nest: nest, wordsNeeded: 2, value: [lengthString], marshalInfo: marshalInfo ]; WFL[nest, "IF BASE["--L--, name, "] # NIL THEN"--L--]; IF Private.Passing[Result, argument, marshalInfo] THEN WFL1[nest+1, "NULL; -- Call by result, send length only."--L--] ELSE BEGIN MarshalVector[ nest: nest+1, vectorName: name, vectorInfo: descInfo, indexType: descInfo.indexType, elementType: descInfo.elementType, parentInfo: parentInfo, marshalInfo: marshalInfo ]; END; END; fromPkt => BEGIN WFSL[Indent[nest], "DescriptorType: TYPE = RECORD ["--L--, (IF descInfo.packed THEN "PACKED "--L-- ELSE ""--L--), "SEQUENCE COMPUTED CARDINAL OF "--L--]; Declare.WriteTypeName[descInfo.elementType]; WFS1["];*N"--L--]; WFL1[nest, "descLength: Lupine.SequenceHeader;"--L--]; Private.CopyTwo[ nest: nest, wordsNeeded: 2, value: ["descLength"--L--], marshalInfo: marshalInfo]; IF Private.Passing[Result, result, marshalInfo] OR Private.Passing[Var,result,marshalInfo] THEN BEGIN WFL[nest, "IF descLength # "--L--, lengthString]; WFL[nest+1, "THEN Lupine.UnmarshalingError;"--L--]; WFL1[nest, "NULL; -- Call by var or result, use existing descriptor."--L--]; END ELSE BEGIN WFSL[Indent[nest], name, " _ DESCRIPTOR[*N"--L--, Indent[nest+1], "("--L--]; Private.WriteNEW[ptrInfo: descInfo, marshalInfo: marshalInfo]; WFS["[DescriptorType[Lupine.SHORT[descLength]]]),*N"--L--, Indent[nest+1], "Lupine.SHORT[descLength]];*N"--L--]; END; IF Private.Passing[Result, argument, marshalInfo] THEN WFL1[nest, "NULL; -- Call by result, use uninitialized descriptor."--L--] ELSE BEGIN MarshalVector[ nest: nest, vectorName: name, vectorInfo: descInfo, indexType: descInfo.indexType, elementType: descInfo.elementType, parentInfo: parentInfo, marshalInfo: marshalInfo ] END; END; ENDCASE => ERROR; END; MarshalSequence: PUBLIC PROCEDURE [ name: String, seqInfo: Sequence ST.TypeInfo, parentInfo: ParentInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN Private.VerifyPassingMethods[value: TRUE, marshalInfo: marshalInfo]; WITH tagName: seqInfo SELECT FROM Computed => Private.Error[code: ComputedSequence, type: seqInfo.self]; Named => BEGIN WFL1[nest, "-- The sequence's length was carried by its record."--L--]; IF ~Private.NeedsMarshaling[seqInfo.elementType] THEN ERROR; MarshalVector[ nest: nest, vectorName: name, vectorInfo: seqInfo, indexType: seqInfo.indexType, elementType: seqInfo.elementType, parentInfo: parentInfo, marshalInfo: marshalInfo ]; END; ENDCASE => ERROR; END; MarshalVector: PROCEDURE [ vectorName: String, vectorInfo: ST.TypeInfo, indexType, elementType: ST.TypeHandle, parentInfo: ParentInfo, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN -- MarshalVector must generate exactly one statement. -- Caller guarantees that the vector has >= 0 elements in it, and that -- any header information for sequences and descriptors has been sent. IF ~Private.NeedsMarshaling[elementType] THEN Private.CopyType[ nest: nest, variableName: vectorName, variableInfo: vectorInfo, parentInfo: parentInfo, marshalInfo: marshalInfo ] ELSE DoVectorOperation[ nest: nest, opProc: Private.MarshalType, needsOpProc: Private.NeedsMarshaling, vectorName: vectorName, vectorInfo: vectorInfo, indexType: indexType, elementType: elementType, marshalInfo: marshalInfo ]; END; DoVectorOperation: PROCEDURE [ opProc: OperationProc, needsOpProc: NeedsOperationProc, vectorName: String, vectorInfo: ST.TypeInfo, indexType, elementType: ST.TypeHandle, marshalInfo: MarshalInfo, nest: Nest ] = BEGIN -- Must generate one statement. IF needsOpProc[elementType] THEN BEGIN indexName: AllocString = [MaxGeneratedIdLength]; elementName: AllocString = [MaxIdentifierLength+MaxGeneratedIdLength]; Private.UniqueName[ root: "element"--L--, nameString: indexName, marshalInfo: marshalInfo]; CWF.SWF2[elementName, "%LS[%S]"--L--, vectorName, indexName]; WFSL[Indent[nest], "FOR "--L--, indexName, ": "--L--]; Declare.WriteTypeName[indexType]; WFS1[" IN "--L--]; SELECT vectorInfo.type FROM Array => Declare.WriteTypeName[indexType]; Descriptor, Sequence => BEGIN WFS1["[FIRST["--L--]; Declare.WriteTypeName[indexType]; WFS1["]..FIRST["--L--]; Declare.WriteTypeName[indexType]; WFSL["]+LENGTH["--L--, (IF vectorInfo.type=Sequence THEN "DESCRIPTOR["--L-- ELSE ""--L--), vectorName, (IF vectorInfo.type=Sequence THEN "]"--L-- ELSE ""--L--), "])"--L--]; END; ENDCASE => ERROR; WFS1[" DO*N"--L--]; opProc[ nest: nest+1, name: elementName, type: elementType, parentInfo: [vectorName, vectorInfo], marshalInfo: marshalInfo ]; WFL[nest+1, "ENDLOOP; -- FOR "--L--, indexName, "."--L--]; END; END; -- Marshaling utility routines. MakeRefsNil: OperationProc = BEGIN -- Make only refs in safe storage NIL, not those in pkts. IF marshalInfo.direction=fromPkt AND Private.ContainsRefs[type: type] THEN BEGIN WFL1[nest, "-- Restore garbled REFs to NIL following copy."--L--]; AssignNilToRefs[ nest: nest, name: name, type: type, parentInfo: parentInfo, marshalInfo: marshalInfo ]; END; END; AssignNilToRefs: OperationProc = BEGIN typeInfo: ST.TypeInfo = ST.GetTypeInfo[type: type]; SELECT marshalInfo.paramFieldInfo.passingMethod FROM Handle => NULL; InterMds => ERROR; Var, Value, Result => WITH typeInfo: typeInfo SELECT FROM Null, Definition, Basic, Pointer, RelativePtr, String, StringBody, Text, Any, Opaque, Zone, Other => NULL; Ref, List, Rope, Atom, Transfer => WFLL[nest, "LOOPHOLE["--L--, name, ", "--L--, (IF typeInfo.type#Transfer THEN "LONG "--L-- ELSE ""--L--), "POINTER] _ NIL;"--L-- ]; Record => DoRecordOperation[ nest: nest, opProc: AssignNilToRefs, needsOpProc: Private.ContainsRefs, recName: name, recInfo: typeInfo, marshalInfo: marshalInfo ]; VariantPart => DoVariantOperation[ nest: nest, opProc: AssignNilToRefs, needsOpProc: Private.ContainsRefs, varName: name, varInfo: typeInfo, marshalInfo: marshalInfo ]; Array => DoVectorOperation[ nest: nest, opProc: AssignNilToRefs, needsOpProc: Private.ContainsRefs, vectorName: name, vectorInfo: typeInfo, indexType: typeInfo.indexType, elementType: typeInfo.elementType, marshalInfo: marshalInfo ]; Descriptor => DoVectorOperation[ nest: nest, opProc: AssignNilToRefs, needsOpProc: Private.ContainsRefs, vectorName: name, vectorInfo: typeInfo, indexType: typeInfo.indexType, elementType: typeInfo.elementType, marshalInfo: marshalInfo ]; Sequence => DoVectorOperation[ nest: nest, opProc: AssignNilToRefs, needsOpProc: Private.ContainsRefs, vectorName: name, vectorInfo: typeInfo, indexType: typeInfo.indexType, elementType: typeInfo.elementType, marshalInfo: marshalInfo ]; ENDCASE => ERROR; ENDCASE => ERROR; END; FieldName: PROCEDURE [ recordName: String _ "record"L, recordType: ST.TypeHandle, fieldSymbol: ST.SymbolHandle, fieldString: String, anonOk: BOOLEAN _ FALSE ] RETURNS [recordDotField: String _ NULL] = BEGIN recordDotField _ fieldString; IF anonOk OR ~ST.IsAnonymous[symbol: fieldSymbol] THEN BEGIN symbolString: AllocString = [MaxIdentifierLength]; CWF.SWF2[ recordDotField, "%LS.%LS"L, recordName, ST.SymbolName[fieldSymbol, symbolString] ]; END ELSE BEGIN Private.Error[code: AnonymousIdentifier, type: recordType]; CWF.SWF1[recordDotField, "%S"L, "record.unnamedField"L]; END; END; END. -- LupineMarshalTypeConstructorImpl.