<> <> <> DIRECTORY Atom, CD, CDCellCommands, CDCells, CDCellsInteractions, CDCommandOps, CDDirectory, CDLayers, CDOps, CDPanel, CDPanelFonts, CDPopUpMenus, CDProperties, CDRects, CDSatellites, CDTexts, CDSequencer, CDValue, CDViewer, Core, CoreOps, SymTab, IO, PopUpMenus, PopUpSelection, RefTab, RegularExpression, Rope, Sisyph, TerminalIO, TextOps, ViewerOps; TextOpsImpl: CEDAR PROGRAM IMPORTS Atom, CD, CDCellCommands, CDCells, CDCellsInteractions, CDCommandOps, CDDirectory, CDLayers, CDOps, CDPanel, CDPanelFonts, CDProperties, CDRects, CDSatellites, CDSequencer, CDTexts, CDValue, CDViewer, IO, CDPopUpMenus, CoreOps, PopUpSelection, SymTab, RefTab, RegularExpression, Rope, Sisyph, TerminalIO, ViewerOps SHARES CDCellCommands, CDPopUpMenus = BEGIN <> TSPType: TYPE = TextOps.TSPType; firstInvisible: TSPType = expr; tspNms: ARRAY TSPType OF IO.ROPE _ [ text: "Text", sat: "Satellite", expr: "Expression", -- firstInvisible name: "Name", iForC: "Icon Code", iForS: "Icon Sch", extract: "Extract Proc", virus: "Prop Virus", any: "ANY" ]; tspNms3: ARRAY TSPType OF IO.ROPE _ [ text: "text", sat: "sat", expr: "expr", name: "name", iForC: "code", iForS: "schm", extract: "extr", virus: "virus", any: "any" ]; tspProps: ARRAY TSPType OF ATOM _ [ text: NIL, sat: NIL, expr: $SisyphExpressions, name: $SignalName, iForC: $CodeFor, iForS: $IconFor, extract: $SisyphExtractProc, virus: $CDBringoverLibraryName, any: NIL]; Finder: TYPE = RegularExpression.Finder; InstProc: TYPE = PROC[inst: CD.Instance] RETURNS[quit: BOOL _ FALSE]; InstObProc: TYPE = PROC[inst: CD.Instance, ob: CD.Object] RETURNS[quit: BOOL _ FALSE]; ObjProc: TYPE = PROC[obj: CD.Object] RETURNS[quit: BOOL _ FALSE]; Signal: SIGNAL[msg: IO.ROPE] = CODE; <> InitTextScanPropPanel: PROC = { tech: CD.Technology _ CD.FetchTechnology[$cmosB]; panelHeight: INT _ CDValue.FetchInt[tech, $PanelHeight, global, 120]; CDValue.Store[tech, $TextScanProp, NEW[TSPType _ text]]; CDValue.Store[tech, $TextScanPropNm, tspNms[text]]; CDPanel.Button[button: [text: "search", xpos: 0], command: $TextOpsSearch, tech: tech]; CDPanel.Button[button: [text: "replace", xpos: 50], command: $TextOpsReplace, tech: tech]; CDPanel.Button[button: [text: "prop:", xpos: 105], proc: ChangeTextScanProp, tech: tech]; CDPanel.Label[[width: 140, cdValueKey: $TextScanPropNm, redisplay: TRUE], tech]; CDPanel.Line[tech]; CDValue.StoreInt[tech, $PanelHeight, panelHeight+18]}; TextOpsMenuCommand: PROC [command: CDSequencer.Command] ~ { ThreeBools: TYPE = RECORD[doReplace, oneOnly, global: BOOL]; tb: ThreeBools _ SELECT command.key FROM $FindOneMatchingRopeInDesign => [FALSE, TRUE, TRUE], $FindOneMatchingRopeInContext => [FALSE, TRUE, FALSE], $FindEachMatchingRopeInDesign => [FALSE, FALSE, TRUE], $FindEachMatchingRopeInContext => [FALSE, FALSE, FALSE], $ReplaceOneMatchingRopeInDesign => [TRUE, TRUE, TRUE], $ReplaceOneMatchingRopeInContext => [TRUE, TRUE, FALSE], $ReplaceEachMatchingRopeInDesign => [TRUE, FALSE, TRUE], $ReplaceEachMatchingRopeInContext => [TRUE, FALSE, FALSE], ENDCASE => ERROR; TextOpsCommand[command, tb.doReplace, tb.oneOnly, tb.global]}; TextOpsCommand: PROC [command: CDSequencer.Command, doReplace, oneOnly, global: BOOL] ~ { DoInst: InstObProc = { [quit, count] _ IF CDTexts.IsText[inst.ob] THEN ReplaceSat[tsp, design, doReplace, oneOnly, count, inst, ob, finder, replace] ELSE ReplaceExpr[tsp, design, doReplace, oneOnly, count, inst, finder, replace]}; DoObject: ObjProc = {[quit, count] _ ReplaceExpr[tsp, design, doReplace, oneOnly, count, obj, finder, replace]}; design: CD.Design _ command.design; count: NAT _ 0; tsp: TSPType _ GetTextScanProp[design]^; patternRef: IO.ROPE; pattern: IO.ROPE; replace: IO.ROPE; finder: Finder; searched: RefTab.Ref _ RefTab.Create[]; oneFound: BOOL _ FALSE; IF doReplace THEN replace _ GetText[design]; patternRef _ GetPattern[design]; pattern _ OnlyStarOrHashMatching[patternRef]; finder _ RegularExpression.CreateFromRope [pattern: pattern, literal: FALSE, word: FALSE, ignoreCase: FALSE ! RegularExpression.MalformedPattern => { TerminalIO.PutF["Syntax error in adjusted pattern \"%g\"\n", IO.rope[pattern]]; GOTO prematureExit}]; TerminalIO.PutF["\nMatch Property: %g\n", IO.rope[tspNms[tsp]]]; TerminalIO.PutF["Match Pattern: \"%g\"\n", IO.rope[patternRef]]; IF doReplace THEN TerminalIO.PutF[" New Pattern: \"%g\"\n", IO.rope[replace]]; TerminalIO.PutF["Match Context: %g\n", IO.rope[IF global THEN "Global" ELSE "Local"]]; oneFound _ ScanContext[design, DoInst, DoObject, global, oneOnly]; TerminalIO.PutF["%g matches.\n", IO.int[count]]; IF oneFound OR doReplace AND count#0 THEN CDSequencer.ExecuteCommand [key: $ResetScaleTop, design: design, queue: dontQueue, comm: command]; <<[key: $ResetScaleSel, design: design, queue: dontQueue, comm: command];>> EXITS prematureExit => TerminalIO.PutF["Replace not done.\n"]}; ChangeTextScanProp: PROC [comm: CDSequencer.Command] = { tspNmList: LIST OF IO.ROPE; tspCur: TSPType; n: CARDINAL; FOR ts: TSPType DECREASING IN TSPType DO tspNmList _ CONS[tspNms[ts], tspNmList] ENDLOOP; TerminalIO.PutRope["Change Match Property\n"]; n _ PopUpSelection.Request[header: "Match Property", choice: tspNmList]; tspCur _ IF n=0 THEN GetTextScanProp[comm.design]^ ELSE VAL[n-1]; SetTextScanProp[comm.design, tspCur]}; TextOpsButtonCommand: PROC [comm: CDSequencer.Command] ~ { doReplace: BOOL _ SELECT comm.key FROM $TextOpsSearch => FALSE, $TextOpsReplace => TRUE, ENDCASE => ERROR; global: BOOL _ comm.b; oneOnly: BOOL _ comm.n#2; IF comm.n#1 THEN { TerminalIO.PutRope["Flush TextOps Cache\n"]; RefTab.Erase[globalCtx]; globalCtx _ RefTab.Create[]}; TextOpsCommand[comm, doReplace, oneOnly, global]}; <> ScanContext: PROC [design: CD.Design, instProc: InstObProc, objProc: ObjProc, allLevels, oneOnly: BOOL] RETURNS[found: BOOL _ FALSE] = { pushes: INT; IF allLevels THEN WHILE CDCells.IsPushedIn[design] DO [] _ CDCellsInteractions.PopFromCell[design, interactive] ENDLOOP; pushes _ ScanAll[design, design.actual.first.dummyCell.ob, allLevels, oneOnly, instProc, objProc]; IF pushes>1 THEN { THROUGH [2..pushes] DO inst: CD.Instance _ CDOps.TheInstance[design: design, text: "push into "]; []_CDCellsInteractions.PushInCellInstance[design, inst] ENDLOOP}; RETURN[pushes>0]}; ScanAll: PROC[design: CD.Design, top: CD.Object, goDeep, oneOnly: BOOL, instProc: InstObProc, objProc: ObjProc] RETURNS[pushes: INT _ 0] = { doInst: InstProc = { obVal: REF _ RefTab.Fetch[globalCtx, inst.ob].val; dive: BOOL _ goDeep AND (oneOnly OR obVal=NIL OR obVal=inst.ob); IF RefTab.Store[globalCtx, inst, inst] THEN IF instProc[inst, top] THEN GOTO MarkSelected; IF RefTab.Store[globalCtx, inst.ob, inst.ob] THEN IF objProc[inst.ob] THEN GOTO MarkSelected; IF dive AND CDCells.IsCell[inst.ob] THEN IF ((pushes _ ScanAll[design, inst.ob, goDeep, oneOnly, instProc, objProc])>0) THEN GOTO MarkSelected ELSE []_RefTab.Store[globalCtx, inst.ob, NEW[INT_1]]; EXITS MarkSelected => { []_CDCells.EnumerateInstances[top, DeselectAll]; inst.selected _ TRUE; RETURN[TRUE]}}; IF CDCells.EnumerateInstances[top, doInst] THEN pushes _ pushes + 1}; globalCtx: RefTab.Ref _ RefTab.Create[]; DeselectAll: InstProc = {inst.selected _ FALSE}; <> <> <> <> <> <<>> EnumDirectoryObjectsWithPattern: PROC [comm: CDSequencer.Command] ~ { proc: PROC [design: CD.Design, ob: CD.Object] _ GetObProc[comm.key]; finder: Finder _ GetFinder[comm.design]; CellEnumeratorProc: CDDirectory.EachEntryAction = { IF RegularExpression.SearchRope[finder, name].found THEN proc[comm.design, ob]}; [] _ CDDirectory.Enumerate[comm.design, CellEnumeratorProc]}; EnumSelectedObjects: PROC [comm: CDSequencer.Command] ~ { proc: PROC [design: CD.Design, ob: CD.Object] _ GetObProc[comm.key]; FOR w: CD.InstanceList _ CDOps.InstList[comm.design], w.rest WHILE w#NIL DO IF w.first.selected THEN proc[comm.design, w.first.ob] ENDLOOP}; GetObProc: PROC[key: ATOM] RETURNS[proc: PROC [design: CD.Design, ob: CD.Object]] = { proc _ SELECT key FROM $AddIconBorderSelected, $AddIconBorderPattern => AddIconBorder, $ChangeColorSelected, $ChangeColorPattern => ChangeColor, ENDCASE => ERROR}; <> OnlyStarOrHashMatching: PROC[text: IO.ROPE] RETURNS[IO.ROPE] = { Insert: PROC[str: IO.ROPE] = {text _ Rope.Cat[text.Substr[0,index], str, text.Substr[index]]; index _ index+1}; index: INT; FOR index _ 0, index+1 WHILE index ERROR; '* => Insert["#"]; '# => LOOP; '[, '., '], '~, '^, '$, '+, '(, '|, '), '\\, '<, ':, ',, '>, '{, '} => Insert["'"]; ENDCASE ENDLOOP; RETURN[text]}; LogFind: PROC[ design: CD.Design, type: IO.ROPE, text: IO.ROPE, doReplace: BOOL, delete: BOOL, replace: IO.ROPE, on: REF, cell: CD.Object ] = { line0: IO.ROPE _ IO.PutFR["%g: %g ", IO.rope[type], IO.rope[text]]; online: IO.ROPE _ ""; inline: IO.ROPE _ ""; limit: INT _ 90; -- 120 if small IF doReplace THEN IF delete THEN {line0 _ line0.Cat[IO.PutFR["deleted "]]} ELSE { TerminalIO.PutF["%gchanged to\n", IO.rope[line0]]; line0 _ NIL; line0 _ IO.PutFR[" %g ", IO.rope[replace]]}; IF on#NIL THEN IF ISTYPE[on, CD.Object] THEN online _ IO.PutFR["on obj %g ", IO.rope[GetID[design, NARROW[on]]]] ELSE { inst: CD.Instance _ NARROW[on]; iRope: IO.ROPE _ CDOps.InstRope[inst]; IF ~iRope.Equal["rect comment"] THEN { oRope: IO.ROPE _ CDDirectory.Name[inst.ob, design]; IF oRope.Length[]=0 THEN online _ IO.PutFR["on inst %g ", IO.rope[iRope]] ELSE online _ IO.PutFR["on inst %g ", IO.rope[oRope]]}}; IF cell#NIL THEN inline _ IO.PutFR["in %g", IO.rope[GetID[design, cell]]]; IF line0.Length[] + online.Length[] + inline.Length[] < limit THEN {TerminalIO.PutF["%g%g%g\n", IO.rope[line0], IO.rope[online], IO.rope[inline]]; RETURN}; TerminalIO.PutF["%g\n", IO.rope[line0]]; SELECT online.Length[] + inline.Length[] FROM > limit => TerminalIO.PutF[" %g\n %g\n", IO.rope[online], IO.rope[inline]]; > 0 => TerminalIO.PutF[" %g%g\n", IO.rope[online], IO.rope[inline]]; ENDCASE}; GetID: PROC[design: CD.Design, obj: CD.Object] RETURNS[name: IO.ROPE] = { IF obj = CDOps.RealTopCell[design] THEN RETURN["(top level of design)"]; IF obj = design.actual.first.dummyCell.ob THEN RETURN [Rope.Cat[CDDirectory.Name[design.actual.first.mightReplace.ob, design], " (pushed in)"]]; name _ CDDirectory.Name[obj, design]; IF name.Length[]#0 THEN RETURN[name]; name _ CDOps.ToRope[obj]}; ReplaceRope: PROC[finder: Finder, text, replace: IO.ROPE] RETURNS[new: IO.ROPE] = { found: BOOL; at, atEnd, before, after: INT; IF finder=NIL THEN RETURN[text]; [found, at, atEnd, before, after] _ RegularExpression.SearchRope[finder, text]; IF NOT found THEN RETURN[text]; IF at=0 AND atEnd=0 AND before=0 AND after=0 THEN RETURN[replace]; -- * replace new _ Rope.Cat[text.Substr[0,at], replace, text.Substr[atEnd] ]}; ReplaceSat: PROC[tsp: TSPType, design: CD.Design, doReplace, oneOnly: BOOL, count: NAT, inst: CD.Instance, cell: CD.Object, finder: Finder, replace: IO.ROPE] RETURNS[quit: BOOL, newCount: NAT] = { delete: BOOL _ doReplace AND replace.Length[]=0; textSpec: CDTexts.TextSpecific _ NARROW[inst.ob.specific]; on: REF _ CDSatellites.GetMaster[cell, inst]; new: IO.ROPE _ replace; SELECT tsp FROM any => tsp _ IF on#NIL THEN sat ELSE text; text => IF on#NIL THEN RETURN[FALSE, count]; sat => IF on=NIL THEN RETURN[FALSE, count]; ENDCASE => RETURN[FALSE, count]; IF CD.InterestSize[inst.ob].x=0 OR CD.InterestSize[inst.ob].y=0 THEN {Signal["Zero dimension satellite"]; inst.selected _ TRUE; RETURN[TRUE, count]}; IF doReplace THEN { newOb: CD.Object; new _ ReplaceRope[finder, textSpec.text, replace]; IF new=textSpec.text THEN RETURN[FALSE, count]; newOb _ CDTexts.Create[new, textSpec.cdFont]; delete _ CD.InterestSize[newOb].x=0 OR CD.InterestSize[newOb].y=0; CDSequencer.MarkChangedIOOnly[design]; IF delete THEN {inst.selected _ TRUE; oneOnly _ TRUE} ELSE inst.ob _ newOb} ELSE IF ~RegularExpression.SearchRope[finder, textSpec.text].found THEN RETURN[FALSE, count]; LogFind[design, tspNms3[tsp], textSpec.text, doReplace, delete, new, on, cell]; RETURN[oneOnly, count+1]}; ReplaceExpr: PROC[ tsp: TSPType, design: CD.Design, doReplace: BOOL, oneOnly: BOOL, count: NAT, from: REF, finder: Finder, replace: IO.ROPE] RETURNS[quit: BOOL, newCount: NAT] = { quit _ FALSE; newCount _ count; IF tsp#any THEN [quit, newCount] _ ReplaceExprOnProp [tsp, design, doReplace, oneOnly, newCount, from, finder, replace] ELSE FOR tsp IN [firstInvisible..any) WHILE NOT quit DO [quit, newCount] _ ReplaceExprOnProp [tsp, design, doReplace, oneOnly, newCount, from, finder, replace] ENDLOOP}; ReplaceExprOnProp: PROC [tsp: TSPType, design: CD.Design, doReplace, oneOnly: BOOL, count: NAT, from: REF, finder: Finder, replace: IO.ROPE] RETURNS[quit: BOOL, newCount: NAT] = { propAtom: ATOM _ tspProps[tsp]; new: LIST OF IO.ROPE _ NIL; delete: BOOL _ doReplace AND replace.Length[]=0; changed: BOOL _ FALSE; exprs: LIST OF IO.ROPE _ NIL; ref: REF _ CDProperties.GetProp[from, propAtom]; quit _ FALSE; WITH ref SELECT FROM ropes: LIST OF IO.ROPE => {exprs _ ropes}; rope: IO.ROPE => {exprs _ LIST[rope]}; text: REF TEXT => {rope: IO.ROPE _ Rope.FromRefText[text]; exprs _ LIST[rope]}; atom: ATOM => {rope: IO.ROPE _ Atom.GetPName[atom]; exprs _ LIST[rope]}; ENDCASE => {exprs _ NIL}; FOR exprs _ exprs, exprs.rest WHILE exprs#NIL DO IF NOT doReplace THEN { IF ~ RegularExpression.SearchRope[finder, exprs.first].found THEN LOOP; LogFind[design, tspNms3[tsp], exprs.first, doReplace, delete, NIL, from, NIL]; count _ count +1; IF oneOnly THEN RETURN[TRUE, count]} ELSE { expr: IO.ROPE _ ReplaceRope[finder, exprs.first, replace]; IF (expr= exprs.first) THEN LOOP; LogFind[design, tspNms3[tsp], exprs.first, doReplace, delete, expr, from, NIL]; count _ count +1; changed _ TRUE; IF NOT delete THEN new _ CONS[expr, new]; IF oneOnly THEN { FOR temp: LIST OF IO.ROPE _ exprs.rest, temp.rest WHILE temp#NIL DO new _ CONS[temp.first, new] ENDLOOP; quit _ TRUE; EXIT} }; ENDLOOP; IF doReplace AND changed THEN { one: IO.ROPE _ IF new=NIL THEN NIL ELSE new.first; WITH ref SELECT FROM ropes: LIST OF IO.ROPE => ref _ new; rope: IO.ROPE => ref _ one; text: REF TEXT => ref _ Rope.ToRefText[one]; atom: ATOM => ref _ Atom.MakeAtom[one]; ENDCASE => ERROR; CDSequencer.MarkChanged[design]; CDProperties.PutProp[from, propAtom, ref]}; RETURN[quit, count]}; <> AddIconBorder: PROC [design: CD.Design, ob: CD.Object] ~ { name: IO.ROPE _ CDDirectory.Name[ob, design]; layer: CD.Layer _ CDLayers.CurrentLayer[design]; w: INT _ CDLayers.LayerWidth[design, layer]; ir: CD.Rect _ CD.InterestRect[ob]; vert: CD.Object _ CDRects.CreateRect[size: [w,ir.y2-ir.y1], l: layer]; hor: CD.Object _ CDRects.CreateRect[size: [ir.x2-ir.x1,w], l: layer]; inst: CD.Instance; inst _ NEW[CD.InstanceRep _ [ob: vert, trans: [off: [ir.x1, ir.y1]] ] ]; CDProperties.PutProp[inst, $SisyphExtractProc, $ExtractNull]; IF CDCells.IncludeInstance[design, ob, inst] THEN Signal["???"]; inst _ NEW[CD.InstanceRep _ [ob: vert, trans: [off: [ir.x2-w, ir.y1]] ] ]; CDProperties.PutProp[inst, $SisyphExtractProc, $ExtractNull]; IF CDCells.IncludeInstance[design, ob, inst] THEN Signal["???"]; inst _ NEW[CD.InstanceRep _ [ob: hor, trans: [off: [ir.x1, ir.y1]] ] ]; CDProperties.PutProp[inst, $SisyphExtractProc, $ExtractNull]; IF CDCells.IncludeInstance[design, ob, inst] THEN Signal["???"]; inst _ NEW[CD.InstanceRep _ [ob: hor, trans: [off: [ir.x1, ir.y2-w]] ] ]; CDProperties.PutProp[inst, $SisyphExtractProc, $ExtractNull]; IF CDCells.IncludeInstance[design, ob, inst] THEN Signal["???"]; TerminalIO.PutF["Borders added in %g\n", IO.rope[name]]; CDOps.Redraw[design]}; ChangeColor: PROC[design: CD.Design, ob: CD.Object] = { size: CD.Position _ CD.InterestSize[ob]; off: CD.Position _ CD.InterestBase[ob]; layer: CD.Layer _ CDLayers.CurrentLayer[design]; mask: CD.Object _ CDRects.CreateRect[size: size, l: layer]; maskI: CD.Instance; name: IO.ROPE _ CDDirectory.Name[ob, design]; delete: BOOL _ layer = CD.commentLayer; EachInst: CDCells.InstEnumerator = { IF NOT CDRects.IsBareRect[inst.ob] THEN RETURN[FALSE]; IF CD.InterestSize[inst.ob]#size THEN RETURN[FALSE]; IF CD.InterestBase[inst.ob]#inst.trans.off THEN RETURN[FALSE]; IF CDProperties.GetProp[inst, $SisyphExtractProc]=NIL THEN RETURN[FALSE]; IF NARROW[CDProperties.GetProp[inst, $SisyphExtractProc], ATOM]#$ExtractNull THEN RETURN[FALSE]; IF delete THEN {maskI _ inst; TerminalIO.PutF["Color deleted in %g\n", IO.rope[name]]; RETURN[TRUE]}; IF inst.ob.layer=layer THEN {TerminalIO.PutF["Color unchanged in %g\n", IO.rope[name]]; RETURN[TRUE]}; inst.ob _ mask; TerminalIO.PutF["Color modified in %g\n", IO.rope[name]]; RETURN[TRUE]}; IF delete THEN { IF CDCells.EnumerateInstances[ob, EachInst] THEN IF CDCells.RemoveInstance[design, ob, maskI] THEN Signal["???"]} ELSE IF NOT CDCells.EnumerateInstances[ob, EachInst] THEN { maskI _ NEW[CD.InstanceRep _ [ob: mask, trans: [off: off] ] ]; CDProperties.PutProp[maskI, $SisyphExtractProc, $ExtractNull]; IF CDCells.IncludeInstance[design, ob, maskI] THEN Signal["???"]; TerminalIO.PutF["Color added in %g\n", IO.rope[name]]}; CDOps.Redraw[design]}; <> AddExpressionToEachSelected: PROC [command: CDSequencer.Command] ~ { count: NAT _ 0; id: IO.ROPE _ SELECT command.key FROM $AddInstanceExpressionToEachSelected => "Instance", $AddObjectExpressionToEachSelected => "Object", ENDCASE => ERROR; expr: IO.ROPE _ TerminalIO.RequestRope[id.Cat[" expression to add to selected: "]]; FOR w: CD.InstanceList _ CDOps.InstList[command.design], w.rest WHILE w#NIL DO IF w.first.selected THEN { on: REF _ SELECT command.key FROM $AddInstanceExpressionToEachSelected => w.first, $AddObjectExpressionToEachSelected => w.first.ob, ENDCASE => ERROR; exprs: LIST OF IO.ROPE _ NARROW[CDProperties.GetProp[on, Sisyph.expressionsProp]]; FOR test: LIST OF IO.ROPE _ exprs, test.rest WHILE test#NIL DO IF expr.Equal[test.first] THEN GOTO exit; REPEAT exit => LOOP ENDLOOP; exprs _ CONS[expr, exprs]; CDProperties.PutProp[on, Sisyph.expressionsProp, exprs]; count _ count+1}; ENDLOOP; TerminalIO.PutF["%g matches.\n", IO.int[count]]}; <> AddTextLines: PROC [command: CDSequencer.Command] ~ { pos: CD.Position _ command.pos; ob: CD.Object; lay: CD.Layer _ CDLayers.CurrentLayer[command.design]; r: IO.ROPE; font: CDTexts.CDFont _ CDPanelFonts.CurrentFont[command.design]; grid: INT _ Grid[command.design, font]; CDOps.Redraw[command.design]; lay _ CDPanelFonts.LayerForText[lay, command.design.technology]; IF font=NIL THEN CDSequencer.Quit["** no font"]; pos.y _ pos.y + font.origin.y; r _ TerminalIO.RequestRope["create text >"]; DO WHILE ~r.IsEmpty[] AND r.Fetch[] IN [IO.NUL..IO.SP] DO r _ r.Substr[1] ENDLOOP; WHILE ~r.IsEmpty[] AND r.Fetch[r.Length[]-1] IN [IO.NUL..IO.SP] DO r _ r.Substr[0, r.Length[]-1] ENDLOOP; IF r.IsEmpty[] THEN EXIT; ob _ CDTexts.Create[text: r, font: font, layer: lay]; IF ob=NIL THEN CDSequencer.Quit["***bad line***"]; []_CDOps.IncludeObject[design: command.design, ob: ob, trans: [pos, original]]; r _ TerminalIO.RequestRope[NIL]; pos.y _ pos.y - grid ENDLOOP}; <> BuildCrossReferenceLists: PROC [comm: CDSequencer.Command] ~ { InstEnumeratorProc: CDCells.InstEnumerator = { IF CDCells.IsCell[inst.ob] AND inst.selected THEN {nofCells _ nofCells+1; objNms _ CONS[CDDirectory.Name[inst.ob, comm.design], objNms]}}; ListEm: SymTab.EachPairAction = {list _ CONS[NARROW[val], list]}; rootCell: CD.Object _ comm.design^.actual.first.dummyCell.ob; objNms: LIST OF IO.ROPE _ NIL; top: Sisyph.Context _ Sisyph.Create[comm.design]; index: INT _ 0; nofCells: INT _ 0; maxNm: INT _ 0; OccSeq: TYPE = RECORD[name: IO.ROPE, seq: SEQUENCE size: CARDINAL OF BOOL]; list: LIST OF REF OccSeq; table: SymTab.Ref _ SymTab.Create[]; []_CDCells.EnumerateInstances[rootCell, InstEnumeratorProc]; FOR m: LIST OF IO.ROPE _ objNms, m.rest WHILE m#NIL DO AddToTable: PROC[wire: Core.Wire] = { name: IO.ROPE _ CoreOps.GetShortWireName[wire]; IF name.Length[]>0 THEN { ref: REF OccSeq _ NARROW[SymTab.Fetch[table, name].val]; IF ref=NIL THEN ref _ NEW[OccSeq[nofCells]]; ref.name _ name; ref[index] _ TRUE; maxNm _ MAX[name.Length[], maxNm]; []_SymTab.Store[table, name, ref]}; FOR i: INT IN [0..wire.size) DO AddToTable[wire[i]] ENDLOOP}; sub: Core.CellType _ Sisyph.ES[m.first, top]; AddToTable[sub.public]; index _ index +1; ENDLOOP; [ ] _ SymTab.Pairs[table, ListEm]; DO ok: BOOL _ TRUE; FOR l: LIST OF REF OccSeq _ list, l.rest WHILE l.rest#NIL DO TwoOcc: TYPE = RECORD[occ1, occ2: REF OccSeq]; SELECT Rope.Compare[l.first.name, l.rest.first.name] FROM less => LOOP; equal => ERROR; ENDCASE; [l.first, l.rest.first] _ TwoOcc[l.rest.first, l.first]; ok _ FALSE; ENDLOOP; IF ok THEN EXIT; ENDLOOP; TerminalIO.PutF["\nCross reference list for:\n"]; index _ 0; FOR m: LIST OF IO.ROPE _ objNms, m.rest WHILE m#NIL DO TerminalIO.PutF["%4g: %g\n", IO.int[index], IO.rope[m.first]]; index _ index +1; ENDLOOP; FOR m: LIST OF REF OccSeq _ list, m.rest WHILE m#NIL DO IF comm.key=$BuildCrossReferenceListsUnique THEN { used: NAT _ 0; FOR i: INT IN [0..nofCells) DO IF m.first[i] THEN used_used+1 ENDLOOP; IF used#1 THEN LOOP}; TerminalIO.PutF["%g ", IO.rope[m.first.name]]; FOR i: INT IN [0..(maxNm-m.first.name.Length[])) DO TerminalIO.PutRope[" "] ENDLOOP; FOR i: INT IN [0..nofCells) DO IF m.first[i] THEN TerminalIO.PutF["%2g", IO.int[i]] ELSE TerminalIO.PutF[" "] ENDLOOP; TerminalIO.PutF["\n"]; ENDLOOP}; <> Grid: PROC[design: CD.Design, font: CDTexts.CDFont _ NIL] RETURNS[grid: NAT] = { viewers: CDViewer.ViewerList _ CDViewer.ViewersOf[design]; IF viewers#NIL THEN WITH ViewerOps.GetViewer[viewers.first, $Grid] SELECT FROM rgrid: REF CD.Number => grid _ rgrid^; ENDCASE => NULL ELSE grid _ design.technology.lambda*2; IF font#NIL THEN WHILE font.height > (grid*4)/3 DO grid _ grid*2 ENDLOOP}; GetFinder: PROC[design: CD.Design] RETURNS[finder: Finder] = { pattern: IO.ROPE _ OnlyStarOrHashMatching[GetPattern[design]]; finder _ RegularExpression.CreateFromRope [pattern: pattern, literal: FALSE, word: FALSE, ignoreCase: FALSE]}; GetPattern: PROC [design: CD.Design] RETURNS [pattern: Rope.ROPE] = { pattern _ CDPanel.TakeDownText[design, $pattern]; IF Rope.IsEmpty[pattern] THEN pattern _ NIL}; GetText: PROC [design: CD.Design] RETURNS [text: Rope.ROPE] = { text _ CDPanel.TakeDownText[design, $text]; IF Rope.IsEmpty[text] THEN text _ NIL}; PutText: PROC [design: CD.Design, text: Rope.ROPE] RETURNS[Rope.ROPE] = {CDPanel.PutUpText[design, $text, text]; RETURN[text]}; GetTextScanProp: PROC [design: CD.Design] RETURNS[tspRef: REF TSPType] = { tspRef _ NARROW[CDValue.Fetch[design, $TextScanProp]]; IF tspRef=NIL THEN { tspRef _ NEW[TSPType _ text]; CDValue.Store[design, $TextScanProp, tspRef]}; RETURN[tspRef]}; SetTextScanProp: PROC [design: CD.Design, tsp: TSPType] = { tspRef: REF TSPType _ GetTextScanProp[design]; tspRef^ _ tsp; CDValue.Store[design, $TextScanPropNm, tspNms[tsp]]; []_CDPanel.PutUp[design, $TextScanPropNm]}; CycleTextScanProp: PROC[design: CD.Design] = { tsp: TSPType _ GetTextScanProp[design]^; tspLast: TSPType _ LAST[TSPType]; tspn: CARDINAL _ tsp.ORD; tspl: CARDINAL _ tspLast.ORD; SetTextScanProp[design, VAL[(tspn+1) MOD (tspl+1)]]}; <> <> menu: PopUpMenus.Menu _ CDPopUpMenus.MakeMenu[ key: $TextOps, header: "TextOps", doc: "Text Search and Replace Operations" ]; CDCommandOps.RegisterWithMenu[ menu: $OtherProgramMenu, entry: "TextOps", doc: "Text Search and Replace Operations", key: $TextOps, proc: NIL]; CDCommandOps.RegisterWithMenu[ menu: $TextOps, entry: "Find one matching rope in Design", doc: "Find one matching rope in Design", key: $FindOneMatchingRopeInDesign, proc: TextOpsMenuCommand ]; CDCommandOps.RegisterWithMenu[ menu: $TextOps, entry: "Find one matching rope in Context", doc: "Find one matching rope in Context", key: $FindOneMatchingRopeInContext, proc: TextOpsMenuCommand ]; CDCommandOps.RegisterWithMenu[ menu: $TextOps, entry: "Find each matching rope in Design", doc: "Find each matching rope in Design", key: $FindEachMatchingRopeInDesign, proc: TextOpsMenuCommand ]; CDCommandOps.RegisterWithMenu[ menu: $TextOps, entry: "Find each matching rope in Context", doc: "Find each matching rope in Context", key: $FindEachMatchingRopeInContext, proc: TextOpsMenuCommand ]; CDCommandOps.RegisterWithMenu[ menu: $TextOps, entry: "Replace one matching rope in Design", doc: "Replace one matching rope in Design", key: $ReplaceOneMatchingRopeInDesign, proc: TextOpsMenuCommand ]; CDCommandOps.RegisterWithMenu[ menu: $TextOps, entry: "Replace one matching rope in Context", doc: "Replace one matching rope in Context", key: $ReplaceOneMatchingRopeInContext, proc: TextOpsMenuCommand ]; CDCommandOps.RegisterWithMenu[ menu: $TextOps, entry: "Replace each matching rope in Design", doc: "Replace each matching rope in Design", key: $ReplaceEachMatchingRopeInDesign, proc: TextOpsMenuCommand ]; CDCommandOps.RegisterWithMenu[ menu: $TextOps, entry: "Replace each matching rope in Context", doc: "Replace each matching rope in Context", key: $ReplaceEachMatchingRopeInContext, proc: TextOpsMenuCommand ]; CDCommandOps.RegisterWithMenu[ menu: $TextOps, entry: "Search", doc: "Uses PROP and PATTERN from panel", key: $TextOpsSearch, proc: TextOpsButtonCommand ]; CDCommandOps.RegisterWithMenu[ menu: $TextOps, entry: "Replace", doc: "Uses PROP, PATTERN and TEXT from panel", key: $TextOpsReplace, proc: TextOpsButtonCommand ]; CDValue.RegisterKey[ $TextScanProp, NIL, $djc]; CDValue.RegisterKey[ $TextScanPropNm, NIL, $djc]; InitTextScanPropPanel[]; <> CDCommandOps.RegisterWithMenu[ menu: $SisyphIconMenu, entry: "Add Icon Border Pattern", doc: "Uses current layer and width and marks it as invisible to Sisyph.", key: $AddIconBorderPattern, proc: EnumDirectoryObjectsWithPattern ]; CDCommandOps.RegisterWithMenu[ menu: $SisyphIconMenu, entry: "Add Icon Border Selected", doc: "Uses current layer and width and marks it as invisible to Sisyph.", key: $AddIconBorderSelected, proc: EnumSelectedObjects ]; <> CDCommandOps.RegisterWithMenu[ menu: $SisyphIconMenu, entry: "Change Color Pattern", doc: "Use panel color and pattern", key: $ChangeColorPattern, proc: EnumDirectoryObjectsWithPattern ]; CDCommandOps.RegisterWithMenu[ menu: $SisyphIconMenu, entry: "Change Color Selected", doc: "Use panel color and selected cells", key: $ChangeColorSelected, proc: EnumSelectedObjects ]; <> CDCommandOps.RegisterWithMenu[ menu: $TextOps, entry: "Add Instance Expression To Each Selected", doc: "Add Instance Expression To Each Selected", key: $AddInstanceExpressionToEachSelected, proc: AddExpressionToEachSelected ]; CDCommandOps.RegisterWithMenu[ menu: $TextOps, entry: "Add Object Expression To Each Selected", doc: "Add Object Expression To Each Selected", key: $AddObjectExpressionToEachSelected, proc: AddExpressionToEachSelected ]; <> CDCommandOps.RegisterWithMenu[ menu: $TextOps, entry: "Add mulitple text lines", doc: "Terminate with 2 CR's", key: $AddTextLines, proc: AddTextLines ]; <> CDCommandOps.RegisterWithMenu[ menu: $TextOps, entry: "Build Cross Reference Lists", doc: "Build cross reference lists from public of selected", key: $BuildCrossReferenceLists, proc: BuildCrossReferenceLists ]; CDCommandOps.RegisterWithMenu[ menu: $TextOps, entry: "Build Cross Reference Lists - Unique only", doc: "Build cross reference lists from public of selected - Unique only", key: $BuildCrossReferenceListsUnique, proc: BuildCrossReferenceLists ]; END.