/* LMININ (GED) -- Orcad MIN Layout Data Import */ /* LMININ (GED) -- Orcad MIN Layoutdatenuebernahme */ /* // Copyright (c) 2005-2012 Oliver Bartels F+E, Muenchen // Author: Roman Ludwig // Changes History: // rl (120427) RELEASED FOR BAE V7.8. // rl (110218) ENHANCEMENT: // Added dynamic pin text size support. // Optimized all layer pad stackup. // rl (101220) ENHANCEMENT: // Added copper fill area parameter support. // rl (101019) RELEASED FOR BAE V7.6. // rl (091021) RELEASED FOR BAE V7.4. // rl (081014) RELEASED FOR BAE V7.2. // rl (071029) RELEASED FOR BAE V7.0. // rl (070803) BUGFIX: // Fixed problem with rotated pad shapes. // rl (060829) RELEASED FOR BAE V6.8. // rl (050906) RELEASED FOR BAE V6.6. // rl (050323) ORIGINAL CODING. // // DESCRIPTION // // The lminin User Language program reads Orcad layout data // from a selectable MIN file. */ // Includes #include "pop.ulh" // User Language popup utilities #include "lay.ulh" // User Language layout utilities // Disable undo state request #pragma ULCALLERNOUNDO // Messages string REPPARSE = M("Lesen Datei '%s'...","Reading file '%s'..."); string REPDONE = M("Es wurden keine Fehler festgestellt.", "Operation completed."); string UPRPARFILE = M("Parameterdefinitionsdatei ? ", "Parameter Definition File ? "); string UPRMINFILE = M("Orcad-MIN-Eingabe-Datei ? ", "Orcad MIN Library Data File ? "); string REPOVALOBL = M("[%s/%d]: Padstack '%s' Padform Oval in Oblong umgewandelt!\n", "[%s/%d]: Padstack '%s': replaced pad shape oval by oblong!\n"); string ERRPLCPOLY = M("[%s/%d]: Fehler bei der Polygonerzeugung!\n", "[%s/%d]: Error generating polygon!\n"); string ERRPLCPATH = M("[%s/%d]: Fehler bei der Leiterbahnerzeugung!\n", "[%s/%d]: Error generating path!\n"); string ERRPLCTEXT = M("[%s/%d]: Fehler bei der Texterzeugung '%s'!\n", "[%s/%d]: Error generating text '%s'!\n"); string ERRLONGTEXT = M("[%s/%d]: Ueberlanger Text '%s' gekuerzt zu '%s'!\n", "[%s/%d]: Long text '%s' truncated to '%s'!\n"); string ERRPLCPIN = M("[%s/%d]: Fehler bei der Pinplazierung '%s'/'%s'!\n", "[%s/%d]: Error placing pin '%s'/'%s'!\n"); string ERRPLCPART = M("[%s/%d]: Fehler bei der Bauteilplazierung '%s'/'%s'!\n", "[%s/%d]: Error placing part '%s'/'%s'!\n"); string ERRPLCVIA = M("[%s/%d]: Fehler bei der Viaplazierung '%s'!\n", "[%s/%d]: Error placing via '%s'!\n"); string ERREMPTYSTK = M("[%s/%d]: Leerer Padstack '%s' ignoriert!\n", "[%s/%d]: Empty padstack '%s' ignored!\n"); string ERRLONGSYMN = M("[%s/%d]: Ueberlanger Name '%s' gekuerzt zu '%s'!\n", "[%s/%d]: Long name '%s' truncated to '%s'!\n"); // INI file parameter name definitions #define PAR_PLTDRL "PLTDRL_LAY" // Plated drill class #define PAR_UPLTDRL "UPLTDRL_LAY" // Unplated drill class #define PAR_HDRCLAY "HDRC_LAY" // Height DRC layer #define PAR_UNDEFH "UNDEFH_LAY" // Undefined height value #define PAR_MINHEIGHT "MINHEIGHT_LAY" // Min. height value #define PAR_PDRCLAY "PDRCLAY_LAY" // Part DRC layer #define PAR_PICKLAY "PICKLAY_LAY" // Insertion pick layer #define PAR_PICKNAMES "PICKNAMES_LAY" // Insertion pick text size #define PAR_DEFPARFN "DEFPARFN_LAY" // Default parameter setup file name #define PAR_LINEWFAC "LINEWFAC_LAY" // Line width scale factor #define PAR_TEXTWFAC "TEXTWFAC_LAY" // Text width scale factor #define PAR_PARTNAMES "PARTNAMES_LAY" // Part name fixed size #define PAR_PINNAMES "PINNAMES_LAY" // Pin name fixed size #define PAR_PINNLAY "PINNLAY_LAY" // Pin number layer #define PAR_PADCIRC "MINPADCIR_LAY" // Circle pad name pattern #define PAR_PADSQUARE "MINPADSQU_LAY" // Square pad name pattern #define PAR_PADRECT "MINPADREC_LAY" // Rectangle pad name pattern #define PAR_PADOBLONG "MINPADOBL_LAY" // Oblong pad name pattern #define PAR_PADOVAL "MINPADOVL_LAY" // Oval pad name pattern #define PAR_NAMEDIM "MINNAMEDIM_LAY"// Name dimension factor #define PAR_ROUNDDIM "MINRNDDIM_LAY" // Dimension rounding precision #define PAR_DRLISO "MINDRLISO_LAY" // Drill isolation distance // Polygon point definitions struct point { // Point descriptor double x,y /* Point coordinates */; int t /* Point type */; } curpolyl[],emptyl[] /* Polygon buffers */; int curpolyn = 0 /* Polygon buffer size */; // Polygon definitions struct polydes { // Polygon descriptor struct point pl[] /* Polygon point list */; int pn /* Polygon point count */; int lay /* Polygon layer */; int ptyp /* Polygon type */; int netidx /* Polygon net index */; int zorder /* Polygon fill z order */; double mdist /* Polygon min. checking distance */; int line /* Polygon line */; int hdrc /* Polygon height DRC flag */; double w /* Polygon draw width */; }; // Path definitions struct pathdes { // Path descriptor struct point pl[] /* Path point list */; int pn /* Path point count */; int lay /* Path layer */; double w /* Path width */; int fix /* Path fixed flag */; int locked /* Path locked flag */; int line /* Path line */; } pathl[] /* Path list */; int pathn = 0 /* Path count */; // Shape definitions struct shapedes { // Shape descriptor int typ /* Shape type */; double dim1 /* Shape 1st dimension */; double dim2 /* Shape 2nd dimension */; double dim3 /* Shape 3rd dimension */; double dim4 /* Shape 4th dimension */; string name /* Shape name */; } shapel[] /* Shape list */; int shapen = 0 /* Shape count */; struct keepoutdes { // Keepout descriptor int typ /* Keepout shape type */; double dim1 /* Keepout 1st dimension */; double dim2 /* Keepout 2nd dimension */; double dim3 /* Keepout 3rd dimension */; double dim4 /* Keepout 4th dimension */; int lay /* Keepout layer */; int line /* Keepout line */; } keepoutl[] /* Padstack keepout shape list */; int keepoutn = 0 /* Padstack keepout shape count */; // Pad definitions struct paddes { // Pad descriptor int lay /* Pad layer */; int sidx /* Pad shape index */; } padl[] /* Pad list */; int padn = 0 /* Pad count */; // Padstack definitions STRINGS pstkl /* Padstack name list */; int pstkn = 0 /* Padstack count */; // Pin definitions struct pindes { // Pin descriptor string name /* Pin name */; double x,y /* Pin position */; int line /* Pin line */; int pidx /* Pin padstack index */; }; // Text definitions struct textdes { // Text descriptor string str /* Text string */; double x,y /* Text position */; double ang /* Text angle */; int mirr /* Text mirror flag */; double h /* Text height */; double w /* Text line width */; int lay /* Text layer */; int line /* Text line */; } textl[] /* Text list */; int textn = 0 /* Text count */; // Symbol definitions struct symdes { // Symbol descriptor struct polydes pl[] /* Symbol polygon list */; int pn /* Symbol polygon count */; struct pindes pinl[] /* Symbol pin list */; int pinn /* Symbol pin count */; struct textdes textl[] /* Symbol text list */; int textn /* Symbol text count */; int derived /* Symbol derived index */; int via /* Symbol via flag */; double pickx, picky /* Symbol pick point */; string name /* Symbol name */; } syml[] /* Symbol list */; int symn = 0 /* Symbol count */; // Component definitions struct compdes { // Component descriptor int sidx /* Component symbol index */; string name /* Component name */; double x,y /* Component position */; double ang /* Component angle */; int mirr /* Component mirror flag */; int netidx /* Polygon net index */; int via /* Component via flag */; int fixed /* Symbol fixed flag */; int locked /* Symbol locked flag */; int line /* Component line */; } compl[] /* Component list */; int compn = 0 /* Component count */; struct viades { // Via descriptor int sidx /* Via symbol index */; int line /* Via line */; double x,y /* Via position */; int netidx /* Net index */; } vial[] /* Via list */; int vian = 0 /* Via count */; // Net definitions struct netdes { // Net descriptor string name /* Net name */; int compidx /* Net sample component index */; int pinidx /* Net sample pin index */; } netl[] /* Net list */; #define SCIRCLE 0 // Circle shape #define SSQUARE 1 // Square shape #define SRECT 2 // Rectangle shape #define SOBLONG 3 // Oblong shape #define SOVAL 4 // Oblong shape #define SUNDEF 100 // Undefined shape int DRLCLPLATED = bae_iniintval(PAR_PLTDRL,0) /* Plated hole drill class */; int DRLCLUNPLATED = bae_iniintval(PAR_UPLTDRL,1) /* Unplated hole drill class */; int HDRCLAY = bae_iniintval(PAR_HDRCLAY,0x4A0) /* Height DRC layer */; double UNDEFHEIGHT = bae_inidblval(PAR_UNDEFH,0.1) /* Undefined part height */; double MINHEIGHT = bae_inidblval(PAR_MINHEIGHT,0.00003) /* Min. part height */; double DRLISO = bae_inidblval(PAR_DRLISO,0.00025) /* Drill isolation */; int PDRCLAY = bae_iniintval(PAR_PDRCLAY,0x450) /* Part DRC layer */; int PICKLAY = bae_iniintval(PAR_PICKLAY,0x491) /* Insertion pick layer */; double PICKNAMESIZE = bae_inidblval(PAR_PICKNAMES,0.001) /* Pick name size,0.0 for no text */; double LINEWFAC = bae_inidblval(PAR_LINEWFAC,0.0) /* Line width scale factor */; double TEXTWFAC = bae_inidblval(PAR_TEXTWFAC,0.0) /* Text line width scale factor */; double PARTNAMESIZE = bae_inidblval(PAR_PARTNAMES,0.001) /* Part name size,0.0 for inp. size */; int PINNLAY = bae_iniintval(PAR_PINNLAY,0x460) /* Pin number layer */; double PINNAMESIZE = bae_inidblval(PAR_PINNAMES,0.001) /* Pin name size, 0.0 for no disp. */; string PADCIRC = bae_inistrval(PAR_PADCIRC,"c%.3f") /* Circle pad name pattern */; string PADRECT = bae_inistrval(PAR_PADRECT,"r%.3fx%.3f") /* Rectangle pad name pattern */; string PADSQUARE = bae_inistrval(PAR_PADSQUARE,"s%.3f") /* Square pad name pattern */; string PADOBLONG = bae_inistrval(PAR_PADOBLONG,"l%.3fx%.3f") /* Oblong (line) pad name pattern */; string PADOVAL = bae_inistrval(PAR_PADOVAL,"o%.3fx%.3f") /* Oval pad name pattern */; string DEFPARFN = bae_inistrval(PAR_DEFPARFN,"orcad.par") /* Def. parameter setup file name */; double nameconv = bae_inidblval(PAR_NAMEDIM,1000.0) /* Name dimension conversion factor */; double rounddim = bae_inidblval(PAR_ROUNDDIM,0.000001) /* Pad dimension rounding precision */; // Layer definitins #define LAYERDRL (-0x100) // Drill layer struct laydes { /* Layer descriptor */ string name /* Layer name */; int lay /* Layer code */; int used /* Layer used flag */; } layl[] /* Layer list */; int layn = 0 /* Layer count */; int nextilay = 0 /* Next inner layer code */; int inslayidx /* Insert layer index */; int siglaycnt = 0 /* Signal layer count */; int tlayl[] /* Transform layer list */; int tlayn = 0 /* Transform layer count */; struct repldes { /* String replacement descriptor */ string oldstr /* Old sub string */; string newstr /* New sub string */; }; struct repldes rplcstrl[] = { /* Replacement string list */ { "smd-1825-", "1825-" }, { "smd-flat-", "flat-" }, { "smd-minimelf-", "minimelf-" }, { "smd-msop-", "msop-" }, { "smd-plcc-", "plcc-" }, { "smd-pqfp-", "pqfp-" }, { "smd-qfp-", "qfp-" }, { "smd-qsop", "qsop" }, { "smd-to263-", "to263-" }, { "smd-tqfp-", "tqfp-" }, { "smd-tsop-", "tsop-" }, { "smd-tssop-", "tssop-" }, { "smd-s-", "s-" }, { "smd-smt", "smt" }, { "smd-so", "so" }, { "smd-ssop-", "ssop-" }, { "smd-vqfp-", "vqfp-" } }; int rplcstrn= 0/* arylength(rplcstrl)*/ /* Replacement string count */; // Scanner variables string quostr /* Current quoted string value */; string curname /* Current name */; string curtextstr /* Current text string */; string curlayername /* Current layer name */; int curshapetyp /* Current shape type */; int toplayer = 1 /* Current top layer */; int curlayer /* Current layer code */; int pathlayer /* Current path code */; int curidx /* Current index */; int curnetidx /* Current net index */; int curzorder /* Current fill z order */; int curpinidx /* Current pin index */; int curvia /* Current via flag */; int curfixed /* Current fixed flag */; int curlocked /* Current locked flag */; int cursymidx /* Current symbol index */; int curcompidx /* Current component index */; int curnetcompidx /* Current net component index */; int curpolytyp /* Current polygon type */; int curnoconnect /* Current pad connect type */; int curhpoly /* Current height polygon flag */; double curx, cury /* Current coordinates */; double curwidth /* Current width value */; double pathwidth /* Current path width value */; double curheight /* Current height value */; double curdim1 /* Current 1st dimension value */; double curdim2 /* Current 2nd dimension value */; double curdim3 /* Current 3rd dimension value */; double curdim4 /* Current 4th dimension value */; double curang /* Current angle */; int curint /* Current integer */; int curmirr /* Current mirror flag */; int curswitch /* Current switch value */; int curplated /* Current plated drill */; double curdrlrad /* Current drill radius */; double curdrillclass /* Current drill class */; double curflt /* Current float value */; double curmdist /* Current checking distance */; double chkdist = 0.0 /* Current plan checking distance */; double lenconv = 1.0/cvtlength(1.0,0,2) /* Length conv. fact. (default mm) */; double angconv = cvtangle(1.0,1,0)/60.0 /* Angle conv. factor */; // Geometric constants double PI = cvtangle(180.0,1,2) /* PI (180 degree) value */; // File definitions #define MINEXT ".min" // Orcad MIN data file name extension #define PAREXT ".par" // OrCAD parameter file name extension #define MSGEXT "_l.lst" // Message file name extension string minfname /* MIN input file name */; string ddbfname /* Output database file name */; string parfname /* Parameter definition file name */; string msgfname /* Message file name */; int mfh /* Message file handle */; // Main program void main() { int fh /* Test file handle */; // Save current element with verification on request verifysave(); // Test the output file fseterrmode(0); if ((fh=fopen(DEFPARFN,0))!=(-1)) { fclose(fh); parfname=DEFPARFN; fseterrmode(1); } else { fseterrmode(1); // Select the parameter definition file if (bae_askfilename(parfname,PAREXT,UPRPARFILE) || parfname=="") error_abort(); } // Select the Orcad min data file if (bae_askfilename(minfname,MINEXT,UPRMINFILE) || minfname=="") error_abort(); // Save current state for undo bae_callmenu(MNU_BAESAVESTATE); // Build the output database name ddbfname=convstring(minfname,0)+DDBEXT; // Create message file msgfname=convstring(minfname,0)+MSGEXT; if (bae_swconfig(1)==BAE_Demo) mfh=(-1); else mfh=fopen(msgfname,1); parsefiles(minfname,parfname); if (mfh!=(-1)) fclose(mfh); // Print done message bae_prtdialog(REPDONE); } /*________________________________________________________________*/ // Orcad MIN input data BNF syntax description #bnf { // Orcad MIN BNF input syntax definition min_file : "(" "MIN" min_prologcmds "(" "Begin" min_defs "(" "End" ")" ")" ")" (p_storedata) | paramdeflist EOF ; paramdeflist : paramdeflist paramdef | paramdef ; paramdef : namestring (p_layername) "=" baelayer (p_layerend) | "PLATED_DRILLS" "=" drillclass (p_baeplated(1)) | "UNPLATED_DRILLS" "=" drillclass (p_baeplated(0)) | "DRILL_KEEPOUT" "=" mmdim (p_drillisol) | "PART_DRC" "=" docnum (p_partdrc) | "HEIGHT_DRC" "=" docnum (p_heightdrc) | "DEFAULT_HEIGHT" "=" mmdim (p_defheight) | "MINIMUM_HEIGHT" "=" mmdim (p_minheight) | "LINE_WIDTH_SCALE" "=" fltnum (p_linewscale) | "TEXT_WIDTH_SCALE" "=" fltnum (p_textwscale) | "INSERTION_PICK" "=" docnum optdocside (p_picklay) | "PICK_TEXT_SIZE" "=" mmdim (p_picktextsize) | "PART_NAME_SIZE" "=" mmdim (p_partnamesize) | "PIN_NAME_SIZE" "=" mmdim (p_pinnamesize) | "PIN_NAME_LAYER" "=" docnum optdocside (p_pinnamelayer) | "NAME_DIM_BASE" "=" mmdim (p_namedimbase) | "PAD_CIRCLE_PATTERN" "=" DQSTR (p_padcircpattern) | "PAD_RECTANGLE_PATTERN" "=" DQSTR (p_padrectpattern) | "PAD_SQUARE_PATTERN" "=" DQSTR (p_padsquarepattern) | "PAD_OBLONG_PATTERN" "=" DQSTR (p_padoblongpattern) | "PAD_OVAL_PATTERN" "=" DQSTR (p_padovalpattern) | "ROUNDING_BASE" "=" mmdim (p_rnddimbase) ; baelayer : docnum optdocside | "SIGLAYER" NUMBER (p_signal) | "POWLAYER" NUMBER (p_power) | "SIGNALALL" (p_neglaynum(1)) | "OUTLINE" (p_neglaynum(2)) | "SIGNALTOP" (p_neglaynum(5)) | "SIGNALINNER" (p_neglaynum(6)) | "DRILL" (p_neglaynum(256)) ; docnum : "DOCLAYER" NUMBER (p_docnum) ; optdocside : "TOP" (p_docside(1)) | "BOTTOM" (p_docside(0)) | "BOTH" (p_docside(2)) | ; min_prologcmds : min_prologcmds min_prologcmd | min_prologcmd ; min_prologcmd : "(" "Version" NUMBER ")" | "(" "MajorRev" NUMBER ")" | "(" "MinorRev" NUMBER ")" | "(" laynum ")" | "(" "V" NUMBER ")" ; min_defs : min_defs min_def | min_def | ; min_def : "(" "Header" min_headcmds ")" | "(" "Strat" indexval name stratcmds ")" | "(" "PlaceStrat" pstratcmds ")" | "(" layidx name (p_layername) "(" "N" quostr ")" "(" "N" quostr ")" "(" "Uid" intnum ")" layercmds ")" (p_tlayerend) | "(" "THRU" indexval name (p_stkstart) "(" "Uid" intnum ")" stkcmds ")" (p_stkend) | "(" "SYM" symindexval name (p_symstart) "(" "Uid" intnum xcoord ycoord (p_pick) intnum intnum ")" partcmds ")" | "(" "Package" indexval name "(" "Uid" intnum ")" packcmds ")" | "(" "COMP" indexval name (p_compini) compcmds ")" (p_comp) | "(" "Net" netindexval name (p_netname) "(" "Uid" intnum ")" netcmds ")" | "(" "C" "(" "Net" netindexval (p_conini) ")" concmds (p_conend) ")" | "(" "Obs" (p_obsini) indexval "(" "N" quostr ")" "(" "Uid" intnum ")" obscmds ")" (p_obsend) | "(" "Text" indexval "(" "N" quostr (p_textini) ")" "(" "N" quostr ")" "(" "Uid" intnum ")" textcmds ")" (p_text) | "(" "Attr" attdest indexval attrid NUMBER IDENT quostr NUMBER "Uid" intnum ")" | "(" "Err" indexval errcmds ")" | "(" "Report" indexval repcmds ")" | "(" "Aperture" indexval aptcmds ")" | colcmd ; min_headcmds : min_headcmds min_headcmd | min_headcmd ; min_headcmd : "(" "Grid" coorddim ")" | "(" "ViaGrid" coorddim ")" | "(" "UserDiv" coorddim ")" | "(" "DisplayGrid" coorddim ")" | "(" "PlaceGrid" coorddim coorddim ")" | "(" "DetailGrid" coorddim coorddim ")" | "(" "DotGrid" coorddim coorddim ")" | "(" "DisplayPrecision" coorddim ")" | "(" "Origin" coorddim coorddim ")" | "(" "InchFactor" fltnum (p_unit) ")" | "(" "Resume" intnum xcoord ycoord xcoord ycoord ")" | "(" "View" xcoord ycoord xcoord ycoord ")" | "(" "OffGrid" onoff ")" | "(" "MultiVia" onoff ")" | "(" "Metric" onoff ")" | "(" "ConnectThruPours" ")" | "(" "Library" ")" | "(" "BackupSweep" onoff ")" | "(" "BackupInterval" coorddim ")" | "(" "TimeUsed" coorddim ")" | "(" "RotateAngle" coorddim ")" | "(" "AngleSnap" coorddim ")" | "(" "PinTestPoints" onoff ")" | "(" "DrillSize" drillsizecmds ")" | "(" "DrlChartLoc" coorddim coorddim ")" | "(" "DrlChartTextHeight" coorddim ")" | "(" "DrlChartLineWidth" coorddim ")" | "(" "SmallAnnularDrill" coorddim ")" | "(" "SmallIsolationWidth" coorddim ")" | "(" "SmallSpokeWidth" coorddim ")" | "(" "LargeAnnularDrill" coorddim ")" | "(" "LargeIsolationWidth" coorddim ")" | "(" "LargeSpokeWidth" coorddim ")" | "(" "Translucent" onoff ")" | "(" "DoPG" onoff ")" | "(" "PgLock" onoff ")" | "(" "PgDisable" onoff ")" | "(" "PgShare" onoff ")" | "(" "DoSigs" onoff ")" | "(" "SigLock" onoff ")" | "(" "SigShare" onoff ")" | "(" "DirInside" onoff ")" | "(" "DirOutside" onoff ")" | "(" "OnlyOffGrid" onoff ")" | "(" "PgFrVia" onoff ")" | "(" "SigFrVia" onoff ")" | "(" "FanoutVia" NUMBER ")" | "(" "Override" onoff ")" | "(" "MaxDistance" coorddim ")" | "(" UNKNOWN coorddim ")" ; drillsizecmds : drillsizecmds drillsizecmd | drillsizecmd ; drillsizecmd : "(" "Diam" coorddim ")" | "(" "Symbol" symindexval ")" | "(" "DrlTol" quostr ")" | "(" "DrlNote" quostr ")" ; stratcmds : stratcmds stratcmd | stratcmd ; stratcmd : "(" "Diag" "Max" ")" | "(" "Dir" dir dir dir dir ")" | "(" "Pass" indexval passcmds ")" | "(" layidx slaycmds ")" | box ; pstratcmds : pstratcmds pstratcmd | pstratcmd ; pstratcmd : box | "(" "MatrxNoSwp" ")" | "(" "Pass" indexval ppasscmds ")" | "(" layidx slaycmds ")" ; passcmds : passcmds passcmd | passcmd | ; passcmd : enabled | "(" "Done" onoff ")" | "(" "Dispersion" ")" | "(" "Heur" ")" | "(" "Maze" ")" | "(" "ViaReduce" ")" | "(" "Reroute" ")" | "(" "Nearest" onoff ")" | "(" "Partial" onoff ")" | "(" "Fast" onoff ")" | "(" "Via" intnum ")" | "(" "Retry" intnum ")" | "(" "Limit" intnum ")" | "(" "Attempts" intnum ")" ; ppasscmds : ppasscmds ppasscmd | ppasscmd | ; ppasscmd : "(" "ProxPlace" ")" | "(" "ClusterAssign" ")" | "(" "ClusterPlace" ")" | "(" "SwapComp" ")" | "(" "SwapPin" ")" | "(" "Align" ")" | "(" "FastRecon" ")" | enabled | "(" "Done" onoff ")" | "(" "Iterations" intnum ")" | "(" "Attempts" intnum ")" ; slaycmds : slaycmds slaycmd | slaycmd | ; slaycmd : enabled | "(" "Dir" intnum ")" | "(" "Cost" intnum ")" | "(" "BottleNeck" intnum ")" ; layercmds : layercmds layercmd | layercmd | ; layercmd : "(" "Etch" ")" | "(" "Plane" ")" | "(" "Doc" ")" | "(" "Drill" ")" | "(" "Mirror" NUMBER ")" | "(" "TT" NUMBER ")" | "(" "TV" NUMBER ")" | "(" "TP" NUMBER ")" | "(" "VV" NUMBER ")" | "(" "VP" NUMBER ")" | "(" "PP" NUMBER ")" | "(" "Stair" NUMBER ")" | "(" "Unused" ")" ; stkcmds : stkcmds stkcmd | stkcmd | ; stkcmd : "(" "BlockHolder" onoff ")" | "(" "TestPt" onoff ")" | "(" "NonPlated" (p_switchini) onoff (p_plated) ")" | "(" "LgThermal" onoff ")" | "(" "DirectHit" onoff ")" | "(" laynum "(" shape ")" shapespecs ")" (p_padshape) ; shape : "UNDEF" (p_shapetyp(100)) | "Round" (p_shapetyp(0)) dim1 | "Annular" (p_shapetyp(0)) dim1 dim2 dim3 dim4 | "Square" (p_shapetyp(1)) dim1 | "Rect" (p_shapetyp(2)) dim1 dim2 dim3 dim4 | "Oblong" (p_shapetyp(3)) dim1 dim2 dim3 dim4 | "Oval" (p_shapetyp(4)) dim1 dim2 dim3 dim4 ; shapespecs : shapespecs shapespec | shapespec | ; shapespec : "(" "NoConnect" (p_noconnect) ")" | "(" "R" angnum ")" ; netcmds : netcmds netcmd | netcmd | ; netcmd : "(" widthval ")" | "(" "Min" intnum ")" | "(" "Max" intnum ")" | "(" "BW" intnum ")" | "(" "BMin" intnum ")" | "(" "BMax" intnum ")" | "(" "Weight" coorddim ")" | "(" "Group" intnum ")" | "(" "Color" intnum ")" | "(" "Reconnect" onoff ")" | "(" "Reconn" "None" ")" | "(" "NetViaRestrict" ")" ; concmds : concmds concmd | concmd | ; concmd : "(" "P" intnum (p_netcomp) intnum (p_netpin) ")" | "(" laynum (p_conlay) ")" | "(" "V" indexval (p_convia) ")" | "(" widthval ")" | "(" "BW" coorddim (p_conwidth) ")" | "(" xcoord ycoord ")" (p_point) | "(" "AnyLock" ")" | "(" "Locked" (p_locked) ")" ; packcmds : packcmds packcmd | packcmd | ; packcmd : "(" "P" quostr quostr intnum intnum ")" ; partcmds : partcmds partcmd | partcmd | ; partcmd : "(" "Derived" NUMBER (p_derived) ")" | "(" "P" indexval name xcoord ycoord stkref ")" (p_pin) | "(" "Via" (p_symvia) ")" ; stkref : indexval stkrefcmds ; stkrefcmds : stkrefcmds stkrefcmd | stkrefcmd | ; stkrefcmd : "(" "ExitRule" quostr ")" | "(" "ViaUnder" ")" | "(" "ForcedThermalRelief" ")" ; compcmds : compcmds compcmd | compcmd | ; compcmd : "(" "Value" quostr ")" | symref | "(" xcoord ycoord ")" (p_point) | enabled | "(" "Fixed" (p_fixed) ")" | "(" "Group" intnum ")" | "(" "Locked" (p_locked) ")" | "(" "NonElectric" ")" | "(" "NoRename" ")" | "(" "Uid" intnum ")" | "(" "N" quostr ")" | "(" "R" angnum ")" | mirrored | "(" "Via" (p_compvia) ")" | "(" "Package" intnum ")" ; obscmds : obscmds obscmd | obscmd | ; obscmd : "(" "OutLine" (p_polytyp(5)) ")" /* L_POLYDOCLINE */ | "(" "CompOutline" (p_polytyp(102)) ")" /* L_POLYKEEPOUT+h */ | "(" "NoFill" ")" | "(" "LineFill" ")" | "(" "SolidFill" /* Fill ? (p_polytyp(200)) */ ")" | "(" "Poured" (p_polytyp(7)) ")" /* L_POLYCOPFILL */ | "(" "KeepIn" ")" | "(" "KeepOut" (p_polytyp(2)) ")" /* L_POLYKEEPOUT */ | "(" "CompKeepout" ")" | "(" "Detail" (p_polytyp(5)) ")" /* L_POLYDOCLINE */ | "(" "Dimension" ")" | "(" "DrillChart" ")" | "(" "Hole" (p_polytyp(2)) ")" /* L_POLYKEEPOUT */ | "(" "Grid" intnum ")" | "(" "zOrder" intnum (p_zorder) ")" | "(" "Circle" ")" | "(" "Arc" ")" | "(" "Text" ")" | "(" "Generated" ")" | "(" "Created" ")" | "(" "Width" coorddim ")" | pdef | symref | compref | "(" laynum ")" | "(" widthval ")" | "(" "CLEARANCE" coorddim (p_clearance) ")" | "(" "Rot" NUMBER ")" | "(" "NoNet" ")" | "(" "Net" netindexval ")" | "(" xcoord ycoord ")" (p_point) | "(" "CCW" (p_ptyp(1)) ")" | "(" "CW" (p_ptyp(2)) ")" ; textcmds : textcmds textcmd | textcmd | ; textcmd : symref | compref | "(" widthval ")" | "(" heightval ")" | "(" xcoord ycoord ")" | "(" "Aspect" NUMBER ")" | "(" laynum ")" | "(" "R" angnum ")" | "(" "RefDes" ")" | "(" "CompValue" ")" | "(" "Dimension" ")" | "(" "DrillChart" ")" | "(" "Free" ")" | mirrored ; attdest : "Comp" | "Net" | "Count" | "Thru" | "Rpt" | "L" ; errcmds : errcmds errcmd | errcmd | ; errcmd : "(" xcoord ycoord ")" | "(" "ErrKind" NUMBER ")" | "(" "Object" objecttypes ")" | "(" laynum ")" | "(" "Mz" ")" | "(" "Uid" intnum intnum ")" | "(" "OffSet" xcoord ycoord ")" | "(" "Value" intnum ")" | "(" "CheckValue" intnum ")" ; objecttypes : objecttypes objecttyp | objecttyp | ; objecttyp : "Comp" | "Obs" | "Conn" | "Error" ; repcmds : repcmds repcmd | repcmd | ; repcmd : "(" "Output" quostr ")" | "(" "ColorSet" quostr ")" | "(" "Device" quostr ")" | "(" "Comment" quostr ")" | "(" "Position" NUMBER NUMBER NUMBER NUMBER NUMBER ")" | "(" "ColorCount" NUMBER ")" | colcmd | enabled | "(" "Mirror" ")" | "(" "AutoShift" onoff ")" | "(" "NewStyle" onoff ")" ; colcmd : "(" "Color" "(" colelemtyp "(" laynum ")" "(" "Group" NUMBER ")" "(" "Value" intnum ")" optcolspec ")" ")" ; optcolspec : "(" "compInner" ")" | "(" "compOuter" ")" | "(" "compKeepIn" ")" | "(" "compKeepOut" ")" | "(" "groupKeepIn" ")" | "(" "groupKeepOut" ")" | "(" "keepIn" ")" | "(" "keepOut" ")" | "(" "free" ")" | "(" "matrix" ")" | "(" "pinName" ")" | "(" "avoid" ")" | "(" "noVia" ")" | "(" "text" ")" | "(" "hole" ")" | "(" "symName" ")" | "(" "package" ")" | "(" "noRoute" ")" | ; aptcmds : aptcmds aptcmd | aptcmd | ; aptcmd : "(" "DCode" intnum ")" | "(" "Kind" quostr ")" | "(" "Shape" quostr ")" | "(" "Width" coorddim ")" | "(" "Height" coorddim ")" | "(" "Angle" angnum ")" | "(" "Created" ")" | "(" "LgThermal" ")" ; colelemtyp : "background" | "default" | "comp" | "obs" | "text" | "edge" | "highlight" | "errcolor" | "datum" | "grid" ; dir : "UP" | "LEFT" | "RIGHT" | "DOWN" | "NEXT" ; name : "(" "N" quostr (p_name) ")" ; namestring : quostr (p_name) ; pdef : "(" "P" NUMBER (p_pinref) ")" ; box : "(" "Box" dim1 dim2 dim3 dim4 ")" ; enabled : "(" "Enabled" onoff ")" ; mirrored : "(" "Mirrored" (p_mirr) ")" ; xcoord : coorddim (p_x) ; ycoord : coorddim (p_y) ; dim1 : coorddim (p_dim1) ; dim2 : coorddim (p_dim2) ; dim3 : coorddim (p_dim3) ; dim4 : coorddim (p_dim4) ; coorddim : fltnum (p_coorddim) ; mmdim : fltnum "mm" (p_mmdim) ; quostr : DQSTR (p_quostr) ; intnum : NUMBER (p_intval(0)) | "-" NUMBER (p_intval(1)) ; angnum : NUMBER (p_angnum(0)) | "-" NUMBER (p_angnum(1)) ; indexval : NUMBER (p_index) ; symref : "(" "Sym" symindexval ")" ; symindexval : NUMBER (p_symindex) ; netindexval : NUMBER (p_netindex) ; compref : "(" "Comp" compindexval ")" ; compindexval : NUMBER (p_compindex) ; widthval : "W" coorddim (p_width) ; heightval : "H" coorddim (p_height) ; laynum : "L" NUMBER (p_layer) ; layidx : "L" NUMBER (p_layidx) ; attrid : "Count" | "Thru" | IDENT ; drillclass : "-" (p_drillclass(0)) | "A" (p_drillclass(1)) | "B" (p_drillclass(2)) | "C" (p_drillclass(3)) | "D" (p_drillclass(4)) | "E" (p_drillclass(5)) | "F" (p_drillclass(6)) | "G" (p_drillclass(7)) | "H" (p_drillclass(8)) | "I" (p_drillclass(9)) | "J" (p_drillclass(10)) | "K" (p_drillclass(11)) | "L" (p_drillclass(12)) | "M" (p_drillclass(13)) | "N" (p_drillclass(14)) | "O" (p_drillclass(15)) | "P" (p_drillclass(16)) | "Q" (p_drillclass(17)) | "R" (p_drillclass(18)) | "S" (p_drillclass(19)) | "T" (p_drillclass(20)) | "U" (p_drillclass(21)) | "V" (p_drillclass(22)) | "W" (p_drillclass(23)) | "X" (p_drillclass(24)) | "Y" (p_drillclass(25)) | "Z" (p_drillclass(26)) ; onoff : "Off" (p_switchoff) | ; fltnum : NUMBER (p_fltnum(0)) | "-" NUMBER (p_fltnum(1)) ; } // BNF syntax definition end /*________________________________________________________________*/ // Scanner/parser functions void parsefiles(string fn,string pfn) /* // Parse an input file // Parameters : // string fn : File name // string pfn : Parameter definition file name */ { // Parser error messages STRINGS ERRS = { "", M("(synparsefile) Keine BNF-Definition verfuegbar!", "(synparsefile) No BNF definition available!"), M("(synparsefile) Parser ist bereits aktiv!", "(synparsefile) Parser already active!"), M("(synparsefile) Fehler beim Oeffnen der Datei '%s'!", "(synparsefile) Error opening file '%s'!"), M("(synparsefile) Zu viele offene Dateien!", "(synparsefile) Too many open files!"), M("[%s/%d] Fataler Lese-/Schreibfehler!", "[%s/%d] Fatal read/write error!"), M("[%s/%d] Scan Item '%s' zu lang!", "[%s/%d] Scan item '%s' too long!"), M("[%s/%d] Syntaxfehler bei '%s' (unerwartetes Symbol)!", "[%s/%d] Syntax error at '%s' (unexpected symbol)!"), M("[%s/%d] Dateiende erreicht!", "[%s/%d] Unexpected end of file!"), M("[%s/%d] Stackueberlauf (BNF zu komplex)!", "[%s/%d] Stack overflow (BNF too complex)!"), M("[%s/%d] Stackunterlauf (BNF fehlerhaft)!", "[%s/%d] Stack underflow (BNF erroneous)!"), M("[%s/%d] Fehler von Parser Aktion/Funktion!", "[%s/%d] Error from parse action function!"), M("(synparsefile) Unbekannter Fehlercode %d!", "(synparsefile) Unknown error code %d!") }; int status /* Parser status */; string msg /* Error message */; // Parse the parameter definition file sprintf(msg,REPPARSE,pfn); bae_prtdialog(msg); // Parse the input file and evaluate the parser status if ((status=synparsefile(pfn))!=0) { if (status>=arylength(ERRS)) sprintf(msg,ERRS[arylength(ERRS)-1],status); else sprintf(msg,ERRS[status], pfn,synscanline(),synscanstring()); // Print the error message error(msg); } // Parse the Orcad MIN file sprintf(msg,REPPARSE,fn); bae_prtdialog(msg); // Parse the input file and evaluate the parser status synsetintpar(0,1); if ((status=synparsefile(fn))==0) { // No error synsetintpar(0,0); return; } synsetintpar(0,0); if (status>=arylength(ERRS)) sprintf(msg,ERRS[arylength(ERRS)-1],status); else sprintf(msg,ERRS[status], fn,synscanline(),synscanstring()); // Print the error message error(msg); } // Parser action routines int p_name() /* // Receive a name // Return value : // zero if done or (-1) on error */ { // Convert the scanned string curname=convname(quostr); // Return without errors return(0); } int p_pin() /* // Receive a pin placement // Return value : // zero if done or (-1) on error */ { string strbuf /* String buffer */; if (strlen(curname)>MAXKEYLEN) { strbuf=curname; curname[MAXKEYLEN]='\0'; if (mfh!=(-1)) fprintf(mfh,ERRLONGSYMN, minfname,synscanline(),strbuf,curname); } syml[cursymidx].pinl[syml[cursymidx].pinn].name=curname; syml[cursymidx].pinl[syml[cursymidx].pinn].x=curx; syml[cursymidx].pinl[syml[cursymidx].pinn].y=cury; syml[cursymidx].pinl[syml[cursymidx].pinn].pidx=curidx; syml[cursymidx].pinl[syml[cursymidx].pinn].line=synscanline(); syml[cursymidx].pinn++; // Return without errors return(0); } int p_drillclass(int class) /* // Receive a drill class // Return value : // zero if done or (-1) on error // Parameters : // int class : Drill class */ { curdrillclass=class; // Return without errors return(0); } int p_baeplated(int plated) /* // Receive a BAE drill class // Return value : // zero if done or (-1) on error // Parameters : // int plated : Plated drill flag */ { if (plated) DRLCLPLATED=curdrillclass; else DRLCLUNPLATED=curdrillclass; // Return without errors return(0); } int p_heightdrc() /* // Receive the height DRC layer number // Return value : // zero if done or (-1) on error */ { HDRCLAY=curlayer; // Return without errors return(0); } int p_partdrc() /* // Receive the part DRC layer number // Return value : // zero if done or (-1) on error */ { PDRCLAY=curlayer; // Return without errors return(0); } int p_picklay() /* // Receive the nsertion pick layer number // Return value : // zero if done or (-1) on error */ { PICKLAY=curlayer; // Return without errors return(0); } int p_defheight() /* // Receive the default part height // Return value : // zero if done or (-1) on error */ { UNDEFHEIGHT=curflt; // Return without errors return(0); } int p_drillisol() /* // Receive the drill default isolation // Return value : // zero if done or (-1) on error */ { DRLISO=curflt; // Return without errors return(0); } int p_minheight() /* // Receive the minimum part height // Return value : // zero if done or (-1) on error */ { MINHEIGHT=curflt; // Return without errors return(0); } int p_linewscale() /* // Receive the line width scale factor // Return value : // zero if done or (-1) on error */ { LINEWFAC=curflt; // Return without errors return(0); } int p_textwscale() /* // Receive the text line width scale factor // Return value : // zero if done or (-1) on error */ { TEXTWFAC=curflt; // Return without errors return(0); } int p_partnamesize() /* // Receive the part name text size // Return value : // zero if done or (-1) on error */ { PARTNAMESIZE=curflt; // Return without errors return(0); } int p_pinnamesize() /* // Receive the pin name text size // Return value : // zero if done or (-1) on error */ { PINNAMESIZE=curflt; // Return without errors return(0); } int p_picktextsize() /* // Receive the insertion pick text size // Return value : // zero if done or (-1) on error */ { PICKNAMESIZE=curflt; // Return without errors return(0); } int p_pinnamelayer() /* // Receive the pin name layer number // Return value : // zero if done or (-1) on error */ { PINNLAY=curlayer; // Return without errors return(0); } int p_namedimbase() /* // Receive the name pattern dimension scale factor // Return value : // zero if done or (-1) on error */ { if (curflt!=0.0) nameconv=1.0/curflt; // Return without errors return(0); } int p_rnddimbase() /* // Receive the dimension rounding base // Return value : // zero if done or (-1) on error */ { rounddim=curflt; // Return without errors return(0); } int p_padcircpattern() /* // Receive a circle pad name pattern // Return value : // zero if done or (-1) on error */ { PADCIRC=synscanstring(); // Return without errors return(0); } int p_padrectpattern() /* // Receive a rectangle pad name pattern // Return value : // zero if done or (-1) on error */ { PADRECT=synscanstring(); // Return without errors return(0); } int p_padsquarepattern() /* // Receive a square pad name pattern // Return value : // zero if done or (-1) on error */ { PADSQUARE=synscanstring(); // Return without errors return(0); } int p_padoblongpattern() /* // Receive a oblong pad name pattern // Return value : // zero if done or (-1) on error */ { PADOBLONG=synscanstring(); // Return without errors return(0); } int p_padovalpattern() /* // Receive a oval pad name pattern // Return value : // zero if done or (-1) on error */ { PADOVAL=synscanstring(); // Return without errors return(0); } int p_polytyp(int typ) /* // Receive a polygon type // Return value : // zero if done or (-1) on error // Parameters : // int typ : Polygon type */ { if (typ==200) { if (curpolytyp==5) curpolytyp=6; } else if ((curpolytyp=typ)>100) { curpolytyp-=100; curhpoly=1; } else { curhpoly=0; } // Return without errors return(0); } int p_shapetyp(int typ) /* // Receive a shape type // Return value : // zero if done or (-1) on error // Parameters : // int typ : Shape type */ { curshapetyp=typ; curnoconnect=0; curang=0.0; // Return without errors return(0); } int p_padshape() /* // Receive a pad shape end // Return value : // zero if done or (-1) on error */ { double swapbuf /* Swap buffer */; // Check if valid layer and shape if (curlayer==LAYERINV || curshapetyp==SUNDEF) // Ignore pad on undefined layer return(0); // Check if drill size specification if (curlayer==LAYERDRL) { curdrlrad=rnddim(curdim1); return(0); } if (curshapetyp!=SRECT && curshapetyp!=SOBLONG && curshapetyp!=SOVAL) { curdim2=curdim3=curdim4=curdim1; } else { // Check if rotated shape switch (angclass(curang)) { case 1 : case 3 : swapbuf=curdim2; curdim2=curdim1; curdim1=swapbuf; default : ; } } if (curnoconnect) { keepoutl[keepoutn].typ=curshapetyp; keepoutl[keepoutn].dim1=curdim1; keepoutl[keepoutn].dim2=curdim2; keepoutl[keepoutn].dim3=curdim3; keepoutl[keepoutn].dim4=curdim4; keepoutl[keepoutn].lay=curlayer; keepoutl[keepoutn].line=synscanline(); keepoutn++; } else { // Store pad data padl[padn].sidx= gcshape(curshapetyp,curdim1,curdim2,curdim3,curdim4); padl[padn].lay=curlayer; padn++; } // Return without errors return(0); } int p_storedata() /* // Receive buffered symbol and layout data // Return value : // zero if done or (-1) on error */ { index L_FIGURE lastfig /* Last figure list index */; string netname /* Net name */; string stkname /* Via padstack name */; STRINGS viastkl /* Via padstack list */; int viastkn = 0 /* Via padstack count */; int curhidx /* Current height DRC polygon index */; double lx, ly /* Bounding box lower corner coords. */; double ux, uy /* Bounding box upper corner coords. */; double plx,ply,pux,puy /* Polygon boundaries */; int i, j, k /* Loop control variables */; // Save the last element if (bae_planddbclass()!=DDBCLUNDEF) { bae_setintpar(22,1); call(MNU_GEDSAVELEM); bae_setintpar(22,0); } for (i=0;i0.0 && lay_lastfigelem(lastfig)==0) // Assign the width predicate rule rs_assfigdblpred(lastfig,RS_PLOTWIDTH, syml[i].textl[j].w,0.0,""); } curhpoly=0; curhidx=(-1); for (j=0;j=0 && curlayer0.0 && lay_lastfigelem(lastfig)==0) { // Assign the width predicate rule rs_assfigdblpred(lastfig,RS_PLOTWIDTH, syml[i].pl[j].w,0.0,""); } if (syml[i].pl[j].hdrc==1) curhidx=j; } if (!curhpoly) { if (curhidx>=0) { bae_clearpoints(); for (k=0;kux) ux=pux; if (plyuy) uy=puy; } bae_clearpoints(); bae_storepoint(lx,ly,0); bae_storepoint(ux,ly,0); bae_storepoint(ux,uy,0); bae_storepoint(lx,uy,0); if (ged_storepoly( HDRCLAY|1,L_POLYKEEPOUT,"",0)) { if (mfh!=(-1)) fprintf(mfh,ERRPLCPOLY, minfname,syml[i].pl[0].line); } else if (lay_lastfigelem(lastfig)==0) { if (MINHEIGHT<0.0) rs_assfigrule(lastfig, "lay_part_attrheight"); else // Assign the height DRC predicate rule rs_assfigdblpred(lastfig,RS_HEIGHT, UNDEFHEIGHT,0.0,""); } } } if (PICKLAY!=LAYERINV && PICKNAMESIZE!=0.0) ged_storetext("$",syml[i].pickx,syml[i].picky, 0.0,PICKNAMESIZE,PICKLAY,0); // Shrink part bae_setintpar(22,2); baewsshrink(1); bae_setintpar(22,0); // Save the part bae_setintpar(22,1); call(MNU_GEDSAVELEM); bae_setintpar(22,0); } if (compn>0 || pathn>0 || vian>0 || textn>0) { // Check if part already exists if (existddbelem(ddbfname,DDBCLLAY,laydefelemname(ddbfname))==1) return(0);; // Perform the create element call bae_clriactqueue(); bae_storemenuiact(1,0,LMB); bae_storetextiact(1,ddbfname); bae_storetextiact(1,laydefelemname(ddbfname)); bae_storetextiact(1,"1"); bae_storetextiact(1,"1"); bae_setintpar(22,1); call(MNU_GEDCREELEM); bae_setintpar(22,0); ged_setplantoplay(toplayer); if (chkdist!=0.0) lay_setplanchkparam( chkdist,chkdist,chkdist,0.0,"",-1,0); for (i=0;i0 && syml[cursymidx].derived>0) cursymidx=syml[cursymidx].derived; // Check if via component if (compl[i].via) { stkname=pstkl[syml[cursymidx].pinl[0].pidx]; if (ged_storeuref(stkname, compl[i].x,compl[i].y,0.0,0,0)) { if (mfh!=(-1)) fprintf(mfh,ERRPLCVIA,minfname,compl[i].line, pstkl[syml[cursymidx].pinl[0].pidx]); } else if ((netname=getnetname(compl[i].netidx))!="" && lay_lastfigelem(lastfig)==0) { rs_assfigstrpred(lastfig,RS_VIAFILLNET, netname,"",""); } for (j=0;j=viastkn) { viastkl[viastkn]=stkname; viastkn++; } } else { if (ged_storepart(compl[i].name,syml[cursymidx].name, compl[i].x,compl[i].y,compl[i].ang,compl[i].mirr)<0) if (mfh!=(-1)) fprintf(mfh,ERRPLCPART,minfname,compl[i].line, compl[i].name,syml[cursymidx].name); } if (compl[i].fixed && lay_lastfigelem(lastfig)==0) // Fix the part ged_elemfixchg(lastfig,1); if (compl[i].locked && lay_lastfigelem(lastfig)==0) // Assign the glue predicate rule rs_assfigintpred(lastfig,RS_GLUED,1,0,""); } for (i=0;i0 && syml[cursymidx].derived>0) cursymidx=syml[cursymidx].derived; stkname=pstkl[syml[cursymidx].pinl[0].pidx]; if (ged_storeuref(stkname, vial[i].x,vial[i].y,0.0,0,0)) { if (mfh!=(-1)) fprintf(mfh,ERRPLCVIA,minfname,vial[i].line, pstkl[syml[cursymidx].pinl[0].pidx]); } else if ((netname=getnetname(vial[i].netidx))!="" && lay_lastfigelem(lastfig)==0) { rs_assfigstrpred(lastfig,RS_VIAFILLNET, netname,"",""); } for (j=0;j=viastkn) { viastkl[viastkn]=stkname; viastkn++; } } for (i=0;i0.0 && lay_lastfigelem(lastfig)==0) // Assign the width predicate rule rs_assfigdblpred(lastfig,RS_PLOTWIDTH, textl[i].w,0.0,""); } curhpoly=0; curhidx=(-1); for (j=0;j=0 && curlayer0.0 && lay_lastfigelem(lastfig)==0) { // Assign the width predicate rule rs_assfigdblpred(lastfig,RS_PLOTWIDTH, syml[0].pl[j].w,0.0,""); } if (syml[0].pl[j].hdrc==1) curhidx=j; if (curpolytyp==L_POLYCOPFILL && lay_lastfigelem(lastfig)==0) { // Assign the isolation predicate rule rs_assfigdblpred(lastfig,RS_POLYFILLIS, syml[0].pl[j].mdist,0.0,""); // Assign the heat trap width predicate rule rs_assfigdblpred(lastfig,RS_POLYFILLHW, syml[0].pl[j].w,0.0,""); // Assign the fill order predicate rule rs_assfigintpred(lastfig,RS_POLYFILLPR, syml[0].pl[j].zorder,0,""); if (netname=="" && syml[0].pl[j].netidx>=0 && (curcompidx= netl[syml[0].pl[j].netidx].compidx)>=0) { cursymidx=compl[curcompidx].sidx; while (cursymidx>0 && syml[cursymidx].derived>0) cursymidx= syml[cursymidx].derived; rs_assfigstrpred(lastfig,RS_POLYFILLPA, compl[curcompidx].name,"",""); rs_assfigstrpred(lastfig,RS_POLYFILLPI, syml[cursymidx].pinl[netl[syml[ 0].pl[j].netidx].pinidx].name,"",""); } } } if (!curhpoly) { if (curhidx>=0) { bae_clearpoints(); for (k=0;kux) ux=pux; if (plyuy) uy=puy; } bae_clearpoints(); bae_storepoint(lx,ly,0); bae_storepoint(ux,ly,0); bae_storepoint(ux,uy,0); bae_storepoint(lx,uy,0); if (ged_storepoly( HDRCLAY|1,L_POLYKEEPOUT,"",0)) { if (mfh!=(-1)) fprintf(mfh,ERRPLCPOLY, minfname,syml[0].pl[0].line); } else if (lay_lastfigelem(lastfig)==0) if (MINHEIGHT<0.0) rs_assfigrule(lastfig, "lay_part_attrheight"); else // Assign the height DRC predicate rule rs_assfigdblpred(lastfig,RS_HEIGHT, UNDEFHEIGHT,0.0,""); } } // Define vias bae_clriactqueue(); for (i=0;iMAXTEXTLEN) { curtextstr[MAXTEXTLEN]='\0'; if (mfh!=(-1)) fprintf(mfh,ERRLONGTEXT, minfname,synscanline(),quostr,curtextstr); } if (curtextstr=="&Comp") curtextstr="$"; curang=0.0; curmirr=0; cursymidx=curcompidx=0; // Return without errors return(0); } int p_text() /* // Receive a text end // Return value : // zero if done or (-1) on error */ { if (curlayer==LAYERINV || curlayer==LAYERDRL) return(0); if (curmirr) { if (curang>=0.0) curang+=PI; else curang-=PI; } if (cursymidx>0) { syml[cursymidx].textl[syml[cursymidx].textn].str=curtextstr; syml[cursymidx].textl[syml[cursymidx].textn].x=curx; syml[cursymidx].textl[syml[cursymidx].textn].y=cury; syml[cursymidx].textl[syml[cursymidx].textn].ang=curang; syml[cursymidx].textl[syml[cursymidx].textn].mirr=curmirr; syml[cursymidx].textl[syml[cursymidx].textn].w= curwidth*TEXTWFAC; syml[cursymidx].textl[syml[cursymidx].textn].h= (curtextstr=="$" && PARTNAMESIZE!=0.0) ? PARTNAMESIZE : curheight; syml[cursymidx].textl[syml[cursymidx].textn].lay=curlayer; syml[cursymidx].textl[syml[cursymidx].textn].line= synscanline(); syml[cursymidx].textn++; } else if (curcompidx<=0) { textl[textn].str=curtextstr; textl[textn].x=curx; textl[textn].y=cury; textl[textn].ang=curang; textl[textn].mirr=curmirr; textl[textn].w=curwidth*TEXTWFAC; textl[textn].h=curheight; textl[textn].lay=curlayer; textl[textn].line=synscanline(); textn++; } /* if (curcompidx>0 && (cursymidx=compl[curcompidx].sidx)>0) { syml[cursymidx].textl[syml[cursymidx].textn].str=curtextstr; syml[cursymidx].textl[syml[cursymidx].textn].x=curx; syml[cursymidx].textl[syml[cursymidx].textn].y=cury; syml[cursymidx].textl[syml[cursymidx].textn].ang=curang; syml[cursymidx].textl[syml[cursymidx].textn].mirr=curmirr; syml[cursymidx].textl[syml[cursymidx].textn].w= curwidth*TEXTWFAC; syml[cursymidx].textl[syml[cursymidx].textn].h=curheight; syml[cursymidx].textl[syml[cursymidx].textn].lay=curlayer; syml[cursymidx].textl[syml[cursymidx].textn].line= synscanline(); syml[cursymidx].textn++; } */ // Return without errors return(0); } int p_quostr() /* // Receive a quoted string // Return value : // zero if done or (-1) on error */ { string instr /* Input string */; char c /* Character buffer */; int len /* Symbol name length */; int i /* Loop control variable */; // Get the scanned string instr=synscanstring(); // Get the string length len=strlen(instr); // Transfer the string characters quostr=""; for (i=0;i=2.0*PI) curang-=2.0*PI; // Return without errors return(0); } int p_intval(int negflag) /* // Receive an integer value // Return value : // zero if done or (-1) on error // Parameters : // int negflag : Negative number flag */ { // Get the current float value curint=atoi(synscanstring()); // Set negative on request if (negflag) curint*=(-1); // Return without errors return(0); } int p_obsini() /* // Receive an obs initialization // Return value : // zero if done or (-1) on error */ { curpolyn=0; curpolyl=emptyl; cursymidx=curcompidx=0; curwidth=curmdist=0.0; curpolytyp=(-1); curpinidx=(-1); curnetidx=(-1); curzorder=0; // Return without errors return(0); } int p_conini() /* // Receive a connection initialization // Return value : // zero if done or (-1) on error */ { curpolyn=0; curpolyl=emptyl; curwidth=0.0; curlayer=pathlayer=LAYERINV; curlocked=0; // Return without errors return(0); } int p_conlay() /* // Receive a connection layer // Return value : // zero if done or (-1) on error */ { if (curpolyn>1 && curlayer!=pathlayer) { curx=curpolyl[curpolyn-1].x; cury=curpolyl[curpolyn-1].y; storepath(); p_point(); } pathlayer=curlayer; // Return without errors return(0); } int p_convia() /* // Receive a connection via // Return value : // zero if done or (-1) on error */ { // Store via vial[vian].x=curx; vial[vian].y=cury; vial[vian].sidx=curidx; vial[vian].netidx=curnetidx; vial[vian].line=synscanline(); vian++; // Return without errors return(0); } int p_conwidth() /* // Receive a connection width // Return value : // zero if done or (-1) on error */ { curwidth=rnddim(curflt); if (curpolyn>1 && curwidth!=pathwidth) { curx=curpolyl[curpolyn-1].x; cury=curpolyl[curpolyn-1].y; storepath(); p_point(); } pathwidth=curwidth; // Return without errors return(0); } int p_conend() /* // Receive a connection end // Return value : // zero if done or (-1) on error */ { if (curpolyn) storepath(); curwidth=0.0; curlayer=LAYERINV; // Return without errors return(0); } int p_obsend() /* // Receive a obs end // Return value : // zero if done or (-1) on error */ { if (curpolytyp<0 || curlayer==LAYERINV || curlayer==LAYERDRL) return(0); // Check if keepout assigned to pin if (curpinidx>=0 && curpolytyp==L_POLYKEEPOUT) curpolytyp= curlayer>=DOCLAYBASE ? L_POLYDOCAREA : L_POLYCOPPASS; // Check if height DRC polygon if (curhpoly) { // Check if min. height if (curwidth>abs(MINHEIGHT)) { // Transform side if (curlayer=0) curlayer=HDRCLAY; else curlayer=HDRCLAY|1; curhpoly=2; } else { // Store flat height as part DRC if (curlayer=0) curlayer=PDRCLAY; else curlayer=PDRCLAY|1; curwidth=0.0; } } else { // Transform polygon type according to layer if (curlayer==LAYERALL || curlayer==LAYERTOP || curlayer==LAYERBTW || (curlayer>=0 && curlayer=DOCLAYBASE && curpolyn==2) curpolytyp=L_POLYDOCLINE; if (cursymidx>0) { syml[cursymidx].pl[syml[cursymidx].pn].pl=curpolyl; syml[cursymidx].pl[syml[cursymidx].pn].pn=curpolyn; syml[cursymidx].pl[syml[cursymidx].pn].ptyp=curpolytyp; syml[cursymidx].pl[syml[cursymidx].pn].netidx=(-1); syml[cursymidx].pl[syml[cursymidx].pn].zorder=0; syml[cursymidx].pl[syml[cursymidx].pn].mdist=0.0; syml[cursymidx].pl[syml[cursymidx].pn].w=curwidth; syml[cursymidx].pl[syml[cursymidx].pn].lay=curlayer; syml[cursymidx].pl[syml[cursymidx].pn].line=synscanline(); syml[cursymidx].pl[syml[cursymidx].pn].hdrc=curhpoly; syml[cursymidx].pn++; } if (curcompidx>0 && (cursymidx=compl[curcompidx].sidx)>0) { syml[cursymidx].pl[syml[cursymidx].pn].pl=curpolyl; syml[cursymidx].pl[syml[cursymidx].pn].pn=curpolyn; syml[cursymidx].pl[syml[cursymidx].pn].ptyp=curpolytyp; syml[cursymidx].pl[syml[cursymidx].pn].netidx=(-1); syml[cursymidx].pl[syml[cursymidx].pn].zorder=0; syml[cursymidx].pl[syml[cursymidx].pn].mdist=0.0; syml[cursymidx].pl[syml[cursymidx].pn].w= (curhpoly || curlayer==LAYERALL || curlayer==LAYERTOP || curlayer==LAYERBTW || (curlayer>=0 && curlayer=0 && curlayer0) curpolyl[curpolyn-1].t=ptyp; // Return without errors return(0); } int p_point() /* // Receive a polygon point // Return value : // zero if done or (-1) on error */ { curpolyl[curpolyn].x=curx; curpolyl[curpolyn].y=cury; curpolyl[curpolyn].t=0; curpolyn++; // Return without errors return(0); } int p_mirr() /* // Receive a mirror flag // Return value : // zero if done or (-1) on error */ { curmirr=1; // Return without errors return(0); } int p_x() /* // Receive a X coordinate // Return value : // zero if done or (-1) on error */ { curx=curflt; // Return without errors return(0); } int p_y() /* // Receive a Y coordinate // Return value : // zero if done or (-1) on error */ { cury=curflt; // Return without errors return(0); } int p_height() /* // Receive a height value // Return value : // zero if done or (-1) on error */ { curheight=rnddim(curflt); // Return without errors return(0); } int p_width() /* // Receive a width value // Return value : // zero if done or (-1) on error */ { curwidth=rnddim(curflt); // Return without errors return(0); } int p_clearance() /* // Receive a clearance value // Return value : // zero if done or (-1) on error */ { curmdist=rnddim(curflt); if (chkdist==0.0 || curmdistMAXKEYLEN) { strbuf=curname; curname[MAXKEYLEN]='\0'; if (mfh!=(-1)) fprintf(mfh,ERRLONGSYMN, minfname,synscanline(),strbuf,curname); } for (i=pstkn;i=pstkn) pstkn=curidx+1; // Return without errors return(0); } int p_stkend() /* // Receive a padstack end // Return value : // zero if done or (-1) on error */ { double w, h /* Padstack size */; double cx, cy /* Padstack center coordinates */; int data = 0 /* Data found flag */; int padfound = 0 /* Copper layer pad found flag */; int kofound = 0 /* Copper keepout found flag */; int siglaypads = 0 /* Signal layer pad count */; string ipadname = "" /* Inner layer pad name */; string tpadname = "" /* Top layer pad name */; string bpadname = "" /* Bottom layer pad name */; int i /* Loop control variable */; // Save the last element if (bae_planddbclass()!=DDBCLUNDEF) { bae_setintpar(22,1); call(MNU_GEDSAVELEM); bae_setintpar(22,0); } if (pstkl[curidx]=="") return(0); // Check if padstack already exists if (existddbelem(ddbfname,DDBCLLSTK,pstkl[curidx])==1) return(0); // Check if data on padstack if (curdrlrad>0.0 || keepoutn>0) data=1; else for (i=0;i=0 && (padl[i].lay==LAYERTOP || (padl[i].lay>=0 && padl[i].lay=0 && padl[i].lay=DOCLAYBASE ? L_POLYDOCAREA : L_POLYKEEPOUT,"",0)) if (mfh!=(-1)) fprintf(mfh,ERRPLCPOLY, minfname,keepoutl[i].line); if (keepoutl[i].lay0.0) { ged_storedrill(0.0,0.0,curdrlrad, curplated ? DRLCLPLATED : DRLCLUNPLATED); if (!padfound && !kofound && DRLISO!=0.0) { // Store keepout polygon shapepoly(SCIRCLE,curdrlrad+DRLISO,curdrlrad+DRLISO, curdrlrad+DRLISO,curdrlrad+DRLISO); ged_storepoly(LAYERALL,L_POLYKEEPOUT,"",0); } } // Store pin name text if (padfound && PINNLAY!=LAYERINV && PINNAMESIZE>0.0 && strmatch(bae_planename(),"via*")==0) ged_storetext( "$",bae_planwsnx(),bae_planwsny(),0.0,PINNAMESIZE,PINNLAY,0); // Shrink padstack bae_setintpar(22,2); baewsshrink(1); bae_setintpar(22,0); // Store dynamic size pin name text if (padfound && PINNLAY!=LAYERINV && PINNAMESIZE<0.0 && strmatch(bae_planename(),"via*")==0) { w=bae_planwsux()-bae_planwslx(); h=bae_planwsuy()-bae_planwsly(); cx=0.5*(bae_planwsux()+bae_planwslx()); cy=0.5*(bae_planwsuy()+bae_planwsly()); if ((w+0.00001)>=h) { if (h>(-PINNAMESIZE)) h=(-PINNAMESIZE); ged_storetext( "$",cx,cy,0.0,h,PINNLAY,TEXTHCENT|TEXTVCENT); } else { if (w>(-PINNAMESIZE)) w=(-PINNAMESIZE); ged_storetext( "$",cx,cy,0.5*PI,w,PINNLAY,TEXTHCENT|TEXTVCENT); } } // Save the padstack bae_setintpar(22,1); call(MNU_GEDSAVELEM); bae_setintpar(22,0); // Return without errors return(0); } int p_symstart() /* // Receive a symbol start // Return value : // zero if done or (-1) on error */ { string strbuf /* String buffer */; int i /* Loop control variable */; if (strlen(curname)>MAXKEYLEN) { strbuf=curname; curname[MAXKEYLEN]='\0'; if (mfh!=(-1)) fprintf(mfh,ERRLONGSYMN, minfname,synscanline(),strbuf,curname); } for (i=symn;i=symn) symn=cursymidx+1; // Return without errors return(0); } int p_derived() /* // Receive a derived index // Return value : // zero if done or (-1) on error */ { // Get the derived index syml[cursymidx].derived=atoi(synscanstring()); // Return without errors return(0); } int p_symvia() /* // Receive a component via flag // Return value : // zero if done or (-1) on error */ { syml[cursymidx].via=1; // Return without errors return(0); } int p_compini() /* // Receive a component initialization // Return value : // zero if done or (-1) on error */ { curang=0.0; curmirr=0; cursymidx=0; curvia=0; curfixed=0; curlocked=0; // Return without errors return(0); } int p_compvia() /* // Receive a component via flag // Return value : // zero if done or (-1) on error */ { curvia=1; // Return without errors return(0); } int p_comp() /* // Receive a component // Return value : // zero if done or (-1) on error */ { string strbuf /* String buffer */; int i /* Loop control variable */; if (strlen(curname)>MAXKEYLEN) { if (mfh!=(-1)) fprintf(mfh,ERRLONGSYMN, minfname,synscanline(),strbuf,curname); curname[MAXKEYLEN]='\0'; } for (i=compn;i=compn) compn=curidx+1; // Return without errors return(0); } int p_plated() /* // Receive a plated flag // Return value : // zero if done or (-1) on error */ { curplated= curswitch ? 0 : 1 ; // Return without errors return(0); } int p_layer() /* // Receive a layer number // Return value : // zero if done or (-1) on error */ { int layidx /* Layer index */; // Get the layer index layidx=atoi(synscanstring()); // Store the layer number curlayer= (layidx<0 || layidx>=tlayn || tlayl[layidx]<0) ? LAYERINV : layl[tlayl[layidx]].lay; // Return without errors return(0); } int p_layidx() /* // Receive a layer index // Return value : // zero if done or (-1) on error */ { // Get the layer index curlayer=atoi(synscanstring()); // Return without errors return(0); } int p_pinref() /* // Receive a pin reference index // Return value : // zero if done or (-1) on error */ { // Get the pin index curpinidx=atoi(synscanstring()); // Return without errors return(0); } int p_index() /* // Receive an index value // Return value : // zero if done or (-1) on error */ { // Get the index curidx=atoi(synscanstring()); // Return without errors return(0); } int p_symindex() /* // Receive a symbol index value // Return value : // zero if done or (-1) on error */ { // Get the index cursymidx=atoi(synscanstring()); // Return without errors return(0); } int p_zorder() /* // Receive a z order value // Return value : // zero if done or (-1) on error */ { // Get the z order curzorder=curint<0 ? 0 : (curint>5 ? 5 : curint); // Return without errors return(0); } int p_netindex() /* // Receive a net index value // Return value : // zero if done or (-1) on error */ { // Get the index curnetidx=atoi(synscanstring()); // Return without errors return(0); } int p_netname() /* // Receive a net name definition // Return value : // zero if done or (-1) on error */ { string strbuf /* String buffer */; int i /* Loop control variable */; if (curnetidx<0) return(0); if (strlen(curname)>MAXKEYLEN) { strbuf=curname; curname[MAXKEYLEN]='\0'; if (mfh!=(-1)) fprintf(mfh,ERRLONGSYMN, minfname,synscanline(),strbuf,curname); } netl[curnetidx].name=curname; netl[curnetidx].compidx=netl[curnetidx].pinidx=(-1); // Return without errors return(0); } int p_netcomp() /* // Receive a net component index value // Return value : // zero if done or (-1) on error */ { if (curnetidx<0) return(0); curnetcompidx=curint; // Return without errors return(0); } int p_netpin() /* // Receive a net component pin index value // Return value : // zero if done or (-1) on error */ { if (curnetidx<0) return(0); if (curnetcompidx>=0) { if (!compl[curnetcompidx].via) { netl[curnetidx].compidx=curnetcompidx; netl[curnetidx].pinidx=curint-1; } compl[curnetcompidx].netidx=curnetidx; } // Return without errors return(0); } int p_compindex() /* // Receive a component index value // Return value : // zero if done or (-1) on error */ { // Get the index curcompidx=atoi(synscanstring()); // Return without errors return(0); } int p_unit() /* // Handle the length units definition request // Return value : // zero if done or (-1) on error */ { lenconv=cvtlength(curflt,1,0); // Return without errors return(0); } int p_fltnum(int negflag) /* // Receive a float value // Return value : // zero if done or (-1) on error // Parameters : // int negflag : Negative number flag */ { if (negflag==2) { curflt=0.0; } else { // Get the current float value curflt=atof(synscanstring()); // Set negative on request if (negflag) curflt*=(-1); } // Return without errors return(0); } int p_layername() /* // Receive a layer name // Return value : // zero if done or (-1) on error */ { // Store the current layer name strlower(curlayername=curname); // Return without errors return(0); } int p_layerend() /* // Receive a layer definition end // Return value : // zero if done or (-1) on error */ { int i /* Loop control variable */; // Try to find the layer if ((i=findlayer(curlayername))>=0) // Layer found return(0); // Update the layer list layn++; for (i=(layn-1)-1;i>=inslayidx;i--) layl[i+1]=layl[i]; layl[inslayidx].name=curlayername; layl[inslayidx].lay=curlayer; if (curlayer>=0 && curlayernextilay) nextilay=curlayer; // Return without errors return(0); } int p_tlayerend() /* // Receive a layer transformation end // Return value : // zero if done or (-1) on error */ { int layidx /* Layer index */; int i /* Loop control variable */; // Get the transformed layer index layidx=findlayer(curlayername); for (i=tlayn;i=tlayn) tlayn=curlayer+1; if (layidx>=0 && (layl[layidx].lay==LAYERTOP || (layl[layidx].lay>=0 && layl[layidx].lay>1; // Test if layer found if ((compres=strcmp(name,layl[sidx].name))==0) // Layer found return(sidx); // Update the search area if (compres<0) sub=sidx-1; else slb=sidx+1; } // Store the insert layer index inslayidx=slb; // Hole not found return(-1); } int gcshape(int typ,double dim1,double dim2,double dim3,double dim4) /* // Search/create a shape entry // Return value : // shape list index, or (-1) on unknown shape type // Parameters : // int typ : Shape type // double dim1 : Shape 1st dimension // double dim2 : Shape 2nd dimension // double dim3 : Shape 3rd dimension // double dim4 : Shape 4th dimension */ { string shapename /* Shape name */; int i /* Loop control variable */; // Search shape for (i=0;ihx) { hm=hy-hx; bae_storepoint(hx,hm,0); bae_storepoint(0.0,hm,1); bae_storepoint(-hx,hm,0); bae_storepoint(-hx,-hm,0); bae_storepoint(0.0,-hm,1); bae_storepoint(hx,-hm,0); } else { hm=hx-hy; bae_storepoint(hm,-hy,0); bae_storepoint(hm,0.0,1); bae_storepoint(hm,hy,0); bae_storepoint(-hm,hy,0); bae_storepoint(-hm,0.0,1); bae_storepoint(-hm,-hy,0); } break; } } void storepath() /* // Store current path // Return value : // zero if done or (-1) on error */ { if (curpolyn==0 || pathlayer==LAYERINV || curlayer==LAYERDRL) { curpolyn=0; curpolyl=emptyl; return; } pathl[pathn].pl=curpolyl; pathl[pathn].pn=curpolyn; pathl[pathn].w=pathwidth; pathl[pathn].lay=pathlayer; pathl[pathn].fix=0; pathl[pathn].locked=curlocked; pathl[pathn].line=synscanline(); pathn++; if (pathlayer>(toplayer-1)) toplayer=pathlayer+1; curpolyn=0; curpolyl=emptyl; } string getnetname(int netidx) /* // Get the net name for the given net index // Return value : // net name or "" if unnamed net // Parameter : // int netidx : Net index */ { index L_CNET cnet /* Connection net index */; index L_CPART cpart /* Connection part index */; index L_CPIN cpin /* Connection pin index */; int compidx /* Component list index */; int symidx /* Symbol list index */; if (netidx<0) return(""); if (lay_findcontree(netl[netidx].name,cnet)==0) return(cnet.NAME); if ((compidx=netl[netidx].compidx)<0) return(""); cursymidx=compl[compidx].sidx; while (cursymidx>0 && syml[cursymidx].derived>0) cursymidx=syml[cursymidx].derived; if (lay_findconpart(compl[compidx].name,cpart)!=0 || lay_findconpartpin(syml[cursymidx].pinl[netl[netidx].pinidx].name, cpart,cpin)!=0) return(""); return(cpin.CNET.NAME); } double rnddim(double val) /* // Round a double value to setup precision // Return value : // rounded double value // Parameters : // double val : Input value */ { int minus = (val<0.0) /* Minus flag */; double buffer = fabs(val) /* Buffer */; // Shift value for rounding buffer/=rounddim; // Get the remainder after division buffer=fmod(buffer,1.0)>=0.5 ? ceil(buffer) : floor(buffer); // Shift value back after rounding buffer*=rounddim; // Return the result return(minus ? -buffer : buffer); } // User Language program end