DIRECTORY CCTypes USING[CCError, CCErrorCase, CreateIndirectNode, GetAnyTargetType, GetBitSize, GetIndirectCreateNode, GetIndirectType, GetRTargetType, GetTypeClass, Operator], CedarCode USING[CreateCedarNode, GetDataFromNode, GetNodeRepresentation, OperationsBody], CedarOtherPureTypes USING[CreateIndirectToAnUnknownType, CreateUnknownType, CreateUnknownTypeNode], CirioMemory, CirioNubAccess USING[Handle, RemoteAddress, RemoteAddrFault], CirioTypes, CPointerTypes USING [CreatePointerType, PointerNodeInfo, PointerNodeInfoBody, CreatePointerNode], CNumericTypes USING [CreateNumericNode, CreateNumericType, GetDescriptorFromCNumericType, NumericDescriptor, NumericDescriptorBody, PrimaryTag], Convert USING [Error, IntFromRope, RopeFromChar], DeferringTypes, IO, LoadStateAccess USING [BasicPCInfo, GetBasicPCInfo, LoadStateHandle], ObjectFiles, ObjectFilesPrivate, PBasics USING [BITOR, BITSHIFT, LongNumber, Word], PBasics16 USING [BITXOR], Procedures, RCTW, RefTab USING [Create, Key, Ref, Store], RealFns USING [Power], Records USING[CreateIndirectRecordNode, CreateRecordType, FieldCase, IndirectRecordNodeProcs, RecordTypeProcs], RMTWPrivate, Rope USING[Cat, Concat, Equal, FromChar, ROPE], SGI, SymTab, SystemInterface; RCTWOrdinaries: CEDAR PROGRAM IMPORTS CCTypes, CedarCode, CedarOtherPureTypes, CirioMemory, CirioNubAccess, CirioTypes, CNumericTypes, Convert, CPointerTypes, DeferringTypes, IO, LoadStateAccess, ObjectFiles, PBasics, PBasics16, Procedures, RCTW, RealFns, Records, RefTab, RMTWPrivate, Rope, SGI, SymTab, SystemInterface EXPORTS RCTW = BEGIN OPEN LSA:LoadStateAccess, ObjF:ObjectFiles, RCTW; CC: TYPE = CirioTypes.CompilerContext; CCE: ERROR[case: CCTypes.CCErrorCase, msg: Rope.ROPE _ NIL] _ CCTypes.CCError; SIRep: TYPE ~ INT; LIRep: TYPE ~ INT; SCRep: TYPE ~ CARD; LCRep: TYPE ~ CARD; AnalyzeType: PUBLIC PROC[sourceStream: IO.STREAM, bracketEntry: BracketEntry, rctw: RCTWData] RETURNS[ati: RCTW.AnalyzedTypeInfo] ~ { temp: CHAR _ IO.PeekChar[sourceStream]; ati _ NIL; SELECT TRUE FROM IsDigit[temp] OR temp = '( OR temp = '- => -- This might be a definition RETURN[AnalyzeTypeDef[sourceStream, bracketEntry, rctw]]; temp = '* => --This is a pointer type ati _ AnalyzePointerTypeStab[sourceStream, bracketEntry, rctw]; temp = 'a => --This is an array type - create a pointer ati _ AnalyzePointerTypeStab[sourceStream, bracketEntry, rctw]; temp = 'b => --This is a bitwise type (SunOS 5.0) ati _ AnalyzeBitwiseTypeStab[sourceStream, bracketEntry, rctw]; temp = 'R => --This is a floating point type (SunOS 5.0) ati _ AnalyzeRealTypeStab[sourceStream, bracketEntry, rctw]; temp = 'r => --This is a subrange or a floating point type ati _ AnalyzeNumericTypeStab[sourceStream, bracketEntry, rctw]; temp = 's OR temp = 'u => --This is a bit field, record or union type. ati _ AnalyzeRecordTypeStab[sourceStream, bracketEntry, rctw]; temp = 'e => --This is an enumerated type ati _ AnalyzeEnumeratedTypeStab[sourceStream, bracketEntry, rctw]; temp = 'f OR temp = 'F => --This is a procedure type ati _ AnalyzeProcedureTypeStab[sourceStream, bracketEntry, rctw]; temp = 'x => --This is a structure (or union?) reference ati _ AnalyzeReferenceTypeStab[sourceStream, bracketEntry, rctw]; ENDCASE => RETURN[AnalyzedUnknownType[Rope.FromChar[temp].Concat[" and then some"], rctw]]; -- for typeClass SELECT IF ati = NIL THEN CCE[cirioError, IO.PutFR1["ati is NIL in RCTWOrdinaries.AnalyzeType for type beginning with: %g", [character[temp]]]]; RETURN; }; AnalyzeTypeFromFile: PUBLIC PROC[auxIndex: INT32, wireTables: SGI.WireTables, bracketEntry: BracketEntry, rctw: RCTWData, stab: ObjF.Stab, symTabIndex: CARD] RETURNS[ati: RCTW.AnalyzedTypeInfo _ NIL] ~ TRUSTED { i,structIndex,auxCount,basicType, numQualifiers: CARD _ 0; typeInfo: SGI.WireTypeInfoBody; auxSyms: SGI.AuxSymTable _ wireTables.auxSyms; type: Type _ NIL; IndexNil: CARD = 0FFFFFH; -- max valid index for aux entries fdIndex: INT32; thisSym: SGI.WireSTEntry; IF stab.extRef THEN { thisSym _ LOOPHOLE[@wireTables.extSyms[symTabIndex].sym]; fdIndex _ wireTables.extSyms[symTabIndex].fileDescrIndex; } ELSE { thisSym _ LOOPHOLE[@wireTables.localSyms[symTabIndex]]; fdIndex _ stab.fdIndex; }; IF auxIndex = IndexNil THEN { type _ AnalyzeNumericFileStab[[primary: signed, secondary: integer], 32, rctw].directType; RETURN[NEW[AnalyzedTypeInfoBody_[atiValid: TRUE, atiIsProc: FALSE, directType: type, rctw: rctw]]]; }; typeInfo _ auxSyms[auxIndex].typeInfo; basicType _ typeInfo.basicType; SELECT basicType FROM SGI.BTChar => -- character { type _ AnalyzeNumericFileStab[[primary: signed, secondary: character], 8, rctw].directType; }; SGI.BTUchar => -- unsigned character { type _ AnalyzeNumericFileStab[[primary: unsigned, secondary: character], 8, rctw].directType; }; SGI.BTShort => -- short { type _ AnalyzeNumericFileStab[[primary: signed, secondary: shortInteger], 16, rctw].directType; }; SGI.BTUshort => -- unsigned short { type _ AnalyzeNumericFileStab[[primary: unsigned, secondary: shortInteger], 16, rctw].directType; }; SGI.BTRange, -- subrange of int SGI.BTInt, -- integer SGI.BTLong => -- long { type _ AnalyzeNumericFileStab[[primary: signed, secondary: integer], 32, rctw].directType; }; SGI.BTAdr, -- address SGI.BTUint, -- unsigned int SGI.BTUlong => -- unsigned long { type _ AnalyzeNumericFileStab[[primary: unsigned, secondary: integer], 32, rctw].directType; }; SGI.BTFloat, -- float (real) SGI.BTDouble => -- Double (real { type _ AnalyzeNumericFileStab[[primary: float], 32, rctw].directType; }; SGI.BTVoid => -- void { -- void type _ AnalyzeNumericFileStab[[primary: signed, secondary: integer], 0, rctw].directType; }; SGI.BTStruct, -- Structure (Record) SGI.BTUnion => -- Union (variant) { type _ AnalyzeStructTypeFileStab[auxIndex, fdIndex, wireTables, bracketEntry, rctw, stab, symTabIndex].directType; }; SGI.BTEnum => -- Enumerated { type _ AnalyzeEnumeratedTypeFileStab[auxIndex, fdIndex, wireTables, bracketEntry, rctw, stab, symTabIndex].directType; }; SGI.BTTypedef => -- defined via a typedef, isymRef points { type _ AnalyzeTypeDefFileStab[auxIndex, fdIndex, wireTables, bracketEntry, rctw, stab, symTabIndex].directType; }; SGI.BTString => NULL; -- Varying Length Character String SGI.BTBit => NULL; -- Aligned Bit String SGI.BTSet => { -- pascal sets type _ CedarOtherPureTypes.CreateUnknownType[rctw.cc, IO.PutFR["<unimplemented .o type pascal sets from %g>", [rope[ObjF.DescribeModule[rctw.module]]] ]]}; SGI.BTComplex => { -- fortran complex type _ CedarOtherPureTypes.CreateUnknownType[rctw.cc, IO.PutFR["<unimplemented .o type fortran complex from %g>", [rope[ObjF.DescribeModule[rctw.module]]] ]]}; SGI.BTDcomplex => { -- fortran double complex type _ CedarOtherPureTypes.CreateUnknownType[rctw.cc, IO.PutFR["<unimplemented .o type fortran double complex from %g>", [rope[ObjF.DescribeModule[rctw.module]]] ]]}; SGI.BTIndirect => NULL; -- forward or unnamed typedef SGI.BTFixeddec => { -- Fixed Decimal type _ CedarOtherPureTypes.CreateUnknownType[rctw.cc, IO.PutFR["<unimplemented .o type Fixed Decimal from %g>", [rope[ObjF.DescribeModule[rctw.module]]] ]]}; SGI.BTFloatdec => { -- Float Decimal type _ CedarOtherPureTypes.CreateUnknownType[rctw.cc, IO.PutFR["<unimplemented .o type Float Decimal from %g>", [rope[ObjF.DescribeModule[rctw.module]]] ]]}; SGI.BTPicture => { -- Picture type _ CedarOtherPureTypes.CreateUnknownType[rctw.cc, IO.PutFR["<unimplemented .o type Picture from %g>", [rope[ObjF.DescribeModule[rctw.module]]] ]]}; ENDCASE => ERROR; RETURN[NEW[AnalyzedTypeInfoBody_[atiValid: TRUE, atiIsProc: FALSE, directType: type, rctw: rctw]]]; }; IsDigit: PROC [c: CHAR] RETURNS [BOOL] = INLINE { RETURN [c IN ['0 .. '9]] }; IsHexDigit: PROC [c: CHAR] RETURNS [BOOL] = INLINE { RETURN [c IN ['0 .. '9] OR c IN ['a .. 'f] OR c IN ['A .. 'F]] }; RopeFromStream: PROC [sourceStream: IO.STREAM, start: INT] RETURNS [Rope.ROPE] ~ { current: INT _ sourceStream.GetIndex; copyStream: IO.STREAM ~ IO.ROS[]; sourceStream.SetIndex[start]; FOR index: INT IN [start..current) DO copyStream.PutChar[sourceStream.GetChar]; ENDLOOP; sourceStream.SetIndex[current]; RETURN[copyStream.RopeFromROS[]]; }; GetDecimal: PROC [stream: IO.STREAM] RETURNS [INT] ~ { token: Rope.ROPE _ ""; {ENABLE Convert.Error => GOTO doesntConvert; { ENABLE IO.EndOfStream => GOTO finishUp; token: Rope.ROPE _ ""; char: CHAR _ IO.PeekChar[stream]; IF char = '- OR char = '+ THEN BEGIN token _ Rope.FromChar[IO.GetChar[stream]]; char _ IO.PeekChar[stream] END; IF char = '0 THEN BEGIN [] _ IO.GetChar[stream]; token _ Rope.Concat[token, "0"]; char _ IO.PeekChar[stream]; IF char = 'x THEN BEGIN [] _ IO.GetChar[stream]; WHILE IsHexDigit[IO.PeekChar[stream]] DO token _ Rope.Concat[token, Rope.FromChar[IO.GetChar[stream]]]; ENDLOOP; RETURN[Convert.IntFromRope[token, 16]] END END; WHILE IsDigit[IO.PeekChar[stream]] DO token _ Rope.Concat[token, Rope.FromChar[IO.GetChar[stream]]]; ENDLOOP; RETURN[Convert.IntFromRope[token]]; EXITS finishUp => RETURN[Convert.IntFromRope[token]]; }; EXITS doesntConvert => RETURN[-1]; }; }; DebugStabParsing: BOOLEAN _ FALSE; AnalyzeTypeDef: PROC[sourceStream:IO.STREAM, bracketEntry: RCTW.BracketEntry, rctw: RCTW.RCTWData] RETURNS [RCTW.AnalyzedTypeInfo] ~ { typeRef: ROPE _ ObjF.GetTypeRef[rctw.module, sourceStream]; ati: RCTW.AnalyzedTypeInfo _ NIL; dti: RCTW.AnalyzedTypeInfo; IF NOT IO.EndOf[sourceStream] AND IO.PeekChar[sourceStream] = '= THEN {--This is a typedef analyzedTypeInfo: RCTW.AnalyzedTypeInfo; IF IO.GetChar[sourceStream]#'= THEN ERROR; -- remove the '= from the stream dti _ DeferringType[rctw]; IF DebugStabParsing THEN SystemInterface.ShowReport[Rope.Cat["Creating DeferringType for ", typeRef, " in ", ObjectFiles.DescribeModule[rctw.module]], $urgent]; IF NOT SymTab.Insert [rctw.typeRefHashTable, typeRef, dti] THEN CCE[cirioError, Rope.Concat["redefinition of typeRef ", typeRef]]; analyzedTypeInfo _ RCTW.AnalyzeType[sourceStream, bracketEntry, rctw]; IF DebugStabParsing THEN SystemInterface.ShowReport[Rope.Cat["Defining ", typeRef, " in ", ObjectFiles.DescribeModule[rctw.module]], $urgent]; IF NOT SymTab.Insert[rctw.typeRefHashTable, typeRef, analyzedTypeInfo] THEN { old: RCTW.AnalyzedTypeInfo ~ NARROW[rctw.typeRefHashTable.Fetch[typeRef].val]; IF old=analyzedTypeInfo THEN ati _ old ELSE IF DeferringTypes.IsDeferring[old.directType] THEN { DeferringTypes.SetUndertype[old.directType, analyzedTypeInfo.directType]; IF DebugStabParsing THEN SystemInterface.ShowReport[Rope.Cat["Setting UnderType for ", typeRef, " in ", ObjectFiles.DescribeModule[rctw.module]], $urgent]; [] _ SymTab.Replace[rctw.typeRefHashTable, typeRef, analyzedTypeInfo]; ati _ old} ELSE IF DeferringTypes.IsDeferring[analyzedTypeInfo.directType] THEN { DeferringTypes.SetUndertype[ analyzedTypeInfo.directType, old.directType]; ati _ analyzedTypeInfo} ELSE { SystemInterface.ShowReport[Rope.Cat["redefinition of typeRef ", typeRef, " in ", ObjectFiles.DescribeModule[rctw.module]], $urgent]; [] _ SymTab.Replace[rctw.typeRefHashTable, typeRef, analyzedTypeInfo]; <<CCError[cirioError, Rope.Concat["redefinition of typeRef ", typeRef]];>>}; }; } ELSE { -- # '= -- found: BOOLEAN; refany: REF ANY; [found, refany] _ rctw.typeRefHashTable.Fetch[typeRef]; ati _ NARROW[refany]; IF NOT found THEN ati _ AnalyzedUnknownType[typeRef, rctw]; IF DebugStabParsing THEN IF found THEN { SystemInterface.ShowReport[Rope.Cat[typeRef, " FOUND in ", ObjectFiles.DescribeModule[rctw.module]], $urgent]; } ELSE { SystemInterface.ShowReport[Rope.Cat[typeRef, " NOT FOUND in ", ObjectFiles.DescribeModule[rctw.module]], $urgent]; }; }; IF ati = NIL THEN CCE[cirioError, IO.PutFR1["ati is NIL in RCTWOrdinaries.AnalyzeTypeDef for typeRef %g", [rope[typeRef]]]]; RETURN[ati]; }; AnalyzeTypeDefFileStab: PROC[auxIndex: INT32, fdIndex: INT32, wireTables: SGI.WireTables, bracketEntry: RCTW.BracketEntry, rctw: RCTW.RCTWData, stab: ObjF.Stab, symTabIndex: CARD] RETURNS [RCTW.AnalyzedTypeInfo] ~ TRUSTED { ati: RCTW.AnalyzedTypeInfo _ NIL; dti: RCTW.AnalyzedTypeInfo; typeRef: ROPE; auxSyms: SGI.AuxSymTable _ wireTables.auxSyms; symBaseIndex, symIndex, stringOffset: CARD; stringBaseIndex: CARD; analyzedTypeInfo: RCTW.AnalyzedTypeInfo; stringTable: SGI.StringTable _ wireTables.localStrings; currentIndex: CARD; relIndex: SGI.WireRelIndexBody; relFileIndex: INT32; relFileOffset: INT32; relIndex _ auxSyms[auxIndex+1].relIndex; IF relIndex.relFileDescrIndex = 0FFFH THEN { relFileIndex _ auxSyms[auxIndex+2].relFileIndex; } ELSE { relFileIndex _ relIndex.relFileDescrIndex; }; relFileOffset _ wireTables.fileDescr[fdIndex].rfdBase + relFileIndex; IF relFileOffset # 0 THEN fdIndex _ wireTables.relFiles[relFileOffset]; symIndex _ relIndex.index; symBaseIndex _ wireTables.fileDescr[fdIndex].isymBase; stringBaseIndex _ wireTables.fileDescr[fdIndex].issBase; currentIndex _ symIndex + symBaseIndex; stringOffset _ wireTables.localSyms[currentIndex].symStringIndex; typeRef _ RopeFromStringTable[stringTable, stringBaseIndex+stringOffset]; dti _ DeferringType[rctw]; IF DebugStabParsing THEN SystemInterface.ShowReport[Rope.Cat["Creating DeferringType for ", typeRef, " in ", ObjectFiles.DescribeModule[rctw.module]], $urgent]; [] _ SymTab.Insert[rctw.typeRefHashTable, typeRef, dti]; auxIndex _ wireTables.fileDescr[fdIndex].iauxBase + wireTables.localSyms[currentIndex].index; analyzedTypeInfo _ AnalyzeTypeFromFile[auxIndex, wireTables, bracketEntry, rctw, stab, currentIndex]; IF DebugStabParsing THEN SystemInterface.ShowReport[Rope.Cat["Defining ", typeRef, " in ", ObjectFiles.DescribeModule[rctw.module]], $urgent]; IF NOT SymTab.Insert[rctw.typeRefHashTable, typeRef, analyzedTypeInfo] THEN { old: RCTW.AnalyzedTypeInfo ~ NARROW[rctw.typeRefHashTable.Fetch[typeRef].val]; IF old=analyzedTypeInfo THEN ati _ old ELSE IF DeferringTypes.IsDeferring[old.directType] THEN { DeferringTypes.SetUndertype[old.directType, analyzedTypeInfo.directType]; IF DebugStabParsing THEN SystemInterface.ShowReport[Rope.Cat["Setting UnderType for ", typeRef, " in ", ObjectFiles.DescribeModule[rctw.module]], $urgent]; [] _ SymTab.Replace[rctw.typeRefHashTable, typeRef, analyzedTypeInfo]; ati _ old} ELSE IF DeferringTypes.IsDeferring[analyzedTypeInfo.directType] THEN { DeferringTypes.SetUndertype[ analyzedTypeInfo.directType, old.directType]; ati _ analyzedTypeInfo} ELSE { ati _ analyzedTypeInfo; <<[] _ SymTab.Replace[rctw.typeRefHashTable, typeRef, analyzedTypeInfo]; CCError[cirioError, Rope.Concat["redefinition of typeRef ", typeRef]];>>}; }; IF ati = NIL THEN CCE[cirioError, IO.PutFR1["ati is NIL in RCTWOrdinaries.AnalyzeTypeDef for typeRef %g", [rope[typeRef]]]]; RETURN[ati]; }; DeferringType: PROC [rctw: RCTWData] RETURNS [RCTW.AnalyzedTypeInfo] ~ { deferringType: Type _ DeferringTypes.CreateDeferringType[rctw.cc]; analyzedTypeInfo: AnalyzedTypeInfo _ NEW[AnalyzedTypeInfoBody _ [atiValid: TRUE, atiIsProc: FALSE, directType: deferringType, rctw: rctw]]; RETURN[analyzedTypeInfo] }; AnalyzeReferenceTypeStab: PROC [sourceStream: IO.STREAM, bracketEntry: BracketEntry, rctw: RCTWData] RETURNS[ati: AnalyzedTypeInfo] ~ { x: CHAR ~ sourceStream.GetChar[]; kind: CHAR ~ sourceStream.GetChar[]; peek, colon: CHAR; ref, dot: ROPE; IF x#'x THEN ERROR; IF kind#'s AND kind#'u THEN CCE [syntax, Rope.Concat["x", Rope.FromChar[kind]]]; peek _ sourceStream.PeekChar[]; IF RefTok[peek] # other THEN CCE [syntax, Rope.Cat["x", Rope.FromChar[kind], Rope.FromChar[peek]]]; ref _ IO.GetTokenRope[sourceStream, RefTok].token; colon _ sourceStream.GetChar[]; dot _ Rope.Cat["x", Rope.FromChar[kind], ref, Rope.FromChar[colon]]; IF colon#': THEN CCE [syntax, dot]; RETURN AnalyzedUnknownType[dot, rctw]}; RefTok: PROC [char: CHAR] RETURNS [IO.CharClass] ~ {RETURN [SELECT char FROM ': => break, ENDCASE => other]}; AnalyzedUnknownType: PUBLIC PROC [typeRef: Rope.ROPE, rctw: RCTWData] RETURNS [AnalyzedTypeInfo] ~ { analyzedTypeInfo: AnalyzedTypeInfo _ NEW[AnalyzedTypeInfoBody _ [ atiValid: TRUE, atiIsProc: FALSE, directType: CedarOtherPureTypes.CreateUnknownType[rctw.cc, IO.PutFR["<unimplemented .o type %g from %g>", [rope[typeRef]], [rope[ObjF.DescribeModule[rctw.module]]] ]], rctw: rctw]]; RETURN[analyzedTypeInfo] }; UnimplementedTypeNode: PROC[indirectType: Type, rctw: RCTWData, explanation: Rope.ROPE, indirect: BOOL] RETURNS[Node] = { targetType: Type ~ CedarOtherPureTypes.CreateUnknownType[rctw.cc, explanation]; IF indirect THEN RETURN[CedarOtherPureTypes.CreateIndirectToAnUnknownType[targetType, explanation, rctw.cc]]; RETURN[CedarOtherPureTypes.CreateUnknownTypeNode[targetType, explanation, rctw.cc]]}; AnalyzedPointerTypeStab: TYPE = REF AnalyzedPointerTypeStabBody; AnalyzedPointerTypeStabBody: TYPE = RECORD[ rctw: RCTWData, directType: Type, size: CARD, directTargetType: Type ]; AnalyzePointerTypeStab: PROC[sourceStream: IO.STREAM, bracketEntry: BracketEntry, rctw: RCTWData] RETURNS[AnalyzedTypeInfo] ~ { array: BOOL ~ SELECT sourceStream.GetChar[] FROM '* => FALSE, 'a => TRUE, ENDCASE => ERROR CCE[cirioError, "can't happen: AnalyzePointerTypeStab called with stream at non-* non-a char"]; indexATI: AnalyzedTypeInfo ~ IF array THEN AnalyzeType[sourceStream, bracketEntry, rctw] ELSE NIL; sep: Rope.ROPE ~ IF array THEN SELECT sourceStream.GetChar[] FROM '; => ";", ENDCASE => ERROR CCE[cirioError, "found array type constructor (in DBX stab) without semicolon between index and element types"] ELSE NIL; targetATI: AnalyzedTypeInfo ~ AnalyzeType[sourceStream, bracketEntry, rctw]; IF array THEN RETURN AnalyzedUnknownType["Arrays aren't implemented yet.", rctw]; --arrays are NOT just pointers - rather than duplicate the code in RMTWCompounds, wait 'till we can call it {private: AnalyzedPointerTypeStab ~ NEW[AnalyzedPointerTypeStabBody_[ rctw: rctw, size: 32, directTargetType: targetATI.directType]]; bti: BasicTypeInfo ~ NEW [BasicTypeInfoPrivate _ [CreatePointerIndirect, GetPointerBitSize, private]]; private.directType _ CPointerTypes.CreatePointerType[private.directTargetType, rctw.cc, bti]; RETURN[NEW[AnalyzedTypeInfoBody_[atiValid: TRUE, atiIsProc: FALSE, directType: private.directType, rctw: rctw]]]}}; AnalyzePointerTypeFileStab: PUBLIC PROC[auxIndex: INT32, wireTables: SGI.WireTables, bracketEntry: BracketEntry, rctw: RCTWData, stab: ObjF.Stab, symTabIndex: CARD] RETURNS[AnalyzedTypeInfo] ~ { targetType: Type ~ AnalyzeTypeFromFile[auxIndex, wireTables, bracketEntry, rctw, stab, symTabIndex].directType; {private: AnalyzedPointerTypeStab ~ NEW[AnalyzedPointerTypeStabBody_[ rctw: rctw, size: 32, directTargetType: targetType]]; bti: BasicTypeInfo ~ NEW [BasicTypeInfoPrivate _ [CreatePointerIndirect, GetPointerBitSize, private]]; private.directType _ CPointerTypes.CreatePointerType[private.directTargetType, rctw.cc, bti]; RETURN[NEW[AnalyzedTypeInfoBody_[atiValid: TRUE, atiIsProc: FALSE, directType: private.directType, rctw: rctw]]]}}; GetPointerBitSize: PROC[bti: BasicTypeInfo, cc: CC, indirectType, targetType: Type] RETURNS[CARD] ~ { private: AnalyzedPointerTypeStab _ NARROW[bti.btiData]; RETURN[private.size]}; CreatePointerIndirect: PROC [bti: BasicTypeInfo, cc: CC, indirectType, targetType: Type, mem: Mem] RETURNS [Node] ~ { private: AnalyzedPointerTypeStab _ NARROW[bti.btiData]; nodeData: REF PointerNodeData _ NEW[PointerNodeData _ [private, mem]]; RETURN[CedarCode.CreateCedarNode[PointerOps, indirectType, nodeData]]}; PointerNodeData: TYPE = RECORD[ private: AnalyzedPointerTypeStab, mem: Mem]; PointerOps: REF CedarCode.OperationsBody _ NEW[CedarCode.OperationsBody_[ store: PointerStore, load: PointerLoad]]; PointerDirect: TYPE ~ REF PointerDirectPrivate; PointerDirectPrivate: TYPE ~ RECORD [ addr: CARD, eltSize: INT, pnd: REF PointerNodeData, targetMem: Mem]; PointerStore: PROC[valType: Type, valNode: Node, indirectType: Type, indirectNode: Node, cc: CC] = { nodeData: REF PointerNodeData ~ NARROW[CedarCode.GetDataFromNode[indirectNode]]; rctw: RCTWData ~ nodeData.private.rctw; mem: Mem ~ nodeData.mem; pointerSize: CARD ~ nodeData.private.size; valInfo: REF ANY ~ CedarCode.GetDataFromNode[valNode]; WITH valInfo SELECT FROM valPni: CPointerTypes.PointerNodeInfo => { valPD: PointerDirect ~ NARROW[valPni.data]; mem.MemWrite[valPD.addr, 32, zeroBA]}; ENDCASE => CCE[operation, "Can't store a non-C pointer into a C pointer"]; RETURN}; cNIL: CARD _ 0; PointerLoad: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = { nodeData: REF PointerNodeData _ NARROW[CedarCode.GetDataFromNode[indirectNode]]; rctw: RCTWData _ nodeData.private.rctw; mem: Mem _ nodeData.mem; pointerSize: CARD _ nodeData.private.size; {ENABLE { CirioNubAccess.RemoteAddrFault => GOTO unknownAddress; CCE => GOTO unknownAddress}; fieldSizeBa: BitAddr _ mem.MemGetSize[]; fieldSize: CARD _ fieldSizeBa.BaToBits[]; addrBits: CARD _ mem.MemRead[bitsPerPtr, zeroBA]; <<IF (addr.byteAddress = cNIL AND addr.bitOffset = 0) OR addr.nil OR NOT addr.valid THEN RETURN[CPointerTypes.CreateNilPointerNode[cc]];>> {directTargetType: Type ~ nodeData.private.directTargetType; indirectTargetType: Type ~ CCTypes.GetIndirectType[directTargetType]; referentSize: CARD _ 0; referentSizeBa: BitAddr _ unspecdBA; targetMem: Mem; info: CPointerTypes.PointerNodeInfo; { --MJS, January 10, 1992: Made the targetMem use the referentSize, so that NumericLoad will have a meaningful fieldSize ENABLE CCE => CONTINUE; referentSize _ CCTypes.GetBitSize[indirectTargetType, cc]; referentSizeBa _ CirioMemory.BitsToBa[referentSize]}; targetMem _ CirioMemory.CreateSimpleMem[[rctw.nub, LOOPHOLE[addrBits], 0, addrBits=0 OR addrBits=CARD.LAST, TRUE], referentSizeBa]; info _ NEW[CPointerTypes.PointerNodeInfoBody _ [ clientTargetType: directTargetType, indirectToClientTarget: CCTypes.CreateIndirectNode[indirectTargetType, targetMem, cc], add: PointerAdd, subtract: PointerSubtract, compare: PointerCompare, data: NEW [PointerDirectPrivate _ [addrBits, referentSize, nodeData, targetMem]] ]]; RETURN[CPointerTypes.CreatePointerNode[nodeData.private.directType, info, cc]]; }; EXITS unknownAddress => RETURN[UnimplementedTypeNode[indirectType, rctw, "pointer at (not to) bad address", FALSE]]; }}; PointerAdd: PROC [node: Node, offsetNode: Node, info: CPointerTypes.PointerNodeInfo, cc: CC] RETURNS [Node] ~ {RETURN OffsetPointer[node, offsetNode, +1, info, cc]}; PointerSubtract: PROC [leftNode: Node, rightNode: Node, cc: CC] RETURNS [Node] ~ { WITH CedarCode.GetDataFromNode[leftNode] SELECT FROM pni: CPointerTypes.PointerNodeInfo => RETURN OffsetPointer[leftNode, rightNode, -1, pni, cc]; ENDCASE => CCE[cirioError, "C PointerSubtract called with left node not a C pointer"]}; OffsetPointer: PROC [node: Node, offsetNode: Node, sgn: [-1..+1], pni: CPointerTypes.PointerNodeInfo, cc: CC] RETURNS [Node] ~ { pd: PointerDirect ~ NARROW[pni.data]; pnd: REF PointerNodeData ~ pd.pnd; rctw: RCTWData ~ pnd.private.rctw; bitOffset: INT ~ sgn*pd.eltSize*(WITH CedarCode.GetDataFromNode[offsetNode] SELECT FROM ri: REF INT => ri^, rc: REF CARD => LOOPHOLE[rc^, INT], rc: REF CHAR => rc^.ORD, ENDCASE => CCE[operation, "can't add something besides an integer to a pointer"]); byteOffset: INT ~ bitOffset/8; IF pd.eltSize=0 THEN CCE[operation, "can't shift that pointer"]; IF bitOffset # byteOffset*8 THEN CCE[operation, "pointer addition must yield a byte-aligned offset"]; { newAddr: INT ~ LOOPHOLE[pd.addr, INT] + byteOffset; shiftedMem: Mem ~ pd.targetMem.MemShift[CirioTypes.BitsToBa[bitOffset]]; referentIndirect: Node ~ CCTypes.GetIndirectCreateNode[pnd.private.directTargetType, shiftedMem, cc]; newPni: CPointerTypes.PointerNodeInfo ~ NEW[CPointerTypes.PointerNodeInfoBody _ [ clientTargetType: pni.clientTargetType, indirectToClientTarget: referentIndirect, add: PointerAdd, subtract: PointerSubtract, compare: PointerCompare, data: NEW [PointerDirectPrivate _ [LOOPHOLE[newAddr], pd.eltSize, pnd, pd.targetMem]] ]]; RETURN[CPointerTypes.CreatePointerNode[pnd.private.directType, newPni, cc]]}}; PointerCompare: PROC [leftNode: Node, rightNode: Node, op: CCTypes.Operator, cc: CC] RETURNS [Node] ~ { leftPni: CPointerTypes.PointerNodeInfo ~ WITH CedarCode.GetDataFromNode[leftNode] SELECT FROM pni: CPointerTypes.PointerNodeInfo => pni, ENDCASE => CCE[cirioError, "C pointer compare called with non-pointer left arg"]; leftPd: PointerDirect ~ NARROW[leftPni.data]; rightPni: CPointerTypes.PointerNodeInfo ~ WITH CedarCode.GetDataFromNode[rightNode] SELECT FROM pni: CPointerTypes.PointerNodeInfo => pni, ENDCASE => CCE[cirioError, "C pointer compare called with non-pointer right arg"]; rightPd: PointerDirect ~ NARROW[rightPni.data]; ans: BOOL ~ SELECT op FROM $eq => leftPd.addr = rightPd.addr, $ne => leftPd.addr # rightPd.addr, $le => leftPd.addr <= rightPd.addr, $lt => leftPd.addr < rightPd.addr, $ge => leftPd.addr >= rightPd.addr, $gt => leftPd.addr > rightPd.addr, ENDCASE => CCE[cirioError, IO.PutFR1["unexpected comparison op (%g) between C pointers", [atom[op]] ]]; ansType: Type ~ CNumericTypes.CreateNumericType[NEW[CNumericTypes.NumericDescriptorBody _ [signed, integer]], cc, NIL]; RETURN CNumericTypes.CreateNumericNode[ansType, NEW [INT _ IF ans THEN 1 ELSE 0]]}; RemoteAddressNormalize: PROC [address: CirioNubAccess.RemoteAddress] RETURNS [CirioNubAccess.RemoteAddress] ~ { newAddress: CirioNubAccess.RemoteAddress _ IF address.nil THEN [h: address.h, byteAddress: 0 , bitOffset: 0, nil: address.nil, valid: address.valid] ELSE [h: address.h, byteAddress: address.byteAddress + address.bitOffset / 8, bitOffset: address.bitOffset MOD 8, nil: address.nil, valid: address.valid]; RETURN[newAddress] }; RemoteAddressByteDifference: PROC [left: CirioNubAccess.RemoteAddress, right: CirioNubAccess.RemoteAddress, bitSize: CARD] RETURNS [diff: CARD, negative: BOOL] ~ { newLeft: CirioNubAccess.RemoteAddress; newRight: CirioNubAccess.RemoteAddress; IF NOT(left.valid AND right.valid) THEN CCE[cirioError]; newLeft _ RemoteAddressNormalize[left]; newRight _ RemoteAddressNormalize[right]; IF newLeft.bitOffset # 0 OR newRight.bitOffset # 0 THEN CCE[cirioError]; RETURN[ABS[(newLeft.byteAddress - newRight.byteAddress) / bitSize], newLeft.byteAddress < newRight.byteAddress]; }; IntFromBool: PROC [b: BOOL] RETURNS [INT] ~ { IF b THEN RETURN[1] ELSE RETURN[0] }; RemoteAddressCompare: PROC [left: CirioNubAccess.RemoteAddress, right: CirioNubAccess.RemoteAddress, op: CCTypes.Operator] RETURNS [INT] ~ { difference: CARD; negative: BOOLEAN; [difference, negative] _ RemoteAddressByteDifference[left, right, 1]; RETURN[ SELECT op FROM $le => IntFromBool[negative OR difference = 0], $lt => IntFromBool[negative], $eq => IntFromBool[difference = 0], $ne => IntFromBool[difference # 0], $gt => IntFromBool[difference # 0 AND ~negative], $ge => IntFromBool[~negative], ENDCASE => CCE[cirioError]]; }; AnalyzeEnumeratedTypeStab: PROC [sourceStream: IO.STREAM, bracketEntry: BracketEntry, rctw: RCTWData] RETURNS [AnalyzedTypeInfo] ~ { desc: CNumericTypes.NumericDescriptor; type: Type; private: AnalyzedNumericTypeStabPrivate; constantsHashTable: RefTab.Ref _ RefTab.Create[17, RefIntEqual, RefIntHash]; listed: LIST OF DotOListings _ NIL; bti: BasicTypeInfo; char: CHAR _ IO.GetChar[sourceStream]; WHILE NOT IO.EndOf[sourceStream] AND IO.PeekChar[sourceStream] # '; DO value: INT; symbol: Rope.ROPE _ GetTokenRope[sourceStream]; ls: DotOListings _ NARROW[bracketEntry.symbolHashTable.Fetch[symbol].val]; IF IO.GetChar[sourceStream] # ': THEN CCE[cirioError, "missing colon in enumerated type construction"]; value _ GetDecimal[sourceStream]; IF ls#NIL THEN CCE[cirioError, IO.PutFR["enumerator (%g=%g) clashes with some existing symbol in the same scope", [rope[symbol]], [integer[value]] ]]; listed _ CONS[NEW[DotOGlorp[enumerator] _ [NIL, enumerator[symbol, value, NIL]]], listed]; IF NOT bracketEntry.symbolHashTable.Insert[symbol, listed.first] THEN ERROR; [] _ RefTab.Store[constantsHashTable, NEW[INT _ value], symbol]; IF IO.PeekChar[sourceStream] = ', THEN char _ IO.GetChar[sourceStream]; ENDLOOP; desc _ NEW[CNumericTypes.NumericDescriptorBody _ [primary: signed, secondary: enumeration, enumerationConstants: constantsHashTable]]; private _ NEW[AnalyzedNumericTypeStabPrivateBody_[rctw: rctw, desc: desc, bitSize: 32]]; bti _ NEW [BasicTypeInfoPrivate _ [CreateNumericIndirect, GetNumericBitSize, private]]; type _ CNumericTypes.CreateNumericType[desc, rctw.cc, bti]; FOR listed _ listed, listed.rest WHILE listed#NIL DO WITH listed.first SELECT FROM x: DotOEnumr => x.type _ type; ENDCASE => ERROR; ENDLOOP; RETURN[NEW[AnalyzedTypeInfoBody _ [ atiValid: TRUE, atiIsProc: FALSE, directType: type, rctw: rctw]]] }; AnalyzeEnumeratedTypeFileStab: PROC [auxIndex: INT32, fdIndex: INT32, wireTables: SGI.WireTables, bracketEntry: BracketEntry, rctw: RCTWData, stab: ObjF.Stab, symTabIndex: CARD] RETURNS [AnalyzedTypeInfo] ~ TRUSTED { desc: CNumericTypes.NumericDescriptor; type: Type; private: AnalyzedNumericTypeStabPrivate; constantsHashTable: RefTab.Ref _ RefTab.Create[17, RefIntEqual, RefIntHash]; listed: LIST OF DotOListings _ NIL; bti: BasicTypeInfo; symBaseIndex, symIndex, currentIndex: CARD; auxSyms: SGI.AuxSymTable _ wireTables.auxSyms; endIndex: CARD; stringOffset, stringBaseIndex: CARD; stringTable: SGI.StringTable _ wireTables.localStrings; relIndex: SGI.WireRelIndexBody; relFileIndex: INT32; relFileOffset: INT32; relIndex _ auxSyms[auxIndex+1].relIndex; IF relIndex.relFileDescrIndex = 0FFFH THEN { relFileIndex _ auxSyms[auxIndex+2].relFileIndex; } ELSE { relFileIndex _ relIndex.relFileDescrIndex; }; relFileOffset _ wireTables.fileDescr[fdIndex].rfdBase + relFileIndex; IF relFileOffset # 0 THEN fdIndex _ wireTables.relFiles[relFileOffset]; symIndex _ relIndex.index; symBaseIndex _ wireTables.fileDescr[fdIndex].isymBase; stringBaseIndex _ wireTables.fileDescr[fdIndex].issBase; currentIndex _ symIndex + symBaseIndex; endIndex _ wireTables.localSyms[currentIndex].index - 1; currentIndex _ currentIndex + 1; WHILE currentIndex < endIndex DO value: INT; symbol: Rope.ROPE; ls: DotOListings; stringOffset _ wireTables.localSyms[currentIndex].symStringIndex; value _ wireTables.localSyms[currentIndex].value; symbol _ RopeFromStringTable[stringTable, stringBaseIndex+stringOffset]; ls _ NARROW[bracketEntry.symbolHashTable.Fetch[symbol].val]; IF ls#NIL THEN CCE[cirioError, IO.PutFR["enumerator (%g=%g) clashes with some existing symbol in the same scope", [rope[symbol]], [integer[value]] ]]; listed _ CONS[NEW[DotOGlorp[enumerator] _ [NIL, enumerator[symbol, value, NIL]]], listed]; IF NOT bracketEntry.symbolHashTable.Insert[symbol, listed.first] THEN ERROR; [] _ RefTab.Store[constantsHashTable, NEW[INT _ value], symbol]; currentIndex _ currentIndex +1; ENDLOOP; desc _ NEW[CNumericTypes.NumericDescriptorBody _ [primary: signed, secondary: enumeration, enumerationConstants: constantsHashTable]]; private _ NEW[AnalyzedNumericTypeStabPrivateBody_[rctw: rctw, desc: desc, bitSize: 32]]; bti _ NEW [BasicTypeInfoPrivate _ [CreateNumericIndirect, GetNumericBitSize, private]]; type _ CNumericTypes.CreateNumericType[desc, rctw.cc, bti]; FOR listed _ listed, listed.rest WHILE listed#NIL DO WITH listed.first SELECT FROM x: DotOEnumr => x.type _ type; ENDCASE => ERROR; ENDLOOP; RETURN[NEW[AnalyzedTypeInfoBody _ [ atiValid: TRUE, atiIsProc: FALSE, directType: type, rctw: rctw]]] }; RefIntEqual: PROC [key1, key2: RefTab.Key] RETURNS [BOOL] ~ { RETURN [NARROW[key1, REF INT]^ = NARROW[key2, REF INT]^] }; RefIntHash: PROC [key: RefTab.Key] RETURNS [CARDINAL] ~ { lc: PBasics.LongNumber ~ [int[NARROW[key, REF INT]^]]; RETURN [PBasics16.BITXOR[lc.lo, lc.hi]]}; AnalyzedProcedure: TYPE ~ REF AnalyzedProcedurePrivate; AnalyzedProcedurePrivate: TYPE ~ RECORD [ rctw: RCTWData, resultATI: AnalyzedTypeInfo ]; AnalyzeProcedureTypeStab: PROC[sourceStream: IO.STREAM, bracketEntry: BracketEntry, rctw: RCTWData] RETURNS[AnalyzedTypeInfo] = { f: CHAR ~ sourceStream.GetChar[]; IF f#'f AND f#'F THEN CCE[cirioError, "AnalyzeProcedureTypeStab[not f]"]; {protoResult: AnalyzedTypeInfo ~ AnalyzeType[sourceStream, bracketEntry, rctw]; ap: AnalyzedProcedure ~ NEW[AnalyzedProcedurePrivate _ [rctw, protoResult]]; bti: BasicTypeInfo ~ NEW [BasicTypeInfoPrivate _ [CreateProcIndirect, BitSizeIs32, ap]]; procType: Type ~ Procedures.CreateProcedureType[CCTypes.GetAnyTargetType[rctw.cc], protoResult.directType, rctw.cc, bti]; RETURN[NEW[AnalyzedTypeInfoBody _ [ atiValid: TRUE, atiIsProc: TRUE, directType: procType, rctw: rctw]]]}}; AnalyzeProcedureTypeFileStab: PUBLIC PROC [auxIndex: INT32, wireTables: SGI.WireTables, bracketEntry: BracketEntry, rctw: RCTWData, stab: ObjF.Stab, symTabIndex: CARD] RETURNS[AnalyzedTypeInfo] = { {protoResult: AnalyzedTypeInfo ~ AnalyzeTypeFromFile[auxIndex, wireTables, bracketEntry, rctw, stab, symTabIndex]; ap: AnalyzedProcedure ~ NEW[AnalyzedProcedurePrivate _ [rctw, protoResult]]; bti: BasicTypeInfo ~ NEW [BasicTypeInfoPrivate _ [CreateProcIndirect, BitSizeIs32, ap]]; procType: Type ~ Procedures.CreateProcedureType[CCTypes.GetAnyTargetType[rctw.cc], protoResult.directType, rctw.cc, bti]; RETURN[NEW[AnalyzedTypeInfoBody _ [ atiValid: TRUE, atiIsProc: TRUE, directType: procType, rctw: rctw]]]}}; BitSizeIs32: PROC [bti: BasicTypeInfo, cc: CC, indirectType, targetType: Type] RETURNS [CARD] ~ {RETURN[32]}; ProcIndirectData: TYPE ~ REF ProcIndirectDataPrivate; ProcIndirectDataPrivate: TYPE ~ RECORD [ap: AnalyzedProcedure, directType: Type, mem: Mem]; CreateProcIndirect: PROC[bti: BasicTypeInfo, cc: CC, indirectType, targetType: Type, mem: Mem] RETURNS[Node] ~ { ap: AnalyzedProcedure ~ NARROW[bti.btiData]; pid: ProcIndirectData ~ NEW[ProcIndirectDataPrivate _ [ap, targetType, mem]]; RETURN CedarCode.CreateCedarNode[ProcIndirectOps, indirectType, pid]}; ProcIndirectOps: REF CedarCode.OperationsBody _ NEW[CedarCode.OperationsBody_[ store: ProcStore, load: ProcLoad]]; ProcDirectData: TYPE ~ REF ProcDirectDataPrivate; ProcDirectDataPrivate: TYPE ~ RECORD [ lsh: LSA.LoadStateHandle, pc: CARD, desc: Rope.ROPE _ NIL]; ProcStore: PROC[valType: Type, valNode: Node, indirectType: Type, indirectNode: Node, cc: CC] ~ { CCE[operation, "Can't store into a C procedure location"]}; ProcLoad: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] ~ { pid: ProcIndirectData ~ NARROW[CedarCode.GetDataFromNode[indirectNode]]; rctw: RCTWData ~ pid.ap.rctw; directType: Type ~ pid.directType; pdd: ProcDirectData ~ NEW[ProcDirectDataPrivate _ [rctw.lsh, 0]]; pni: Procedures.ProcedureNodeInfo ~ NEW [Procedures.ProcedureNodeInfoBody _ [ call: CallProc, show: DescribeProc, data: pdd]]; codeStart: BitAddr ~ pid.mem.MemGetStart[]; pdd.pc _ codeStart.BaToPtr[]; RETURN Procedures.CreateProcedureNode[directType, pni]}; CallProc: PROC[args: Node, cc: CC, data: REF ANY] RETURNS[Node] ~ {CCE[unimplemented, "C procedure call not implemented"]}; DescribeProc: PROC[to: IO.STREAM, data: REF ANY, depth, width: INT] ~ { pdd: ProcDirectData ~ NARROW[data]; IF pdd.desc=NIL THEN { lsh: LSA.LoadStateHandle ~ pdd.lsh; bpi: REF LSA.BasicPCInfo ~ LSA.GetBasicPCInfo[lsh, pdd.pc]; IF bpi=NIL THEN pdd.desc _ IO.PutFR["pc=0x%x (not known to dynamic loader)", [cardinal[pdd.pc]] ] ELSE { entryPC: CARD ~ bpi.lsi[text].base + bpi.moduleRelativeBaseAddr + bpi.procedureModuleRelativeBaseAddr; IF entryPC=pdd.pc THEN pdd.desc _ bpi.procedureName ELSE pdd.desc _ IO.PutFR["%g+0x%x", [rope[bpi.procedureName]], [cardinal[pdd.pc-entryPC]] ]; }; }; to.PutRope[pdd.desc]}; AnalyzedNumericTypeStabPrivate: TYPE = REF AnalyzedNumericTypeStabPrivateBody; AnalyzedNumericTypeStabPrivateBody: TYPE = RECORD[ rctw: RCTWData, desc: CNumericTypes.NumericDescriptor, bitSize: CARD]; Analyze: PROC[body: CNumericTypes.NumericDescriptorBody, length: CARD, rctw: RCTWData] RETURNS[AnalyzedTypeInfo] = BEGIN desc: CNumericTypes.NumericDescriptor ~ NEW [CNumericTypes.NumericDescriptorBody _ body]; private: AnalyzedNumericTypeStabPrivate ~ NEW[AnalyzedNumericTypeStabPrivateBody _ [rctw: rctw, desc: desc, bitSize: length]]; bti: BasicTypeInfo ~ NEW [BasicTypeInfoPrivate _ [CreateNumericIndirect, GetNumericBitSize, private]]; type: Type ~ CNumericTypes.CreateNumericType[desc, rctw.cc, bti]; RETURN[NEW[AnalyzedTypeInfoBody _ [ atiValid: TRUE, atiIsProc: FALSE, directType: type, rctw: rctw]]]; END; AnalyzeBitwiseTypeStab: PROC[sourceStream: IO.STREAM, bracketEntry: BracketEntry, rctw: RCTWData] RETURNS[AnalyzedTypeInfo] = BEGIN initialIndex: INT _ sourceStream.GetIndex; byteSizeVal: INT; minVal: INT; maxVal: INT; primaryTag: CNumericTypes.PrimaryTag; char: CHAR _ IO.GetChar[sourceStream]; char _ IO.GetChar[sourceStream]; SELECT char FROM 's => primaryTag _ signed; 'u => primaryTag _ unsigned; ENDCASE => CCE[cirioError, "missing 's or 'u in num type const"]; IF IO.PeekChar[sourceStream] = 'c THEN [] _ IO.GetChar[sourceStream]; byteSizeVal _ GetDecimal[sourceStream]; IF IO.GetChar[sourceStream] # '; THEN CCE[cirioError, "missing ; in num type const"]; minVal _ GetDecimal[sourceStream]; IF IO.GetChar[sourceStream] # '; THEN CCE[cirioError, "missing ; in num type const"]; maxVal _ GetDecimal[sourceStream]; SELECT TRUE FROM byteSizeVal = BYTES[INT32] AND minVal = 0 AND maxVal = BITS[INT32] => RETURN Analyze[[primary: primaryTag, secondary: integer], 32, rctw]; byteSizeVal = BYTES[BYTE] AND minVal = 0 AND maxVal = BITS[BYTE] => RETURN Analyze[[primary: primaryTag, secondary: character], 8, rctw]; byteSizeVal = BYTES[INT16] AND minVal = 0 AND maxVal = BITS[INT16] => RETURN Analyze[[primary: primaryTag, secondary: shortInteger], 16, rctw]; byteSizeVal = BYTES[INT64] AND minVal = 0 AND maxVal = BITS[INT64] => RETURN Analyze[[primary: primaryTag, secondary: longInteger], 64, rctw]; ENDCASE => RETURN[AnalyzedUnknownType[RopeFromStream[sourceStream, initialIndex], rctw]]; END; AnalyzeRealTypeStab: PROC[sourceStream: IO.STREAM, bracketEntry: BracketEntry, rctw: RCTWData] RETURNS[AnalyzedTypeInfo] = BEGIN initialIndex: INT _ sourceStream.GetIndex; tagVal: INT; byteSizeVal: INT; char: CHAR _ IO.GetChar[sourceStream]; tagVal _ GetDecimal[sourceStream]; IF IO.GetChar[sourceStream] # '; THEN CCE[cirioError, "missing ; in num type const"]; byteSizeVal _ GetDecimal[sourceStream]; SELECT byteSizeVal FROM 4 => --This is a single precision floating point RETURN[Analyze[[primary: float], 32, rctw]]; 8 => --This is a double precision floating point RETURN[Analyze[[primary: double], 64, rctw]]; 16 => --This is a double precision floating point RETURN[Analyze[[primary: longDouble], 128, rctw]]; ENDCASE => RETURN[AnalyzedUnknownType[RopeFromStream[sourceStream, initialIndex], rctw]]; END; AnalyzeNumericFileStab: PUBLIC PROC[body: CNumericTypes.NumericDescriptorBody, length: CARD, rctw: RCTWData] RETURNS[RCTW.AnalyzedTypeInfo] = BEGIN desc: CNumericTypes.NumericDescriptor ~ NEW [CNumericTypes.NumericDescriptorBody _ body]; private: AnalyzedNumericTypeStabPrivate ~ NEW[AnalyzedNumericTypeStabPrivateBody _ [rctw: rctw, desc: desc, bitSize: length]]; bti: BasicTypeInfo ~ NEW [BasicTypeInfoPrivate _ [CreateNumericIndirect, GetNumericBitSize, private]]; type: Type ~ CNumericTypes.CreateNumericType[desc, rctw.cc, bti]; RETURN[NEW[AnalyzedTypeInfoBody _ [ atiValid: TRUE, atiIsProc: FALSE, directType: type, rctw: rctw]]]; END; AnalyzeNumericTypeStab: PROC[sourceStream: IO.STREAM, bracketEntry: BracketEntry, rctw: RCTWData] RETURNS[AnalyzedTypeInfo] = BEGIN initialIndex: INT _ sourceStream.GetIndex; minVal: INT; maxVal: INT; ati: RCTW.AnalyzedTypeInfo; char: CHAR _ IO.GetChar[sourceStream]; ati _ AnalyzeTypeDef[sourceStream, bracketEntry, rctw]; IF IO.GetChar[sourceStream] # '; THEN CCE[cirioError, "missing ; in num type const"]; minVal _ GetDecimal[sourceStream]; IF IO.GetChar[sourceStream] # '; THEN CCE[cirioError, "missing ; in num type const"]; maxVal _ GetDecimal[sourceStream]; IF maxVal = 0 THEN BEGIN SELECT minVal FROM 4 => --This is a single precision floating point RETURN[Analyze[[primary: float], 32, rctw]]; 8 => --This is a double precision floating point RETURN[Analyze[[primary: double], 64, rctw]]; ENDCASE => RETURN[AnalyzedUnknownType[RopeFromStream[sourceStream, initialIndex], rctw]]; END ELSE BEGIN SELECT TRUE FROM minVal = INT32.FIRST AND maxVal = INT32.LAST => RETURN Analyze[[primary: signed, secondary: integer], 32, rctw]; minVal = 0 AND maxVal = 127 => RETURN Analyze[[primary: signed, secondary: character], 8, rctw]; minVal = 0 AND maxVal = 255 => RETURN Analyze[[primary: unsigned, secondary: character], 8, rctw]; minVal = FIRST[INT16] AND maxVal = LAST[INT16] => RETURN Analyze[[primary: signed, secondary: shortInteger], 16, rctw]; minVal = 0 AND maxVal = LAST[CARD16] => RETURN Analyze[[primary: unsigned, secondary: shortInteger], 16, rctw]; minVal = 0 AND LOOPHOLE[maxVal, CARD] = LAST[CARD] => RETURN Analyze[[primary: unsigned, secondary: integer], 32, rctw]; ENDCASE => RETURN[AnalyzedUnknownType[RopeFromStream[sourceStream, initialIndex], rctw]]; END END; GetNumericBitSize: PROC[bti: BasicTypeInfo, cc: CC, indirectType, targetType: Type] RETURNS[CARD] = { private: AnalyzedNumericTypeStabPrivate _ NARROW[bti.btiData]; RETURN[private.bitSize]}; CreateNumericIndirect: PROC[bti: BasicTypeInfo, cc: CC, indirectType, targetType: Type, mem: Mem] RETURNS[Node] = { private: AnalyzedNumericTypeStabPrivate _ NARROW[bti.btiData]; nodeData: REF NumericNodeData _ NEW[NumericNodeData _ [private.rctw, private.desc, targetType, mem]]; RETURN[CedarCode.CreateCedarNode[NumericOps, indirectType, nodeData]]}; NumericNodeData: TYPE = RECORD[ rctw: RCTWData, desc: CNumericTypes.NumericDescriptor, targetType: Type, mem: Mem]; NumericOps: REF CedarCode.OperationsBody _ NEW[CedarCode.OperationsBody_[ store: NumericStore, load: NumericLoad]]; NumericStore: PROC[valType: Type, valNode: Node, indirectType: Type, indirectNode: Node, cc: CC] = { nodeData: REF NumericNodeData ~ NARROW[CedarCode.GetDataFromNode[indirectNode]]; mem: Mem ~ nodeData.mem; type: Type ~ CCTypes.GetRTargetType[indirectType, cc]; descriptor: CNumericTypes.NumericDescriptor ~ CNumericTypes.GetDescriptorFromCNumericType[type, cc]; valRep: REF ANY ~ CedarCode.GetNodeRepresentation[valNode, cc]; Bitch: PROC ~ {CCE[operation, "storing non-C numbers into C numeric locations"]}; fieldSize: BitAddr ~ mem.MemGetSize[]; SELECT fieldSize.BaToBits[] FROM 0 => CCE[operation, "storing into 0-bit numeric location"]; 8 => WITH valRep SELECT FROM x: REF CHAR => mem.MemWrite[x^.ORD, 8, zeroBA]; ENDCASE => Bitch[]; 16 => SELECT descriptor.primary FROM signed => WITH valRep SELECT FROM x: REF INTEGER => mem.MemWrite[offset:zeroBA, bitSize:16, bits: IF x^>=0 THEN CARD[x^] ELSE CARD[INT[x^]+65536]]; ENDCASE => Bitch[]; unsigned => WITH valRep SELECT FROM x: REF CARDINAL => mem.MemWrite[offset:zeroBA, bitSize:16, bits:x^]; ENDCASE => Bitch[]; ENDCASE => CCE[cirioError, "unexpected 16-bit descriptor"]; 32 => SELECT descriptor.primary FROM signed =>WITH valRep SELECT FROM x: REF INT => mem.MemWrite[offset:zeroBA, bitSize:32, bits:LOOPHOLE[x^]]; ENDCASE => Bitch[]; unsigned => WITH valRep SELECT FROM x: REF CARD => mem.MemWrite[offset:zeroBA, bitSize:32, bits:x^]; ENDCASE => Bitch[]; float => WITH valRep SELECT FROM x: REF REAL => mem.MemWrite[offset:zeroBA, bitSize:32, bits:LOOPHOLE[x^]]; ENDCASE => Bitch[]; ENDCASE => CCE[cirioError, "unexpected 32-bit descriptor"]; 64 => CCE[unimplemented, "double store"]; ENDCASE => CCE[cirioError, "strange numeric width"]}; NumericLoad: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] ~ { nodeData: REF NumericNodeData ~ NARROW[CedarCode.GetDataFromNode[indirectNode]]; mem: Mem ~ nodeData.mem; type: Type ~ CCTypes.GetRTargetType[indirectType, cc]; descriptor: CNumericTypes.NumericDescriptor ~ CNumericTypes.GetDescriptorFromCNumericType[type, cc]; {ENABLE CirioNubAccess.RemoteAddrFault => GOTO unknownAddress; fieldSize: BitAddr ~ mem.MemGetSize[]; SELECT fieldSize.BaToBits[] FROM 0 => RETURN[LoadFromUnknownIndirect[indirectType, indirectNode, cc]]; 8 => { bits: CARD _ mem.MemRead[offset: zeroBA, bitSize: 8]; char: CHAR _ VAL[BYTE[bits]]; RETURN CNumericTypes.CreateNumericNode[type, NEW[CHAR _ char]]}; 16 => SELECT descriptor.primary FROM signed => { bits: CARD _ mem.MemRead[offset: zeroBA, bitSize: 16]; word: INTEGER _ IF bits <= LAST[INT16] THEN bits ELSE INT[bits] - INT[LAST[CARD16]].SUCC; RETURN CNumericTypes.CreateNumericNode[type, NEW[SIRep _ word]]}; unsigned => { bits: CARD _ mem.MemRead[offset: zeroBA, bitSize: 16]; RETURN CNumericTypes.CreateNumericNode[type, NEW[SCRep _ bits]]}; ENDCASE => CCE[cirioError, "NumericLoad: unrecognized 16-bit primary"]; 32 => { typeClass: CirioTypes.TypeClass _ CCTypes.GetTypeClass[type]; SELECT typeClass FROM $numeric => { SELECT descriptor.primary FROM signed => { bits: CARD _ mem.MemRead[offset: zeroBA, bitSize: 32]; word: INT _ LOOPHOLE[bits]; RETURN CNumericTypes.CreateNumericNode[type, NEW[LIRep _ word]]}; unsigned => { word: CARD _ mem.MemRead[offset: zeroBA, bitSize: 32]; RETURN CNumericTypes.CreateNumericNode[type, NEW[LCRep _ word]]}; float => { bits: CARD _ mem.MemRead[offset: zeroBA, bitSize: 32]; word: REAL _ LOOPHOLE[bits]; RETURN CNumericTypes.CreateNumericNode[type, NEW[REAL _ word]]}; ENDCASE => CCE[cirioError, "NumericLoad: unrecognized 32-bit primary"]; }; ENDCASE => CCE[cirioError, "NumericLoad: unrecognized 32-bit type class"]; }; 64 => RETURN[NumericLoad64BitsIndirect[indirectType, indirectNode, cc]]; ENDCASE => RETURN[NumericLoadBitFieldIndirect[indirectType, indirectNode, cc]]; EXITS unknownAddress => RETURN[LoadFromUnknownIndirect[indirectType, indirectNode, cc]]}}; NumericLoad64BitsIndirect: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = { oneWord: BitAddr ~ CirioTypes.BitsToBa[32]; nodeData: REF NumericNodeData _ NARROW[CedarCode.GetDataFromNode[indirectNode]]; mem: Mem _ nodeData.mem; type: Type _ CCTypes.GetRTargetType[indirectType, cc]; word1: PBasics.Word _ LOOPHOLE[mem.MemRead[offset: zeroBA, bitSize: 32], PBasics.Word]; word2: PBasics.Word _ LOOPHOLE[mem.MemRead[offset: oneWord, bitSize: 32], PBasics.Word]; sign: INT _ LOOPHOLE[PBasics.BITSHIFT[word1, -31], CARD] * -2 + 1; exponent: INT _ LOOPHOLE[PBasics.BITSHIFT[word1, -20], CARD]; mantissa: REAL _ LOOPHOLE[PBasics.BITSHIFT[PBasics.BITOR[PBasics.BITSHIFT[word1, 12], PBasics.BITSHIFT[word2, -20]], -1], CARD] * RealFns.Power[2, -32] *2 + 1; word:REAL _ sign * RealFns.Power[2, exponent - 1023] * mantissa; wordNode: Node _ CNumericTypes.CreateNumericNode[type, NEW[REAL _ word]]; RETURN[wordNode]}; NumericLoadBitFieldIndirect: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = { nodeData: REF NumericNodeData _ NARROW[CedarCode.GetDataFromNode[indirectNode]]; mem: Mem _ nodeData.mem; type: Type _ CCTypes.GetRTargetType[indirectType, cc]; typeClass: CirioTypes.TypeClass _ CCTypes.GetTypeClass[type]; SELECT typeClass FROM $numeric => BEGIN descriptor: CNumericTypes.NumericDescriptor _ CNumericTypes.GetDescriptorFromCNumericType[type, cc]; SELECT descriptor.primary FROM signed => BEGIN SELECT descriptor.secondary FROM integer => BEGIN bits: CARD _ mem.MemRead[offset: zeroBA, bitSize: 32]; word: INT _ LOOPHOLE[bits]; wordNode: Node _ CNumericTypes.CreateNumericNode[type, NEW[LIRep _ word]]; RETURN[wordNode]; END; ENDCASE => CCE[cirioError]; -- descriptor.secondary END; ENDCASE => CCE[cirioError]; -- descriptor.primary END; ENDCASE => CCE[cirioError]; -- typeClass }; LoadFromUnknownIndirect: PROC[indirectType: Type, indirectNode: Node, cc: CC] RETURNS[Node] = BEGIN wordType: Type _ CedarOtherPureTypes.CreateUnknownType[cc, "Unimplemented type"]; wordNode: Node _ CedarOtherPureTypes.CreateIndirectToAnUnknownType[wordType, "Unimplemented type", cc]; RETURN[wordNode]; END; AnalyzeRecordTypeStab: PROC[sourceStream: IO.STREAM, bracketEntry: BracketEntry, rctw: RCTWData] RETURNS[AnalyzedTypeInfo] = { analyzedCTX: AnalyzedCTX; RETURN[AnalyzeCTX[sourceStream, bracketEntry, rctw]]; }; AnalyzeCTX: PROC[sourceStream: IO.STREAM, bracketEntry: BracketEntry, rctw: RCTWData] RETURNS[AnalyzedTypeInfo] = { fieldCount: INT _ 0; fieldNameList: LIST OF Rope.ROPE _ NIL; atiList: LIST OF AnalyzedTypeInfo _ NIL; bitOffsetList: LIST OF INT _ NIL; bitSizeList: LIST OF INT _ NIL; byteSize: INT; lastBitOffset: INT _ -1; -- Assume there are no negative offsets lastBitSize: INT; totalBitSize: CARD; result: AnalyzedCTX; resultATI: AnalyzedTypeInfo; char: CHAR _ IO.GetChar[sourceStream]; byteSize _ GetDecimal[sourceStream]; WHILE NOT IO.EndOf[sourceStream] DO bitSize: INT; bitOffset: INT; ati: AnalyzedTypeInfo; fieldName: Rope.ROPE; IF IO.PeekChar[sourceStream] = '; THEN EXIT; fieldName _ GetTokenRope[sourceStream]; IF IO.GetChar[sourceStream] # ': THEN CCE[cirioError]; ati _ AnalyzeType[sourceStream, bracketEntry, rctw]; IF IO.GetChar[sourceStream] # ', THEN CCE[cirioError]; bitOffset _ GetDecimal[sourceStream]; IF IO.GetChar[sourceStream] # ', THEN CCE[cirioError]; bitSize _ GetDecimal[sourceStream]; IF IO.GetChar[sourceStream] # '; THEN CCE[cirioError]; fieldNameList _ CONS[fieldName, fieldNameList]; atiList _ CONS[ati, atiList]; bitOffsetList _ CONS[bitOffset, bitOffsetList]; bitSizeList _ CONS[bitSize, bitSizeList]; IF bitOffset > lastBitOffset THEN { lastBitOffset _ bitOffset; lastBitSize _ bitSize; }; fieldCount _ fieldCount +1 ENDLOOP; totalBitSize _ lastBitOffset + lastBitSize; result _ NEW[AnalyzedCTXBody[fieldCount]]; result.blockRecord _ FALSE; result.rctw _ rctw; result.bitSize _ CirioTypes.BitsToBa[totalBitSize]; FOR i:INT DECREASING IN [0..fieldCount) DO result[i] _ [ name: fieldNameList.first, fiValid: TRUE, fiIsProc: atiList.first.atiIsProc, fieldDirectType: atiList.first.directType, fieldCase: nodeTimeReadWrite, fieldLoc: NEW[BitStretch _ [CirioTypes.BitsToBa[bitOffsetList.first], CirioTypes.BitsToBa[bitSizeList.first] ]] ]; fieldNameList _ fieldNameList.rest; atiList _ atiList.rest; bitOffsetList _ bitOffsetList.rest; bitSizeList _ bitSizeList.rest; ENDLOOP; result.recordType _ Records.CreateRecordType[CTXRecordTypeProcs, rctw.cc, result]; resultATI _ NEW[AnalyzedTypeInfoBody _ [atiValid: TRUE, atiIsProc: FALSE, directType: result.recordType, rctw: rctw]]; RETURN[resultATI]}; RopeFromStringTable: PROC [table: SGI.StringTable, offset: CARD] RETURNS [name: Rope.ROPE _ NIL] = TRUSTED { c: CHAR; DO c _ LOOPHOLE[table[offset]]; IF (c = VAL[0]) THEN EXIT; name _ name.Concat[Convert.RopeFromChar[from: c, quote: FALSE]]; offset _ offset + 1; ENDLOOP; RETURN }; AnalyzeStructTypeFileStab: PROC[auxIndex: INT32, fdIndex: INT32, wireTables: SGI.WireTables, bracketEntry: BracketEntry, rctw: RCTWData, stab: ObjF.Stab, symTabIndex: CARD] RETURNS[AnalyzedTypeInfo] = TRUSTED { fieldCount: INT _ 0; fieldNameList: LIST OF Rope.ROPE _ NIL; atiList: LIST OF AnalyzedTypeInfo _ NIL; bitOffsetList: LIST OF INT _ NIL; bitSizeList: LIST OF INT _ NIL; lastBitOffset: INT _ -1; -- Assume there are no negative offsets lastBitSize: INT; totalBitSize: CARD; result: AnalyzedCTX; resultATI: AnalyzedTypeInfo; auxSyms: SGI.AuxSymTable _ wireTables.auxSyms; symBaseIndex, symIndex, currentIndex, memberIndex: CARD; stringBaseIndex: CARD; endStruct: CARD; stringOffset: CARD; bitSize: INT32; bitOffset: INT32 _ 0; stringTable: SGI.StringTable _ wireTables.localStrings; relIndex: SGI.WireRelIndexBody; relFileIndex: INT32; relFileOffset: INT32; IF auxSyms[auxIndex+1].symIndex = -1 THEN { resultATI _ NEW[AnalyzedTypeInfoBody _ [atiValid: TRUE, atiIsProc: FALSE, directType: AnalyzeNumericFileStab[[primary: signed, secondary: integer], 0, rctw].directType, rctw: rctw]]; RETURN[resultATI] }; relIndex _ auxSyms[auxIndex+1].relIndex; IF relIndex.relFileDescrIndex = 0FFFH THEN { relFileIndex _ auxSyms[auxIndex+2].relFileIndex; } ELSE { relFileIndex _ relIndex.relFileDescrIndex; }; relFileOffset _ wireTables.fileDescr[fdIndex].rfdBase + relFileIndex; IF relFileOffset # 0 THEN fdIndex _ wireTables.relFiles[relFileOffset]; symIndex _ relIndex.index; symBaseIndex _ wireTables.fileDescr[fdIndex].isymBase; stringBaseIndex _ wireTables.fileDescr[fdIndex].issBase; currentIndex _ symIndex + symBaseIndex; endStruct _ wireTables.localSyms[currentIndex].index + symBaseIndex - 1; memberIndex _ currentIndex + 1; WHILE memberIndex < endStruct DO ati: AnalyzedTypeInfo; fieldName: Rope.ROPE; stringOffset _ wireTables.localSyms[memberIndex].symStringIndex; fieldName _ RopeFromStringTable[stringTable, stringBaseIndex+stringOffset]; auxIndex _ wireTables.fileDescr[fdIndex].iauxBase + wireTables.localSyms[memberIndex].index; ati _ AnalyzeTypeFromFile[auxIndex, wireTables, bracketEntry, rctw, stab, memberIndex]; bitSize _ SGI.CalcSymbolSize[memberIndex, fdIndex, wireTables, FALSE]; bitOffset _ wireTables.localSyms[memberIndex].value; fieldNameList _ CONS[fieldName, fieldNameList]; atiList _ CONS[ati, atiList]; bitOffsetList _ CONS[bitOffset, bitOffsetList]; bitSizeList _ CONS[bitSize, bitSizeList]; IF bitOffset > lastBitOffset THEN { lastBitOffset _ bitOffset; lastBitSize _ bitSize; }; fieldCount _ fieldCount +1; memberIndex _ memberIndex +1 ENDLOOP; totalBitSize _ lastBitOffset + lastBitSize; result _ NEW[AnalyzedCTXBody[fieldCount]]; result.blockRecord _ FALSE; result.rctw _ rctw; result.bitSize _ CirioTypes.BitsToBa[totalBitSize]; FOR i:INT DECREASING IN [0..fieldCount) DO result[i] _ [ name: fieldNameList.first, fiValid: TRUE, fiIsProc: atiList.first.atiIsProc, fieldDirectType: atiList.first.directType, fieldCase: nodeTimeReadWrite, fieldLoc: NEW[BitStretch _ [CirioTypes.BitsToBa[bitOffsetList.first], CirioTypes.BitsToBa[bitSizeList.first] ]] ]; fieldNameList _ fieldNameList.rest; atiList _ atiList.rest; bitOffsetList _ bitOffsetList.rest; bitSizeList _ bitSizeList.rest; ENDLOOP; result.recordType _ Records.CreateRecordType[CTXRecordTypeProcs, rctw.cc, result]; resultATI _ NEW[AnalyzedTypeInfoBody _ [atiValid: TRUE, atiIsProc: FALSE, directType: result.recordType, rctw: rctw]]; RETURN[resultATI]}; CTXRecordTypeProcs: PUBLIC REF Records.RecordTypeProcs _ NEW[Records.RecordTypeProcs_[ createIndirectNode: CTXRecordsCreateIndirectNode, getBitSize: CTXRecordsGetBitSize, getPaint: CTXRecordsGetPaint, comparePaint: CTXRecordsComparePaint, nFields: CTXRecordsNFields, fieldIndexToName: CTXRecordsFieldIndexToName, nameToFieldIndex: CTXRecordsNameToFieldIndex, fieldIndexToType: CTXRecordsFieldIndexToType, fieldIndexToFieldCase: CTXRecordsFieldIndexToFieldCase, fieldIndexToCompileTimeConstantValue: CTXRecordsFieldIndexToTypeTimeConstant]]; CTXRecordsGetPaint: PROC[data: REF ANY] RETURNS[REF ANY] = { ac: AnalyzedCTX _ NARROW[data]; RETURN[ac]}; CTXRecordsComparePaint: PROC[data: REF ANY, otherPaint: REF ANY] RETURNS[BOOLEAN] = BEGIN ac: AnalyzedCTX _ NARROW[data]; IF otherPaint = NIL THEN CCE[cirioError]; -- we shouldn't be called in this situation WITH otherPaint SELECT FROM other: AnalyzedCTX => RETURN[ac = other]; ENDCASE => RETURN[FALSE]; END; CTXRecordsNFields: PROC[data: REF ANY] RETURNS[INT] = BEGIN ac: AnalyzedCTX _ NARROW[data]; RETURN[ac.nFields]; END; CTXRecordsFieldIndexToName: PROC[index: INT, data: REF ANY] RETURNS[Rope.ROPE] = BEGIN ac: AnalyzedCTX _ NARROW[data]; RETURN[ac.fields[index].name]; END; CTXRecordsNameToFieldIndex: PROC[name: Rope.ROPE, data: REF ANY] RETURNS[INT] = BEGIN ac: AnalyzedCTX _ NARROW[data]; FOR I: INT IN [0..ac.nFields) DO IF Rope.Equal[name, ac.fields[I].name] THEN RETURN[I]; ENDLOOP; RETURN[-1]; END; CTXRecordsFieldIndexToType: PROC[index: INT, cc: CC, data: REF ANY] RETURNS [Type] ~ { ac: AnalyzedCTX ~ NARROW[data]; IF NOT ac.fields[index].fiValid THEN { directType: Type ~ IF ac.blockRecord THEN NARROW[ac.fields[index].idStab, DotOListing].directType ELSE ac.fields[index].directType; ac.fields[index].fieldDirectType _ directType; ac.fields[index].fieldCase _ IF ac.blockRecord AND ac.fields[index].fiIsProc THEN nodeTimeConstant ELSE nodeTimeReadWrite; ac.fields[index].fiValid _ TRUE; IF ac.blockRecord THEN ac.fields[index].fieldLoc _ VarLocFromDotOListings[ac.fields[index].idStab, ac.rctw]; }; RETURN [ac.fields[index].fieldDirectType]}; CTXRecordsFieldIndexToFieldCase: PROC[index: INT, cc: CC, data: REF ANY] RETURNS[Records.FieldCase] ~ { ac: AnalyzedCTX ~ NARROW[data]; [] _ CTXRecordsFieldIndexToType[index, cc, data]; --ensure ac.fields[index].fiValid RETURN [ac.fields[index].fieldCase]}; CTXRecordsFieldIndexToTypeTimeConstant: PROC[index: INT, cc: CC, data: REF ANY] RETURNS[Node] ~ { ac: AnalyzedCTX ~ NARROW[data]; IF NOT ac.blockRecord THEN CCE[cirioError, "asking for type-time constant from a non-block C record"]; WITH ac[index].idStab SELECT FROM x: DotOEnumr => RETURN CNumericTypes.CreateNumericNode[x.type, NEW[LIRep _ x.value]]; x: DotOListing => CCE[cirioError, IO.PutFR1["asking for field %g as type-time constant", [integer[index]] ]]; ENDCASE => ERROR; }; CTXRecordsGetBitSize: PROC[indirectType: Type, cc: CC, data: REF ANY] RETURNS[CARD] = { ac: AnalyzedCTX ~ NARROW[data]; RETURN [ac.bitSize.BaToBits[]]}; CTXRecordsCreateIndirectNode: PROC [cc: CC, data: REF ANY, indirectType, targetType: Type, mem: CirioTypes.Mem] RETURNS [Node] ~ { ac: AnalyzedCTX ~ NARROW[data]; nodeData: REF RecordNodeData ~ NEW [RecordNodeData _ [ac, targetType, mem]]; RETURN[Records.CreateIndirectRecordNode[targetType, RecordProcs, nodeData, ac.rctw.cc]]}; RecordNodeData: TYPE = RECORD[ private: AnalyzedCTX, targetType: Type, mem: Mem]; RecordProcs: REF Records.IndirectRecordNodeProcs _ NEW[Records.IndirectRecordNodeProcs_[ selectField: RecordSelectField, fieldIndexToNodeTimeConstantValue: RecordIndexToNTConstant]]; RecordSelectField: PROC[index: INT, indirectFieldType: Type, data: REF ANY, cc: CC] RETURNS[Node] = { nodeData: REF RecordNodeData ~ NARROW[data]; ac: AnalyzedCTX ~ nodeData.private; rctw: RCTWData ~ ac.rctw; fieldType: Type; subMem: Mem; IF ac.blockRecord THEN { varLoc: VarLoc _ NARROW[ac.fields[index].fieldLoc]; IF NOT ac.fields[index].fiValid THEN CCE[cirioError, "select block record field with NOT fiValid"]; subMem _ RMTWPrivate.SelectVarLoc[rctw.nub, nodeData.mem, varLoc]; RETURN CCTypes.CreateIndirectNode[indirectFieldType, subMem, cc]} ELSE { fieldLoc: REF BitStretch _ NARROW[ac.fields[index].fieldLoc]; IF NOT ac.fields[index].fiValid THEN CCE[cirioError, "trying to select an unanalyzed field"]; IF fieldLoc = NIL THEN RETURN UnimplementedTypeNode[indirectFieldType, rctw, IO.PutFR1["ordinary record field (index %g) with unknown location", [integer[index]]], TRUE]; subMem _ nodeData.mem.MemSubfield[fieldLoc^]; RETURN CCTypes.CreateIndirectNode[indirectFieldType, subMem, cc]}}; RecordIndexToNTConstant: PROC[index: INT, fieldType: Type, data: REF ANY, cc: CC] RETURNS[Node] ~ { nodeData: REF RecordNodeData ~ NARROW[data]; ac: AnalyzedCTX ~ nodeData.private; rctw: RCTWData ~ ac.rctw; fieldLoc: REF ANY ~ ac.fields[index].fieldLoc; IF NOT ac.fields[index].fiValid THEN CCE[cirioError, "trying to construct the node-time constant value for an unanalyzed field"]; IF ac.fields[index].fieldCase#nodeTimeConstant THEN CCE[cirioError, ac.fields[index].name.Concat[" is not a node-time constant"]]; WITH fieldLoc SELECT FROM vl: VarLoc => { codeMem: Mem ~ RMTWPrivate.SelectVarLoc[rctw.nub, nodeData.mem, vl]; pcBa: BitAddr ~ codeMem.MemGetStart[]; pc: CARD ~ pcBa.BaToPtr[]; pdd: ProcDirectData ~ NEW[ProcDirectDataPrivate _ [rctw.lsh, pc]]; pni: Procedures.ProcedureNodeInfo ~ NEW [Procedures.ProcedureNodeInfoBody _ [ call: CallProc, show: DescribeProc, data: pdd]]; RETURN Procedures.CreateProcedureNode[fieldType, pni]}; ENDCASE => CCE[cirioError, "RecordIndexToNTConstant[fieldLoc not a Varloc"]}; END.. ��ê�� RCTWOrdinaries.mesa Copyright Ó 1989, 1990, 1991, 1992 by Xerox Corporation. All rights reserved. Hopcroft, August 18, 1989 6:25:15 pm PDT Last changed by Theimer on October 9, 1989 2:06:28 pm PDT Sturgis, January 2, 1990 12:21:25 pm PST Last tweaked by Mike Spreitzer on April 10, 1992 6:19 pm PDT Philip James, February 24, 1992 10:22 am PST Laurie Horton, June 24, 1992 6:47 pm PDT Chauser, June 1, 1992 1:10 pm PDT Katsuyuki Komatsu December 17, 1992 5:59 pm PST Jas, January 5, 1993 12:04 pm PST If this is a definition, then check if already defined. If so, then ERROR. Otherwise, Create a DeferringType that is undefined. Do the analysis (recursively). Set the DeferringType to the result of the analysis. Return the DeferringType. If a typeref but not a definition, then check if defined. If not, create an UnknownType. Return the UnknownType. Otherwise, Return the Type. If not a typeref, then Do the analysis (recursively). Return the Type. access the current symbol entry and the file descriptor index Record Types Unknown Types GetDecimal: PROC [stream: IO.STREAM] RETURNS [INT] ~ { token: Rope.ROPE _ ""; value: INT _ -1; base: CARD _ 10; parsed: BOOL _ FALSE; char: CHAR _ IO.PeekChar[stream]; IF char = '- OR char = '+ THEN { token _ Rope.FromChar[IO.GetChar[stream]]; char _ IO.PeekChar[stream]; }; IF char = '0 THEN { [] _ IO.GetChar[stream]; token _ Rope.Concat[token, "0"]; base _ 10; parsed _ FALSE; IF NOT IO.EndOf[stream] THEN { parsed _ TRUE; char _ IO.PeekChar[stream]; IF char = 'x THEN { [] _ IO.GetChar[stream]; WHILE NOT IO.EndOf[stream] AND IsHexDigit[IO.PeekChar[stream]] DO token _ Rope.Concat[token, Rope.FromChar[IO.GetChar[stream]]]; ENDLOOP; base _ 16; parsed _ TRUE; }; }; }; IF NOT parsed THEN { WHILE NOT IO.EndOf[stream] AND IsDigit[IO.PeekChar[stream]] DO token _ Rope.Concat[token, Rope.FromChar[IO.GetChar[stream]]]; ENDLOOP; base _ 10; parsed _ TRUE; }; IF parsed THEN { value _ Convert.IntFromRope[token, base ! Convert.Error => { value _ LOOPHOLE[(Convert.CardFromRope[token, base]), INT]; CONTINUE; }; ]; }; RETURN[value]; }; Create a DeferringType as a place holder and put it in the hash table Create a DeferringType as a place holder and put it in the hash table the new auxIndex is the stTypedef symbols` auxIndex Deferring Types Unknown Types PointerTypes we nest a block to handle unknown address, allowing nodeData to be visible PointerAdd: PROC [node: Node, offsetNode: Node, info: CPointerTypes.PointerNodeInfo, cc: CC] RETURNS [Node] ~ { nodeData: REF PointerNodeData _ NARROW[CedarCode.GetDataFromNode[node]]; bfs: BitFieldSchema _ nodeData.nsData.bfs; mem: Mem _ nodeData.mem; addr: CirioNubAccess.RemoteAddress _ bfs.procs.followPointer[bfs, nodeData.mem]; offset: INT _ NARROW[CedarCode.GetDataFromNode[offsetNode], REF INT]^; bitSize: CARD _ nodeData.nsData.private.analyzedTargetTypeStab.bitSize[ nodeData.nsData.private.analyzedTargetTypeStab, cc]; normalizedAddr: CirioNubAccess.RemoteAddress _ RemoteAddressNormalize[addr]; newAddr: CirioNubAccess.RemoteAddress _ [nub: normalizedAddr.nub, byteAddress: normalizedAddr.byteAddress + (offset * bitSize) / 8, bitOffset: normalizedAddr.bitOffset + (offset * bitSize) MOD 8, nil: FALSE, valid: normalizedAddr.valid]; newMem: Mem _ CreateRawMem[newAddr]; newNodeData: REF PointerNodeData _ NEW[PointerNodeData _ [nsData: nodeData.nsData, mem: newMem]]; RETURN[CPointerTypes.CreatePointerNode[nodeData.nsData.private.type, info, cc]]; }; PointerSubtract: PROC [leftNode: Node, rightNode: Node, cc: CC] RETURNS [Node] ~ { leftNodeData: REF PointerNodeData _ NARROW[CedarCode.GetDataFromNode[leftNode]]; leftrctw: RCTWData _ leftNodeData.nsData.private.rctw; leftBfs: BitFieldSchema _ leftNodeData.nsData.bfs; leftMem: Mem _ leftNodeData.mem; leftAddr: CirioNubAccess.RemoteAddress _ leftBfs.procs.followPointer[leftBfs, leftMem]; bitSize: CARD _ leftNodeData.nsData.private.analyzedTargetTypeStab.bitSize[ leftNodeData.nsData.private.analyzedTargetTypeStab, leftrctw]; rightNodeData: REF PointerNodeData _ NARROW[CedarCode.GetDataFromNode[rightNode]]; rightBfs: BitFieldSchema _ rightNodeData.nsData.bfs; rightMem: Mem _ rightNodeData.mem; rightAddr: CirioNubAccess.RemoteAddress _ rightBfs.procs.followPointer[rightBfs, rightMem]; difference: INT _ RemoteAddressByteDifference[leftAddr, rightAddr, bitSize]; newType: Type _ CNumericTypes.CreateNumericType[NEW[CNumericTypes.NumericDescriptorBody _ [primary: signed, secondary: integer]], cc]; RETURN[CNumericTypes.CreateNumericNode[newType, NEW[INT _ difference]]]; }; PointerCompare: PROC [leftNode: Node, rightNode: Node, op: CCTypes.Operator, cc: CC] RETURNS [Node] ~ { leftNodeData: REF PointerNodeData _ NARROW[CedarCode.GetDataFromNode[leftNode]]; leftrctw: RCTWData _ leftNodeData.nsData.private.rctw; leftBfs: BitFieldSchema _ leftNodeData.nsData.bfs; leftMem: Mem _ leftNodeData.mem; leftAddr: CirioNubAccess.RemoteAddress _ leftBfs.procs.followPointer[leftBfs, leftMem]; bitSize: CARD _ leftNodeData.nsData.private.analyzedTargetTypeStab.bitSize[ leftNodeData.nsData.private.analyzedTargetTypeStab, leftrctw]; rightNodeData: REF PointerNodeData _ NARROW[CedarCode.GetDataFromNode[rightNode]]; rightBfs: BitFieldSchema _ rightNodeData.nsData.bfs; rightMem: Mem _ rightNodeData.mem; rightAddr: CirioNubAccess.RemoteAddress _ rightBfs.procs.followPointer[rightBfs, rightMem]; returnValue: INT _ RemoteAddressCompare[leftAddr, rightAddr, op]; newType: Type _ CNumericTypes.CreateNumericType[NEW[CNumericTypes.NumericDescriptorBody _ [primary: signed, secondary: integer]], cc]; RETURN[CNumericTypes.CreateNumericNode[newType, NEW[INT _ returnValue]]]; }; Should be inline eventually $le => IntFromBool[difference <= 0], $lt => IntFromBool[difference < 0], $eq => IntFromBool[difference = 0], $ne => IntFromBool[difference # 0], $gt => IntFromBool[difference > 0], $ge => IntFromBool[difference >= 0], Enumerated Types This is an enumerated type This is an enumerated type set the current index to the first stMember C Procedures C Numeric Types This is a bitwise type (SunOS 5.0) This is a floating point type (SunOS 5.0) This is a subrange or a floating point type This is a floating point type This is a subrange type Note: subrange types need to be fixed to correctly compute the actual bit size of the representation. Currently they use a value in the descriptor that describes the supertype. Theimer: Need to eventually change the 32 to a more general constant defn. Record Types As a special dispensation, in order to handle empty argument/result records, this procedure will accept ctxh=NIL to produce an effectively empty record. Note: Assuming that no C records have variants. now we can build the result Note: Assuming that no C records have variants. there was a pointer to an undefined structure that never got dereferenced. just return a void the index field is the reference to one symbol past the stEnd symbol for the structure set the current index to the first stMember the new auxIndex is the stMember symbols` auxIndex now we can build the result we shall use the address of the record data as the paint. Note that we are trusting the assorted hash table mechanisms to prevent the construction of more than one RecordData for a given record type. We could speed this up by using atoms here is where we finally compute the field type, after we haved exited from the local type construction routine for the record as a whole. should never happen, this field should have been filled in when someone inspected the type of the field. should never happen, this field should have been filled in when someone inspected the type of the field. Ê?��•NewlineDelimiter – "cedar" style™�code™K™NK™(K™9K™(K™<K™,K™(K™!K™/K™!—K˜�šÏk ˜ Kšœœ™˜¦Kšœ œJ˜YKšœœJ˜cKšœ˜Kšœœ)˜=Kšœ˜KšœœN˜aKšœœ}˜Kšœœ$˜1Kšœ˜Kšœ˜Kšœœ0˜EK˜K˜Kšœœœœ˜2Kšœ œœ˜K˜Kšœ˜Kšœœ˜'Kšœœ ˜Kšœœb˜oK˜Kšœœœ˜/K˜Kšœ˜Kšœ˜—K˜�KšÐlnœœ˜KšœŠœ@œK˜¢Kšœ˜KšœœœœÏnœœ˜9K˜�Kšœœ˜&Kšœœ&œœ˜NKšœœœ˜Kšœœœ˜Kšœœœ˜Kšœœœ˜K˜�šŸœœœœœ.œœ˜…™�™7K™šœ ™ Kšœ)™)K™K™4™K™�———™9™K™—™ K™—K™�—™K™K™—K™�Kšœœœ˜'šœœ˜ šœœœ˜šœœœÏc˜IKšœœ3˜:—šœ ˜%Kšœ?˜?—šœ *˜7Kšœ?˜?—šœ $˜1Kšœ?˜?—šœ +˜8Kšœ<˜<—šœ -˜:Kšœ?˜?—šœ œ ,˜FKšœ>˜>—šœ ˜)KšœB˜B—šœ œ ˜4KšœA˜A—šœ +˜8KšœA˜A—šœ˜ KšœL ˜i————˜�š œœœœ œd˜ˆK˜�—Kšœ˜—Kšœ˜K˜�—šŸœœœœhœœœœœ˜ÓKšœ1œ˜:Jšœ˜Jšœ.˜.Jšœ œ˜Jšœ œ "˜<Jšœ œ˜J˜J˜�J™=šœ ˜J˜Jšœ œ'˜9Jšœ9˜9J˜—š˜J˜Jšœ œ%˜7Jšœ˜J˜—J˜�šœ˜J˜JšœZ˜ZJšœœ!œ œ"˜cJ˜J˜�—J˜&J˜�J˜J˜�šœ˜šœ ˜J˜Jšœ[˜[Jšœ˜—šœ ˜$Jšœ˜Jšœ]˜]Jšœ˜—šœ ˜Jšœ˜Jšœ_˜_Jšœ˜—šœ ˜"Jšœ˜Jšœa˜aJšœ˜—Jšœ ˜Jšœ ˜šœ ˜Jšœ˜JšœZ˜ZJšœ˜—Jšœ ˜Jšœ ˜šœ ˜Jšœ˜Jšœ\˜\Jšœ˜—Jšœ ˜šœ ˜ Jšœ˜JšœE˜EJšœ˜—šœ ˜Jšœ ˜ JšœY˜YJšœ˜J˜�—J˜�J™Jšœ ˜#šœ ˜!Jšœ˜Jšœr˜rJ˜—šœ ˜Jšœ˜Jšœv˜vJ˜—šœ )˜9Jšœ˜Jšœo˜oJ˜—Jšœœ "˜8Jšœ œ ˜(J˜�J™ šœ ˜Jšœ6œc˜›—šœ ˜&Jšœ6œg˜Ÿ—šœ ˜-Jšœ6œn˜¦—Jšœœ ˜5šœ ˜$Jšœ6œe˜—šœ ˜$Jšœ6œe˜—šœ ˜Jšœ6œ_˜——J˜�Jšœœ˜J˜�—Jšœœ!œ œ"˜c—Kšœ˜˜�K˜�—š Ðbnœœœœœ˜&Kšœœœœ˜&—K˜�š ¡ œœœœœ˜)Kšœœœœœœœœ˜L—K˜�šŸœœœœ œœœ˜RKšœ œ˜%Kš œœœœœ˜!Kšœ˜šœœœ˜%Kšœ)˜)—Kšœ˜Kšœ˜Kšœ˜!K˜K˜�—šŸ œœ œœœœ˜6Kšœœ˜šœœœ˜,šœœœœ ˜)K˜�Kšœœ˜Kšœœœ˜!K˜�Kšœœ˜š˜Kšœœ˜*Kšœœ˜Kšœ˜—šœ˜Kš˜Kšœœ˜K˜ Kšœœ˜šœœ˜Kšœœ˜šœœ˜(Kšœ)œ˜>—Kšœ˜Kšœ ˜&Kš˜—Kšœ˜—šœ œ˜%Kšœ)œ˜>—Kšœ˜Kšœ˜#š˜Kšœœ˜/—K˜—š˜Kšœœ˜—K˜—K˜K˜�—šŸ œœ œœœœ™6Kšœœ™Kšœœ™Kšœœ™Kšœœœ™Kšœœœ™!šœœœ™ Kšœœ™*Kšœœ™Kšœ™—šœœ™Kšœœ™K™ K™ Kšœ œ™šœœœœ™Kšœ œ™Kšœœ™šœœ™Kšœœ™šœœœœœ™AKšœ)œ™>—Kšœ™K™ Kšœ œ™Kšœ™—K™—Kšœ™—šœœœ™šœœœœ œ™>Kšœ)œ™>—Kšœ™K™ Kšœ œ™K™—K™�šœœ™šœ*™*šœ™Kšœœ&œ™;Kšœ™ Kšœ™—Kšœ™—Kšœ™—Kšœ™K™—K˜�KšŸœœœ˜"š¡œœœœœœœœ˜‡Kšœ œ.˜;Kšœœœ˜!Kšœœ˜š œœœœœœ ˜Zšœœ˜(Kš œœœœ ˜LK˜�K™EKšœÏbœ˜K˜�šœ˜Kšœ‡˜‡—K˜�šœœ˜šœ&˜*Kšœ?˜BK˜�——Kšœœ/˜FK˜�šœ˜Kšœu˜u—K˜�šœœAœ˜MKšœœœ+˜NKšœœ ˜&š˜Kšœ,œ˜4KšœI˜IK˜�šœ˜Kšœ‚˜‚—K˜�KšœF˜FKšœ ˜ š˜š˜Kšœ7˜7—šœ˜KšœJ˜JKšœ˜—šœ˜Kšœ„˜„KšœF˜FKšœL˜L———K˜—Kšœ˜—šœ ˜Kšœœ˜Kšœœœ˜Kšœ7˜7Kšœœ ˜K˜�Jšœœœ*˜;J˜�šœ˜šœœ˜Kšœn˜n—K˜šœ˜Kšœr˜r—J˜—Kšœ˜——Kš œœœœ œX˜|Kšœ˜Kšœ˜—K™�š¡Ÿœœœœ,œœ)œœœœ˜àK˜�Kšœœœ˜!Kšœœ˜Kšœ œ˜Jšœ.˜.Jšœ&œ˜+Jšœœ˜Kšœœ˜(Jšœ7˜7Jšœœ˜Jšœ˜Jšœœ˜Jšœœ˜K˜�K™�Jšœ(˜(šœ$˜*J˜Jšœ0˜0J˜—š˜J˜Jšœ*˜*Jšœ˜—JšœF˜Fšœ˜Jšœ-˜-—J˜�Jšœ˜Jšœ6˜6Kšœ8˜8Kšœ'˜'J˜�JšœA˜AJ˜�KšœJ˜JK˜�K™Ešœ¢œ˜K˜�—šœ˜Kšœ‡˜‡K˜�—šœ8˜8K˜�—K™3šœ]˜]J˜�—šœe˜eK˜�—šœ˜Kšœu˜uK˜�—šœœAœ˜MKšœœœ+˜NKšœœ ˜&š˜Kšœ,œ˜4KšœI˜IK˜�šœ˜Kšœ‚˜‚—K˜�KšœF˜FKšœ ˜ š˜š˜Kšœ7˜7—šœ˜KšœJ˜JKšœ˜—šœ˜Kšœ˜K˜�KšœH˜HKšœJ˜J———K˜K˜�—Kš œœœœ œX˜|Kšœ˜Kšœ˜—K™�K™�K™˜�š¡ œœœœ˜HKšœB˜BKšœ%œ#œ œ*˜‹Kšœ˜K˜K˜�——K˜�K™ ˜�š Ÿœœœœ.œ˜‡Kšœœ˜!Kšœœ˜$Kšœ œ˜Kšœ œ˜Kšœœœ˜Kšœ œ œœ1˜PKšœ˜KšœœœC˜cKšœœ*˜2Kšœ˜KšœD˜DKšœ œœ˜#Kšœ!˜'š Ÿœœœœœ˜0Kš œœœœœ˜<—K˜�—š Ÿœœœœœ˜dšœ%œ˜AKšœ œ œ˜!Kšœ;œj˜§Kšœ ˜ —Kšœ˜K˜—K˜�š Ÿœœ7œœœ ˜yKšœO˜OKšœ œœV˜mKšœO˜U——K˜�K™™�Kšœœœ˜@šœœœ˜+Kšœ˜Kšœ˜Kšœœ˜K˜Kšœ˜—K˜�š Ÿœœœœ/œ˜€Kšœœœœœœœœœ\˜ºKš œœœ/œœ˜bšœ œœ˜šœœ˜'K˜ Kšœœœl˜€—Kšœœ˜ —KšœL˜LKšœœœ> k˜½šœ$œ˜EK˜Kšœ ˜ Kšœ)˜)—KšœœN˜fKšœ]˜]Kšœœ!œ œ2˜s—K˜�šŸœœœœiœœ˜ÃKšœo˜ošœ$œ˜EK˜Kšœ ˜ Kšœ˜—KšœœN˜fKšœ]˜]Kšœœ!œ œ2˜s—K˜�K˜�š Ÿœœœ"œœ˜eKšœ#œ˜7Kšœ˜—K˜�šŸœœœ,œ˜uKšœ#œ˜7Kšœ œœ#˜FKšœA˜G—K˜�šœœœ˜Kšœ!˜!K˜ —K˜�šŸ œœœ˜IKšœ˜Kšœ˜—K˜�Kšœœœ˜/šœœœ˜%Kšœœ˜Kšœ œ˜ Kšœœ˜Kšœ˜—K˜�š¡œœKœ˜dKšœ œœ*˜PKšœ'˜'Kšœ˜Kšœ œ˜*Kšœ œœ&˜6šœ œ˜šœ*˜*Kšœœ˜+Kšœ&˜&—Kšœœ<˜J—Kšœ˜—K˜�Kšœœ˜K˜�š¡œœ-œœ ˜SKšœ œœ*˜PK˜'Kšœ˜Kšœ œ˜*KšœJ™Jšœœ˜ Kšœ"œ˜6Kšœœ˜—Kšœ(˜(Kšœœ˜)Kšœ œ#˜1KšœŠ˜ŠKšœ<˜<KšœE˜EKšœœ˜Kšœ$˜$Kšœ˜Kšœ$˜$šœ v˜xKšœœœ˜Kšœ:˜:Kšœ5˜5—Kšœ3œœ œœœ˜ƒšœœ&˜0Kšœ#˜#KšœV˜VKšœ˜K˜Kšœ˜KšœœK˜T—KšœI˜OKšœ˜š˜KšœœNœ˜n—šœ˜K˜�——šŸ œœIœœ˜kKšœœ0˜9—K˜�šŸœœ'œœ˜Ršœ%œ˜4Kšœ&œ1˜]KšœœI˜W——K˜�šŸ œœWœœ˜€Kšœœ˜%Kšœœ˜"Kšœ"˜"šœœœ'œ˜WKšœœœ˜Kš œœœœœ˜#Kšœœœœ˜KšœœD˜R—Kšœœ˜Kšœœœ(˜@KšœœœA˜eKšœ˜Kšœ œœ œ˜3KšœH˜HKšœe˜ešœ(œ&˜QKšœ'˜'Kšœ)˜)Kšœ˜K˜Kšœ˜Kšœœœ*˜UK˜—KšœH˜N—K˜�šŸœœ=œœ˜gšœ)œ%œ˜]Kšœ*˜*KšœœC˜Q—Kšœœ˜-šœ*œ&œ˜_Kšœ*˜*KšœœD˜R—Kšœœ˜/šœœœ˜K˜"K˜"K˜#K˜"K˜#K˜"Kšœœ œJ˜g—Kšœ0œ?œ˜wKšœ*œœœœœ˜S—K˜�šŸ œœMœ™oKšœ œœ"™HKšœ*™*Kšœ™KšœP™PK™FKšœ|™|KšœL™LKšœï™ïK™$Kšœ œQ™aKšœP™PK™—K˜�šŸœœ+œ™RKšœœœ&™PKšœ6™6Kšœ2™2Kšœ ™ KšœW™WKšœŠ™ŠKšœœœ'™RKšœ4™4Kšœ"™"Kšœ[™[KšœM™MKšœ†™†KšœH™HK™K™�—šŸœœAœ™gKšœœœ&™PKšœ6™6Kšœ2™2Kšœ ™ KšœW™WKšœŠ™ŠKšœœœ'™RKšœ4™4Kšœ"™"Kšœ[™[KšœA™AKšœ†™†KšœI™IK™K™�K™�—šŸœœ)œ#˜ošœ+œ ˜>KšœU˜U—š˜Kšœfœ,˜•—Kšœ˜K˜K˜�—š¡œœTœœœœ˜£Kšœ&˜&Kšœ'˜'šœœœ˜'Kšœ ˜—Kšœ'˜'Kšœ)˜)šœœ˜7Kšœ ˜—Kšœœf˜pK˜—K˜�Kš Ÿœœœœœ˜-™šœ˜ Kšœ˜ —š˜Kšœ˜ —K˜—K˜�š¡œœaœœ˜ŒKšœœ˜Kšœ œ˜KšœE˜Ešœ˜šœ˜Kšœœ˜/Kšœ˜K˜#K˜#Kšœ"œ˜1K˜K™$Kšœ#™#K™#K™#K™#K™$Kšœœ˜——K˜—K˜�—K™˜�š ¡œœœœ/œ˜…K™K˜&K˜Kšœ(˜(K˜LKšœœœœ˜#Kšœ˜Kšœœœ˜&šœœœœœœ˜GKšœœ˜Kšœ œ˜/Kšœœ1˜Jšœœ˜ Kšœœ>˜F—K˜!Kš œœœœ œu˜–Kš œ œœœœ ˜ZKšœœ;œœ˜LKšœ&œœ˜@Kšœœœœ˜GKšœ˜—Kšœœ|˜†Kšœ œK˜XKšœœN˜WK˜;šœœœ˜4šœœ˜Kšœ˜Kšœœ˜—Kšœ˜—šœœ˜#Kšœ œ œ˜!Kšœ˜Jšœ ˜ —K˜—K˜�š¡œœœœiœœœ˜ÙK™K˜&K˜Kšœ(˜(K˜LKšœœœœ˜#Kšœ˜Jšœ&œ˜+Jšœ.˜.Jšœ œ˜Jšœœ˜$Jšœ7˜7Jšœ˜Jšœœ˜Jšœœ˜J™�K™�Jšœ(˜(šœ$˜*J˜Jšœ0˜0J˜—š˜J˜Jšœ*˜*Jšœ˜—JšœF˜Fšœ˜Jšœ-˜-—J˜�Jšœ˜Jšœ6˜6Kšœ8˜8J˜�Kšœ'˜'Jšœ8˜8K˜�K™+Kšœ ˜ J˜�šœœ˜!Kšœœ˜Kšœ œ˜Kšœ˜K˜�KšœA˜Ašœ1˜1J˜�—KšœH˜HK˜�Kšœœ1˜<K˜�Kš œœœœ œu˜–Kš œ œœœœ ˜ZKšœœ;œœ˜LKšœ&œœ˜@K˜�Kšœ˜Kšœ˜—Kšœœ|˜†Kšœ œK˜XKšœœN˜WK˜;šœœœ˜4šœœ˜Kšœ˜Kšœœ˜—Kšœ˜—šœœ˜#Kšœ œ œ˜!Kšœ˜Jšœ ˜ —K˜—K˜�K˜�š¡œœœœ˜=Kšœœœœœœœ˜8K˜—K˜�š¡ œœœœ˜9Kšœœœœ˜6Kšœœ˜)—K˜�K˜�—™K™�Kšœœœ˜7šœœœ˜)Kšœ˜Kšœ˜K˜—K˜�š Ÿœœœœ/œ˜‚Kšœœ˜!Kšœœœœ0˜IKšœO˜OKšœœ1˜LKšœœ@˜XKšœy˜yšœœ˜#Kšœ œ œ˜ K˜K˜——K˜�š Ÿœœœiœœ˜ÆK˜�K˜�Kšœr˜rKšœœ1˜LKšœœ@˜XKšœy˜yšœœ˜#Kšœ œ œ˜ K˜K˜——K˜�š Ÿœœœ"œœ˜]Kšœœ˜—K˜�Kšœœœ˜5Kšœœœ5˜[K˜�šŸœœœ,œ ˜pKšœœ˜,Kšœœ2˜MKšœ@˜F—K˜�šŸœœœ˜NK˜K˜—K˜�Kšœœœ˜1šœœœ˜&Kšœœ˜Kšœœ˜ Kšœœœ˜—K˜�šŸ œœKœ˜aKšœ8˜;—K˜�šŸœœ-œœ ˜PKšœœ*˜HKšœ˜Kšœ"˜"Kšœœ(˜Ašœ$œ&˜MK˜0—Kšœ+˜+Kšœ˜Kšœ2˜8—K˜�šŸœœœœœœ˜?Kšœœ5˜;—K˜�šŸœœœœœœœ˜GKšœœ˜#šœ œœ˜Kšœœ˜#Kšœœœœ˜;KšœœœœD˜ašœ˜Kšœ œY˜fšœ˜Kšœ˜!KšœœJ˜\—K˜—K˜—Kšœ˜—K˜�—™K™�Kšœ œœ$˜Nšœ$œœ˜2Kšœ˜Kšœ&˜&Kšœ œ˜—K™�šŸœœ4œœ˜rKš˜Kšœ(œ.˜YKšœ*œQ˜~KšœœN˜fK˜Ašœœ˜#Kšœ œ œ˜!Kšœ˜Kšœ˜—Kšœ˜K˜�—š Ÿœœœœ/œ˜~Kš˜Kšœ ™"Kšœœ˜*Kšœ œ˜Kšœœ˜Kšœœ˜Kšœ%˜%Kšœœœ˜&Kšœœ˜ šœ˜Kšœ˜Kšœ˜Kšœœ3˜A—Kšœœœœ˜EKšœ'˜'Kšœœœœ,˜UK˜"Kšœœœœ,˜UK˜"šœœ˜š œœœœœ œœ˜FKšœ>˜D—š œœœœœ œœ˜DKšœ?˜E—š œœœœœ œœ˜FKšœC˜I—š œœœœœ œœ˜FKšœB˜H—šœ˜ KšœH˜N——Kšœ˜K˜�—š Ÿœœœœ/œ˜{Kš˜Kšœ ™)Kšœœ˜*Kšœœ˜Kšœ œ˜Kšœœœ˜&K˜"Kšœœœœ,˜UKšœ'˜'šœ ˜šœ +˜0Kšœ&˜,—šœ +˜0Kšœ'˜-—šœ +˜1Kšœ,˜2—šœ˜ KšœH˜N——Kšœ˜—K˜�šŸœœœ4œœœ˜Kš˜Kšœ(œ.˜YKšœ*œQ˜~KšœœN˜fK˜Ašœœ˜#Kšœ œ œ˜!Kšœ˜Kšœ˜—Kšœ˜J˜�—š Ÿœœœœ/œ˜~Kš˜K™+Kšœœ˜*Kšœœ˜Kšœœ˜Kšœœ˜Kšœœœ˜&Kšœ7˜7Kšœœœœ,˜UK˜"Kšœœœœ,˜UK˜"šœ˜Kš˜K™šœ˜šœ +˜0Kšœ&˜,—šœ +˜0Kšœ'˜-—šœ˜ KšœH˜N——Kš˜—š˜š˜K™šœœ˜šœ œœœ œœ˜0Kšœ:˜@—šœœ˜ Kšœ;˜A—šœœ˜ Kšœ=˜C—šœ œœœ œœ˜3Kšœ?˜E—šœœ œœ˜)KšœA˜G—šœœœ œœœ˜6Kšœ<˜B—šœ˜ KšœH˜N———Kš˜—Kšœ˜—K™�š Ÿœœœ"œœ˜eKšœ*œ˜>Kšœ˜—K™�šŸœœœ,œ ˜sKšœ*œ˜>Kšœ œœB˜eKšœA˜G—K˜�šœœœ˜Kšœ˜Kšœ&˜&K˜K˜ —K˜�šŸ œœœ˜IKšœ˜Kšœ˜—K˜�šŸœœKœ˜dKšœ œœ*˜PKšœ˜Kšœ6˜6Kšœd˜dKšœœœ0˜?KšŸœœœ?˜QK˜&šœ˜ Kšœœ3˜;šœœœ˜Kšœœœœ ˜/Kšœ˜—šœœ˜$šœ œœ˜!Kšœœœ2œœœœœœ ˜qKšœ˜—šœœœ˜#Kšœœœ5˜DKšœ˜—Kšœœ-˜;—šœœ˜$šœ œœ˜ Kšœœœ1œ˜IKšœ˜—šœœœ˜#Kšœœœ5˜@Kšœ˜—šœ œœ˜ Kšœœœ1œ˜JKšœ˜—Kšœœ-˜;—Kšœœ ˜)Kšœœ'˜5——˜�K™±—šŸœœ-œœ ˜SKšœ œœ*˜PKšœ˜Kšœ6˜6Kšœd˜dKšœœ#œ˜>K˜&šœ˜ Kšœœ:˜Ešœ˜Kšœœ+˜5Kšœœœœ˜Kšœ'œœ˜@—šœœ˜$šœ˜Kšœœ,˜6Kšœœœ œœœœœ œœœœ˜YKšœ'œ˜A—šœ ˜ Kšœœ,˜6Kšœ'œ˜A—Kšœœ9˜G—šœ˜Kšœ=˜=šœ˜˜ šœ˜šœ˜Kšœœ,˜6Kšœœœ˜Kšœ'œ˜A—šœ ˜ Kšœœ,˜6Kšœ'œ˜A—šœ ˜ Kšœœ,˜6Kšœœœ˜Kšœ'œœ˜@—Kšœœ9˜G—Kšœ˜—Kšœœ<˜J—K˜—Kšœœ<˜HKšœœ>˜O—Kšœœ<˜Z—K˜�š¡œœ-œœ ˜aK˜+Kšœ œœ*˜PKšœ˜Kšœ6˜6Kšœœ9˜WKšœœ:˜XKš œœœ œœ˜BKš œ œœ œœ˜=Kšœ œœ œ œ œœœ!˜ŸKšœœ7˜@K˜�Kšœ7œœ ˜IKšœ˜—K˜�š¡œœ-œœ ˜cKšœ œœ*˜PKšœ˜Kšœ6˜6Kšœ=˜=šœ˜˜Kš˜Kšœd˜dšœ˜šœ ˜ Kš˜šœ˜ šœ˜Kš˜šœœ,˜6K™J—Kšœœœ˜Kšœ7œ˜JKšœ˜Kšœ˜—Kšœœ ˜4—Kšœ˜—Kšœœ ˜2—Kšœ˜—Kšœœ ˜)—Kšœ˜—K˜�š¡œœ-œœ˜]Kš˜K˜QK˜hKšœ˜Kšœ˜——K˜�K˜�K˜�™K˜�K˜�š Ÿœœœœ.œ˜~Kšœ˜Kšœ/˜5Kšœ˜—K˜�Kšœmœ(™˜š Ÿ œœœœ.œ˜sK™/Kšœœ˜Kš œœœœœ˜'Kšœ œœœ˜(Kš œœœœœ˜!Kš œ œœœœ˜Kšœ œ˜Kšœœ '˜AKšœ œ˜Kšœœ˜Kšœ˜Kšœ˜K˜�Kšœœœ˜&K˜$šœœœ˜#Kšœ œ˜ Kšœœ˜Kšœ˜Kšœœ˜Kšœœœœ˜-K˜'Kšœœœœ ˜6Kšœ4˜4Kšœœœœ ˜6K˜%Kšœœœœ ˜6K˜#Kšœœœœ ˜6Kšœœ˜/Kšœ œ˜Kšœœ˜/Kšœœ˜)šœœ˜#K˜K˜Kšœ˜—K˜Kšœ˜—K˜�K˜+K˜�K™K™�Kšœ œ˜*Kšœœ˜Kšœ˜Kšœ3˜3š œœ œœ˜*šœ ˜ Kšœ˜Kšœ œ˜Kšœ"˜"Kšœ*˜*Kšœ˜Kšœ œb˜oKšœ˜—K˜#K˜K˜#K˜Kšœ˜—KšœR˜RKšœœ#œ œ.˜vKšœ ˜—K˜�šŸœœ"œ˜@Jšœ œœ˜!—Jš˜˜Jšœœ˜—˜�š˜Jšœœ˜šœœ˜Jšœ˜—Jšœ8œ˜@Jšœ˜Jšœ˜——˜�Jš˜—J˜J˜�šŸœœœœhœœœ˜ÒK™/Kšœœ˜Kš œœœœœ˜'Kšœ œœœ˜(Kš œœœœœ˜!Kš œ œœœœ˜Kšœœ '˜AKšœ œ˜Kšœœ˜Kšœ˜Kšœ˜Jšœ.˜.Jšœ3œ˜8Jšœœ˜Jšœœ˜Jšœœ˜Kšœ œ˜Kšœœ˜Jšœ7˜7Jšœ˜Kšœœ˜Jšœœ˜J˜�J˜�šœ#œ˜*K˜K™JK™Kšœœ#œ œn˜¶Kšœ˜Kšœ˜K˜�—Jšœ(˜(šœ$˜*J˜Jšœ0˜0J˜—š˜J˜Jšœ*˜*Jšœ˜—JšœF˜Fšœ˜Jšœ-˜-—J˜�Jšœ˜Jšœ6˜6Kšœ8˜8Kšœ'˜'K™�K™VšœH˜HJ˜�—K˜�K™+Kšœ˜K˜�šœ˜ Kšœ˜Kšœœ˜K˜�Kšœ@˜@KšœK˜KK™�K™2Jšœ\˜\KšœW˜WKšœ?œ˜FKšœ4˜4K˜�Kšœœ˜/Kšœ œ˜Kšœœ˜/Kšœœ˜)šœœ˜#K˜K˜Kšœ˜—K˜Kšœ˜Kšœ˜—K˜�K˜+K˜�K™K™�Kšœ œ˜*Kšœœ˜Kšœ˜Kšœ3˜3š œœ œœ˜*šœ ˜ Kšœ˜Kšœ œ˜Kšœ"˜"Kšœ*˜*Kšœ˜Kšœ œb˜oKšœ˜—K˜#K˜K˜#K˜Kšœ˜—KšœR˜RKšœœ#œ œ.˜vKšœ ˜—K˜�K˜�šŸœœœœ˜VKšœ1˜1Kšœ!˜!Kšœ˜Kšœ%˜%Kšœ˜Kšœ-˜-Kšœ-˜-Kšœ-˜-Kšœ7˜7KšœO˜O—K˜�K™ÈšŸœœœœœœœ˜<Kšœœ˜Kšœ˜—K˜�šŸœœœœœœœœ˜SKš˜Kšœœ˜Kš œœœœ +˜Ušœœ˜Kšœœ ˜)Kšœœœ˜—Kšœ˜—K˜�šŸœœœœœœ˜5Kš˜Kšœœ˜Kšœ ˜Kšœ˜—K˜�šŸœœœœœœœ˜PKš˜Kšœœ˜Kšœ˜Kšœ˜—˜�K™%—šŸœœœœœœœ˜OKš˜Kšœœ˜š œŸœœœ˜ Kšœ%œœ˜6Kšœ˜—Kšœ˜Kšœ˜—K˜�šŸœœœœœœœ˜VKšœœ˜šœœœ˜&K™Ššœœ˜$Kšœœ1˜<Kšœ˜!—Kšœ.˜.Kš œœœœœ˜zKšœœ˜ KšœœV˜lKšœ˜—Kšœ%˜+—K˜�šŸœœœœœœœ˜gKšœœ˜Kšœ2 !˜SKšœ˜%—K™�šŸ&œœœœœœœ ˜aKšœœ˜KšœœœœH˜fšœœ˜!Kšœœ)œ˜UKšœœ œI˜mKšœœ˜—K˜—K˜�šŸœœœœœœœ˜WKšœœ˜Jšœ˜ —K˜�šŸœœœœœ7œ˜‚Kšœœ˜Kšœ œœ*˜LKšœS˜Y—K˜�šœœœ˜Kšœ˜K˜K˜ —K˜�šŸœœ#œ"˜XKšœ˜Kšœ=˜=—K˜�šŸœœœ!œœœœ ˜eKšœ œœ˜,Kšœ#˜#Kšœ˜Kšœ˜Kšœ˜šœœ˜Kšœœ˜3šœœœœ;˜cKšœh™h—KšœB˜BKšœ;˜A—šœ˜Kšœ œœ˜=šœœœœ5˜]Kšœh™h—Kšœœœœ0œUœ˜ªK˜-Kšœ=˜C——K˜�šŸœœœœœœœ ˜cKšœ œœ˜,Kšœ#˜#Kšœ˜Kšœ œœ˜.KšœœœœY˜Kšœ-œœK˜‚šœ œ˜˜KšœD˜DKšœ&˜&Kšœœ˜Kšœœ)˜Bšœ$œ&˜MK˜0—Kšœ1˜7—Kšœœ?˜M——K˜�—K™�Kšœ˜J˜�J˜�—�…—����è†��Er�