<> <> <> DIRECTORY Basics, IntDefs, IO, IntUtilityDefs, List, ParserErrorDefs, IntStorageDefs, IntTransDefs, OutputDefs, ParserTypeDefs, Rope; IntPhase1: CEDAR PROGRAM IMPORTS IO, List, OutputDefs, ParserTypeDefs, IntUtilityDefs, ParserErrorDefs, IntTransDefs, Rope EXPORTS IntDefs, IntStorageDefs = BEGIN OPEN IntUtilityDefs, IntStorageDefs; <> Layer: TYPE = RECORD [num: CARDINAL, body: Rope.ROPE]; curLayer, rootLayer: Layer; curSymbol: STEntry; -- symbol currently being defined rootSymbol: PUBLIC STEntry; endSeen: BOOLEAN; InitInterpreter: PUBLIC PROCEDURE RETURNS [BOOLEAN] = BEGIN curLayer _ [num: LAST[CARDINAL], body: NIL]; endSeen _ FALSE; rootSymbol _ NEW[STEntryRec _ [ bb: BBoxRecord[left:0,right:0,bottom:0,top:0], bbValid: FALSE, guts: NIL, symNumber: LAST[LONG CARDINAL], deleted: FALSE, expanded: FALSE, bound: FALSE, defined: FALSE, calledBy: NIL]]; curSymbol _ rootSymbol; RETURN[IntTransDefs.InitTransformation[] AND InitUtilities[]]; END; FinishInterpreter: PUBLIC PROCEDURE RETURNS [BOOLEAN] = BEGIN rootSymbol _ curSymbol _ NIL; RETURN[IntTransDefs.FinishTransformation[] AND FinishUtilities[]]; END; IDefineStart: PUBLIC PROCEDURE [symbolNumber: LONG CARDINAL, multiplier, divisor: LONG CARDINAL] = BEGIN rootLayer _ curLayer; curLayer _ [num: LAST[CARDINAL], body: NIL]; SetScale[multiplier,divisor]; -- SetScale does range checking curSymbol _ LookUp[symbolNumber]; IF curSymbol.defined THEN <> BEGIN mess: IO.STREAM _ IO.ROS[]; CompareSymNumbers: PROC [ ref1, ref2: REF ANY ] RETURNS [ c: Basics.Comparison ] -- List.CompareProc -- = BEGIN s1: STEntry = NARROW[ref1]; s2: STEntry = NARROW[ref2]; c _ SELECT s1.symNumber FROM < s2.symNumber => less, = s2.symNumber => equal, ENDCASE => greater; END; PrintSymbol: PROC [r: REF ANY, lr: LIST OF REF ANY ] = BEGIN s: STEntry = NARROW[r]; IF s = rootSymbol THEN mess.PutRope[" top"] ELSE mess.PutF[" %g", IO.int[s.symNumber]]; END; ParserErrorDefs.Report[IO.PutFR["Redefining Symbol %g", IO.int[symbolNumber]], Advisory]; TRUSTED BEGIN curSymbol.calledBy _ LOOPHOLE[List.Sort[LOOPHOLE[curSymbol.calledBy, LIST OF REF ANY], CompareSymNumbers]]; List.Map[LOOPHOLE[curSymbol.calledBy, LIST OF REF ANY], PrintSymbol]; END; IF mess.GetLength > 0 THEN OutputDefs.SendMessage[Other, IO.PutFR["Is called in symbols: %g", IO.rope[mess.RopeFromROS[]]]]; curSymbol.deleted _ TRUE; curSymbol _ LookUp[symbolNumber]; -- get a new one END; END; IDefineEnd: PUBLIC PROCEDURE = BEGIN curSymbol.defined _ TRUE; curSymbol _ rootSymbol; SetScale[1,1]; curLayer _ rootLayer; END; IDeleteDef: PUBLIC PROCEDURE [nSym: LONG CARDINAL] = BEGIN UndefineLarge: PROC [sym: STEntry] = BEGIN IF sym.symNumber >= nSym AND sym.defined THEN sym.deleted _ TRUE; END; MapSymbols[UndefineLarge]; END; ILayer: PUBLIC PROCEDURE [layerName: Rope.ROPE] = BEGIN curLayer _ [num: OutputDefs.Map[layerName], body: layerName]; END; IWire: PUBLIC PROCEDURE [width: LONG CARDINAL, a: ParserTypeDefs.Path] = BEGIN OPEN ParserTypeDefs; path1,path2: ParserTypeDefs.Path; l,r,b,t: INT; IF ParserTypeDefs.PathLength[a] = 1 THEN ParserErrorDefs.Report["Wire with Only One Point in Path", Advisory]; IF width = 0 THEN BEGIN ParserErrorDefs.Report["Wire with Null Width Specified, Ignored", Advisory]; RETURN; END; CheckLayer[]; path1 _ ParserTypeDefs.AllocatePath[]; ParserTypeDefs.CopyPath[a,path1]; IF curSymbol # NIL THEN BEGIN tpath: ParserTypeDefs.Path _ ParserTypeDefs.AllocatePath[]; ScalePath[path1,tpath]; ParserTypeDefs.FreePath[path1]; path1 _ tpath; width _ ScaleLong[width]; END; path2 _ ParserTypeDefs.AllocatePath[]; ParserTypeDefs.CopyPath[path1,path2]; [l,r,b,t] _ OutputDefs.BBWire[curLayer.num,width,path2]; StowObject[NEW[WireRec _ [ bb: BBoxRecord[left:l,right:r,bottom:b,top:t], layer: curLayer.num, width: width, p: path1]]]; ParserTypeDefs.FreePath[path1]; ParserTypeDefs.FreePath[path2]; END; StowObject: PROC [obj: ObjectRef] = BEGIN curSymbol.guts _ CONS[obj, curSymbol.guts]; END; IFlash: PUBLIC PROCEDURE [diameter: LONG CARDINAL, center: ParserTypeDefs.Point] = BEGIN l,r,b,t: INT; IF diameter = 0 THEN BEGIN ParserErrorDefs.Report["Flash with Null diameter Specified, Ignored", Advisory]; RETURN; END; CheckLayer[]; IF curSymbol # NIL THEN BEGIN diameter _ ScaleLong[diameter]; center _ ScalePoint[center]; END; [l,r,b,t] _ OutputDefs.BBFlash[curLayer.num,diameter,center]; StowObject[NEW[FlashRec _ [ bb: BBoxRecord[left:l,right:r,bottom:b,top:t], layer: curLayer.num, diameter: diameter, center: center]]]; END; IPolygon: PUBLIC PROCEDURE [a: ParserTypeDefs.Path] = BEGIN OPEN ParserTypeDefs; path1,path2: ParserTypeDefs.Path; l,r,b,t: INT; IF ParserTypeDefs.PathLength[a] < 3 THEN BEGIN ParserErrorDefs.Report["Polygon with < 3 Points in Path, Ignored", Advisory]; RETURN; END; CheckLayer[]; path1 _ ParserTypeDefs.AllocatePath[]; ParserTypeDefs.CopyPath[a,path1]; IF curSymbol # NIL THEN BEGIN tpath: ParserTypeDefs.Path _ ParserTypeDefs.AllocatePath[]; ScalePath[path1,tpath]; ParserTypeDefs.FreePath[path1]; path1 _ tpath; END; path2 _ ParserTypeDefs.AllocatePath[]; ParserTypeDefs.CopyPath[path1,path2]; [l,r,b,t] _ OutputDefs.BBPolygon[curLayer.num,path2]; StowObject[NEW[PolygonRec _ [ bb: BBoxRecord[left:l,right:r,bottom:b,top:t], layer: curLayer.num, p: path1]]]; ParserTypeDefs.FreePath[path1]; ParserTypeDefs.FreePath[path2]; END; IBox: PUBLIC PROCEDURE [length, width: LONG CARDINAL, center: ParserTypeDefs.Point, xRotation, yRotation: INT] = BEGIN l,r,b,t: INT; len,wid: INT; IF width = 0 OR length = 0 THEN BEGIN ParserErrorDefs.Report["Box with Null Width or Length Specified, Ignored", Advisory]; RETURN; END; IF xRotation = 0 AND yRotation = 0 THEN BEGIN ParserErrorDefs.Report["0,0 Rotation Defaulted to 1,0", Advisory]; xRotation _ 1; END; CheckLayer[]; IF curSymbol # NIL THEN BEGIN length _ ScaleLong[length]; width _ ScaleLong[width]; center _ ScalePoint[center]; END; [l,r,b,t] _ OutputDefs.BBBox[curLayer.num,length,width,center,xRotation,yRotation]; len _ length; wid _ width; StowObject[(IF yRotation=0 AND len=r-l AND wid=t-b AND center.x=(l+r)/2 AND center.y=(b+t)/2 THEN NEW[MBoxRec _ [ bb: BBoxRecord[left:l,right:r,bottom:b,top:t], layer: curLayer.num]] ELSE NEW[BoxRec _ [ bb: BBoxRecord[left:l,right:r,bottom:b,top:t], layer: curLayer.num, length: length, width: width, center: center, xRot: xRotation, yRot: yRotation]])]; END; ICallSymbol: PUBLIC PROCEDURE [symbolNumber: LONG CARDINAL, list: ParserTypeDefs.TList] = BEGIN OPEN ParserTypeDefs, IntTransDefs; call: Call; IntTransDefs.Push[]; <> WHILE TListLength[list] > 0 DO entry: ParserTypeDefs.TEntry; [,entry] _ ParserTypeDefs.RemoveTList[list]; WITH entry SELECT FROM t: ParserTypeDefs.Mirror => SELECT t.coords FROM X => IntTransDefs.Mirror[x]; Y => IntTransDefs.Mirror[y]; ENDCASE; t: ParserTypeDefs.Translate => IF t.x # 0 OR t.y # 0 THEN -- don't do null translations BEGIN IF curSymbol # NIL THEN IntTransDefs.Translate[ScaleLongInt[t.x],ScaleLongInt[t.y]] ELSE IntTransDefs.Translate[t.x, t.y]; END; t: ParserTypeDefs.Rotate => IntTransDefs.Rotate[t.xRot, t.yRot]; ENDCASE => ERROR; ENDLOOP; call _ NEW[CallRec _ [ bb: BBoxRecord[left:0,right:0,bottom:0,top:0], callee: LookUp[symbolNumber], t: IntTransDefs.GetLocal[]]]; IntTransDefs.Pop[]; TRUSTED {call.callee.calledBy _ LOOPHOLE[InsertIfNotMemb[LOOPHOLE[curSymbol], LOOPHOLE[call.callee.calledBy]]]}; StowObject[call]; END; IUserCommand: PUBLIC PROCEDURE[command: [0..9], userText: Rope.ROPE] = BEGIN user: UserCmd = NEW[UserCmdRec _ [ command: command, data: userText ]]; StowObject[user]; END; InsertIfNotMemb: PROC [ref: REF ANY, list: LIST OF REF ANY] RETURNS [LIST OF REF ANY] = BEGIN prev: LIST OF REF ANY _ NIL; FOR l: LIST OF REF ANY _ list, l.rest WHILE l#NIL DO IF l.first = ref THEN BEGIN IF prev=NIL THEN RETURN[list] ELSE { prev.rest _ l.rest; l.rest _ list; RETURN[l] }; END; prev _ l; ENDLOOP; RETURN[CONS[ref, list]]; END; IComment: PUBLIC PROCEDURE [contents: Rope.ROPE] = {NULL}; IEnd: PUBLIC PROCEDURE = BEGIN endSeen _ TRUE; END; <> CheckLayer: PROCEDURE = INLINE BEGIN IF curLayer.body.Length = 0 THEN LogError["No Layer Specified"]; END; IUserObject: PUBLIC PROCEDURE [data: REF ANY] = BEGIN OPEN ParserTypeDefs; l,r,b,t: INT; [l,r,b,t] _ OutputDefs.BBUserObject[curLayer.num, data]; StowObject[NEW[UserObRec _ [ bb: BBoxRecord[left:l,right:r,bottom:b,top:t], layer: curLayer.num, data: data]]]; END; <> IScaleLong: PUBLIC PROCEDURE [n: LONG CARDINAL] RETURNS [LONG CARDINAL] = BEGIN RETURN[ScaleLong[n]]; END; <> IScaleLongInt: PUBLIC PROCEDURE [n: INT] RETURNS [INT] = BEGIN RETURN[ScaleLongInt[n]]; END; END.