DIRECTORY CCTypes USING[CCError, CCErrorCase, CreateIndirectNode, GetBitSize, GetIndirectType, GetTargetTypeOfIndirect, GetTypeClass, PrintType], CedarOtherPureTypes USING[CreateIndirectToAnUnknownType, CreateUnknownType], CirioMemory, CirioNubAccess USING[Handle, RemoteAddress, LookupSymEntryByName, SymEntry], CirioTypes, DeferringTypes USING [UndertypeStar], Frames USING[CreateIndirectFrameNode, CreateIndirectFrameType, CreateIndirectGlobalFrameNode, CreateIndirectGlobalFrameType, IndirectFrameData, IndirectFrameTypeData, IndirectGlobalFrameData, IndirectGlobalFrameTypeData], IO USING[EndOf, EndOfStream, GetChar, PeekChar, PutFR, PutFR1, RIS, RopeFromROS, ROS, STREAM], ObjectFiles USING[BracketNest, BracketPair, CGrammar, CGrammarOfStab, DescribeModule, GenSymbolStabs, MakeUnknownVarLoc, Module, Stab, VarLocFromStab], ObjectFilesPrivate, RCTW, Records USING[CreateIndirectRecordNode, CreateRecordType, IndirectRecordNodeProcs, RecordTypeProcs], RefTab USING[Fetch, Key, Ref, Store], RMTWPrivate, Rope USING[Cat, Concat, Find, FromChar, IsEmpty, ROPE, Substr], SymTab USING [Create, Fetch, Insert, Key, Pairs, Ref, Replace, Store, Val], SystemInterface, SGI; RCTWFrames: CEDAR PROGRAM IMPORTS CCTypes, CedarOtherPureTypes, CirioMemory, CirioNubAccess, DeferringTypes, Frames, IO, ObjectFiles, RCTW, Records, RefTab, RMTWPrivate, Rope, SymTab, SystemInterface EXPORTS RCTW = BEGIN OPEN ObjF:ObjectFiles, RCTW; ROPE: TYPE ~ Rope.ROPE; RopeList: TYPE ~ LIST OF ROPE; CCError: ERROR[case: CCTypes.CCErrorCase, msg: ROPE _ NIL] _ CCTypes.CCError; Parsed: TYPE = REF ParsedBody; ParsedBody: PUBLIC TYPE = ObjectFilesPrivate.ParsedBody; Module: TYPE = REF ModuleBody; ModuleBody: PUBLIC TYPE = ObjectFilesPrivate.ModuleBody; CreateZeroLengthRecordType: PROC[cc: CC] RETURNS[Type] = {RETURN[Records.CreateRecordType[ZeroLengthRecordTypeProcs, cc, NIL]]}; ZeroLengthRecordTypeProcs: REF Records.RecordTypeProcs _ NEW[Records.RecordTypeProcs_[ getPaint: ZeroLengthRecordGetPaint, comparePaint: ZeroLengthRecordComparePaint, nFields: ZeroLengthRecordnFields, fieldIndexToName: ZeroLengthRecordFieldIndexToName, nameToFieldIndex: ZeroLengthRecordNameToFieldIndex, fieldIndexToType: ZeroLengthRecordFieldIndexToType]]; ZeroLengthRecordGetPaint: PROC[data: REF ANY] RETURNS[REF ANY] = {RETURN[NIL]}; ZeroLengthRecordComparePaint: PROC[data: REF ANY, otherPaint: REF ANY] RETURNS[BOOLEAN] = {ERROR}; ZeroLengthRecordnFields: PROC[data: REF ANY] RETURNS[INT] = {RETURN[0]}; ZeroLengthRecordFieldIndexToName: PROC[index: INT, data: REF ANY] RETURNS[ROPE] = {ERROR}; ZeroLengthRecordNameToFieldIndex: PROC[name: ROPE, data: REF ANY] RETURNS[INT] = {RETURN[-1]}; ZeroLengthRecordFieldIndexToType: PROC[index: INT, cc: CC, data: REF ANY] RETURNS[Type] = {ERROR}; CreateZeroLengthRecordNode: PROC[indirectRecordType: Type, cc: CC] RETURNS[Node] = BEGIN RETURN[Records.CreateIndirectRecordNode[CCTypes.GetTargetTypeOfIndirect[indirectRecordType], ZeroLengthRecordNodeProcs, NIL, cc]]; END; ZeroLengthRecordNodeProcs: REF Records.IndirectRecordNodeProcs _ NEW[Records.IndirectRecordNodeProcs _ [ selectField: NIL]]; CreateArgsRecordType: PROC [rctw: RCTWData] RETURNS [type: Type] ~ { bracketPair:ObjF.BracketPair _ rctw.bracketNest.rest.first; type _ CreateBlockRecordType[ArgumentListFromRCTW[rctw], bracketPair, rctw]; type _ CCTypes.GetIndirectType[type]; RETURN}; CreateLocalsRecordType: PROC [bracketPair: ObjF.BracketPair, rctw: RCTWData, procTop: BOOL] RETURNS [type: Type] ~ { locals: RopeList ~ LocalsListFromBracketPair[bracketPair, rctw, procTop]; type _ CreateBlockRecordType[locals, bracketPair, rctw]; type _ CCTypes.GetIndirectType[type]; RETURN}; CreateBlockRecordType: PROC [argumentList: RopeList, bracketPair: ObjF.BracketPair, rctw: RCTWData] RETURNS [type: Type] ~ { numberOfArguments: INT _ RopeListLength[argumentList]; abc: AnalyzedCTX; index: INT; abc _ NEW[AnalyzedCTXBody[numberOfArguments]]; index _ 0; FOR remainingArguments: RopeList _ argumentList, remainingArguments.rest WHILE remainingArguments # NIL DO dotOListings: DotOListings _ DotOListingsFromRope[remainingArguments.first, rctw, bracketPair]; abc[index].name _ remainingArguments.first; abc[index].idStab _ dotOListings; SELECT dotOListings.kind FROM ordinary => abc[index].fiValid _ FALSE; enumerator => {abc[index].fiValid _ TRUE; abc[index].fieldCase _ typeTimeConstant; abc[index].fieldLoc _ abc[index].fieldDirectType _ NIL}; ENDCASE => ERROR; index _ index + 1 ENDLOOP; abc.blockRecord _ TRUE; abc.bitSize _ CirioTypes.unspecdBA; abc.rctw _ rctw; abc.recordType _ Records.CreateRecordType[CTXRecordTypeProcs, rctw.cc, abc]; RETURN[abc.recordType]}; IsDigit: PROC [c:CHAR] RETURNS [BOOL] = INLINE { RETURN [c IN ['0 .. '9]] }; GetTokenRope: PUBLIC PROC [stream: IO.STREAM] RETURNS [ROPE] ~ { IsNonDigit: PROC [c:CHAR] RETURNS [BOOL] = INLINE { RETURN [c IN ['a .. 'z] OR c IN ['A .. 'Z] OR c='_ OR c = '-] }; IsAlphaNum: PROC [c:CHAR] RETURNS [BOOL] = INLINE { RETURN [c IN ['0 .. '9] OR c IN ['a .. 'z] OR c IN ['A .. 'Z] OR c='_ OR c = '-] }; token: ROPE _ NIL; IF NOT IO.EndOf[stream] AND IsNonDigit[IO.PeekChar[stream]] THEN { token _ Rope.FromChar[IO.GetChar[stream]]; WHILE NOT IO.EndOf[stream] AND IsAlphaNum[IO.PeekChar[stream]] DO token _ Rope.Concat[token, Rope.FromChar[IO.GetChar[stream]]]; ENDLOOP}; RETURN[token]}; DotOListingsFromRope: PROC [symbol: ROPE, rctw: RCTWData, bracketPair: ObjF.BracketPair] RETURNS [DotOListings] ~ { bracketEntry: BracketEntry _ GetBracketEntry[bracketPair, rctw]; dotOListings: DotOListings _ NARROW[SymTab.Fetch[bracketEntry.symbolHashTable, symbol].val]; IF dotOListings = NIL THEN CCError[cirioError, Rope.Concat["no .o listings for ", symbol]]; RETURN [dotOListings]}; GetBracketEntry: PROC [bracketPair: ObjF.BracketPair, rctw: RCTWData] RETURNS [bracketEntry: BracketEntry] = BEGIN ProcessStab:PROC [stab: ObjF.Stab] RETURNS [BOOLEAN] = { ParseStab[stab, rctw, bracketEntry]; RETURN [FALSE]; }; bracketEntry _ NARROW[RefTab.Fetch[rctw.bracketHashTable, bracketPair].val]; IF bracketEntry = NIL THEN BEGIN bracketEntry _ NEW[BracketEntryBody]; bracketEntry.symbolHashTable _ SymTab.Create[]; bracketEntry.typeNameHashTable _ SymTab.Create[]; IF NOT RefTab.Store[rctw.bracketHashTable, bracketPair, bracketEntry] THEN CCError[cirioError]; ObjF.GenSymbolStabs[bracketPair, ProcessStab]; END; RETURN[bracketEntry] END; -- of GetBracketEntry GetSymbol: PROC [sourceStream: IO.STREAM] RETURNS [symbol: ROPE] ~ { WHILE IO.PeekChar[sourceStream] # ': DO symbol _ Rope.Concat[symbol, Rope.FromChar[IO.GetChar[sourceStream]]]; ENDLOOP; RETURN[symbol] }; CCE: ERROR[case: CCTypes.CCErrorCase, msg: Rope.ROPE _ NIL] _ CCTypes.CCError; FmtType: PROC [type: Type, printDepth: INT, printWidth: INT, cc: CC, oc: Type _ NIL] RETURNS [ans: ROPE] = { ENABLE CCE => {ans _ "??"; CONTINUE}; buf1: IO.STREAM ~ IO.ROS[]; CCTypes.PrintType[buf1, type, printDepth, printWidth, cc, oc]; RETURN [buf1.RopeFromROS]}; DebugStabParsing: BOOLEAN _ FALSE; ParseStab: PROC [stab: ObjF.Stab, rctw: RCTWData, bracketEntry: BracketEntry] ~ { Bitch: PROC [why: ROPE] ~ {CCError[cirioError, IO.PutFR["%g in stab (X: %g, string: \"%q\") in %g", [rope[why]], [cardinal[stab.stabX]], [rope[stab.rope]], [rope[ObjF.DescribeModule[rctw.module]]] ]]}; Define: PROC [name: ROPE, l: ordinary DotOGlorp] ~ { ls: DotOListings _ NARROW[bracketEntry.symbolHashTable.Fetch[name].val]; IF ls#NIL THEN WITH ls SELECT FROM x: DotOEnumr => CCError[cirioError, IO.PutFR["enumerator (%g=%g) has same name as a non-enumerator (stabX=%g, string=%g) in %g", [rope[name]], [integer[x.value]], [cardinal[stab.stabX]], [rope[stab.rope]], [rope[ObjF.DescribeModule[rctw.module]]] ]]; x: DotOListing => IF (x.directType # l.directType) THEN { SystemInterface.ShowReport[IO.PutFR["New type (%g) different from other one (%g) in stab (X: %g, string: \"%q\") in %g", [rope[FmtType[l.directType, 2,10, rctw.cc]]], [rope[FmtType[x.directType, 2,10, rctw.cc]]], [cardinal[stab.stabX]], [rope[stab.rope]], [rope[ObjF.DescribeModule[rctw.module]]] ], $normal]; RETURN}; ENDCASE => ERROR; l.rest _ ls; ls _ NEW [DotOGlorp[ordinary] _ l]; [] _ bracketEntry.symbolHashTable.Store[name, ls]; IF DebugStabParsing THEN SystemInterface.ShowReport[Rope.Cat["Defining symbol ", name, " in ", ObjectFiles.DescribeModule[rctw.module]], $urgent]; RETURN}; ParseStabFromRope: PROC [stab: ObjF.Stab] ~ { SELECT stab.stabType FROM LSym, GSym, PSym, STSym, LCSym, RSym, Fun => { sourceStream: IO.STREAM _ IO.RIS[stab.rope]; symbol: ROPE _ GetSymbol[sourceStream]; symbolDescriptor: CHAR; noDescriptor: BOOLEAN _ FALSE; IF IO.GetChar[sourceStream] # ': THEN Bitch["no colon after symbol"]; symbolDescriptor _ IO.PeekChar[sourceStream ! IO.EndOfStream => Bitch["nothing after colon"]]; SELECT symbolDescriptor FROM 't, 'T => { type: Type; IF IO.GetChar[sourceStream] # symbolDescriptor THEN ERROR; type _ AnalyzeType[sourceStream, bracketEntry, rctw].directType; IF Rope.IsEmpty[symbol] THEN { symbol _ Rope.Concat["unnamed", Rope.Substr[stab.rope, 3, Rope.Find[stab.rope, ")"] - 3]]; }; IF NOT bracketEntry.typeNameHashTable.Insert[symbol, type] THEN { oldVal: Type ~ NARROW[bracketEntry.typeNameHashTable.Fetch[symbol].val]; IF NOT (DeferringTypes.UndertypeStar[type] = DeferringTypes.UndertypeStar[oldVal]) THEN { [] _ bracketEntry.typeNameHashTable.Replace[symbol, type]; SystemInterface.ShowReport[Rope.Cat["REDEFINING symbol ", symbol, " in ", ObjectFiles.DescribeModule[rctw.module]], $urgent]; }; }; }; 'F, 'f, 'G, 'S, 'V, 'p, 'P, 'r => { IF symbolDescriptor#'f AND symbolDescriptor#'F AND IO.GetChar[sourceStream]#symbolDescriptor THEN ERROR; Define[symbol, [NIL, ordinary[ descriptor: Rope.FromChar[symbolDescriptor], directType: AnalyzeType[sourceStream, bracketEntry, rctw].directType, stab: stab]]]; }; '( => {--This must be either a local variable declaration or a register variable declaration Define[symbol, [NIL, ordinary[ descriptor: Rope.FromChar[symbolDescriptor], directType: AnalyzeType[sourceStream, bracketEntry, rctw].directType, stab: stab]]]; }; ENDCASE => { IF IsDigit[symbolDescriptor] OR symbolDescriptor = '- THEN { Define[symbol, [NIL, ordinary[ descriptor: Rope.FromChar[symbolDescriptor], directType: AnalyzeType[sourceStream, bracketEntry, rctw].directType, stab: stab]]]; } ELSE Bitch["unrecognized descriptor"]; } } ENDCASE => {} -- We do not parse these types of stabs }; ParseStabFromFile: PROC [stab: ObjF.Stab] = TRUSTED { DefineFileStab: PROC [name: ROPE, l: ordinary DotOGlorp] = TRUSTED { ls: DotOListings _ NARROW[bracketEntry.symbolHashTable.Fetch[name].val]; l.rest _ ls; ls _ NEW [DotOGlorp[ordinary] _ l]; [] _ bracketEntry.symbolHashTable.Store[name, ls]; RETURN }; ParseTypeFromFile: PROC [wireTables: SGI.WireTables] = TRUSTED { sourceStream: IO.STREAM _ IO.RIS[stab.rope]; symbol: ROPE _ GetSymbol[sourceStream]; auxIndex: INT32; auxSyms: SGI.AuxSymTable _ wireTables.auxSyms; typeInfo: SGI.WireTypeInfoBody; basicType: CARD _ 0; type: Type _ NIL; thisSymAuxIndex: INT32; maxQualifier: CARD = 256; numQualifiers: INT32 _ 0; qualifier: ARRAY [0..maxQualifier) OF BYTE; -- for now just make big enough to handle an outrageous number of qualifiers, CHANGE ME! thisSym: SGI.WireSTEntry; fdIndex: INT32; IF stab.extRef THEN { thisSym _ LOOPHOLE[@wireTables.extSyms[stab.stabX].sym]; fdIndex _ wireTables.extSyms[stab.stabX].fileDescrIndex; } ELSE { thisSym _ LOOPHOLE[@wireTables.localSyms[stab.stabX]]; fdIndex _ stab.fdIndex; }; thisSymAuxIndex _ auxIndex _ wireTables.fileDescr[fdIndex].iauxBase + thisSym.index; SELECT stab.stabType FROM LSym, GSym, PSym, STSym, LCSym, RSym, Fun => { IF stab.stabType = Fun THEN { thisSymAuxIndex _ auxIndex + 1; }; typeInfo _ auxSyms[auxIndex].typeInfo; basicType _ typeInfo.basicType; IF (basicType = SGI.BTNil) THEN RETURN; DO typeInfo _ auxSyms[auxIndex].typeInfo; auxIndex _ auxIndex + 1; IF (typeInfo.typeQual0 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] _ typeInfo.typeQual0; numQualifiers _ numQualifiers + 1; IF (typeInfo.typeQual1 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] _ typeInfo.typeQual1; numQualifiers _ numQualifiers + 1; IF (typeInfo.typeQual2 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] _ typeInfo.typeQual2; numQualifiers _ numQualifiers + 1; IF (typeInfo.typeQual3 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] _ typeInfo.typeQual3; numQualifiers _ numQualifiers + 1; IF (typeInfo.typeQual4 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] _ typeInfo.typeQual4; numQualifiers _ numQualifiers + 1; IF (typeInfo.typeQual5 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] _ typeInfo.typeQual5; numQualifiers _ numQualifiers + 1; IF (numQualifiers > maxQualifier) THEN ERROR; IF (LOOPHOLE[typeInfo.continued,CARD] = 0) THEN EXIT; ENDLOOP; IF numQualifiers # 0 THEN { i,low,high,bitWidth: INT32; FOR i IN [0..numQualifiers) DO SELECT qualifier[i] FROM SGI.TQNil => NULL; -- do nuthin, we should never get this SGI.TQPtr => NULL; -- we have a pointer SGI.TQProc => NULL; -- we have a function SGI.TQVol => NULL; -- volatile is pretty irrelevant SGI.TQArray => { auxIndex _ auxIndex + 2; low _ LOOPHOLE[auxSyms[auxIndex].lowIndex]; auxIndex _ auxIndex + 1; high _ LOOPHOLE[auxSyms[auxIndex].highIndex]; auxIndex _ auxIndex + 1; bitWidth _ LOOPHOLE[auxSyms[auxIndex].bitWidth]; auxIndex _ auxIndex + 1; } ENDCASE => NULL; ENDLOOP; SELECT qualifier[i] FROM SGI.TQPtr => -- we have a pointer { DefineFileStab[symbol, [NIL, ordinary[descriptor:Rope.FromChar['z], directType: AnalyzePointerTypeFileStab[thisSymAuxIndex, wireTables, bracketEntry, rctw, stab, stab.stabX].directType, stab: stab]]]; }; SGI.TQProc => -- we have a function returning { DefineFileStab[symbol, [NIL, ordinary[descriptor:Rope.FromChar['z], directType: AnalyzeProcedureTypeFileStab[thisSymAuxIndex, wireTables, bracketEntry, rctw, stab, stab.stabX].directType, stab: stab]]]; }; SGI.TQVol => -- volatile is pretty irrelevant { DefineFileStab[symbol, [NIL, ordinary[descriptor:Rope.FromChar['z], directType: AnalyzeTypeFromFile[thisSymAuxIndex, wireTables, bracketEntry, rctw, stab, stab.stabX].directType, stab: stab]]]; }; SGI.TQArray => NULL; ENDCASE => NULL; } ELSE { DefineFileStab[symbol, [NIL, ordinary[descriptor:Rope.FromChar['z], directType: AnalyzeTypeFromFile[thisSymAuxIndex, wireTables, bracketEntry, rctw, stab, stab.stabX].directType, stab: stab]]]; }; } ENDCASE => {} -- We do not parse these types of stabs }; module: Module; parsed: Parsed; wireTables: SGI.WireTables; module _ LOOPHOLE[stab.module]; parsed _ module.whole; wireTables _ LOOPHOLE[parsed.privateInfo]; ParseTypeFromFile[wireTables]; }; SELECT ObjectFiles.CGrammarOfStab[stab] FROM SunADotOut, XCOFF => ParseStabFromRope[stab]; SGIOBJ => ParseStabFromFile[stab]; UNKNOWN => NULL; ENDCASE => Bitch["unrecognized C grammar type"]; }; StabValueAsInt: PROC [x: CARD32] RETURNS [INT] ~ {RETURN[LOOPHOLE[x, INT]]}; RemoteAddrFromCard: PROC[rctw: RCTWData, card: CARD, bitOffset: CARD _ 0] RETURNS[CirioNubAccess.RemoteAddress] = {RETURN[[rctw.nub, card, bitOffset, FALSE, rctw.nub # NIL]]}; VarLocFromDotOListings: PUBLIC PROC [dotOListings: DotOListings, rctw: RCTWData] RETURNS [VarLoc] ~ { dol: DotOListing _ NIL; indirectType: Type; vl: VarLoc; WHILE dol=NIL DO WITH dotOListings SELECT FROM x: DotOEnumr => CCError[cirioError, "asking for VarLoc of enumerator"]; x: DotOListing => { goRound: BOOL _ x.stab.stabType#RSym AND dotOListings.rest#NIL; IF goRound THEN { WITH dotOListings.rest SELECT FROM y: DotOEnumr => CCError[cirioError, "mixed dotOListings"]; y: DotOListing => goRound _ y.stab.stabType=RSym; ENDCASE => ERROR}; IF goRound THEN dotOListings _ dotOListings.rest ELSE dol _ x}; ENDCASE => ERROR; ENDLOOP; indirectType _ CCTypes.GetIndirectType[dol.directType]; vl _ ObjF.VarLocFromStab[dol.stab]; vl.bitSize _ SELECT CCTypes.GetTypeClass[indirectType] FROM $unknown => 32, ENDCASE => CCTypes.GetBitSize[indirectType, rctw.cc]; WITH vl SELECT FROM nc: REF namedCommon VarLocBody => { EnsureAbsValid[rctw.nub, nc]; IF NOT nc.absFound THEN RETURN ObjF.MakeUnknownVarLoc[IO.PutFR1["named common %g not found", [rope[nc.name]] ]]}; ENDCASE => NULL; RETURN [vl]}; EnsureAbsValid: PUBLIC PROC [nub: CirioNubAccess.Handle, nc: REF namedCommon VarLocBody] ~ { IF NOT nc.absValid THEN { se: CirioNubAccess.SymEntry ~ CirioNubAccess.LookupSymEntryByName[nub, nc.name, TRUE, TRUE, 0]; IF se#NIL THEN {nc.absBase _ se.value; nc.absFound _ TRUE} ELSE nc.absFound _ FALSE; nc.absValid _ TRUE}; RETURN}; ArgumentListFromRCTW: PROC [rctw: RCTWData] RETURNS [RopeList] ~ { argumentList: RopeList _ NIL; reverseArgumentList: RopeList _ NIL; MakeArgsList:PROC [stab: ObjF.Stab] RETURNS [BOOLEAN] ~ { IF stab.stabType = PSym THEN BEGIN sourceStream:IO.STREAM _ IO.RIS[stab.rope]; reverseArgumentList _ CONS[GetSymbol[sourceStream], reverseArgumentList] END; RETURN[FALSE] }; lastBracketPair: ObjF.BracketPair; lastBracketPair _ rctw.bracketNest.rest.first; ObjF.GenSymbolStabs[lastBracketPair, MakeArgsList]; FOR remainingArguments: RopeList _ reverseArgumentList, remainingArguments.rest WHILE remainingArguments # NIL DO argumentList _ CONS[remainingArguments.first, argumentList]; ENDLOOP; RETURN [argumentList] }; LocalsListFromBracketPair: PROC [bracketPair: ObjF.BracketPair, rctw: RCTWData, procTop: BOOL] RETURNS [RopeList] ~ { localsList: RopeList _ NIL; AddSymbol: PROC [key:SymTab.Key, val:SymTab.Val] RETURNS [BOOLEAN] = { FOR dotOListings: DotOListings _ NARROW[val], dotOListings.rest WHILE dotOListings#NIL DO WITH dotOListings SELECT FROM x: DotOListing => IF procTop AND x.stab.stabType=PSym THEN RETURN [FALSE]; x: DotOEnumr => NULL; ENDCASE => ERROR; REPEAT FINISHED => localsList _ CONS[key, localsList]; ENDLOOP; RETURN[FALSE]}; bracketEntry: BracketEntry _ GetBracketEntry[bracketPair, rctw]; [] _ SymTab.Pairs[bracketEntry.symbolHashTable, AddSymbol]; RETURN[localsList]}; RopeListLength: PROC [list: RopeList] RETURNS [length: INT] ~ { length _ 0; FOR remaining: RopeList _ list, remaining.rest WHILE remaining # NIL DO length _ length + 1; ENDLOOP }; MakeSimpleFrame: PUBLIC PROC[frameInfo: ProcedureFrameInfo, rctw: RCTWData] RETURNS[Node] = { cc: CC _ rctw.cc; globalsType: Type; --indirect argsType: Type; --indirect blockType: Type; blockCount:INT _ 0; blockTypeList: LIST OF Type _ NIL; igftd: REF Frames.IndirectGlobalFrameTypeData; igfd: REF Frames.IndirectGlobalFrameData; iftd: REF Frames.IndirectFrameTypeData; ifd: REF Frames.IndirectFrameData; frameType: Type; frameNode: Node; frameMem: Mem; BuildIGFTD: PROC RETURNS [REF Frames.IndirectGlobalFrameTypeData] = { x: REF Frames.IndirectGlobalFrameTypeData _ NEW[Frames.IndirectGlobalFrameTypeData _ [globalVars: globalsType]]; RETURN[x]}; BuildIGFD: PROC RETURNS [REF Frames.IndirectGlobalFrameData] = { x: REF Frames.IndirectGlobalFrameData _ NEW[Frames.IndirectGlobalFrameData]; x.globalVars _ CCTypes.CreateIndirectNode[igftd.globalVars, frameMem, rctw.cc]; x.descriptor _ CedarOtherPureTypes.CreateIndirectToAnUnknownType[CedarOtherPureTypes.CreateUnknownType[cc, "C Frame Descriptor"], "C Global Frame", cc]; RETURN[x]}; BuildIFTD: PROC RETURNS[REF Frames.IndirectFrameTypeData] = { x: REF Frames.IndirectFrameTypeData _ NEW[Frames.IndirectFrameTypeData[blockCount]]; index:INT _ 0; x.enclosingContext _ Frames.CreateIndirectGlobalFrameType[igftd, cc]; x.args _ argsType; x.results _ CCTypes.GetIndirectType[CreateZeroLengthRecordType[cc]]; FOR remainingBlocks: LIST OF Type _ blockTypeList, remainingBlocks.rest WHILE remainingBlocks # NIL DO x.blocks[index] _ remainingBlocks.first; index _ index +1 ENDLOOP; RETURN[x]}; BuildIFD: PROC RETURNS[REF Frames.IndirectFrameData] = { x: REF Frames.IndirectFrameData _ NEW[Frames.IndirectFrameData[blockCount]]; x.procedure _ CedarOtherPureTypes.CreateIndirectToAnUnknownType[CedarOtherPureTypes.CreateUnknownType[cc, "no procedure for simple c frame types"], "no procedure for simple c frame types", cc]; x.descriptor _ CedarOtherPureTypes.CreateIndirectToAnUnknownType[CedarOtherPureTypes.CreateUnknownType[cc, "C Frame Descriptor"], "C Frame Descriptor", cc]; x.enclosingContext _ Frames.CreateIndirectGlobalFrameNode[igfd, iftd.enclosingContext, cc]; x.args _ CCTypes.CreateIndirectNode[iftd.args, frameMem, rctw.cc]; x.results _ CreateZeroLengthRecordNode[iftd.results, cc]; FOR index: INT IN [0..iftd.nBlocks) DO x.blocks[index] _ CCTypes.CreateIndirectNode[iftd.blocks[index], frameMem, rctw.cc]; ENDLOOP; RETURN[x]}; frameMem _ RMTWPrivate.MakeDualMem[rctw.nub, frameInfo.framePointer, frameInfo.stackPointer, [frameInfo.codeBase, INT.LAST], [frameInfo.dataBase, INT.LAST], [frameInfo.bssBase, INT.LAST], [unspecdBA, unspecdBA], [unspecdBA, unspecdBA] ]; [] _ frameMem.MemReadSegReg["text", 0]; --make sure it got created OK globalsType _ CreateLocalsRecordType[rctw.bracketNest.first, rctw, FALSE]; igftd _ BuildIGFTD[]; igfd _ BuildIGFD[]; FOR remainingBrackets:ObjectFiles.BracketNest _ rctw.bracketNest.rest, remainingBrackets.rest WHILE remainingBrackets # NIL DO blockType _ CreateLocalsRecordType[remainingBrackets.first, rctw, blockCount=0]; blockTypeList _ CONS[blockType, blockTypeList]; blockCount _ blockCount + 1 ENDLOOP; argsType _ CreateArgsRecordType[rctw]; iftd _ BuildIFTD[]; frameType _ Frames.CreateIndirectFrameType[iftd, cc]; ifd _ BuildIFD[]; frameNode _ Frames.CreateIndirectFrameNode[ifd, frameType, cc]; RETURN [frameNode]}; END.. ^ RCTWFrames.mesa Copyright Ó 1989, 1990, 1991, 1992 by Xerox Corporation. All rights reserved. Hopcroft, August 18, 1989 11:44:24 am PDT Sturgis, December 22, 1989 1:49:56 pm PST Last changed by Theimer on October 9, 1989 2:06:15 pm PDT Last tweaked by Mike Spreitzer on October 1, 1992 4:09 pm PDT Philip James, February 22, 1992 9:57 am PST Laurie Horton, July 20, 1992 11:44 am PDT Katsuyuki Komatsu December 18, 1992 9:57 am PST Jas, January 5, 1993 3:19 pm PST Following types are defined in ObjectFilesPrivate zero length records Zero length indirect record nodes Analyzing block records This procedure is copied from CCTypesImpl. It should really be promoted to the CCTypes interface. Type information is stored in an encoded rope. This is a type declaration unnamed type of SunOS 5.x e.g. "typedef struct {word f0, f1;} W2;" will generate following stab. ":T(0,29)=s8f0:(0,21),0,32;f1:(0,21),32,32;;" "W2:t(0,30)=(0,29)" IF NOT (type = oldVal) THEN Bitch["symbol being redefined"]; This is a not type symbol declaration This must be either a local variable declaration or a register variable declaration Type information stored in tables in the object file. access the current symbol entry and the file descriptor index skip the endref count the number of type qualifiers qualifiers are basically in reverse order...including array dimensions -- go past the rndx (it always is the same) and the blank No Qualifiers Returns the list of argument names for the current rctw. This is done by looking for parameter stabs inside the second to last pair of bracket stabs in the current scope's bracket nest. ʹ– "cedar" style•NewlineDelimiter ™code™K™NK™)K™)K™9K™=K™+K™)K™/K™ —K˜šÏk ˜ Kšœœz˜‡Kšœœ3˜LKšœ ˜ Kšœœ8˜LKšœ ˜ Kšœœ˜%KšœœÒ˜ÞKš œœ7œœœ˜^Kšœ œ†˜—Kšœ˜Kšœ˜KšœœW˜dKšœœ˜%K˜ Kšœœ'œ ˜?Kšœœ?˜KKšœ˜Kšœ˜—K˜K˜KšÐln œœ˜KšœTœœ=˜­Kšœ˜ Kš œœœÏnœœ˜$K˜Kšœœœ˜Kš œ œœœœ˜K˜KšŸœœ!œœ˜MKšœ1™1J™Jšœœœ ˜Jšœ œœ!˜8Jšœœœ ˜Jšœ œœ!˜8J˜K˜™K™šŸœœœœ˜8Kšœœ9œ˜G—K˜šŸœœœ˜VKšœ#˜#Kšœ+˜+Kšœ!˜!Kšœ3˜3Kšœ3˜3Kšœ5˜5—K˜šŸœœœœœœœ˜@Kšœœœ˜K˜—šŸœœœœœœœœ˜YKšœœ˜K˜—š Ÿœœœœœœ˜;Kšœœ˜ K˜—šŸ œœœœœœœ˜QKšœœ˜K˜—šŸ œœœœœœœ˜PKšœœ˜ K˜—šŸ œœœœœœœ˜YKšœœ˜——K˜™!K™šÐbnœœœœ ˜SKš˜Kšœrœ˜‚Kšœ˜—K˜š œœ#œ$˜hKšœ œ˜——K˜K™K™™K˜šŸœœœ˜DKšœ;˜;KšœL˜LK˜%Kšœ˜——˜šŸœœ:œœ˜tKšœI˜IKšœ8˜8K˜%Kšœ˜——K˜˜šŸœœIœ˜|K˜Kšœœ ˜6K˜Kšœ˜Kšœœ˜ K˜Kšœœ%˜.K˜K˜ šœFœœ˜jKšœ_˜_K˜+Kšœ!˜!šœ˜Kšœ!œ˜'šœ$œ˜)Kšœ(˜(Kšœ3œ˜8—Kšœœ˜—K˜Kšœ˜—Kšœœ˜Kšœ#˜#Kšœ˜KšœL˜LKšœ˜—K˜š  œœœœœ˜%Kšœœœœ˜&—K˜K™šŸ œœœ œœœœ˜@š Ÿ œœœœœ˜(Kšœœœœ œœ œœ ˜K—š Ÿ œœœœœ˜(Kšœœœœ œœ œœ œœ ˜^—Kšœœœ˜š œœœœ œœ˜BKšœœ˜*š œœœœ œ˜AKšœ)œ˜>—Kšœ˜ —Kšœ ˜—K˜K˜šŸœœ œ1œ˜sKšœ@˜@Kšœœ9˜\KšœœœA˜[Kšœ˜—K˜K™š œœ1œ˜lKš˜šŸ œœœœ˜8K˜$Kšœœ˜K˜—Kšœœ7˜Lšœœ˜Kš˜Kšœœ˜%K˜/K˜1šœœA˜KK˜—Kšœ.˜.Kšœ˜—Kšœ˜KšœÏc˜—K˜š Ÿ œœœœœ œ˜Dšœœ˜'Kšœ+œ˜FKšœ˜—Kšœ˜K˜——˜K™bKšœœ&œœ˜NšŸœœœœœ œœœ˜lKšœœœ˜%Kš œœœœœ˜Kšœ>˜>Kšœ˜K˜—KšŸœœœ˜"šŸ œœB˜QšŸœœœ˜Kšœœ˜˜±—šŸœœœ˜4Kšœœ/˜Hš œœœœœ˜"Kšœ$œÔ˜úšœœœ˜9Kšœœ˜˜µKšœ˜—Kšœœ˜—K˜ Kšœœ˜#Kšœ2˜2šœ˜Kšœy˜y—Kšœ˜K˜—šŸœœ˜-Kšœ.™.Kšœ˜šœ.˜.Kš œœœœœ ˜,Kšœœ˜'Kšœœ˜Kšœœœ˜Kšœœœ ˜EKšœœœ/˜_šœ˜˜ K™Kšœ ˜ Kšœœ*œœ˜:Kšœ@˜@šœœ˜Kšœ¤™¤KšœZ˜ZK˜—šœœ5œ˜AKšœœ3˜HKšœœœ!™<šœœMœ˜YKšœ:˜:Kšœ}˜}K˜—K˜—K˜—˜#K™%Kš œœœœ(œœ˜hšœœ ˜K˜,KšœE˜EKšœ˜—K˜—šœ¡U˜\šœœ ˜K˜,KšœE˜EKšœ˜—Kšœ˜—šœ˜ šœœœ˜