DIRECTORY AMTypes USING [Error], Basics USING [LowHalf], BasicTime USING [FromNSTime], BcdDefs USING [BcdBase, FTSelf, SGIndex, SGHandle, SGNull, VersionID], BcdOps USING [ProcessSegs], ConvertUnsafe USING [SubString, SubStringToRope], FS USING [Error, GetInfo, nullOpenFile, OpenFile, Read, WordsForPages], IO USING [PutFR], LupineSymbolTable USING [ ComponentProcedure, DirectoryProcedure, FullTypeName, GMT, Index, InterfaceInfo, IsAnonymous, OpenErrorCode, ParamPassingMethod, STBase, String, StringNIL, SymbolHandle, SymbolType, TransferProcedure, TransferTypes, TypeHandle, TypeInfo, VariantProcedure, VersionStamp, Words ], Rope USING[ Fetch, Find, Length, Substr ], RTSymbolDefs USING[ SymbolTableBase, SymbolIdIndex ], RTSymbolOps USING[ EnumerateCtxIseis, NullISEI, NullCtx, ISECtx ], RTSymbols USING [AcquireSTBFromSGI, ReleaseSTB ], Symbols USING [ Base, BodyRecord, BTIndex, codeANY, codeCHAR, codeINT, CSEIndex, CTXIndex, CTXRecord, HTIndex, HTNull, ISEIndex, ISENull, lZ, MDIndex, OwnMdi, RecordSEIndex, RecordSENull, SEIndex, SENull, SERecord, TransferMode, TypeClass, typeTYPE, WordLength ], SymbolTable USING [Base], Table USING [Base, Limit], VM USING [Allocate, Free, Interval, nullInterval, AddressForPageNumber, PagesForWords]; LupineSymbolTableImpl: PROGRAM IMPORTS AMTypes, Basics, BasicTime, BcdOps, ConvertUnsafe, FS, IO, LupineSymbolTable, Rope, RTSymbolOps, RTSymbols, VM EXPORTS LupineSymbolTable SHARES LupineSymbolTable = BEGIN OPEN Symbols, ST: LupineSymbolTable; STBase: TYPE = ST.STBase; String: TYPE = ST.String; AllocSubString: TYPE = ConvertUnsafe.SubString _ [base: NIL, offset: NULL, length: NULL] | NULL; rootSTB: STBase _ NIL; rootFile: FS.OpenFile _ FS.nullOpenFile; rootSpace: VM.Interval _ VM.nullInterval; rootBcd: BcdDefs.BcdBase _ NIL; qualifyOpenNames: BOOL_FALSE; -- IF TRUE, fully qualify names even if from open interface OpenInterface: PUBLIC PROCEDURE [ interfaceFilename: String, interfaceCapability: FS.OpenFile ] = BEGIN ENABLE UNWIND => CloseInterface[]; symbols: BcdDefs.SGIndex; rootFile _ interfaceCapability; qualifyOpenNames _FALSE; [rootSpace, rootBcd] _ LoadUpBcd[ interfaceCapability ! LoadVersionError => ERROR OpenError[interfaceFilename, badFileVersion] ]; IF (symbols _ GetOwnSymbolsSGI[rootBcd]) = BcdDefs.SGNull THEN ERROR OpenError[interfaceFilename, badFileFormat]; rootSTB _ NARROW [RTSymbols.AcquireSTBFromSGI[ bcd: rootBcd, sgi: symbols ! AMTypes.Error => BEGIN IF reason = noSymbols THEN ERROR OpenError[msg, badFileName] ; END ], RTSymbolDefs.SymbolTableBase.x].e; IF ~rootBcd.definitions THEN ERROR OpenError[interfaceFilename, notInterfaceModule]; InitializeBuiltinTypes[standardStb: rootSTB]; END; OpenError: PUBLIC ERROR [fileOrModuleName: String, why: ST.OpenErrorCode] = CODE; CloseInterface: PUBLIC PROCEDURE = BEGIN IF rootSTB # NIL THEN RTSymbols.ReleaseSTB[[x[rootSTB]]]; IF rootSpace # VM.nullInterval THEN VM.Free[rootSpace]; rootSTB _ NIL; rootFile _ FS.nullOpenFile; rootSpace _ VM.nullInterval; rootBcd _ NIL; END; GetInterfaceInfo: PUBLIC PROCEDURE RETURNS [ contents: ST.InterfaceInfo, moduleName, fileName: String, moduleVersion: ST.VersionStamp, moduleCreateTime, sourceCreateTime: ST.GMT ] = BEGIN CheckContents: ContextProcedure = BEGIN SELECT itemStb.TypeForm[SymType[itemStb,itemIsei]] FROM transfer => contents.transfers[XferModeToTransferType[ itemStb.XferMode[SymType[itemStb,itemIsei]]] ] _ TRUE; opaque => contents.types _ TRUE; ENDCASE => IF ~itemStb.seb[itemIsei].constant THEN contents.variables _ TRUE; END; contents _ []; -- Initialize contents. [] _ EnumerateContext[ ctxStb: rootSTB, ctx: rootSTB.stHandle.outerCtx, ctxProc: CheckContents]; [moduleName, fileName] _ GetModuleInfo[ rootSTB, OwnMdi]; moduleVersion _ rootSTB.stHandle.version; moduleCreateTime _ FS.GetInfo[rootFile ! FS.Error => CONTINUE].created; sourceCreateTime _ BasicTime.FromNSTime[rootSTB.stHandle.sourceVersion.time]; END; QualifyOpenNames: PUBLIC PROCEDURE[qualify: BOOL] RETURNS [oldQualify: BOOL ] = { oldQualify _ qualifyOpenNames; qualifyOpenNames _ qualify; }; VersionStampString: PUBLIC PROCEDURE [stamp: ST.VersionStamp] RETURNS [stampString: String] = BEGIN stampString _ IO.PutFR["%b#%b#%b", [integer[stamp.net]], [integer[stamp.host]], [cardinal[stamp.time]] ]; END; XferModeToTransferType: PACKED ARRAY TransferMode OF ST.TransferTypes = [ proc: Procedure, error: Error, signal: Signal, port: Port, program: Program, process: Process, none: Other ]; GetModuleInfo: PROCEDURE [ stBase: STBase, module: MDIndex] RETURNS[moduleName, fileName: String] = --INLINE-- BEGIN moduleName _ HtiString[stBase, stBase.mdb[module].moduleId]; fileName _ HtiString[stBase, stBase.mdb[module].fileId]; END; LoadVersionError: ERROR = CODE; LoadUpBcd: PROC [bcdFile: FS.OpenFile] RETURNS [bcdSpace: VM.Interval_VM.nullInterval, bcd: BcdDefs.BcdBase] = BEGIN bcdSpaceBase: INT = 0; pages: CARDINAL; BEGIN ENABLE UNWIND => IF bcdSpace#VM.nullInterval THEN VM.Free[bcdSpace]; bcdSpace _ VM.Allocate[VM.PagesForWords[FS.WordsForPages[1]]]; bcd _ VM.AddressForPageNumber[bcdSpace.page]; FS.Read[file: bcdFile, from: bcdSpaceBase, nPages: 1, to: bcd]; IF bcd.versionIdent # BcdDefs.VersionID THEN ERROR LoadVersionError; pages _ bcd.nPages; IF pages > 1 THEN BEGIN VM.Free[bcdSpace]; bcdSpace _ VM.Allocate[VM.PagesForWords[FS.WordsForPages[pages]]]; bcd _ VM.AddressForPageNumber[bcdSpace.page]; FS.Read[file: bcdFile, from: bcdSpaceBase, nPages: pages, to: bcd]; END; END; END; GetOwnSymbolsSGI: PROC [ownBcd: BcdDefs.BcdBase] RETURNS [ownSGI: BcdDefs.SGIndex] = BEGIN OPEN BcdOps, BcdDefs; CheckSeg: PROC [sgh: SGHandle, sgi: SGIndex] RETURNS [--stop:-- BOOLEAN] = {RETURN[sgh.class=symbols AND sgh.file=FTSelf]}; ownSGI _ ProcessSegs[bcd: ownBcd, proc: CheckSeg].sgi; END; EnumerateDirectory: PUBLIC PROCEDURE [proc: ST.DirectoryProcedure] RETURNS [stopped: BOOLEAN_FALSE] = BEGIN DoDirItem: ContextProcedure = BEGIN OPEN itemStb; moduleName: String; fileName: String; imported: BOOLEAN; defContext: CTXIndex; module: MDIndex; WITH seb[UnderType[seb[itemIsei].idType]] SELECT FROM definition => defContext _ defCtx; transfer => defContext _ bb[LOOPHOLE[seb[itemIsei].idInfo, BTIndex]].localCtx; ENDCASE => ERROR; WITH ctx: ctxb[defContext] SELECT FROM simple => {module _ OwnMdi; imported _ FALSE}; included => {module _ ctx.module; imported _ FALSE}; imported => {module _ ctxb[ctx.includeLink].module; imported_TRUE}; ENDCASE => ERROR; [moduleName, fileName] _ GetModuleInfo[itemStb, module]; { index: INT = fileName.Find["."]; IF index >= 0 THEN fileName _ fileName.Substr[start: 0, len: index] }; RETURN[stop: proc[moduleName: moduleName, fileName: fileName, imported: imported, directoryIndex: itemIndex].stop]; END; stopped _ EnumerateContext[ ctxStb: rootSTB, ctx: rootSTB.stHandle.directoryCtx, ctxProc: DoDirItem]; END; EnumerateTransfers: PUBLIC PROCEDURE [ proc: ST.TransferProcedure, all, procs, signals, errors: BOOLEAN _ FALSE ] RETURNS [stopped: BOOLEAN_FALSE] = BEGIN index: ST.Index _ 0; DoTransfer: ContextProcedure = BEGIN InlineOrMachineCode: PROCEDURE [transfer: ISEIndex] RETURNS [BOOLEAN] = INLINE {RETURN[itemStb.seb[transfer].constant]}; topType: SEIndex = SymType[itemStb, itemIsei]; type: CSEIndex = itemStb.UnderType[topType]; WITH xfer: itemStb.seb[type] SELECT FROM transfer => SELECT xfer.mode FROM proc => IF (all OR procs) AND ~InlineOrMachineCode[itemIsei] THEN stop _ proc[ transfer: [itemStb, itemIsei], transferType: [itemStb, topType], kind: Procedure, argumentRecordType: [itemStb, xfer.typeIn], resultRecordType: [itemStb, xfer.typeOut], transferIndex: (index _ index+1) ]; error => IF all OR errors THEN stop _ proc[ transfer: [itemStb, itemIsei], transferType: [itemStb, topType], kind: Error, argumentRecordType: [itemStb, xfer.typeIn], resultRecordType: [itemStb, xfer.typeOut], transferIndex: (index _ index+1) ]; signal => IF all OR signals THEN stop _ proc[ transfer: [itemStb, itemIsei], transferType: [itemStb, topType], kind: Signal, argumentRecordType: [itemStb, xfer.typeIn], resultRecordType: [itemStb, xfer.typeOut], transferIndex: (index _ index+1) ]; ENDCASE => IF all THEN stop _ proc[ transfer: [itemStb, itemIsei], transferType: [itemStb, topType], kind: XferModeToTransferType[xfer.mode], argumentRecordType: [itemStb, xfer.typeIn], resultRecordType: [itemStb, xfer.typeOut], transferIndex: (index _ index+1) ]; ENDCASE => NULL; END; stopped _ EnumerateContext[ ctxStb: rootSTB, ctx: rootSTB.stHandle.outerCtx, ctxProc: DoTransfer]; END; EnumerateRecord: PUBLIC PROCEDURE [ recordType: ST.TypeHandle, proc: ST.ComponentProcedure] RETURNS [stopped: BOOLEAN_FALSE] = BEGIN recStb: STBase = recordType.base; IF recordType.type = SENull THEN RETURN; WITH rec: recStb.seb[recStb.UnderType[recordType.type]] SELECT FROM record => BEGIN DoComponent: ContextProcedure = BEGIN RETURN[ stop: proc[ component: [itemStb, itemIsei], componentType: [itemStb, SymType[itemStb, itemIsei]], componentIndex: itemIndex ].stop ]; END; stopped _ EnumerateContext[ ctxStb: recStb, ctx: rec.fieldCtx, ctxProc: DoComponent] END; ENDCASE => ERROR; END; EnumerateVariants: PUBLIC PROCEDURE [ variantPartType: ST.TypeHandle, proc: ST.VariantProcedure] RETURNS [stopped: BOOLEAN_FALSE] = BEGIN varStb: STBase = variantPartType.base; IF variantPartType.type = SENull THEN ERROR; WITH var: varStb.seb[varStb.UnderType[variantPartType.type]] SELECT FROM union => BEGIN DoVariant: ContextProcedure = BEGIN RETURN[ stop: proc[ variantTag: [itemStb, itemIsei], variantNumber: itemStb.seb[itemIsei].idValue, variantRecordType: [itemStb, itemStb.seb[itemIsei].idInfo], variantIndex: itemIndex ].stop ]; END; stopped _ EnumerateContext[ ctxStb: varStb, ctx: var.caseCtx, ctxProc: DoVariant]; END; ENDCASE => ERROR; END; ContextProcedure: TYPE = PROCEDURE [ itemStb: SymbolTable.Base, itemIsei: ISEIndex, itemIndex: ST.Index] RETURNS [stop: BOOLEAN_FALSE]; EnumerateContext: PROCEDURE [ ctxStb: STBase, ctx: CTXIndex, ctxProc: ContextProcedure ] RETURNS [stopped: BOOLEAN_FALSE] = BEGIN item: ST.Index _ 0; SkipRecordPackingInfo: PROCEDURE [stb: RTSymbolDefs.SymbolTableBase, isei: RTSymbolDefs.SymbolIdIndex] RETURNS [--stop:-- BOOLEAN] = BEGIN RETURN[IF item=0 AND NOT RTSymbolOps.NullISEI[isei] AND RTSymbolOps.NullCtx[RTSymbolOps.ISECtx[stb, isei]] THEN FALSE ELSE ctxProc[itemStb: NARROW[stb, RTSymbolDefs.SymbolTableBase.x].e, itemIsei: NARROW[isei, RTSymbolDefs.SymbolIdIndex.x].e, itemIndex: (item_item+1) ].stop ]; END; stopped _ RTSymbolOps.EnumerateCtxIseis[ stb: [x[ctxStb]], ctx: [x[ctx]], proc: SkipRecordPackingInfo ! AMTypes.Error => BEGIN IF reason = noSymbols THEN ERROR OpenError[msg, badFileName]; END ]; END; SymType: PROCEDURE [stb: STBase, isei: ISEIndex] RETURNS [SEIndex] = INLINE BEGIN RETURN[ IF stb.seb[isei].idType = SENull THEN ERROR ELSE stb.seb[isei].idType]; END; SearchTypeDefinition: PUBLIC PROCEDURE [ rootDef: ST.TypeHandle, candidateDefs: LONG DESCRIPTOR FOR READONLY ARRAY OF ST.FullTypeName ] RETURNS [indexOfMatch: INTEGER _ -1 --No match--] = BEGIN thisBase: STBase = rootDef.base; thisType: SEIndex _ rootDef.type; thisName, thisModule: AllocSubString; DO WITH sei: thisBase.seb[thisType] SELECT FROM id => BEGIN thisName _ IseiSubString[ stb: thisBase, isei: ISEI[thisType] ]; thisModule _ HtiSubString[ stb: thisBase, hti: ModuleHtiOfTypeName[thisBase, ISEI[thisType]]]; FOR type: INTEGER IN [0..LENGTH[candidateDefs]) DO IF StringEqualSubString[candidateDefs[type].name, thisName] AND StringEqualSubString[candidateDefs[type].module, thisModule] THEN RETURN[type]; REPEAT FINISHED => thisType _ sei.idInfo; ENDLOOP; END; cons => WITH csei: sei SELECT FROM long => thisType _ csei.rangeType; ENDCASE => RETURN; ENDCASE => ERROR; ENDLOOP; END; Size: PUBLIC PROCEDURE [type: ST.TypeHandle] RETURNS [size: ST.Words] = BEGIN RETURN[type.base.WordsForType[type.type]]; END; ComputeArraySize: PUBLIC PROCEDURE [ index, elements: ST.TypeHandle, packed: BOOLEAN ] RETURNS [--size:-- ST.Words] = BEGIN bits: LONG CARDINAL; cardinality: ST.Words = WITH indexInfo: GetTypeInfo[type: index] SELECT FROM Basic => indexInfo.cardinality, ENDCASE => ERROR; RETURN[ IF (bits_elements.base.BitsPerElement[elements.type, packed]) < WordLength THEN (cardinality+(WordLength/bits-1)) / (WordLength/bits) ELSE cardinality * ((bits+WordLength-1)/WordLength) ]; END; ModuleHtiOfTypeName: PROCEDURE [stBase: STBase, typeName: ISEIndex] RETURNS [--moduleHti:-- HTIndex] = --INLINE-- BEGIN RETURN[stBase.mdb[ModuleOfTypeName[stBase, typeName]].moduleId] END; ModuleOfTypeName: PROCEDURE [stBase: STBase, typeName: ISEIndex] RETURNS [module: MDIndex] = BEGIN typeNameCtx: CTXRecord = stBase.ctxb[stBase.seb[typeName].idCtx]; WITH ctx: typeNameCtx SELECT FROM simple => module _ OwnMdi; included => module _ ctx.module; imported => module _ stBase.ctxb[ctx.includeLink].module; ENDCASE => ERROR; END; HtiSubString: PROCEDURE [stb: STBase, hti: HTIndex] RETURNS[ConvertUnsafe.SubString] = INLINE BEGIN -- hti=HTNull is OK; returns null substring. RETURN[stb.SubStringForName[hti]]; END; HtiString: PROCEDURE [stb: STBase, hti: HTIndex] RETURNS[String] = BEGIN RETURN[ConvertUnsafe.SubStringToRope[HtiSubString[stb, hti]]] END; ISEI: PROCEDURE [sei: SEIndex] RETURNS [--isei:-- ISEIndex] = INLINE BEGIN RETURN[LOOPHOLE[sei]] END; IseiSubString: PROCEDURE [stb: STBase, isei: ISEIndex] RETURNS[ConvertUnsafe.SubString] = --INLINE-- BEGIN RETURN[HtiSubString[stb, (IF isei=ISENull THEN HTNull ELSE stb.seb[isei].hash)] ]; END; StringEqualSubString: PROCEDURE [a: String, b: ConvertUnsafe.SubString] RETURNS [--exactMatch:-- BOOLEAN] = INLINE BEGIN RETURN [a.Length[]=b.length AND SlowStringEqualSubString[a,b]]; END; SlowStringEqualSubString: PROCEDURE [a: String, b: ConvertUnsafe.SubString] RETURNS [exactMatch: BOOLEAN] = BEGIN IF a.Length[] # b.length THEN RETURN[FALSE]; FOR i: CARDINAL IN [0..b.length) DO IF a.Fetch[i] # b.base[b.offset+i] THEN RETURN[FALSE] ENDLOOP; RETURN[TRUE] END; GetTypeInfo: PUBLIC PROC [type: ST.TypeHandle] RETURNS [info: ST.TypeInfo_[]] = BEGIN OPEN ST; typeStb: STBase = type.base; typeSei: SEIndex = type.type; IF typeSei = SENull THEN RETURN[[self: type, info: Null[]]]; WITH typeSer: typeStb.seb[typeSei] SELECT FROM id => SELECT TRUE FROM typeSer.idType # typeTYPE => ERROR; typeSer.idCtx = StandardTypeContext => SELECT typeSei FROM UNSPECIFIEDIndex => RETURN[ [self: type, info: Basic[ kind: Unspecified, origin: FIRST[WORD], cardinality: (LONG[LAST[WORD]]-FIRST[WORD]+1) ]] ]; INTEGERIndex => RETURN[ [self: type, info: Basic[ kind: Integer, origin: FIRST[INTEGER], cardinality: (LONG[LAST[INTEGER]]-FIRST[INTEGER]+1) ]] ]; CARDINALIndex => RETURN[ [self: type, info: Basic[ kind: Cardinal, origin: FIRST[CARDINAL], cardinality: (LONG[LAST[CARDINAL]]-FIRST[CARDINAL]+1) ]] ]; NATIndex => RETURN[ [self: type, info: Basic[ kind: Nat, origin: FIRST[NAT], cardinality: (LONG[LAST[NAT]]-FIRST[NAT]+1) ]] ]; REALIndex => RETURN[ [self: type, info: Basic[ kind: Real, origin: 0, cardinality: 0 ]] ]; WORDIndex => RETURN[ [self: type, info: Basic[ kind: Word, origin: FIRST[WORD], cardinality: (LONG[LAST[WORD]]-FIRST[WORD]+1) ]] ]; CHARACTERIndex => RETURN[ [self: type, info: Basic[ kind: Character, origin: LOOPHOLE[FIRST[CHARACTER], INTEGER], cardinality: LONG[ LOOPHOLE[LAST[CHARACTER], INTEGER] - LOOPHOLE[FIRST[CHARACTER], INTEGER] + 1 ] ]] ]; BOOLEANIndex => RETURN[ [self: type, info: Basic[ kind: Boolean, origin: LOOPHOLE[FIRST[BOOLEAN], INTEGER], cardinality: 2 ]] ]; TEXTIndex => RETURN[[self: type, info: Text[]]]; STRINGIndex => RETURN[[self: type, info: String[]]]; StringBodyIndex => RETURN[[self: type, info: StringBody[]]]; ATOMIndex => RETURN[[self: type, info: Atom[], readonly: FALSE]]; MONITORLOCKIndex, CONDITIONIndex => RETURN[[self: type, info: Other[]]]; MDSZoneIndex => RETURN[ [self: type, info: Zone[allocation: Uncounted, mdsZone: TRUE]] ]; ENDCASE => BEGIN synonymInfo: TypeInfo _ GetTypeInfo[[typeStb, typeSer.idInfo]]; synonymInfo.self _ type; RETURN[ SELECT synonymInfo.type FROM Basic, String, StringBody, Text, Atom, Rope, Any => synonymInfo, ENDCASE => [self: type, info: Other[]] ]; END; IsType[["Rope", "ROPE"], typeStb, ISEI[typeSei]] => RETURN[[self: type, info: Rope[], readonly: FALSE]]; ENDCASE => BEGIN method: ParamPassingMethod=GetParamMethod[typeStb, ISEI[typeSei]]; symInfo: TypeInfo _ GetTypeInfo[[typeStb, typeSer.idInfo]]; symInfo.self _ type; IF method # standard THEN symInfo.passingMethod _ method; RETURN[symInfo]; END; cons => WITH typeCser: typeSer SELECT FROM basic, real => ERROR; -- Should have been in StandardTypeContext. definition => RETURN[[self: type, info: Definition[]]]; subrange => RETURN[ [self: type, info: Basic[ kind: Subrange, origin: typeCser.origin, cardinality: IF typeCser.empty THEN 0 ELSE typeCser.range+1]] ]; enumerated => RETURN[ [self: type, info: Basic[ kind: Enumeration, origin: 0, cardinality: typeCser.nValues]] ]; transfer => RETURN[ [self: type, info: Transfer[ kind: XferModeToTransferType[typeCser.mode], safe: typeCser.safe, argumentType: TypeHandle[typeStb, typeCser.typeIn], resultType: TypeHandle[typeStb, typeCser.typeOut]]] ]; record => BEGIN variantType: TypeClass _ record; GetVariantType: ComponentProcedure = BEGIN variantType _ componentType.base.TypeForm[componentType.type]; RETURN[ stop: SELECT variantType FROM union, sequence => TRUE, ENDCASE => FALSE]; END; -- GetVariantType. IF typeCser.hints.variant THEN [] _ EnumerateRecord[type, GetVariantType]; RETURN[ [self: type, info: Record[ painted: typeCser.painted, paramRecord: typeCser.argument, monitored: typeCser.monitored, uniField: typeCser.hints.unifield, hasVariants: variantType=union, hasSequences: variantType=sequence]] ]; END; union => IF typeCser.controlled THEN SELECT typeStb.seb[SymType[typeStb, typeCser.tagSei]].seTag FROM id => RETURN[ [self: type, info: VariantPart[ tag: Named[ name: SymbolHandle[typeStb, typeCser.tagSei], type: ST.SymbolType[[typeStb, typeCser.tagSei]]]]] ]; cons => RETURN[ [self: type, info: VariantPart[ tag: Star[ name: SymbolHandle[typeStb, typeCser.tagSei]]]] ]; ENDCASE => ERROR ELSE RETURN[ [self: type, info: VariantPart[tag: Computed[]]] ]; ref => SELECT TRUE FROM ~typeCser.counted => RETURN[ [self: type, info: Pointer[ referentType: TypeHandle[typeStb,typeCser.refType]], readonly: typeCser.readOnly] ]; typeCser.list => { base: STBase; first, rest: SEIndex; [base, first, rest] _ ListTypes[typeStb, typeSei]; RETURN[ [self: type, info: List[ firstType: TypeHandle[base, first], restType: TypeHandle[base, rest]], readonly: typeCser.readOnly] ] }; typeCser.counted => RETURN[ [self: type, info: Ref[ referentType: TypeHandle[typeStb,typeCser.refType]], readonly: typeCser.readOnly] ]; ENDCASE => ERROR; relative => RETURN[ [self: type, info: RelativePtr[ baseType: TypeHandle[typeStb, typeCser.baseType], offsetType: TypeHandle[typeStb, typeCser.offsetType], resultType: TypeHandle[typeStb, typeCser.resultType]]] ]; array => RETURN[ [self: type, info: Array[ packed: typeCser.packed, indexType: TypeHandle[typeStb, typeCser.indexType], elementType: TypeHandle[typeStb, typeCser.componentType]]] ]; arraydesc => BEGIN arrayInfo: TypeInfo _ GetTypeInfo[[typeStb, typeCser.describedType]]; WITH array: arrayInfo SELECT FROM Array => RETURN[ [self: type, info: Descriptor[ packed: array.packed, indexType: array.indexType, elementType: array.elementType], readonly: typeCser.readOnly] ]; ENDCASE => ERROR; END; sequence => IF typeCser.controlled THEN RETURN [ [self: type, info: Sequence[ packed: typeCser.packed, indexType: ST.SymbolType[[typeStb, typeCser.tagSei]], elementType: TypeHandle[typeStb, typeCser.componentType], tagName: Named[ name: SymbolHandle[typeStb, typeCser.tagSei]]]] ] ELSE RETURN [ [self: type, info: Sequence[ packed: typeCser.packed, indexType: ST.SymbolType[[typeStb, typeCser.tagSei]], elementType: TypeHandle[typeStb, typeCser.componentType], tagName: Computed[]]] ]; long => BEGIN shortInfo: TypeInfo _ GetTypeInfo[[typeStb, typeCser.rangeType]]; shortInfo.self _ type; shortInfo.long _ SELECT shortInfo.type FROM Ref, List, Zone => FALSE, ENDCASE => TRUE; RETURN[shortInfo]; END; zone => RETURN[ [self: type, info: Zone[ allocation: IF typeCser.counted THEN Counted ELSE Uncounted, mdsZone: typeCser.mds ]] ]; opaque => RETURN[ [self: type, info: Opaque[lengthKnown: typeCser.lengthKnown]] ]; any => RETURN[[self: type, info: Any[]]]; ENDCASE => RETURN[[self: type, info: Other[]]]; ENDCASE => ERROR; END; IsType: PROCEDURE [ type: ST.FullTypeName, candidateStb: STBase, candidateIsei: ISEIndex ] RETURNS [--yes:-- BOOLEAN] = BEGIN candidate: AllocSubString _ IseiSubString[candidateStb, candidateIsei]; IF ~StringEqualSubString[type.name, candidate] THEN RETURN[FALSE]; candidate _ HtiSubString[ stb: candidateStb, hti: ModuleHtiOfTypeName[candidateStb, candidateIsei]]; RETURN[StringEqualSubString[type.module, candidate]]; END; GetParamMethod: PROC [paramStb: STBase, paramIsei: ISEIndex] RETURNS [method: ST.ParamPassingMethod] = BEGIN Check: PROC [prefix: STRING] RETURNS [--isMatch:-- BOOLEAN] = BEGIN IF prefix.length >= typeName.length THEN RETURN[FALSE]; FOR i: CARDINAL IN NAT[0..prefix.length) DO IF typeName.base[typeName.offset+i] # prefix[i] THEN RETURN[FALSE]; ENDLOOP; RETURN[TRUE]; END; typeName: AllocSubString = IseiSubString[paramStb, paramIsei]; RETURN[ SELECT TRUE FROM Check["VAR"L], Check["VALUERESULT"L] => var, Check["VALUE"L] => value, Check["RESULT"L] => result, Check["HANDLE"L] => handle, ENDCASE => standard]; END; ListTypes: PROC [listStb: STBase, listSei: --Ref--SEIndex] RETURNS [base: STBase, first, rest: SEIndex_SENull] = BEGIN componentName: AllocSubString; gotFirst, gotRest: BOOLEAN _ FALSE; CheckFirstRest: ST.ComponentProcedure = BEGIN componentName _ IseiSubString[component.base, component.symbol]; SELECT TRUE FROM gotFirst => NULL; StringEqualSubString["first", componentName] => {gotFirst _ TRUE; base _ componentType.base; first _ componentType.type}; ENDCASE => NULL; SELECT TRUE FROM gotRest => NULL; StringEqualSubString["rest", componentName] => {gotRest _ TRUE; rest _ componentType.type}; ENDCASE => NULL; RETURN[stop: gotFirst AND gotRest]; END; -- CheckFirstRest. listCsei: CSEIndex = listStb.UnderType[listSei]; WITH listRef: listStb.seb[listCsei] SELECT FROM ref => { IF ~listRef.list OR ~listRef.counted THEN ERROR; IF ~EnumerateRecord[ recordType: [listStb, listRef.refType], proc: CheckFirstRest ].stopped THEN ERROR }; ENDCASE => ERROR; END; UNSPECIFIEDIndex, INTEGERIndex, CARDINALIndex, NATIndex, REALIndex, WORDIndex, CHARACTERIndex, BOOLEANIndex, TEXTIndex, STRINGIndex, StringBodyIndex, ATOMIndex, MONITORLOCKIndex, CONDITIONIndex, MDSZoneIndex: ISEIndex _ ISENull; StandardTypeContext: CTXIndex = LOOPHOLE[2]; InitializeBuiltinTypes: PROCEDURE [standardStb: STBase] = BEGIN GetTypeISEIndex: PROC [standardType: STRING, system: {Mesa, Cedar}_Mesa] RETURNS [typesISE: ISEIndex] = BEGIN subString: ConvertUnsafe.SubString = [standardType, 0, standardType.length]; typesISE _ standardStb.SearchContext[ name: standardStb.FindString[subString], ctx: StandardTypeContext ]; IF typesISE=ISENull AND system=Mesa THEN ERROR; END; UNSPECIFIEDIndex _ GetTypeISEIndex["UNSPECIFIED"L]; INTEGERIndex _ GetTypeISEIndex["INTEGER"L]; CARDINALIndex _ GetTypeISEIndex["CARDINAL"L]; NATIndex _ GetTypeISEIndex["NAT"L, Cedar]; REALIndex _ GetTypeISEIndex["REAL"L]; WORDIndex _ GetTypeISEIndex["WORD"L]; CHARACTERIndex _ GetTypeISEIndex["CHARACTER"L]; BOOLEANIndex _ GetTypeISEIndex["BOOLEAN"L]; TEXTIndex _ GetTypeISEIndex["TEXT"L]; STRINGIndex _ GetTypeISEIndex["STRING"L]; StringBodyIndex _ GetTypeISEIndex["StringBody"L]; ATOMIndex _ GetTypeISEIndex["ATOM"L, Cedar]; MONITORLOCKIndex _ GetTypeISEIndex["MONITORLOCK"L]; CONDITIONIndex _ GetTypeISEIndex["CONDITION"L]; MDSZoneIndex _ GetTypeISEIndex["MDSZone"L]; END; PutTypeName: PUBLIC PROCEDURE [ putProc: PROC[CHARACTER], type: ST.TypeHandle, includeReadonly: BOOLEAN_TRUE, rootInterfaceOpenName: String_ST.StringNIL, extraFirstArg: String _ NIL ] = BEGIN ENABLE UNWIND => putChar _ NIL; putChar _ putProc; rootInterfaceQualifier _ rootInterfaceOpenName; [] _ PrintType[ stBase: type.base, tsei: type.type, printReadonly: includeReadonly, dosub: NoSub, extraFirstArg: extraFirstArg ]; END; putChar: PROCEDURE [CHARACTER] _ NIL; -- Set by PutTypeName. PutChar: PROC [chr: CHARACTER] = INLINE {putChar[chr]}; PutString: PROC [str: String] = BEGIN FOR i: INT IN [0..str.Length[]) DO PutChar[str.Fetch[i]] ENDLOOP; END; PutSubString: PROC [subStr: ConvertUnsafe.SubString] = BEGIN FOR i: CARDINAL IN [subStr.offset..subStr.offset+subStr.length) DO PutChar[subStr.base[i]]; ENDLOOP; END; PutDecimal: PROC [n: LONG INTEGER] = BEGIN radix: CARDINAL = 10; radixPower: LONG CARDINAL _ 1; lwb: LONG CARDINAL ; IF n < 0 THEN { PutChar['-]; n _ -n }; lwb _ n/radix; WHILE radixPower <= lwb DO radixPower _ radixPower*radix ENDLOOP; WHILE radixPower > 0 DO x: CARDINAL = n/radixPower; PutChar['0+x]; n _ n - x*radixPower; radixPower _ radixPower/radix; ENDLOOP; END; PutOctal: PROC [n: LONG CARDINAL, trailingB: BOOLEAN_TRUE] = BEGIN radix: CARDINAL = 8; radixPower: LONG CARDINAL _ 1; lwb: LONG CARDINAL _ n/radix; WHILE radixPower <= lwb DO radixPower _ radixPower*radix ENDLOOP; WHILE radixPower > 0 DO x: CARDINAL = n/radixPower; PutChar['0+x]; n _ n - x*radixPower; radixPower _ radixPower/radix; ENDLOOP; IF trailingB THEN PutChar['B]; END; PrintType: PROCEDURE [ stBase: STBase, tsei: SEIndex, dosub: PROCEDURE [vf: ValFormat], printReadonly: BOOLEAN_TRUE, extraFirstArg: String _ NIL ] RETURNS [vf: ValFormat _ [none[]] ] = BEGIN OPEN Symbols, stBase; -- This damn OPEN was here when I arrived! PrintReadonly: PROC [wantReadonly: BOOLEAN] = BEGIN IF wantReadonly AND printReadonly THEN PutString["READONLY "]; IF ~printReadonly THEN printReadonly _ TRUE; END; WITH t: seb[tsei] SELECT FROM id => BEGIN printBase: BOOLEAN _ TRUE; ifInteger: BOOLEAN _ FALSE; bsei: SEIndex _ tsei; csei: CSEIndex; DO csei _ UnderType[bsei]; WITH c: seb[csei] SELECT FROM basic => SELECT c.code FROM codeINT => BEGIN printBase _ ifInteger; vf _ [num[]] END; codeCHAR => vf _ [char[]]; ENDCASE; subrange => {bsei _ c.rangeType; ifInteger _ TRUE; LOOP}; enumerated => {printBase _ TRUE; vf _ [enum[stBase, LOOPHOLE[csei]]]}; ENDCASE; EXIT; ENDLOOP; SELECT TRUE FROM ~printReadonly AND GetTypeInfo[type: [stBase, csei]].readonly => [] _ PrintType[stBase, csei, dosub, FALSE]; printBase OR dosub = NoSub => BEGIN PrintModuleQualifier[stBase, tsei]; WITH seb[csei] SELECT FROM record => BEGIN PrintBoundVariants: PROC [recordType: ISEIndex] = BEGIN parent: SEIndex; IF (parent _ TypeLink[recordType]) = SENull THEN PrintSei[stBase, recordType] ELSE BEGIN WITH seb[parent] SELECT FROM id => PrintBoundVariants[ISEI[parent]]; cons => [] _ PrintType[stBase, parent, dosub]; ENDCASE => ERROR; PutChar['[]; PrintSei[stBase, recordType]; PutChar[']]; END; END; -- PrintBoundVariants. PrintBoundVariants[ISEI[tsei]]; END; ENDCASE => PrintSei[stBase, ISEI[tsei]]; END; ENDCASE => NULL; dosub[vf]; END; cons => WITH t SELECT FROM enumerated => BEGIN PrintEnumItem: ContextProcedure = BEGIN IF itemIndex > 1 THEN PutString[", "]; PrintSei[itemStb, itemIsei]; END; IF machineDep THEN PutString["MACHINE DEPENDENT "]; PutChar['{]; [] _ EnumerateContext[ ctxStb: stBase, ctx: valueCtx, ctxProc: PrintEnumItem]; PutChar['}]; END; record => BEGIN IF ctxb[fieldCtx].level # lZ THEN BEGIN fctx: CTXIndex = fieldCtx; bti: BTIndex _ FIRST[BTIndex]; btlimit: BTIndex = bti + stHandle.bodyBlock.size; PutString["FRAME ["]; UNTIL bti = btlimit DO WITH entry: bb[bti] SELECT FROM Callable => BEGIN IF entry.localCtx = fctx THEN BEGIN PrintSei[stBase, entry.id]; PutChar[']]; EXIT END; bti _ bti + (WITH entry SELECT FROM Inner => SIZE[Inner Callable BodyRecord], ENDCASE => SIZE[Outer Callable BodyRecord]); END; ENDCASE => bti _ bti + SIZE[Other BodyRecord]; ENDLOOP; END ELSE BEGIN IF machineDep THEN PutString["MACHINE DEPENDENT "]; PutString[IF painted THEN "RECORD " ELSE "STRUCT "]; PrintFieldCtx[stBase, fieldCtx]; END; END; ref => IF ~list THEN { -- Normal POINTER or REF. IF ordered THEN PutString["ORDERED "]; IF basing THEN PutString["BASE "]; PutString[IF counted THEN "REF " ELSE "POINTER"]; IF dosub # NoSub THEN {PutChar[' ]; dosub[[num[]]]}; IF ~readOnly THEN WITH seb[UnderType[refType]] SELECT FROM basic => IF code = Symbols.codeANY THEN GO TO noprint; ENDCASE; IF ~counted THEN PutString[" TO "]; PrintReadonly[readOnly]; [] _ PrintType[stBase, refType, NoSub]; EXITS noprint => NULL } ELSE { -- LIST OF something. firstBase: STBase; firstBody: SEIndex; [base: firstBase, first: firstBody] _ ListTypes[stBase, tsei]; PutString["LIST OF "]; PrintReadonly[readOnly]; [] _ PrintType[firstBase, firstBody, NoSub] }; array => BEGIN IF packed THEN PutString["PACKED "]; PutString["ARRAY "]; [] _ PrintType[stBase, indexType, NoSub]; PutString[" OF "]; [] _ PrintType[stBase, componentType, NoSub]; END; arraydesc => BEGIN PutString["DESCRIPTOR FOR "]; PrintReadonly[readOnly]; [] _ PrintType[stBase, describedType, NoSub]; END; transfer => BEGIN ArgRes: PROC[type: CSEIndex, extraFirstArg: String] = BEGIN WITH argRes: seb[type] SELECT FROM record => PrintFieldCtx[stBase, argRes.fieldCtx, extraFirstArg]; any => PutString["ANY"]; ENDCASE => ERROR;--?-- END; IF safe THEN PutString["SAFE "]; PrintModeName[mode]; IF typeIn # RecordSENull THEN BEGIN PutChar[' ]; ArgRes[typeIn, extraFirstArg]; END ELSE IF extraFirstArg # NIL THEN { PutChar['[]; PutString[extraFirstArg]; PutChar[']]; }; IF typeOut # RecordSENull THEN BEGIN PutString[" RETURNS "]; ArgRes[typeOut, NIL]; END; END; union => BEGIN tagType: SEIndex; PutString["SELECT "]; IF ~controlled THEN IF overlaid THEN PutString["OVERLAID "] ELSE PutString["COMPUTED "] ELSE BEGIN PrintSei[stBase, tagSei]; PutString[": "] END; tagType _ seb[tagSei].idType; IF seb[tagSei].public # defaultPublic THEN PutString[ IF defaultPublic THEN "PRIVATE " ELSE "PUBLIC "]; WITH seb[tagType] SELECT FROM id => [] _ PrintType[stBase, tagType, NoSub]; cons => PutChar['*]; ENDCASE; PutString[" FROM "]; BEGIN isei: ISEIndex; first: BOOLEAN _ TRUE; varRec: RecordSEIndex; FOR isei _ FirstCtxSe[caseCtx], NextSe[isei] UNTIL isei=ISENull DO IF first THEN first _ FALSE ELSE PutString[", "]; PrintSei[stBase, isei]; PutString[" => "]; varRec _ seb[isei].idInfo; PrintFieldCtx[stBase, seb[varRec].fieldCtx]; ENDLOOP; PutString[" ENDCASE"]; END; END; sequence => BEGIN IF packed THEN PutString["PACKED "]; PutString["SEQUENCE "]; IF controlled THEN {PrintSei[stBase, tagSei]; PutString[": "]} ELSE PutString["COMPUTED "]; [] _ PrintType[stBase, SymType[stBase,tagSei], NoSub]; PutString[" OF "]; [] _ PrintType[stBase, componentType, NoSub]; END; relative => BEGIN IF baseType # SENull THEN [] _ PrintType[stBase, baseType, NoSub, printReadonly]; PutString[" RELATIVE "]; [] _ PrintType[stBase, offsetType, dosub, printReadonly]; END; subrange => BEGIN org: LONG INTEGER _ origin; size: LONG CARDINAL _ range; upperBound: LONG INTEGER = org + size; doit: PROCEDURE [pvf: ValFormat] = BEGIN PutChar['[]; PrintTypedVal[org, pvf, TRUE]; PutString[".."]; IF empty THEN {PrintTypedVal[org, pvf, TRUE]; PutChar[')]} ELSE { PrintTypedVal[ upperBound, pvf, upperBound < INTEGER[0]]; PutChar[']] }; END; vf _ PrintType[stBase, rangeType, doit]; END; long => BEGIN range: CSEIndex = stBase.UnderType[rangeType]; refOrList: BOOLEAN = WITH refType: stBase.seb[range] SELECT FROM ref => refType.counted OR refType.list, ENDCASE => FALSE; IF ~refOrList THEN PutString["LONG "]; [] _ PrintType[stBase, rangeType, NoSub, printReadonly]; END; real => PutString["REAL"]; opaque => BEGIN PutString["TYPE"]; IF lengthKnown THEN { PutString[" ["]; PrintValue[length]; PutString["]"]; }; END; zone => --Not totally corrrect for MdsZone:-- PutString[IF ~counted THEN "UNCOUNTED ZONE" ELSE "ZONE"]; any => PutString["ANY"]; ENDCASE => PutString["--!!!Unknown Type!!!--"]; ENDCASE; END; -- PrintType. rootInterfaceQualifier: String; -- Set by PutTypeName. PrintModuleQualifier: PROCEDURE [stBase: STBase, typeSei: SEIndex] = --INLINE-- BEGIN WITH type: stBase.seb[typeSei] SELECT FROM id => BEGIN module: MDIndex; IF type.idCtx = StandardTypeContext THEN RETURN; module _ ModuleOfTypeName[stBase, ISEI[typeSei]]; IF ~qualifyOpenNames AND module = OwnMdi THEN {IF rootInterfaceQualifier=NIL OR rootInterfaceQualifier.Length[]=0 THEN RETURN ELSE PutString[rootInterfaceQualifier] } ELSE PrintHti[stBase, stBase.mdb[module].moduleId]; PutChar['.]; END; ENDCASE => NULL; END; defaultPublic: BOOLEAN _ TRUE; PrintSymbolType: PRIVATE PROCEDURE [stb: STBase, sei: ISEIndex] = BEGIN OPEN stb; savePublic: BOOLEAN _ defaultPublic; typeSei: SEIndex; IF seb[sei].public # defaultPublic THEN BEGIN defaultPublic _ seb[sei].public; PutString[IF defaultPublic THEN "PUBLIC " ELSE "PRIVATE "]; END; IF seb[sei].idType = typeTYPE THEN BEGIN typeSei _ seb[sei].idInfo; PutString["TYPE = "]; [] _ PrintType[tsei: typeSei, dosub: NoSub, stBase: stb]; END ELSE BEGIN vf: ValFormat; typeSei _ seb[sei].idType; vf _ PrintType[tsei: typeSei, dosub: NoSub, stBase: stb]; IF seb[sei].constant AND vf.tag # none THEN BEGIN PutString[" = "]; PrintTypedVal[LONG[seb[sei].idValue], vf]; END; END; defaultPublic _ savePublic; END; PrintFieldCtx: PROCEDURE [stBase: STBase, ctx: CTXIndex, extraFirstArg: String _ NIL] = BEGIN forceComma: BOOL _ FALSE; PrintFieldItem: ContextProcedure = BEGIN IF itemIndex > 1 OR forceComma THEN PutString[", "]; IF ~ST.IsAnonymous[[itemStb, itemIsei]] THEN {PrintSei[itemStb, itemIsei]; PutString[": "] }; PrintSymbolType[itemStb, itemIsei]; END; PutChar['[]; IF extraFirstArg # NIL THEN {PutString[extraFirstArg]; forceComma _ TRUE}; [] _ EnumerateContext[ctxStb: stBase, ctx: ctx, ctxProc: PrintFieldItem]; PutChar[']]; END; PrintModeName: PROCEDURE [mode: TransferMode] = BEGIN ModePrintName: PACKED ARRAY TransferMode OF String = ["PROCEDURE", "PORT", "SIGNAL", "ERROR", "PROCESS", "PROGRAM", "NONE"]; PutString[ModePrintName[mode]] END; ValFormat: TYPE = RECORD [ SELECT tag: * FROM none => NULL, num => NULL, char => NULL, enum => [stBase: STBase, esei: EnumeratedSEIndex], ENDCASE]; PrintTypedVal: PROCEDURE [ val: LONG UNSPECIFIED, vf: ValFormat, integer: BOOLEAN_FALSE] = BEGIN WITH vf SELECT FROM num => PrintValue[val, integer]; enum => PrintEnum[val, stBase, esei]; char => IF val IN [' ..'~] THEN {PutChar['']; PutChar[VAL[Basics.LowHalf[val]]]} ELSE {PutOctal[n: val, trailingB: FALSE]; PutChar['C]}; ENDCASE; END; PrintValue: PROCEDURE [value: LONG UNSPECIFIED, integer: BOOLEAN _ FALSE] = BEGIN IF integer OR LOOPHOLE[value,LONG CARDINAL] < LOOPHOLE[LAST[LONG INTEGER],LONG CARDINAL] THEN PutDecimal[LOOPHOLE[value, LONG INTEGER]] ELSE PutOctal[LOOPHOLE[value, LONG CARDINAL]]; END; NoSub: PROCEDURE [vf: ValFormat] = BEGIN NULL END; EnumeratedSEIndex: TYPE = Table.Base RELATIVE POINTER [0..Table.Limit) TO enumerated cons SERecord; PrintEnum: PROCEDURE [ val: LONG UNSPECIFIED, stBase: STBase, esei: EnumeratedSEIndex] = BEGIN OPEN Symbols, stb: stBase; sei: ISEIndex; FOR sei _ stb.FirstCtxSe[stb.seb[esei].valueCtx], stb.NextSe[sei] WHILE sei # ISENull DO IF stb.seb[sei].idValue = val THEN {PrintSei[stBase, sei]; RETURN}; ENDLOOP; PutString["LOOPHOLE ["]; PrintValue[val]; PutChar[']]; END; PrintHti: PROCEDURE [stb: STBase, hti: Symbols.HTIndex] = BEGIN IF hti = HTNull THEN ERROR; PutSubString[HtiSubString[stb, hti]]; END; PrintSei: PROCEDURE [stb: STBase, sei: Symbols.ISEIndex] = BEGIN IF sei = ISENull THEN ERROR; PutSubString[IseiSubString[stb, sei]]; END; END. -- LupineSymbolTableImpl. ΜLupineSymbolTableImpl.mesa. Copyright c 1985 by Xerox Corporation. All rights reserved. Last edited by BZM on 11-May-82 14:12:53. Last edited by Andrew Birrell October 24, 1983 4:50 pm (changes for 3.4) Last edited by Paul Rovner January 28, 1983 1:37 pm (changes for 4.0) Last Edited by: Swinehart, July 11, 1984 11:49:45 pm PDT Last Edited by: Bob Hagmann February 8, 1985 5:26:05 pm PST Interface file operations. This is root interface symbol table info (from OpenInterface). Be sure to set LupineSymbolTable.MaxVersionStampStringLength correctly. Enumeration routines that generate an interface's contents. The ContextProcedure's itemIndex is invalid here because this enumeration is of the ST's outer context. General operations for types and symbols. This array size code is from from SymbolPack.WordsForType. It's been changed to work properly for CARDINAL, INTEGER, etc., index types, for which the compiler's Cardinality is zero! In many discriminating SELECT statements, an SEIndex is properly known to be an ISEIndex, but Mesa cannot infer this because both are relative pointers. This procedure captures the coercion. Detailed operations for types. This code automatically handles INT, CHAR, BOOL and other synonyms. It could cause unforeseeable problems with future builtin types. Beware. Checks to see if the candidate type ID = FullTypeName. Type printing routines. The output must be compilable. Most of these routines are derived from Lister>ListPub.mesa. putChar _ NIL; rootInterfaceQualifier _ NIL; These global routines are used by PrintType and friends (below). Exclude only the top-level appearance of READONLY in a type expression. This prints variant records in the Cedar style. For example: short red Dress => Dress[red][short]. Old variant record code: UNTIL (tsei _ TypeLink[tsei]) = SENull DO WITH seb[tsei] SELECT FROM id => {PutChar[' ]; PrintSei[stBase, ISEI[tsei]]}; ENDCASE; ENDLOOP; basic => Should see the ID first. IF monitored THEN PutString["MONITORED "]; The LOCK field is printed below, so MONITORED is redundant. This has changes to (TRY) do intervals with negative endpoints such as (3..-1]) correctly. It still has problems for values not contained in LONG INTEGERs. Module Initialization Κ+Υ˜headšœ™Icodešœ Οmœ1™<—Jšœ)™)JšœH™HJšœE™EJ™8L™;J˜J˜šΟk ˜ Jšœžœ ˜Jšœžœ ˜Jšœ žœ˜Jšœžœ9˜FJšœžœ˜Jšœžœ˜1Jšœžœ?˜GJšžœžœ ˜šœžœ˜J˜Jšœ"žœ˜&J˜1J˜J˜,J˜-J˜2—Jšœžœ ˜*Jšœ žœ#˜5Jšœ žœ1˜BJšœ žœ"˜1šœžœ˜J˜J˜J˜J˜'J˜J˜7J˜0—Jšœ žœ˜Jšœžœ˜JšœW˜WJ˜J˜—šœž˜Jšžœ4žœžœ3ž˜vJšžœ˜Jšžœ˜Jšœžœžœ žœ˜,J˜J˜Jšœžœžœ˜J˜Jšœžœžœ˜J˜šœžœ˜0Jš œžœ žœ žœžœ˜/J˜—J˜Jšœ™J˜˜Jšœ>™>Jšœžœ˜J˜(J˜)Jšœžœ˜J˜JšœžœžœΟc;˜YJ˜J˜šΟn œžœž œ˜!J˜J˜$Jšž˜Jšžœžœ˜"J˜J˜Jšœžœ˜šœ!˜!J˜Jšœžœ0˜K—Jšžœ7˜9Jšžœžœ-˜7šœ ž˜˜J˜ ˜ ˜Jšž˜šžœ˜Jšžœžœ˜(—Jšžœ˜——J˜"——Jšžœ˜Jšžœžœ2˜J˜-Jšœ?˜?Jšžœ&žœžœ˜DJ˜šžœ ž˜Jšž˜J˜JšœB˜BJ˜-JšœC˜CJšžœ˜——Jšžœ˜Jšžœ˜J˜—š œžœ˜0Jšžœ˜#Jšžœžœ˜š œžœ˜,JšžœŸ œžœ˜Jšœžœžœ˜0—J˜6Jšžœ˜———˜Jšœ;™;J˜š œžœž œžœ˜BJšžœ žœžœ˜"Jšž˜˜Jšžœžœ ˜J˜J˜Jšœ žœ˜J˜J˜šžœ&žœž˜5J˜"˜Jšœžœ*˜5—Jšžœžœ˜—šžœžœž˜&Jšœ'žœ˜.Jšœ-žœ˜4Jšœ=žœ˜CJšžœžœ˜—J˜8šœ žœ˜"Jšžœ žœ4˜F—šžœ7˜=J˜5—Jšžœ˜—˜J˜I—Jšžœ˜J˜š œžœž œ˜&Jšœžœ˜Jšœžœžœ˜.Jšžœ žœžœ˜"Jšž˜šœžœ ˜Jšœ0™0Jšœ6™6—˜Jšž˜š œž œžœžœ˜GJšžœžœ"˜0—J˜.J˜,šžœžœž˜(˜ šžœ ž˜˜šžœžœžœ ž˜9˜ J˜J˜2J˜+J˜*J˜#———˜šžœžœž˜˜ J˜J˜.J˜+J˜*J˜#———˜ šžœžœ ž˜˜ J˜J˜/J˜+J˜*J˜#———šžœ˜ šžœž˜ ˜ J˜J˜!J˜(J˜+J˜*J˜#————Jšžœžœ˜——Jšžœ˜—˜J˜F—Jšžœ˜J˜—š œžœž œ˜#Jšœ žœžœ˜7Jšžœ žœžœ˜"Jšž˜J˜!Jšžœžœžœ˜(šžœ4žœž˜C˜ Jšž˜˜Jšž˜šžœ˜˜ J˜J˜5J˜$——Jšžœ˜—˜J˜8—Jšžœ˜—Jšžœžœ˜—Jšžœ˜J˜—š œžœž œ˜%Jšœžœžœ˜:Jšžœ žœžœ˜"Jšž˜J˜&Jšžœžœžœ˜,šžœ9žœž˜H˜Jšž˜˜Jšž˜šžœ˜˜ J˜ J˜-J˜;J˜"——Jšžœ˜—˜J˜6—Jšžœ˜—Jšžœžœ˜—Jšžœ˜J˜—š œžœž œ˜$Jšœ:žœ˜CJšžœžœžœ˜J˜—š œž œ˜J˜J˜J˜Jšžœ žœžœ˜"Jšž˜Jšœžœ ˜š œž œ$˜DJ˜!JšžœŸ œžœ˜Jšž˜šžœžœžœžœ˜3Jšžœ3˜6Jšžœž˜ šžœžœ(˜DJšœ žœ'˜7J˜#——Jšžœ˜—˜(J˜šžœ˜šœžœ ž˜Jšœžœžœžœ˜+——JšžœŸ˜—šžœž˜J˜+—šžœ˜˜ ˜J˜J˜J˜J˜"J˜J˜'———Jšžœ˜—˜šžœž˜šžœ6ž˜@šœžœ˜ J˜ ˜˜ J˜-J˜5———šœžœ˜J˜ ˜˜ J˜2———Jšžœž˜—šžœžœ˜ J˜ J˜&———˜šžœžœž˜šœžœ˜˜ ˜J˜4—J˜——˜J˜ J˜J˜2šžœ˜˜ ˜ J˜#J˜"—J˜!———šœžœ˜˜ ˜ J˜4—J˜——Jšžœžœ˜——šœ žœ˜˜ ˜J˜1J˜5J˜9———šœ žœ˜˜ ˜ J˜J˜3˜ J˜0————˜ Jšž˜˜J˜/—šžœžœž˜!šœ žœ˜˜ ˜J˜J˜J˜ —J˜ ——Jšžœžœ˜—Jšžœ˜—˜ šžœ˜šžœžœ˜ ˜ ˜J˜J˜5J˜9˜J˜1————šžœžœ˜ ˜ ˜J˜J˜5J˜9J˜—————˜Jšž˜J˜AJ˜šœžœž˜+Jšœžœžœžœ˜*—Jšžœ ˜Jšžœ˜—šœžœ˜˜ ˜ Jšœ žœžœ žœ ˜šžœ˜šžœžœž˜J˜,J˜J˜J˜Jšžœ˜——Jšžœ˜J˜—š  œžœŸœ˜:Jšžœ.˜5Jšž˜J˜Jšœžœžœ˜#šœžœ˜'Jšž˜J˜@šžœžœž˜Jšœ žœ˜˜/šœ žœ˜J˜J˜——Jšžœžœ˜—šžœžœž˜Jšœ žœ˜˜.šœ žœ˜J˜——Jšžœžœ˜—Jšžœžœ ˜#JšžœŸ˜J˜0šžœ žœž˜/˜Jšžœžœžœžœ˜0šžœ˜J˜'J˜Jšžœžœ˜ ——Jšžœžœ˜——Jšžœ˜J˜—J˜.J˜=J˜3J˜EJ˜Jšœ žœ˜,J˜š œž œ˜9Jšž˜š œžœžœ˜HJšžœ˜Jšž˜J˜L˜%Jšœ(˜(J˜—Jšžœžœ žœžœ˜/Jšžœ˜—J˜3J˜+J˜-J˜*J˜%J˜%J˜/J˜+J˜%J˜)J˜1J˜,J˜3J˜/J˜+Jšžœ˜——J˜Jšœ7™7JšœB™B˜š  œžœž œ˜Jšœ žœž œ˜Jšœžœ ˜Jšœžœžœ˜Jšœžœ ˜+Jšœ žœ˜Jšžœžœžœžœ˜%J˜J˜/˜J˜J˜J˜J˜ Jšœ˜—Jšœ™Jšœ™Jšžœ˜J˜—Jšœ@™@Jšœ ž œž œžœŸ˜=J˜Jš œžœž œžœ˜7J˜š  œžœ˜Jšž˜Jš žœžœžœžœžœ˜AJšžœ˜—J˜š  œžœ$˜6Jšž˜šžœžœžœ.ž˜BJ˜Jšžœ˜—Jšžœ˜—J˜š  œžœžœžœ˜%Jšž˜Jšœžœ˜Jšœ žœžœ˜Jšœžœžœ˜Jšžœžœ˜&Jšœ˜Jšžœžœžœ˜AJšžœ˜šžœžœ˜Jšœ˜Jšœ˜Jšœ˜—Jšžœ˜Jšžœ˜—J˜š  œžœžœžœ žœžœ˜Jšžœžœžœ˜,Jšžœ˜—šžœžœž˜˜Jšž˜Jšœ žœžœ˜Jšœ žœžœ˜J˜J˜šž˜J˜šžœžœž˜˜šžœž˜Jšœ žœ%žœ˜9J˜Jšžœ˜——˜ Jšœ!žœžœ˜-—˜ Jšœ žœžœ ˜8—Jšžœ˜—Jšžœ˜Jšžœ˜—šžœžœž˜šœžœ.˜@Jšœ$žœ˜+—šœ žœ˜Jšž˜J˜#šžœ žœž˜˜ Jšž˜Jšœ/™/Jšœ3™3Jšœ™Jšœ)™)Jšœ™Jšœ2™2Jšœ™Jšœ™š œžœ˜1Jšž˜J˜šžœ)˜+Jšžœ˜!šžœž˜ šžœ žœž˜Jšœžœ ˜(J˜/Jšžœžœ˜—J˜9Jšžœ˜——JšžœŸ˜—Jšœžœ˜Jšžœ˜—Jšžœžœ˜(—Jšžœ˜—Jšžœžœ˜—J˜ Jšžœ˜—˜šžœžœž˜Jšœ"™"˜ Jšž˜˜!Jšž˜Jšžœžœ˜&J˜Jšžœ˜—Jšžœ žœ!˜3J˜ ˜J˜7—J˜ Jšžœ˜—˜ Jšž˜šžœž˜!Jšž˜J˜Jšœžœ ˜J˜1J˜šžœž˜šžœžœž˜˜ Jšž˜šžœž˜Jšžœ*žœžœ˜8—˜˜šœžœžœž˜Jšœ žœ˜)Jšžœžœ˜,———Jšžœ˜—Jšžœžœ˜.—Jšžœ˜—Jšž˜—šž˜Jšž˜—šœ*™*Jšœ;™;Jšžœ žœ!˜3Jšœ žœ žœ žœ ˜4J˜ Jšžœ˜—Jšžœ˜—˜šžœ˜šžœŸ˜!Jšžœ žœ˜&Jšžœžœ˜"Jšœ žœ žœžœ ˜1Jšžœžœ˜4š žœ žœžœžœž˜:Jš œ žœžœžœžœ ˜6Jšžœ˜—Jšžœ žœ˜#J˜J˜'Jšžœ žœ˜—šžœŸ˜J˜'J˜>J˜J˜J˜.———˜Jšž˜Jšžœžœ˜$J˜J˜)J˜J˜-Jšžœ˜—˜ Jšž˜J˜J˜J˜-Jšžœ˜—˜ Jšž˜š œžœ)˜5Jšž˜šžœžœž˜"Jšœ@˜@J˜—JšžœžœŸ˜Jšžœ˜—Jšžœžœ˜ J˜šžœž˜Jšž˜J˜ Jšœ˜Jšž˜—š œžœžœžœžœ˜#Jšœ ˜ Jšœ˜Jšœ ˜ Jšœ˜—šžœž˜Jšž˜J˜J˜Jšžœ˜—Jšžœ˜—˜Jšž˜J˜J˜šžœ ž˜Jšžœ žœ˜'Jšžœ˜—Jšžœžœ+žœ˜9J˜šžœ$ž˜*˜ Jšžœžœ žœ ˜1——šžœžœž˜J˜-J˜Jšžœ˜—J˜Jšž˜J˜Jšœžœžœ˜J˜šžœ*žœž˜BJšžœžœ žœžœ˜1J˜J˜J˜J˜,Jšžœ˜—J˜Jšžœ˜Jšžœ˜—˜ Jšž˜Jšžœžœ˜$J˜šžœ ˜ Jšžœ,˜0Jšžœ˜—J˜6J˜J˜-Jšžœ˜—˜ Jšž˜šžœ˜Jšžœ8˜<—J˜J˜9Jšžœ˜—˜ Jšž˜Jšœ>™>Jšœ™Jšœ@™@Jšœžœžœ ˜Jšœžœžœ ˜Jšœ žœžœ˜&šœž œ˜"Jšž˜J˜ Jšœžœ˜J˜šžœ˜Jšžœžœ˜1šžœ˜˜Jšœžœ˜*—J˜——Jšžœ˜—J˜(Jšžœ˜—˜Jšž˜J˜.šœ žœ˜šžœžœž˜+Jšœžœ˜'Jšžœžœ˜——Jšžœ žœ˜&J˜8Jšžœ˜—J˜˜ Jšž˜J˜šžœ žœ˜J˜7—Jšžœ˜—šœŸ%˜-Jšœ žœ žœžœ ˜9—J˜—Jšžœ(˜/——Jšžœ˜JšžœŸ ˜—J˜Jšœ!Ÿ˜7J˜š œž œ%˜DJšŸ œž˜šžœžœž˜*˜Jšž˜J˜Jšžœ"žœžœ˜0Jšœ"žœ ˜1šžœžœ˜(šžœžœžœžœ"˜HJšžœž˜ Jšžœ$˜(—Jšžœ/˜3—J˜ Jšžœ˜—Jšžœžœ˜—Jšžœ˜J˜—Jšœžœžœ˜J˜š œžœž œ˜AJšžœžœ˜Jšœ žœ˜$J˜šžœ!ž˜'Jšž˜J˜ Jšœ žœžœ žœ ˜;Jšžœ˜—šžœ˜šžœž˜ J˜J˜J˜9Jšž˜—šžœž˜ J˜J˜J˜9šžœžœž˜+Jšž˜J˜Jšœžœ˜*Jšžœ˜—Jšžœ˜——J˜Jšžœ˜J˜—š  œž œ?˜WJšž˜Jšœ žœžœ˜˜"Jšž˜Jšžœžœ žœ˜4šžœ%˜'Jšžœ1˜5—J˜#Jšžœ˜—J˜ JšœJ˜JJ˜IJ˜ Jšžœ˜J˜—š  œž œ˜/Jšž˜Jšœžœžœžœ ˜4˜(J˜—J˜Jšžœ˜J˜—šœ žœžœ˜šžœž˜Jšœžœ˜ Jšœžœ˜ Jšœžœ˜ J˜2Jšžœ˜ J˜——š  œž œ˜Jš œžœž œžœžœ˜?Jšž˜šžœžœž˜J˜!J˜%šœžœžœ ˜Jšžœžœ˜6Jšžœžœ˜7—Jšžœ˜—Jšžœ˜J˜—š   œž œ žœž œ žœžœ˜KJšž˜šžœ ž˜ šžœžœžœžœžœžœžœžœžœ˜JJšžœ žœžœžœ˜.Jšžœ žœžœžœ˜.——Jšžœ˜J˜—Jš  œž œžœžœžœ˜2J˜šœžœ˜Jšœ žœžœžœ˜IJ˜—š  œž œ˜Jšœžœž œ,˜AJšžœžœ˜ J˜šžœ>˜AJšžœž˜Jšžœžœžœ˜CJšžœ˜—J˜8Jšžœ˜J˜—š œž œ&˜9Jšž˜Jšžœžœžœ˜J˜%Jšžœ˜J˜—š œž œ'˜:Jšž˜Jšžœžœžœ˜J˜&Jšžœ˜J˜J˜J˜—Jšœ™J˜J˜JšžœŸ˜J˜——…—‹"ΏΓ