You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

3985 lines
98 KiB

18 years ago
17 years ago
17 years ago
17 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2007-2013 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  5. * Copyright (C) 2007-2015 KiCad Developers, see change_log.txt for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. #ifndef SPECCTRA_H_
  25. #define SPECCTRA_H_
  26. // see http://www.boost.org/libs/ptr_container/doc/ptr_sequence_adapter.html
  27. #include <boost/ptr_container/ptr_vector.hpp>
  28. // see http://www.boost.org/libs/ptr_container/doc/ptr_set.html
  29. #include <boost/ptr_container/ptr_set.hpp>
  30. #include <fctsys.h>
  31. #include "specctra_lexer.h"
  32. #include <pcbnew.h>
  33. #include <memory>
  34. // all outside the DSN namespace:
  35. class BOARD;
  36. class TRACK;
  37. class VIA;
  38. class NETCLASS;
  39. class MODULE;
  40. class SHAPE_POLY_SET;
  41. typedef DSN::T DSN_T;
  42. /**
  43. This source file implements export and import capabilities to the
  44. specctra dsn file format. The grammar for that file format is documented
  45. fairly well. There are classes for each major type of descriptor in the
  46. spec.
  47. Since there are so many classes in here, it may be helpful to generate
  48. the Doxygen directory:
  49. $ cd &ltkicadSourceRoot&gt
  50. $ doxygen
  51. Then you can view the html documentation in the &ltkicadSourceRoot&gt/doxygen
  52. directory. The main class in this file is SPECCTRA_DB and its main
  53. functions are LoadPCB(), LoadSESSION(), and ExportPCB().
  54. Wide use is made of boost::ptr_vector&lt&gt and std::vector&lt&gt template classes.
  55. If the contained object is small, then std::vector tends to be used.
  56. If the contained object is large, variable size, or would require writing
  57. an assignment operator() or copy constructore, then boost::ptr_vector
  58. cannot be beat.
  59. */
  60. namespace DSN {
  61. class SPECCTRA_DB;
  62. /**
  63. * Function GetTokenText
  64. * is in the DSN namespace and returns the C string representing a
  65. * SPECCTRA_DB::keyword. We needed a non-instanance function to get at
  66. * the SPECCTRA_DB::keyword[] and class SPECCTRA_DB is not defined yet.
  67. */
  68. const char* GetTokenText( T aTok );
  69. /**
  70. * Struct POINT
  71. * is a holder for a point in the SPECCTRA DSN coordinate system. It can also
  72. * be used to hold a distance (vector really) from some origin.
  73. */
  74. struct POINT
  75. {
  76. double x;
  77. double y;
  78. POINT() { x=0.0; y=0.0; }
  79. POINT( double aX, double aY ) :
  80. x(aX), y(aY)
  81. {
  82. }
  83. bool operator==( const POINT& other ) const
  84. {
  85. return x==other.x && y==other.y;
  86. }
  87. bool operator!=( const POINT& other ) const
  88. {
  89. return !( *this == other );
  90. }
  91. POINT& operator+=( const POINT& other )
  92. {
  93. x += other.x;
  94. y += other.y;
  95. return *this;
  96. }
  97. POINT& operator=( const POINT& other )
  98. {
  99. x = other.x;
  100. y = other.y;
  101. return *this;
  102. }
  103. /**
  104. * Function FixNegativeZero
  105. * will change negative zero to positive zero in the IEEE floating point
  106. * storage format. Basically turns off the sign bit if the mantissa and
  107. * exponent say the value is otherwise zero.
  108. */
  109. void FixNegativeZero()
  110. {
  111. if( x == -0.0 )
  112. x = 0.0;
  113. if( y == -0.0 )
  114. y = 0.0;
  115. }
  116. /**
  117. * Function Format
  118. * writes this object as ASCII out to an OUTPUTFORMATTER according to the
  119. * SPECCTRA DSN format.
  120. * @param out The formatter to write to.
  121. * @param nestLevel A multiple of the number of spaces to preceed the output with.
  122. * @throw IO_ERROR if a system error writing the output, such as a full disk.
  123. */
  124. void Format( OUTPUTFORMATTER* out, int nestLevel ) const
  125. {
  126. out->Print( nestLevel, " %.6g %.6g", x, y );
  127. }
  128. };
  129. typedef std::vector<std::string> STRINGS;
  130. typedef std::vector<POINT> POINTS;
  131. struct PROPERTY
  132. {
  133. std::string name;
  134. std::string value;
  135. /**
  136. * Function Format
  137. * writes this object as ASCII out to an OUTPUTFORMATTER according to the
  138. * SPECCTRA DSN format.
  139. * @param out The formatter to write to.
  140. * @param nestLevel A multiple of the number of spaces to preceed the output with.
  141. * @throw IO_ERROR if a system error writing the output, such as a full disk.
  142. */
  143. void Format( OUTPUTFORMATTER* out, int nestLevel ) const
  144. {
  145. const char* quoteName = out->GetQuoteChar( name.c_str() );
  146. const char* quoteValue = out->GetQuoteChar( value.c_str() );
  147. out->Print( nestLevel, "(%s%s%s %s%s%s)\n",
  148. quoteName, name.c_str(), quoteName,
  149. quoteValue, value.c_str(), quoteValue );
  150. }
  151. };
  152. typedef std::vector<PROPERTY> PROPERTIES;
  153. class UNIT_RES;
  154. /**
  155. * Class ELEM
  156. * is a base class for any DSN element class.
  157. * See class ELEM_HOLDER also.
  158. */
  159. class ELEM
  160. {
  161. friend class SPECCTRA_DB;
  162. protected:
  163. DSN_T type;
  164. ELEM* parent;
  165. /**
  166. * Function makeHash
  167. * returns a string which uniquely represents this ELEM amoung other
  168. * ELEMs of the same derived class as "this" one.
  169. * It is not useable for all derived classes, only those which plan for
  170. * it by implementing a FormatContents() function that captures all info
  171. * which will be used in the subsequent string compare. THIS SHOULD
  172. * NORMALLY EXCLUDE THE TYPENAME, AND INSTANCE NAME OR ID AS WELL.
  173. */
  174. std::string makeHash()
  175. {
  176. sf.Clear();
  177. FormatContents( &sf, 0 );
  178. sf.StripUseless();
  179. return sf.GetString();
  180. }
  181. // avoid creating this for every compare, make static.
  182. static STRING_FORMATTER sf;
  183. public:
  184. ELEM( DSN_T aType, ELEM* aParent = 0 );
  185. virtual ~ELEM();
  186. DSN_T Type() const { return type; }
  187. const char* Name() const;
  188. /**
  189. * Function GetUnits
  190. * returns the units for this section. Derived classes may override this
  191. * to check for section specific overrides.
  192. * @return UNIT_RES* - from a local or parent scope
  193. */
  194. virtual UNIT_RES* GetUnits() const;
  195. /**
  196. * Function Format
  197. * writes this object as ASCII out to an OUTPUTFORMATTER according to the
  198. * SPECCTRA DSN format.
  199. * @param out The formatter to write to.
  200. * @param nestLevel A multiple of the number of spaces to preceed the output with.
  201. * @throw IO_ERROR if a system error writing the output, such as a full disk.
  202. */
  203. virtual void Format( OUTPUTFORMATTER* out, int nestLevel );
  204. /**
  205. * Function FormatContents
  206. * writes the contents as ASCII out to an OUTPUTFORMATTER according to the
  207. * SPECCTRA DSN format. This is the same as Format() except that the outer
  208. * wrapper is not included.
  209. * @param out The formatter to write to.
  210. * @param nestLevel A multiple of the number of spaces to preceed the output with.
  211. * @throw IO_ERROR if a system error writing the output, such as a full disk.
  212. */
  213. virtual void FormatContents( OUTPUTFORMATTER* out, int nestLevel )
  214. {
  215. // overridden in ELEM_HOLDER
  216. }
  217. void SetParent( ELEM* aParent )
  218. {
  219. parent = aParent;
  220. }
  221. };
  222. /**
  223. * Class ELEM_HOLDER
  224. * is a holder for any DSN class. It can contain other
  225. * class instances, including classes derived from this class.
  226. */
  227. class ELEM_HOLDER : public ELEM
  228. {
  229. friend class SPECCTRA_DB;
  230. typedef boost::ptr_vector<ELEM> ELEM_ARRAY;
  231. ELEM_ARRAY kids; ///< ELEM pointers
  232. public:
  233. ELEM_HOLDER( DSN_T aType, ELEM* aParent = 0 ) :
  234. ELEM( aType, aParent )
  235. {
  236. }
  237. virtual void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override;
  238. //-----< list operations >--------------------------------------------
  239. /**
  240. * Function FindElem
  241. * finds a particular instance number of a given type of ELEM.
  242. * @param aType The type of ELEM to find
  243. * @param instanceNum The instance number of to find: 0 for first, 1 for second, etc.
  244. * @return int - The index into the kids array or -1 if not found.
  245. */
  246. int FindElem( DSN_T aType, int instanceNum = 0 );
  247. /**
  248. * Function Length
  249. * returns the number of ELEMs in this ELEM.
  250. * @return int - the count of children
  251. */
  252. int Length() const
  253. {
  254. return kids.size();
  255. }
  256. void Append( ELEM* aElem )
  257. {
  258. kids.push_back( aElem );
  259. }
  260. ELEM* Replace( int aIndex, ELEM* aElem )
  261. {
  262. ELEM_ARRAY::auto_type ret = kids.replace( aIndex, aElem );
  263. return ret.release();
  264. }
  265. ELEM* Remove( int aIndex )
  266. {
  267. ELEM_ARRAY::auto_type ret = kids.release( kids.begin()+aIndex );
  268. return ret.release();
  269. }
  270. void Insert( int aIndex, ELEM* aElem )
  271. {
  272. kids.insert( kids.begin()+aIndex, aElem );
  273. }
  274. ELEM* At( int aIndex ) const
  275. {
  276. // we have varying sized objects and are using polymorphism, so we
  277. // must return a pointer not a reference.
  278. return (ELEM*) &kids[aIndex];
  279. }
  280. ELEM* operator[]( int aIndex ) const
  281. {
  282. return At( aIndex );
  283. }
  284. void Delete( int aIndex )
  285. {
  286. kids.erase( kids.begin()+aIndex );
  287. }
  288. };
  289. /**
  290. * Class PARSER
  291. * is simply a configuration record per the SPECCTRA DSN file spec.
  292. * It is not actually a parser, but rather corresponds to &lt;parser_descriptor&gt;
  293. */
  294. class PARSER : public ELEM
  295. {
  296. friend class SPECCTRA_DB;
  297. char string_quote;
  298. bool space_in_quoted_tokens;
  299. bool case_sensitive;
  300. bool wires_include_testpoint;
  301. bool routes_include_testpoint;
  302. bool routes_include_guides;
  303. bool routes_include_image_conductor;
  304. bool via_rotate_first;
  305. bool generated_by_freeroute;
  306. /// This holds pairs of strings, one pair for each constant definition
  307. STRINGS constants;
  308. std::string host_cad;
  309. std::string host_version;
  310. public:
  311. PARSER( ELEM* aParent );
  312. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override;
  313. };
  314. /**
  315. * Class UNIT_RES
  316. * is a holder for either a T_unit or T_resolution object which are usually
  317. * mutually exclusive in the dsn grammar, except within the T_pcb level.
  318. */
  319. class UNIT_RES : public ELEM
  320. {
  321. friend class SPECCTRA_DB;
  322. DSN_T units;
  323. int value;
  324. public:
  325. /**
  326. * A static instance which holds the default units of T_inch and 2540000.
  327. * See page 108 of the specctra spec, May 2000.
  328. */
  329. static UNIT_RES Default;
  330. UNIT_RES( ELEM* aParent, DSN_T aType ) :
  331. ELEM( aType, aParent )
  332. {
  333. units = T_inch;
  334. value = 2540000;
  335. }
  336. DSN_T GetEngUnits() const { return units; }
  337. int GetValue() const { return value; }
  338. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  339. {
  340. if( type == T_unit )
  341. out->Print( nestLevel, "(%s %s)\n", Name(),
  342. GetTokenText(units) );
  343. else // T_resolution
  344. out->Print( nestLevel, "(%s %s %d)\n", Name(),
  345. GetTokenText(units), value );
  346. }
  347. };
  348. class RECTANGLE : public ELEM
  349. {
  350. friend class SPECCTRA_DB;
  351. std::string layer_id;
  352. POINT point0; ///< one of two opposite corners
  353. POINT point1;
  354. public:
  355. RECTANGLE( ELEM* aParent ) :
  356. ELEM( T_rect, aParent )
  357. {
  358. }
  359. void SetLayerId( const char* aLayerId )
  360. {
  361. layer_id = aLayerId;
  362. }
  363. void SetCorners( const POINT& aPoint0, const POINT& aPoint1 )
  364. {
  365. point0 = aPoint0;
  366. point0.FixNegativeZero();
  367. point1 = aPoint1;
  368. point1.FixNegativeZero();
  369. }
  370. POINT GetOrigin() { return point0; }
  371. POINT GetEnd() { return point1; }
  372. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  373. {
  374. const char* newline = nestLevel ? "\n" : "";
  375. const char* quote = out->GetQuoteChar( layer_id.c_str() );
  376. out->Print( nestLevel, "(%s %s%s%s %.6g %.6g %.6g %.6g)%s",
  377. Name(),
  378. quote, layer_id.c_str(), quote,
  379. point0.x, point0.y,
  380. point1.x, point1.y,
  381. newline );
  382. }
  383. };
  384. /**
  385. * Class RULE
  386. * corresponds to the &lt;rule_descriptor&gt; in the specctra dsn spec.
  387. */
  388. class RULE : public ELEM
  389. {
  390. friend class SPECCTRA_DB;
  391. STRINGS rules; ///< rules are saved in std::string form.
  392. public:
  393. RULE( ELEM* aParent, DSN_T aType ) :
  394. ELEM( aType, aParent )
  395. {
  396. }
  397. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  398. {
  399. out->Print( nestLevel, "(%s", Name() );
  400. bool singleLine;
  401. if( rules.size() == 1 )
  402. {
  403. singleLine = true;
  404. out->Print( 0, " %s)", rules.begin()->c_str() );
  405. }
  406. else
  407. {
  408. out->Print( 0, "\n" );
  409. singleLine = false;
  410. for( STRINGS::const_iterator i = rules.begin(); i!=rules.end(); ++i )
  411. out->Print( nestLevel+1, "%s\n", i->c_str() );
  412. out->Print( nestLevel, ")" );
  413. }
  414. if( nestLevel || !singleLine )
  415. out->Print( 0, "\n" );
  416. }
  417. };
  418. class LAYER_RULE : public ELEM
  419. {
  420. friend class SPECCTRA_DB;
  421. STRINGS layer_ids;
  422. RULE* rule;
  423. public:
  424. LAYER_RULE( ELEM* aParent ) :
  425. ELEM( T_layer_rule, aParent )
  426. {
  427. rule = 0;
  428. }
  429. ~LAYER_RULE()
  430. {
  431. delete rule;
  432. }
  433. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  434. {
  435. out->Print( nestLevel, "(%s", Name() );
  436. for( STRINGS::const_iterator i=layer_ids.begin(); i!=layer_ids.end(); ++i )
  437. {
  438. const char* quote = out->GetQuoteChar( i->c_str() );
  439. out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
  440. }
  441. out->Print( 0 , "\n" );
  442. if( rule )
  443. rule->Format( out, nestLevel+1 );
  444. out->Print( nestLevel, ")\n" );
  445. }
  446. };
  447. typedef boost::ptr_vector<LAYER_RULE> LAYER_RULES;
  448. /**
  449. * Class PATH
  450. * supports both the &lt;path_descriptor&gt; and the &lt;polygon_descriptor&gt; per
  451. * the specctra dsn spec.
  452. */
  453. class PATH : public ELEM
  454. {
  455. friend class SPECCTRA_DB;
  456. std::string layer_id;
  457. double aperture_width;
  458. POINTS points;
  459. DSN_T aperture_type;
  460. public:
  461. PATH( ELEM* aParent, DSN_T aType = T_path ) :
  462. ELEM( aType, aParent )
  463. {
  464. aperture_width = 0.0;
  465. aperture_type = T_round;
  466. }
  467. void AppendPoint( const POINT& aPoint )
  468. {
  469. points.push_back( aPoint );
  470. }
  471. POINTS& GetPoints() {return points; }
  472. void SetLayerId( const char* aLayerId )
  473. {
  474. layer_id = aLayerId;
  475. }
  476. void SetAperture( double aWidth )
  477. {
  478. aperture_width = aWidth;
  479. }
  480. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  481. {
  482. const char* newline = nestLevel ? "\n" : "";
  483. const char* quote = out->GetQuoteChar( layer_id.c_str() );
  484. const int RIGHTMARGIN = 70;
  485. int perLine = out->Print( nestLevel, "(%s %s%s%s %.6g",
  486. Name(),
  487. quote, layer_id.c_str(), quote,
  488. aperture_width );
  489. int wrapNest = std::max( nestLevel+1, 6 );
  490. for( unsigned i=0; i<points.size(); ++i )
  491. {
  492. if( perLine > RIGHTMARGIN )
  493. {
  494. out->Print( 0, "\n" );
  495. perLine = out->Print( wrapNest, "%s", "" );
  496. }
  497. else
  498. perLine += out->Print( 0, " " );
  499. perLine += out->Print( 0, "%.6g %.6g", points[i].x, points[i].y );
  500. }
  501. if( aperture_type == T_square )
  502. {
  503. out->Print( 0, "(aperture_type square)" );
  504. }
  505. out->Print( 0, ")%s", newline );
  506. }
  507. };
  508. typedef boost::ptr_vector<PATH> PATHS;
  509. class BOUNDARY : public ELEM
  510. {
  511. friend class SPECCTRA_DB;
  512. // only one or the other of these two is used, not both
  513. PATHS paths;
  514. RECTANGLE* rectangle;
  515. public:
  516. BOUNDARY( ELEM* aParent, DSN_T aType = T_boundary ) :
  517. ELEM( aType, aParent )
  518. {
  519. rectangle = 0;
  520. }
  521. ~BOUNDARY()
  522. {
  523. delete rectangle;
  524. }
  525. /**
  526. * GetCorners fills aBuffer with a list of coordinates (x,y) of corners
  527. */
  528. void GetCorners( std::vector<double>& aBuffer )
  529. {
  530. if( rectangle )
  531. {
  532. aBuffer.push_back( rectangle->GetOrigin().x );
  533. aBuffer.push_back( rectangle->GetOrigin().y );
  534. aBuffer.push_back( rectangle->GetOrigin().x );
  535. aBuffer.push_back( rectangle->GetEnd().y );
  536. aBuffer.push_back( rectangle->GetEnd().x );
  537. aBuffer.push_back( rectangle->GetEnd().y );
  538. aBuffer.push_back( rectangle->GetEnd().x );
  539. aBuffer.push_back( rectangle->GetOrigin().y );
  540. }
  541. else
  542. {
  543. for( PATHS::iterator i=paths.begin(); i!=paths.end(); ++i )
  544. {
  545. POINTS& plist = i->GetPoints();
  546. for( unsigned jj = 0; jj < plist.size(); jj++ )
  547. {
  548. aBuffer.push_back( plist[jj].x );
  549. aBuffer.push_back( plist[jj].y );
  550. }
  551. }
  552. }
  553. }
  554. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  555. {
  556. out->Print( nestLevel, "(%s\n", Name() );
  557. if( rectangle )
  558. rectangle->Format( out, nestLevel+1 );
  559. else
  560. {
  561. for( PATHS::iterator i=paths.begin(); i!=paths.end(); ++i )
  562. i->Format( out, nestLevel+1 );
  563. }
  564. out->Print( nestLevel, ")\n" );
  565. }
  566. };
  567. class CIRCLE : public ELEM
  568. {
  569. friend class SPECCTRA_DB;
  570. std::string layer_id;
  571. double diameter;
  572. POINT vertex; // POINT's constructor sets to (0,0)
  573. public:
  574. CIRCLE( ELEM* aParent ) :
  575. ELEM( T_circle, aParent )
  576. {
  577. diameter = 0.0;
  578. }
  579. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  580. {
  581. const char* newline = nestLevel ? "\n" : "";
  582. const char* quote = out->GetQuoteChar( layer_id.c_str() );
  583. out->Print( nestLevel, "(%s %s%s%s %.6g", Name(),
  584. quote, layer_id.c_str(), quote,
  585. diameter );
  586. if( vertex.x!=0.0 || vertex.y!=0.0 )
  587. out->Print( 0, " %.6g %.6g)%s", vertex.x, vertex.y, newline );
  588. else
  589. out->Print( 0, ")%s", newline );
  590. }
  591. void SetLayerId( const char* aLayerId )
  592. {
  593. layer_id = aLayerId;
  594. }
  595. void SetDiameter( double aDiameter )
  596. {
  597. diameter = aDiameter;
  598. }
  599. void SetVertex( const POINT& aVertex )
  600. {
  601. vertex = aVertex;
  602. }
  603. };
  604. class QARC : public ELEM
  605. {
  606. friend class SPECCTRA_DB;
  607. std::string layer_id;
  608. double aperture_width;
  609. POINT vertex[3];
  610. public:
  611. QARC( ELEM* aParent ) :
  612. ELEM( T_qarc, aParent )
  613. {
  614. aperture_width = 0.0;
  615. }
  616. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  617. {
  618. const char* newline = nestLevel ? "\n" : "";
  619. const char* quote = out->GetQuoteChar( layer_id.c_str() );
  620. out->Print( nestLevel, "(%s %s%s%s %.6g", Name() ,
  621. quote, layer_id.c_str(), quote,
  622. aperture_width);
  623. for( int i=0; i<3; ++i )
  624. out->Print( 0, " %.6g %.6g", vertex[i].x, vertex[i].y );
  625. out->Print( 0, ")%s", newline );
  626. }
  627. void SetLayerId( const char* aLayerId )
  628. {
  629. layer_id = aLayerId;
  630. }
  631. void SetStart( const POINT& aStart )
  632. {
  633. vertex[0] = aStart;
  634. // no -0.0 on the printouts!
  635. vertex[0].FixNegativeZero();
  636. }
  637. void SetEnd( const POINT& aEnd )
  638. {
  639. vertex[1] = aEnd;
  640. // no -0.0 on the printouts!
  641. vertex[1].FixNegativeZero();
  642. }
  643. void SetCenter( const POINT& aCenter )
  644. {
  645. vertex[2] = aCenter;
  646. // no -0.0 on the printouts!
  647. vertex[2].FixNegativeZero();
  648. }
  649. };
  650. class WINDOW : public ELEM
  651. {
  652. friend class SPECCTRA_DB;
  653. protected:
  654. /* <shape_descriptor >::=
  655. [<rectangle_descriptor> |
  656. <circle_descriptor> |
  657. <polygon_descriptor> |
  658. <path_descriptor> |
  659. <qarc_descriptor> ]
  660. */
  661. ELEM* shape;
  662. public:
  663. WINDOW( ELEM* aParent, DSN_T aType = T_window ) :
  664. ELEM( aType, aParent )
  665. {
  666. shape = 0;
  667. }
  668. ~WINDOW()
  669. {
  670. delete shape;
  671. }
  672. void SetShape( ELEM* aShape )
  673. {
  674. delete shape;
  675. shape = aShape;
  676. if( aShape )
  677. {
  678. wxASSERT(aShape->Type()==T_rect || aShape->Type()==T_circle
  679. || aShape->Type()==T_qarc || aShape->Type()==T_path
  680. || aShape->Type()==T_polygon);
  681. aShape->SetParent( this );
  682. }
  683. }
  684. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  685. {
  686. out->Print( nestLevel, "(%s ", Name() );
  687. if( shape )
  688. shape->Format( out, 0 );
  689. out->Print( 0, ")\n" );
  690. }
  691. };
  692. typedef boost::ptr_vector<WINDOW> WINDOWS;
  693. /**
  694. * Class KEEPOUT
  695. * is used for &lt;keepout_descriptor&gt; and &lt;plane_descriptor&gt;.
  696. */
  697. class KEEPOUT : public ELEM
  698. {
  699. friend class SPECCTRA_DB;
  700. protected:
  701. std::string name;
  702. int sequence_number;
  703. RULE* rules;
  704. RULE* place_rules;
  705. WINDOWS windows;
  706. /* <shape_descriptor >::=
  707. [<rectangle_descriptor> |
  708. <circle_descriptor> |
  709. <polygon_descriptor> |
  710. <path_descriptor> |
  711. <qarc_descriptor> ]
  712. */
  713. ELEM* shape;
  714. public:
  715. /**
  716. * Constructor KEEPOUT
  717. * requires a DSN_T because this class is used for T_place_keepout, T_via_keepout,
  718. * T_wire_keepout, T_bend_keepout, and T_elongate_keepout as well as T_keepout.
  719. */
  720. KEEPOUT( ELEM* aParent, DSN_T aType ) :
  721. ELEM( aType, aParent )
  722. {
  723. rules = 0;
  724. place_rules = 0;
  725. shape = 0;
  726. sequence_number = -1;
  727. }
  728. ~KEEPOUT()
  729. {
  730. delete rules;
  731. delete place_rules;
  732. delete shape;
  733. }
  734. void SetShape( ELEM* aShape )
  735. {
  736. delete shape;
  737. shape = aShape;
  738. if( aShape )
  739. {
  740. wxASSERT(aShape->Type()==T_rect || aShape->Type()==T_circle
  741. || aShape->Type()==T_qarc || aShape->Type()==T_path
  742. || aShape->Type()==T_polygon);
  743. aShape->SetParent( this );
  744. }
  745. }
  746. void AddWindow( WINDOW* aWindow )
  747. {
  748. aWindow->SetParent( this );
  749. windows.push_back( aWindow );
  750. }
  751. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  752. {
  753. const char* newline = "\n";
  754. out->Print( nestLevel, "(%s", Name() );
  755. if( name.size() )
  756. {
  757. const char* quote = out->GetQuoteChar( name.c_str() );
  758. out->Print( 0, " %s%s%s", quote, name.c_str(), quote );
  759. }
  760. // Could be not needed:
  761. #if 1
  762. else
  763. out->Print( 0, " \"\"" ); // the zone with no name or net_code == 0
  764. #endif
  765. if( sequence_number != -1 )
  766. out->Print( 0, " (sequence_number %d)", sequence_number );
  767. if( shape )
  768. {
  769. out->Print( 0, " " );
  770. shape->Format( out, 0 );
  771. }
  772. if( rules )
  773. {
  774. out->Print( 0, "%s", newline );
  775. newline = "";
  776. rules->Format( out, nestLevel+1 );
  777. }
  778. if( place_rules )
  779. {
  780. out->Print( 0, "%s", newline );
  781. newline = "";
  782. place_rules->Format( out, nestLevel+1 );
  783. }
  784. if( windows.size() )
  785. {
  786. out->Print( 0, "%s", newline );
  787. newline = "";
  788. for( WINDOWS::iterator i=windows.begin(); i!=windows.end(); ++i )
  789. i->Format( out, nestLevel+1 );
  790. out->Print( nestLevel, ")\n" );
  791. }
  792. else
  793. out->Print( 0, ")\n" );
  794. }
  795. };
  796. typedef boost::ptr_vector<KEEPOUT> KEEPOUTS;
  797. /**
  798. * Class VIA
  799. * corresponds to the &lt;via_descriptor&gt; in the specctra dsn spec.
  800. */
  801. class VIA : public ELEM
  802. {
  803. friend class SPECCTRA_DB;
  804. STRINGS padstacks;
  805. STRINGS spares;
  806. public:
  807. VIA( ELEM* aParent ) :
  808. ELEM( T_via, aParent )
  809. {
  810. }
  811. void AppendVia( const char* aViaName )
  812. {
  813. padstacks.push_back( aViaName );
  814. }
  815. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  816. {
  817. const int RIGHTMARGIN = 80;
  818. int perLine = out->Print( nestLevel, "(%s", Name() );
  819. for( STRINGS::iterator i=padstacks.begin(); i!=padstacks.end(); ++i )
  820. {
  821. if( perLine > RIGHTMARGIN )
  822. {
  823. out->Print( 0, "\n" );
  824. perLine = out->Print( nestLevel+1, "%s", "");
  825. }
  826. const char* quote = out->GetQuoteChar( i->c_str() );
  827. perLine += out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
  828. }
  829. if( spares.size() )
  830. {
  831. out->Print( 0, "\n" );
  832. perLine = out->Print( nestLevel+1, "(spare" );
  833. for( STRINGS::iterator i=spares.begin(); i!=spares.end(); ++i )
  834. {
  835. if( perLine > RIGHTMARGIN )
  836. {
  837. out->Print( 0, "\n" );
  838. perLine = out->Print( nestLevel+2, "%s", "");
  839. }
  840. const char* quote = out->GetQuoteChar( i->c_str() );
  841. perLine += out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
  842. }
  843. out->Print( 0, ")" );
  844. }
  845. out->Print( 0, ")\n" );
  846. }
  847. };
  848. class CLASSES : public ELEM
  849. {
  850. friend class SPECCTRA_DB;
  851. STRINGS class_ids;
  852. public:
  853. CLASSES( ELEM* aParent ) :
  854. ELEM( T_classes, aParent )
  855. {
  856. }
  857. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  858. {
  859. for( STRINGS::iterator i=class_ids.begin(); i!=class_ids.end(); ++i )
  860. {
  861. const char* quote = out->GetQuoteChar( i->c_str() );
  862. out->Print( nestLevel, "%s%s%s\n", quote, i->c_str(), quote );
  863. }
  864. }
  865. };
  866. class CLASS_CLASS : public ELEM_HOLDER
  867. {
  868. friend class SPECCTRA_DB;
  869. CLASSES* classes;
  870. /* rule | layer_rule are put into the kids container.
  871. */
  872. public:
  873. /**
  874. * Constructor CLASS_CLASS
  875. * @param aParent - Parent element of the object.
  876. * @param aType May be either T_class_class or T_region_class_class
  877. */
  878. CLASS_CLASS( ELEM* aParent, DSN_T aType ) :
  879. ELEM_HOLDER( aType, aParent )
  880. {
  881. classes = 0;
  882. }
  883. ~CLASS_CLASS()
  884. {
  885. delete classes;
  886. }
  887. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  888. {
  889. if( classes )
  890. classes->Format( out, nestLevel );
  891. // format the kids
  892. ELEM_HOLDER::FormatContents( out, nestLevel );
  893. }
  894. };
  895. class CONTROL : public ELEM_HOLDER
  896. {
  897. friend class SPECCTRA_DB;
  898. bool via_at_smd;
  899. bool via_at_smd_grid_on;
  900. public:
  901. CONTROL( ELEM* aParent ) :
  902. ELEM_HOLDER( T_control, aParent )
  903. {
  904. via_at_smd = false;
  905. via_at_smd_grid_on = false;
  906. }
  907. ~CONTROL()
  908. {
  909. }
  910. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  911. {
  912. out->Print( nestLevel, "(%s\n", Name() );
  913. //if( via_at_smd )
  914. {
  915. out->Print( nestLevel+1, "(via_at_smd %s", via_at_smd ? "on" : "off" );
  916. if( via_at_smd_grid_on )
  917. out->Print( 0, " grid %s", via_at_smd_grid_on ? "on" : "off" );
  918. out->Print( 0, ")\n" );
  919. }
  920. for( int i=0; i<Length(); ++i )
  921. {
  922. At(i)->Format( out, nestLevel+1 );
  923. }
  924. out->Print( nestLevel, ")\n" );
  925. }
  926. };
  927. class LAYER : public ELEM
  928. {
  929. friend class SPECCTRA_DB;
  930. std::string name;
  931. DSN_T layer_type; ///< one of: T_signal, T_power, T_mixed, T_jumper
  932. int direction;
  933. int cost; ///< [forbidden | high | medium | low | free | \<positive_integer\> | -1]
  934. int cost_type; ///< T_length | T_way
  935. RULE* rules;
  936. STRINGS use_net;
  937. PROPERTIES properties;
  938. public:
  939. LAYER( ELEM* aParent ) :
  940. ELEM( T_layer, aParent )
  941. {
  942. layer_type = T_signal;
  943. direction = -1;
  944. cost = -1;
  945. cost_type = -1;
  946. rules = 0;
  947. }
  948. ~LAYER()
  949. {
  950. delete rules;
  951. }
  952. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  953. {
  954. const char* quote = out->GetQuoteChar( name.c_str() );
  955. out->Print( nestLevel, "(%s %s%s%s\n", Name(),
  956. quote, name.c_str(), quote );
  957. out->Print( nestLevel+1, "(type %s)\n", GetTokenText( layer_type ) );
  958. if( properties.size() )
  959. {
  960. out->Print( nestLevel+1, "(property\n" );
  961. for( PROPERTIES::iterator i = properties.begin(); i != properties.end(); ++i )
  962. {
  963. i->Format( out, nestLevel+2 );
  964. }
  965. out->Print( nestLevel+1, ")\n" );
  966. }
  967. if( direction != -1 )
  968. out->Print( nestLevel+1, "(direction %s)\n",
  969. GetTokenText( (DSN_T)direction ) );
  970. if( rules )
  971. rules->Format( out, nestLevel+1 );
  972. if( cost != -1 )
  973. {
  974. if( cost < 0 )
  975. out->Print( nestLevel+1, "(cost %d", -cost ); // positive integer, stored as negative
  976. else
  977. out->Print( nestLevel+1, "(cost %s", GetTokenText( (DSN_T)cost ) );
  978. if( cost_type != -1 )
  979. out->Print( 0, " (type %s)", GetTokenText( (DSN_T)cost_type ) );
  980. out->Print( 0, ")\n" );
  981. }
  982. if( use_net.size() )
  983. {
  984. out->Print( nestLevel+1, "(use_net" );
  985. for( STRINGS::const_iterator i = use_net.begin(); i!=use_net.end(); ++i )
  986. {
  987. quote = out->GetQuoteChar( i->c_str() );
  988. out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
  989. }
  990. out->Print( 0, ")\n" );
  991. }
  992. out->Print( nestLevel, ")\n" );
  993. }
  994. };
  995. typedef boost::ptr_vector<LAYER> LAYERS;
  996. class SPECCTRA_LAYER_PAIR : public ELEM
  997. {
  998. friend class SPECCTRA_DB;
  999. std::string layer_id0;
  1000. std::string layer_id1;
  1001. double layer_weight;
  1002. public:
  1003. SPECCTRA_LAYER_PAIR( ELEM* aParent ) :
  1004. ELEM( T_layer_pair, aParent )
  1005. {
  1006. layer_weight = 0.0;
  1007. }
  1008. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  1009. {
  1010. const char* quote0 = out->GetQuoteChar( layer_id0.c_str() );
  1011. const char* quote1 = out->GetQuoteChar( layer_id1.c_str() );
  1012. out->Print( nestLevel, "(%s %s%s%s %s%s%s %.6g)\n", Name(),
  1013. quote0, layer_id0.c_str(), quote0,
  1014. quote1, layer_id1.c_str(), quote1,
  1015. layer_weight );
  1016. }
  1017. };
  1018. typedef boost::ptr_vector<SPECCTRA_LAYER_PAIR> SPECCTRA_LAYER_PAIRS;
  1019. class LAYER_NOISE_WEIGHT : public ELEM
  1020. {
  1021. friend class SPECCTRA_DB;
  1022. SPECCTRA_LAYER_PAIRS layer_pairs;
  1023. public:
  1024. LAYER_NOISE_WEIGHT( ELEM* aParent ) :
  1025. ELEM( T_layer_noise_weight, aParent )
  1026. {
  1027. }
  1028. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  1029. {
  1030. out->Print( nestLevel, "(%s\n", Name() );
  1031. for( SPECCTRA_LAYER_PAIRS::iterator i=layer_pairs.begin(); i!=layer_pairs.end(); ++i )
  1032. i->Format( out, nestLevel+1 );
  1033. out->Print( nestLevel, ")\n" );
  1034. }
  1035. };
  1036. /**
  1037. * Class COPPER_PLANE
  1038. * corresponds to a &lt;plane_descriptor&gt; in the specctra dsn spec.
  1039. */
  1040. class COPPER_PLANE : public KEEPOUT
  1041. {
  1042. friend class SPECCTRA_DB;
  1043. public:
  1044. COPPER_PLANE( ELEM* aParent ) :
  1045. KEEPOUT( aParent, T_plane )
  1046. {}
  1047. };
  1048. typedef boost::ptr_vector<COPPER_PLANE> COPPER_PLANES;
  1049. /**
  1050. * Class TOKPROP
  1051. * is a container for a single property whose value is another DSN_T token.
  1052. * The name of the property is obtained from the DSN_T Type().
  1053. */
  1054. class TOKPROP : public ELEM
  1055. {
  1056. friend class SPECCTRA_DB;
  1057. DSN_T value;
  1058. public:
  1059. TOKPROP( ELEM* aParent, DSN_T aType ) :
  1060. ELEM( aType, aParent )
  1061. {
  1062. // Do not leave uninitialized members
  1063. value = T_NONE;
  1064. }
  1065. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  1066. {
  1067. out->Print( nestLevel, "(%s %s)\n", Name(),
  1068. GetTokenText( value ) );
  1069. }
  1070. };
  1071. /**
  1072. * Class STRINGPROP
  1073. * is a container for a single property whose value is a string.
  1074. * The name of the property is obtained from the DSN_T.
  1075. */
  1076. class STRINGPROP : public ELEM
  1077. {
  1078. friend class SPECCTRA_DB;
  1079. std::string value;
  1080. public:
  1081. STRINGPROP( ELEM* aParent, DSN_T aType ) :
  1082. ELEM( aType, aParent )
  1083. {
  1084. }
  1085. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  1086. {
  1087. const char* quote = out->GetQuoteChar( value.c_str() );
  1088. out->Print( nestLevel, "(%s %s%s%s)\n", Name(),
  1089. quote, value.c_str(), quote );
  1090. }
  1091. };
  1092. class REGION : public ELEM_HOLDER
  1093. {
  1094. friend class SPECCTRA_DB;
  1095. std::string region_id;
  1096. //-----<mutually exclusive>--------------------------------------
  1097. RECTANGLE* rectangle;
  1098. PATH* polygon;
  1099. //-----</mutually exclusive>-------------------------------------
  1100. /* region_net | region_class | region_class_class are all mutually
  1101. exclusive and are put into the kids container.
  1102. */
  1103. RULE* rules;
  1104. public:
  1105. REGION( ELEM* aParent ) :
  1106. ELEM_HOLDER( T_region, aParent )
  1107. {
  1108. rectangle = 0;
  1109. polygon = 0;
  1110. rules = 0;
  1111. }
  1112. ~REGION()
  1113. {
  1114. delete rectangle;
  1115. delete polygon;
  1116. delete rules;
  1117. }
  1118. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  1119. {
  1120. if( region_id.size() )
  1121. {
  1122. const char* quote = out->GetQuoteChar( region_id.c_str() );
  1123. out->Print( nestLevel, "%s%s%s\n", quote, region_id.c_str(), quote );
  1124. }
  1125. if( rectangle )
  1126. rectangle->Format( out, nestLevel );
  1127. if( polygon )
  1128. polygon->Format( out, nestLevel );
  1129. ELEM_HOLDER::FormatContents( out, nestLevel );
  1130. if( rules )
  1131. rules->Format( out, nestLevel );
  1132. }
  1133. };
  1134. class GRID : public ELEM
  1135. {
  1136. friend class SPECCTRA_DB;
  1137. DSN_T grid_type; ///< T_via | T_wire | T_via_keepout | T_place | T_snap
  1138. double dimension;
  1139. DSN_T direction; ///< T_x | T_y | -1 for both
  1140. double offset;
  1141. DSN_T image_type;
  1142. public:
  1143. GRID( ELEM* aParent ) :
  1144. ELEM( T_grid, aParent )
  1145. {
  1146. grid_type = T_via;
  1147. direction = T_NONE;
  1148. dimension = 0.0;
  1149. offset = 0.0;
  1150. image_type= T_NONE;
  1151. }
  1152. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  1153. {
  1154. out->Print( nestLevel, "(%s %s %.6g",
  1155. Name(),
  1156. GetTokenText( grid_type ), dimension );
  1157. if( grid_type == T_place )
  1158. {
  1159. if( image_type==T_smd || image_type==T_pin )
  1160. out->Print( 0, " (image_type %s)", GetTokenText( image_type ) );
  1161. }
  1162. else
  1163. {
  1164. if( direction==T_x || direction==T_y )
  1165. out->Print( 0, " (direction %s)", GetTokenText( direction ) );
  1166. }
  1167. if( offset != 0.0 )
  1168. out->Print( 0, " (offset %.6g)", offset );
  1169. out->Print( 0, ")\n");
  1170. }
  1171. };
  1172. class STRUCTURE_OUT : public ELEM
  1173. {
  1174. friend class SPECCTRA_DB;
  1175. LAYERS layers;
  1176. RULE* rules;
  1177. public:
  1178. STRUCTURE_OUT( ELEM* aParent ) :
  1179. ELEM( T_structure_out, aParent )
  1180. {
  1181. rules = 0;
  1182. }
  1183. ~STRUCTURE_OUT()
  1184. {
  1185. delete rules;
  1186. }
  1187. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  1188. {
  1189. for( LAYERS::iterator i=layers.begin(); i!=layers.end(); ++i )
  1190. i->Format( out, nestLevel );
  1191. if( rules )
  1192. rules->Format( out, nestLevel );
  1193. }
  1194. };
  1195. class STRUCTURE : public ELEM_HOLDER
  1196. {
  1197. friend class SPECCTRA_DB;
  1198. UNIT_RES* unit;
  1199. LAYERS layers;
  1200. LAYER_NOISE_WEIGHT* layer_noise_weight;
  1201. BOUNDARY* boundary;
  1202. BOUNDARY* place_boundary;
  1203. VIA* via;
  1204. CONTROL* control;
  1205. RULE* rules;
  1206. KEEPOUTS keepouts;
  1207. COPPER_PLANES planes;
  1208. typedef boost::ptr_vector<REGION> REGIONS;
  1209. REGIONS regions;
  1210. RULE* place_rules;
  1211. typedef boost::ptr_vector<GRID> GRIDS;
  1212. GRIDS grids;
  1213. public:
  1214. STRUCTURE( ELEM* aParent ) :
  1215. ELEM_HOLDER( T_structure, aParent )
  1216. {
  1217. unit = 0;
  1218. layer_noise_weight = 0;
  1219. boundary = 0;
  1220. place_boundary = 0;
  1221. via = 0;
  1222. control = 0;
  1223. rules = 0;
  1224. place_rules = 0;
  1225. }
  1226. ~STRUCTURE()
  1227. {
  1228. delete unit;
  1229. delete layer_noise_weight;
  1230. delete boundary;
  1231. delete place_boundary;
  1232. delete via;
  1233. delete control;
  1234. delete rules;
  1235. delete place_rules;
  1236. }
  1237. void SetBOUNDARY( BOUNDARY *aBoundary )
  1238. {
  1239. delete boundary;
  1240. boundary = aBoundary;
  1241. if( boundary )
  1242. {
  1243. boundary->SetParent( this );
  1244. }
  1245. }
  1246. void SetPlaceBOUNDARY( BOUNDARY *aBoundary )
  1247. {
  1248. delete place_boundary;
  1249. place_boundary = aBoundary;
  1250. if( place_boundary )
  1251. place_boundary->SetParent( this );
  1252. }
  1253. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  1254. {
  1255. if( unit )
  1256. unit->Format( out, nestLevel );
  1257. for( LAYERS::iterator i=layers.begin(); i!=layers.end(); ++i )
  1258. i->Format( out, nestLevel );
  1259. if( layer_noise_weight )
  1260. layer_noise_weight->Format( out, nestLevel );
  1261. if( boundary )
  1262. boundary->Format( out, nestLevel );
  1263. if( place_boundary )
  1264. place_boundary->Format( out, nestLevel );
  1265. for( COPPER_PLANES::iterator i=planes.begin(); i!=planes.end(); ++i )
  1266. i->Format( out, nestLevel );
  1267. for( REGIONS::iterator i=regions.begin(); i!=regions.end(); ++i )
  1268. i->Format( out, nestLevel );
  1269. for( KEEPOUTS::iterator i=keepouts.begin(); i!=keepouts.end(); ++i )
  1270. i->Format( out, nestLevel );
  1271. if( via )
  1272. via->Format( out, nestLevel );
  1273. if( control )
  1274. control->Format( out, nestLevel );
  1275. for( int i=0; i<Length(); ++i )
  1276. {
  1277. At(i)->Format( out, nestLevel );
  1278. }
  1279. if( rules )
  1280. rules->Format( out, nestLevel );
  1281. if( place_rules )
  1282. place_rules->Format( out, nestLevel );
  1283. for( GRIDS::iterator i=grids.begin(); i!=grids.end(); ++i )
  1284. i->Format( out, nestLevel );
  1285. }
  1286. UNIT_RES* GetUnits() const override
  1287. {
  1288. if( unit )
  1289. return unit;
  1290. return ELEM::GetUnits();
  1291. }
  1292. };
  1293. /**
  1294. * Class PLACE
  1295. * implements the &lt;placement_reference&gt; in the specctra dsn spec.
  1296. */
  1297. class PLACE : public ELEM
  1298. {
  1299. friend class SPECCTRA_DB;
  1300. std::string component_id; ///< reference designator
  1301. DSN_T side;
  1302. double rotation;
  1303. bool hasVertex;
  1304. POINT vertex;
  1305. DSN_T mirror;
  1306. DSN_T status;
  1307. std::string logical_part;
  1308. RULE* place_rules;
  1309. PROPERTIES properties;
  1310. DSN_T lock_type;
  1311. //-----<mutually exclusive>--------------
  1312. RULE* rules;
  1313. REGION* region;
  1314. //-----</mutually exclusive>-------------
  1315. std::string part_number;
  1316. public:
  1317. PLACE( ELEM* aParent ) :
  1318. ELEM( T_place, aParent )
  1319. {
  1320. side = T_front;
  1321. rotation = 0.0;
  1322. hasVertex = false;
  1323. mirror = T_NONE;
  1324. status = T_NONE;
  1325. place_rules = 0;
  1326. lock_type = T_NONE;
  1327. rules = 0;
  1328. region = 0;
  1329. }
  1330. ~PLACE()
  1331. {
  1332. delete place_rules;
  1333. delete rules;
  1334. delete region;
  1335. }
  1336. void SetVertex( const POINT& aVertex )
  1337. {
  1338. vertex = aVertex;
  1339. vertex.FixNegativeZero();
  1340. hasVertex = true;
  1341. }
  1342. void SetRotation( double aRotation )
  1343. {
  1344. rotation = aRotation;
  1345. }
  1346. void Format( OUTPUTFORMATTER* out, int nestLevel ) override;
  1347. };
  1348. typedef boost::ptr_vector<PLACE> PLACES;
  1349. /**
  1350. * Class COMPONENT
  1351. * implements the &lt;component_descriptor&gt; in the specctra dsn spec.
  1352. */
  1353. class COMPONENT : public ELEM
  1354. {
  1355. friend class SPECCTRA_DB;
  1356. // std::string hash; ///< a hash string used by Compare(), not Format()ed/exported.
  1357. std::string image_id;
  1358. PLACES places;
  1359. public:
  1360. COMPONENT( ELEM* aParent ) :
  1361. ELEM( T_component, aParent )
  1362. {
  1363. }
  1364. const std::string& GetImageId() const { return image_id; }
  1365. void SetImageId( const std::string& aImageId )
  1366. {
  1367. image_id = aImageId;
  1368. }
  1369. /**
  1370. * Function Compare
  1371. * compares two objects of this type and returns <0, 0, or >0.
  1372. */
  1373. // static int Compare( IMAGE* lhs, IMAGE* rhs );
  1374. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  1375. {
  1376. const char* quote = out->GetQuoteChar( image_id.c_str() );
  1377. out->Print( nestLevel, "(%s %s%s%s\n", Name(),
  1378. quote, image_id.c_str(), quote );
  1379. FormatContents( out, nestLevel+1 );
  1380. out->Print( nestLevel, ")\n" );
  1381. }
  1382. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  1383. {
  1384. for( PLACES::iterator i=places.begin(); i!=places.end(); ++i )
  1385. i->Format( out, nestLevel );
  1386. }
  1387. };
  1388. typedef boost::ptr_vector<COMPONENT> COMPONENTS;
  1389. class PLACEMENT : public ELEM
  1390. {
  1391. friend class SPECCTRA_DB;
  1392. UNIT_RES* unit;
  1393. DSN_T flip_style;
  1394. COMPONENTS components;
  1395. public:
  1396. PLACEMENT( ELEM* aParent ) :
  1397. ELEM( T_placement, aParent )
  1398. {
  1399. unit = 0;
  1400. flip_style = DSN_T( T_NONE );
  1401. }
  1402. ~PLACEMENT()
  1403. {
  1404. delete unit;
  1405. }
  1406. /**
  1407. * Function LookupCOMPONENT
  1408. * looks up a COMPONENT by name. If the name is not found, a new
  1409. * COMPONENT is added to the components container. At any time the
  1410. * names in the component container should remain unique.
  1411. * @return COMPONENT* - an existing or new
  1412. */
  1413. COMPONENT* LookupCOMPONENT( const std::string& imageName )
  1414. {
  1415. for( unsigned i=0; i<components.size(); ++i )
  1416. {
  1417. if( 0 == components[i].GetImageId().compare( imageName ) )
  1418. return &components[i];
  1419. }
  1420. COMPONENT* added = new COMPONENT(this);
  1421. components.push_back( added );
  1422. added->SetImageId( imageName );
  1423. return added;
  1424. }
  1425. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  1426. {
  1427. if( unit )
  1428. unit->Format( out, nestLevel );
  1429. if( flip_style != DSN_T( T_NONE ) )
  1430. {
  1431. out->Print( nestLevel, "(place_control (flip_style %s))\n",
  1432. GetTokenText( flip_style ) );
  1433. }
  1434. for( COMPONENTS::iterator i=components.begin(); i!=components.end(); ++i )
  1435. i->Format( out, nestLevel );
  1436. }
  1437. UNIT_RES* GetUnits() const override
  1438. {
  1439. if( unit )
  1440. return unit;
  1441. return ELEM::GetUnits();
  1442. }
  1443. };
  1444. /**
  1445. * Class SHAPE
  1446. * corresponds to the "(shape ..)" element in the specctra dsn spec.
  1447. * It is not a &lt;shape_descriptor&gt;, which is one of things that this
  1448. * elements contains, i.e. in its "shape" field. This class also implements
  1449. * the "(outline ...)" element as a dual personality.
  1450. */
  1451. class SHAPE : public WINDOW
  1452. {
  1453. friend class SPECCTRA_DB;
  1454. DSN_T connect;
  1455. /* <shape_descriptor >::=
  1456. [<rectangle_descriptor> |
  1457. <circle_descriptor> |
  1458. <polygon_descriptor> |
  1459. <path_descriptor> |
  1460. <qarc_descriptor> ]
  1461. ELEM* shape; // inherited from WINDOW
  1462. */
  1463. WINDOWS windows;
  1464. public:
  1465. /**
  1466. * Constructor SHAPE
  1467. * alternatively takes a DSN_T aType of T_outline
  1468. */
  1469. SHAPE( ELEM* aParent, DSN_T aType = T_shape ) :
  1470. WINDOW( aParent, aType )
  1471. {
  1472. connect = T_on;
  1473. }
  1474. void SetConnect( DSN_T aConnect )
  1475. {
  1476. connect = aConnect;
  1477. }
  1478. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  1479. {
  1480. out->Print( nestLevel, "(%s ", Name() );
  1481. if( shape )
  1482. shape->Format( out, 0 );
  1483. if( connect == T_off )
  1484. out->Print( 0, "(connect %s)", GetTokenText( connect ) );
  1485. if( windows.size() )
  1486. {
  1487. out->Print( 0, "\n" );
  1488. for( WINDOWS::iterator i=windows.begin(); i!=windows.end(); ++i )
  1489. i->Format( out, nestLevel+1 );
  1490. out->Print( nestLevel, ")\n" );
  1491. }
  1492. else
  1493. out->Print( 0, ")\n" );
  1494. }
  1495. };
  1496. class PIN : public ELEM
  1497. {
  1498. friend class SPECCTRA_DB;
  1499. std::string padstack_id;
  1500. double rotation;
  1501. bool isRotated;
  1502. std::string pin_id;
  1503. POINT vertex;
  1504. int kiNetCode; ///< KiCad netcode
  1505. public:
  1506. PIN( ELEM* aParent ) :
  1507. ELEM( T_pin, aParent )
  1508. {
  1509. rotation = 0.0;
  1510. isRotated = false;
  1511. kiNetCode = 0;
  1512. }
  1513. void SetRotation( double aRotation )
  1514. {
  1515. rotation = aRotation;
  1516. isRotated = (aRotation != 0.0);
  1517. }
  1518. void SetVertex( const POINT& aPoint )
  1519. {
  1520. vertex = aPoint;
  1521. vertex.FixNegativeZero();
  1522. }
  1523. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  1524. {
  1525. const char* quote = out->GetQuoteChar( padstack_id.c_str() );
  1526. if( isRotated )
  1527. out->Print( nestLevel, "(pin %s%s%s (rotate %.6g)",
  1528. quote, padstack_id.c_str(), quote,
  1529. rotation
  1530. );
  1531. else
  1532. out->Print( nestLevel, "(pin %s%s%s", quote, padstack_id.c_str(), quote );
  1533. quote = out->GetQuoteChar( pin_id.c_str() );
  1534. out->Print( 0, " %s%s%s %.6g %.6g)\n", quote, pin_id.c_str(), quote,
  1535. vertex.x, vertex.y );
  1536. }
  1537. };
  1538. typedef boost::ptr_vector<PIN> PINS;
  1539. class LIBRARY;
  1540. class IMAGE : public ELEM_HOLDER
  1541. {
  1542. friend class SPECCTRA_DB;
  1543. friend class LIBRARY;
  1544. std::string hash; ///< a hash string used by Compare(), not Format()ed/exported.
  1545. std::string image_id;
  1546. DSN_T side;
  1547. UNIT_RES* unit;
  1548. /* The grammar spec says only one outline is supported, but I am seeing
  1549. *.dsn examples with multiple outlines. So the outlines will go into
  1550. the kids list.
  1551. */
  1552. PINS pins;
  1553. RULE* rules;
  1554. RULE* place_rules;
  1555. KEEPOUTS keepouts;
  1556. int duplicated; ///< no. times this image_id is duplicated
  1557. public:
  1558. IMAGE( ELEM* aParent ) :
  1559. ELEM_HOLDER( T_image, aParent )
  1560. {
  1561. side = T_both;
  1562. unit = 0;
  1563. rules = 0;
  1564. place_rules = 0;
  1565. duplicated = 0;
  1566. }
  1567. ~IMAGE()
  1568. {
  1569. delete unit;
  1570. delete rules;
  1571. delete place_rules;
  1572. }
  1573. /**
  1574. * Function Compare
  1575. * compares two objects of this type and returns <0, 0, or >0.
  1576. */
  1577. static int Compare( IMAGE* lhs, IMAGE* rhs );
  1578. std::string GetImageId()
  1579. {
  1580. if( duplicated )
  1581. {
  1582. char buf[32];
  1583. std::string ret = image_id;
  1584. ret += "::";
  1585. sprintf( buf, "%d", duplicated );
  1586. ret += buf;
  1587. return ret;
  1588. }
  1589. return image_id;
  1590. }
  1591. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  1592. {
  1593. std::string imageId = GetImageId();
  1594. const char* quote = out->GetQuoteChar( imageId.c_str() );
  1595. out->Print( nestLevel, "(%s %s%s%s", Name(),
  1596. quote, imageId.c_str(), quote );
  1597. FormatContents( out, nestLevel+1 );
  1598. out->Print( nestLevel, ")\n" );
  1599. }
  1600. // this is here for makeHash()
  1601. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  1602. {
  1603. if( side != T_both )
  1604. out->Print( 0, " (side %s)", GetTokenText( side ) );
  1605. out->Print( 0, "\n");
  1606. if( unit )
  1607. unit->Format( out, nestLevel );
  1608. // format the kids, which in this class are the shapes
  1609. ELEM_HOLDER::FormatContents( out, nestLevel );
  1610. for( PINS::iterator i=pins.begin(); i!=pins.end(); ++i )
  1611. i->Format( out, nestLevel );
  1612. if( rules )
  1613. rules->Format( out, nestLevel );
  1614. if( place_rules )
  1615. place_rules->Format( out, nestLevel );
  1616. for( KEEPOUTS::iterator i=keepouts.begin(); i!=keepouts.end(); ++i )
  1617. i->Format( out, nestLevel );
  1618. }
  1619. UNIT_RES* GetUnits() const override
  1620. {
  1621. if( unit )
  1622. return unit;
  1623. return ELEM::GetUnits();
  1624. }
  1625. };
  1626. typedef boost::ptr_vector<IMAGE> IMAGES;
  1627. /**
  1628. * Class PADSTACK
  1629. * holds either a via or a pad definition.
  1630. */
  1631. class PADSTACK : public ELEM_HOLDER
  1632. {
  1633. friend class SPECCTRA_DB;
  1634. std::string hash; ///< a hash string used by Compare(), not Format()ed/exported.
  1635. std::string padstack_id;
  1636. UNIT_RES* unit;
  1637. /* The shapes are stored in the kids list */
  1638. DSN_T rotate;
  1639. DSN_T absolute;
  1640. DSN_T attach;
  1641. std::string via_id;
  1642. RULE* rules;
  1643. public:
  1644. /**
  1645. * Constructor PADSTACK()
  1646. * cannot take ELEM* aParent because PADSTACKSET confuses this with a
  1647. * copy constructor and causes havoc. Instead set parent with
  1648. * LIBRARY::AddPadstack()
  1649. */
  1650. PADSTACK() :
  1651. ELEM_HOLDER( T_padstack, NULL )
  1652. {
  1653. unit = 0;
  1654. rotate = T_on;
  1655. absolute = T_off;
  1656. rules = 0;
  1657. attach = T_off;
  1658. }
  1659. ~PADSTACK()
  1660. {
  1661. delete unit;
  1662. delete rules;
  1663. }
  1664. const std::string& GetPadstackId()
  1665. {
  1666. return padstack_id;
  1667. }
  1668. /**
  1669. * Function Compare
  1670. * compares two objects of this type and returns <0, 0, or >0.
  1671. */
  1672. static int Compare( PADSTACK* lhs, PADSTACK* rhs );
  1673. void SetPadstackId( const char* aPadstackId )
  1674. {
  1675. padstack_id = aPadstackId;
  1676. }
  1677. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  1678. {
  1679. const char* quote = out->GetQuoteChar( padstack_id.c_str() );
  1680. out->Print( nestLevel, "(%s %s%s%s\n", Name(),
  1681. quote, padstack_id.c_str(), quote );
  1682. FormatContents( out, nestLevel+1 );
  1683. out->Print( nestLevel, ")\n" );
  1684. }
  1685. // this factored out for use by Compare()
  1686. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  1687. {
  1688. if( unit )
  1689. unit->Format( out, nestLevel );
  1690. // format the kids, which in this class are the shapes
  1691. ELEM_HOLDER::FormatContents( out, nestLevel );
  1692. out->Print( nestLevel, "%s", "" );
  1693. // spec for <attach_descriptor> says default is on, so
  1694. // print the off condition to override this.
  1695. if( attach == T_off )
  1696. out->Print( 0, "(attach off)" );
  1697. else if( attach == T_on )
  1698. {
  1699. const char* quote = out->GetQuoteChar( via_id.c_str() );
  1700. out->Print( 0, "(attach on (use_via %s%s%s))",
  1701. quote, via_id.c_str(), quote );
  1702. }
  1703. if( rotate == T_off ) // print the non-default
  1704. out->Print( 0, "(rotate %s)", GetTokenText( rotate ) );
  1705. if( absolute == T_on ) // print the non-default
  1706. out->Print( 0, "(absolute %s)", GetTokenText( absolute ) );
  1707. out->Print( 0, "\n" );
  1708. if( rules )
  1709. rules->Format( out, nestLevel );
  1710. }
  1711. UNIT_RES* GetUnits() const override
  1712. {
  1713. if( unit )
  1714. return unit;
  1715. return ELEM::GetUnits();
  1716. }
  1717. };
  1718. typedef boost::ptr_vector<PADSTACK> PADSTACKS;
  1719. /**
  1720. * Function operator<
  1721. * is used by the PADSTACKSET boost::ptr_set below
  1722. */
  1723. inline bool operator<( const PADSTACK& lhs, const PADSTACK& rhs )
  1724. {
  1725. return PADSTACK::Compare( (PADSTACK*) &lhs, (PADSTACK*) &rhs ) < 0;
  1726. }
  1727. /**
  1728. * Class LIBRARY
  1729. * corresponds to the &lt;library_descriptor&gt; in the specctra dsn specification.
  1730. * Only unit_descriptor, image_descriptors, and padstack_descriptors are
  1731. * included as children at this time.
  1732. */
  1733. class LIBRARY : public ELEM
  1734. {
  1735. friend class SPECCTRA_DB;
  1736. UNIT_RES* unit;
  1737. IMAGES images;
  1738. PADSTACKS padstacks; ///< all except vias, which are in 'vias'
  1739. PADSTACKS vias;
  1740. public:
  1741. LIBRARY( ELEM* aParent, DSN_T aType = T_library ) :
  1742. ELEM( aType, aParent )
  1743. {
  1744. unit = 0;
  1745. // via_start_index = -1; // 0 or greater means there is at least one via
  1746. }
  1747. ~LIBRARY()
  1748. {
  1749. delete unit;
  1750. }
  1751. void AddPadstack( PADSTACK* aPadstack )
  1752. {
  1753. aPadstack->SetParent( this );
  1754. padstacks.push_back( aPadstack );
  1755. }
  1756. /*
  1757. void SetViaStartIndex( int aIndex )
  1758. {
  1759. via_start_index = aIndex;
  1760. }
  1761. int GetViaStartIndex()
  1762. {
  1763. return via_start_index;
  1764. }
  1765. */
  1766. /**
  1767. * Function FindIMAGE
  1768. * searches this LIBRARY for an image which matches the argument.
  1769. * @return int - if found the index into the images list, else -1.
  1770. */
  1771. int FindIMAGE( IMAGE* aImage )
  1772. {
  1773. unsigned i;
  1774. for( i=0; i<images.size(); ++i )
  1775. {
  1776. if( 0 == IMAGE::Compare( aImage, &images[i] ) )
  1777. return (int) i;
  1778. }
  1779. // There is no match to the IMAGE contents, but now generate a unique
  1780. // name for it.
  1781. int dups = 1;
  1782. for( i=0; i<images.size(); ++i )
  1783. {
  1784. if( 0 == aImage->image_id.compare( images[i].image_id ) )
  1785. aImage->duplicated = dups++;
  1786. }
  1787. return -1;
  1788. }
  1789. /**
  1790. * Function AppendIMAGE
  1791. * adds the image to the image list.
  1792. */
  1793. void AppendIMAGE( IMAGE* aImage )
  1794. {
  1795. aImage->SetParent( this );
  1796. images.push_back( aImage );
  1797. }
  1798. /**
  1799. * Function LookupIMAGE
  1800. * will add the image only if one exactly like it does not already exist
  1801. * in the image container.
  1802. * @return IMAGE* - the IMAGE which is registered in the LIBRARY that
  1803. * matches the argument, and it will be either the argument or
  1804. * a previous image which is a duplicate.
  1805. */
  1806. IMAGE* LookupIMAGE( IMAGE* aImage )
  1807. {
  1808. int ndx = FindIMAGE( aImage );
  1809. if( ndx == -1 )
  1810. {
  1811. AppendIMAGE( aImage );
  1812. return aImage;
  1813. }
  1814. return &images[ndx];
  1815. }
  1816. /**
  1817. * Function FindVia
  1818. * searches this LIBRARY for a via which matches the argument.
  1819. * @return int - if found the index into the padstack list, else -1.
  1820. */
  1821. int FindVia( PADSTACK* aVia )
  1822. {
  1823. for( unsigned i=0; i<vias.size(); ++i )
  1824. {
  1825. if( 0 == PADSTACK::Compare( aVia, &vias[i] ) )
  1826. return int( i );
  1827. }
  1828. return -1;
  1829. }
  1830. /**
  1831. * Function AppendVia
  1832. * adds \a aVia to the internal via container.
  1833. */
  1834. void AppendVia( PADSTACK* aVia )
  1835. {
  1836. aVia->SetParent( this );
  1837. vias.push_back( aVia );
  1838. }
  1839. /**
  1840. * Function AppendPADSTACK
  1841. * adds the padstack to the padstack container.
  1842. */
  1843. void AppendPADSTACK( PADSTACK* aPadstack )
  1844. {
  1845. aPadstack->SetParent( this );
  1846. padstacks.push_back( aPadstack );
  1847. }
  1848. /**
  1849. * Function LookupVia
  1850. * will add the via only if one exactly like it does not already exist
  1851. * in the padstack container.
  1852. * @return PADSTACK* - the PADSTACK which is registered in the LIBRARY that
  1853. * matches the argument, and it will be either the argument or
  1854. * a previous padstack which is a duplicate.
  1855. */
  1856. PADSTACK* LookupVia( PADSTACK* aVia )
  1857. {
  1858. int ndx = FindVia( aVia );
  1859. if( ndx == -1 )
  1860. {
  1861. AppendVia( aVia );
  1862. return aVia;
  1863. }
  1864. return &vias[ndx];
  1865. }
  1866. /**
  1867. * Function FindPADSTACK
  1868. * searches the padstack container by name.
  1869. * @return PADSTACK* - The PADSTACK with a matching name if it exists, else NULL.
  1870. */
  1871. PADSTACK* FindPADSTACK( const std::string& aPadstackId )
  1872. {
  1873. for( unsigned i=0; i<padstacks.size(); ++i )
  1874. {
  1875. PADSTACK* ps = &padstacks[i];
  1876. if( 0 == ps->GetPadstackId().compare( aPadstackId ) )
  1877. return ps;
  1878. }
  1879. return NULL;
  1880. }
  1881. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  1882. {
  1883. if( unit )
  1884. unit->Format( out, nestLevel );
  1885. for( IMAGES::iterator i=images.begin(); i!=images.end(); ++i )
  1886. i->Format( out, nestLevel );
  1887. for( PADSTACKS::iterator i=padstacks.begin(); i!=padstacks.end(); ++i )
  1888. i->Format( out, nestLevel );
  1889. for( PADSTACKS::iterator i=vias.begin(); i!=vias.end(); ++i )
  1890. i->Format( out, nestLevel );
  1891. }
  1892. UNIT_RES* GetUnits() const override
  1893. {
  1894. if( unit )
  1895. return unit;
  1896. return ELEM::GetUnits();
  1897. }
  1898. };
  1899. /**
  1900. * Class PIN_REF
  1901. * corresponds to the &lt;pin_reference&gt; definition in the specctra dsn spec.
  1902. */
  1903. struct PIN_REF : public ELEM
  1904. {
  1905. std::string component_id;
  1906. std::string pin_id;
  1907. PIN_REF( ELEM* aParent ) :
  1908. ELEM( T_pin, aParent )
  1909. {
  1910. }
  1911. /**
  1912. * Function FormatIt
  1913. * is like Format() but is not virual and returns the number of characters
  1914. * that were output.
  1915. */
  1916. int FormatIt( OUTPUTFORMATTER* out, int nestLevel )
  1917. {
  1918. // only print the newline if there is a nest level, and make
  1919. // the quotes unconditional on this one.
  1920. const char* newline = nestLevel ? "\n" : "";
  1921. const char* cquote = out->GetQuoteChar( component_id.c_str() );
  1922. const char* pquote = out->GetQuoteChar( pin_id.c_str() );
  1923. return out->Print( nestLevel, "%s%s%s-%s%s%s%s",
  1924. cquote, component_id.c_str(), cquote,
  1925. pquote, pin_id.c_str(), pquote,
  1926. newline );
  1927. }
  1928. };
  1929. typedef std::vector<PIN_REF> PIN_REFS;
  1930. class FROMTO : public ELEM
  1931. {
  1932. friend class SPECCTRA_DB;
  1933. std::string fromText;
  1934. std::string toText;
  1935. DSN_T fromto_type;
  1936. std::string net_id;
  1937. RULE* rules;
  1938. // std::string circuit;
  1939. LAYER_RULES layer_rules;
  1940. public:
  1941. FROMTO( ELEM* aParent ) :
  1942. ELEM( T_fromto, aParent )
  1943. {
  1944. rules = 0;
  1945. fromto_type = DSN_T( T_NONE );
  1946. }
  1947. ~FROMTO()
  1948. {
  1949. delete rules;
  1950. }
  1951. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  1952. {
  1953. // no quoting on these two, the lexer preserved the quotes on input
  1954. out->Print( nestLevel, "(%s %s %s ",
  1955. Name(), fromText.c_str(), toText.c_str() );
  1956. if( fromto_type != DSN_T( T_NONE ) )
  1957. out->Print( 0, "(type %s)", GetTokenText( fromto_type ) );
  1958. if( net_id.size() )
  1959. {
  1960. const char* quote = out->GetQuoteChar( net_id.c_str() );
  1961. out->Print( 0, "(net %s%s%s)", quote, net_id.c_str(), quote );
  1962. }
  1963. bool singleLine = true;
  1964. if( rules || layer_rules.size() )
  1965. {
  1966. out->Print( 0, "\n" );
  1967. singleLine = false;
  1968. }
  1969. if( rules )
  1970. rules->Format( out, nestLevel+1 );
  1971. /*
  1972. if( circuit.size() )
  1973. out->Print( nestLevel, "%s\n", circuit.c_str() );
  1974. */
  1975. for( LAYER_RULES::iterator i=layer_rules.begin(); i!=layer_rules.end(); ++i )
  1976. i->Format( out, nestLevel+1 );
  1977. out->Print( singleLine ? 0 : nestLevel, ")" );
  1978. if( nestLevel || !singleLine )
  1979. out->Print( 0, "\n" );
  1980. }
  1981. };
  1982. typedef boost::ptr_vector<FROMTO> FROMTOS;
  1983. /**
  1984. * Class COMP_ORDER
  1985. * corresponds to the &lt;component_order_descriptor&gt;
  1986. */
  1987. class COMP_ORDER : public ELEM
  1988. {
  1989. friend class SPECCTRA_DB;
  1990. STRINGS placement_ids;
  1991. public:
  1992. COMP_ORDER( ELEM* aParent ) :
  1993. ELEM( T_comp_order, aParent )
  1994. {
  1995. }
  1996. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  1997. {
  1998. out->Print( nestLevel, "(%s", Name() );
  1999. for( STRINGS::iterator i=placement_ids.begin(); i!=placement_ids.end(); ++i )
  2000. {
  2001. const char* quote = out->GetQuoteChar( i->c_str() );
  2002. out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
  2003. }
  2004. out->Print( 0, ")" );
  2005. if( nestLevel )
  2006. out->Print( 0, "\n" );
  2007. }
  2008. };
  2009. typedef boost::ptr_vector<COMP_ORDER> COMP_ORDERS;
  2010. /**
  2011. * Class NET
  2012. * corresponds to a &lt;net_descriptor&gt;
  2013. * in the DSN spec.
  2014. */
  2015. class NET : public ELEM
  2016. {
  2017. friend class SPECCTRA_DB;
  2018. std::string net_id;
  2019. bool unassigned;
  2020. int net_number;
  2021. DSN_T pins_type; ///< T_pins | T_order, type of field 'pins' below
  2022. PIN_REFS pins;
  2023. PIN_REFS expose;
  2024. PIN_REFS noexpose;
  2025. PIN_REFS source;
  2026. PIN_REFS load;
  2027. PIN_REFS terminator;
  2028. DSN_T type; ///< T_fix | T_normal
  2029. DSN_T supply; ///< T_power | T_ground
  2030. RULE* rules;
  2031. LAYER_RULES layer_rules;
  2032. FROMTOS fromtos;
  2033. COMP_ORDER* comp_order;
  2034. public:
  2035. NET( ELEM* aParent ) :
  2036. ELEM( T_net, aParent )
  2037. {
  2038. unassigned = false;
  2039. net_number = T_NONE;
  2040. pins_type = T_pins;
  2041. type = T_NONE;
  2042. supply = T_NONE;
  2043. rules = 0;
  2044. comp_order = 0;
  2045. }
  2046. ~NET()
  2047. {
  2048. delete rules;
  2049. delete comp_order;
  2050. }
  2051. int FindPIN_REF( const std::string& aComponent )
  2052. {
  2053. for( unsigned i=0; i<pins.size(); ++i )
  2054. {
  2055. if( 0 == aComponent.compare( pins[i].component_id ) )
  2056. return int(i);
  2057. }
  2058. return -1;
  2059. }
  2060. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  2061. {
  2062. const char* quote = out->GetQuoteChar( net_id.c_str() );
  2063. const char* space = " ";
  2064. out->Print( nestLevel, "(%s %s%s%s", Name(),
  2065. quote, net_id.c_str(), quote );
  2066. if( unassigned )
  2067. {
  2068. out->Print( 0, "%s(unassigned)", space );
  2069. space = ""; // only needed one space
  2070. }
  2071. if( net_number != T_NONE )
  2072. {
  2073. out->Print( 0, "%s(net_number %d)", space, net_number );
  2074. // space = "";
  2075. }
  2076. out->Print( 0, "\n" );
  2077. if( pins.size() )
  2078. {
  2079. const int RIGHTMARGIN = 80;
  2080. int perLine = out->Print( nestLevel+1, "(%s", GetTokenText( pins_type ) );
  2081. for( PIN_REFS::iterator i=pins.begin(); i!=pins.end(); ++i )
  2082. {
  2083. if( perLine > RIGHTMARGIN )
  2084. {
  2085. out->Print( 0, "\n");
  2086. perLine = out->Print( nestLevel+2, "%s", "" );
  2087. }
  2088. else
  2089. perLine += out->Print( 0, " " );
  2090. perLine += i->FormatIt( out, 0 );
  2091. }
  2092. out->Print( 0, ")\n" );
  2093. }
  2094. if( comp_order )
  2095. comp_order->Format( out, nestLevel+1 );
  2096. if( type != T_NONE )
  2097. out->Print( nestLevel+1, "(type %s)\n", GetTokenText( type ) );
  2098. if( rules )
  2099. rules->Format( out, nestLevel+1 );
  2100. for( LAYER_RULES::iterator i=layer_rules.begin(); i!=layer_rules.end(); ++i )
  2101. i->Format( out, nestLevel+1 );
  2102. for( FROMTOS::iterator i=fromtos.begin(); i!=fromtos.end(); ++i )
  2103. i->Format( out, nestLevel+1 );
  2104. out->Print( nestLevel, ")\n" );
  2105. }
  2106. };
  2107. typedef boost::ptr_vector<NET> NETS;
  2108. class TOPOLOGY : public ELEM
  2109. {
  2110. friend class SPECCTRA_DB;
  2111. FROMTOS fromtos;
  2112. COMP_ORDERS comp_orders;
  2113. public:
  2114. TOPOLOGY( ELEM* aParent ) :
  2115. ELEM( T_topology, aParent )
  2116. {
  2117. }
  2118. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  2119. {
  2120. for( FROMTOS::iterator i=fromtos.begin(); i!=fromtos.end(); ++i )
  2121. i->Format( out, nestLevel );
  2122. for( COMP_ORDERS::iterator i=comp_orders.begin(); i!=comp_orders.end(); ++i )
  2123. i->Format( out, nestLevel );
  2124. }
  2125. };
  2126. /**
  2127. * Class CLASS
  2128. * corresponds to the &lt;class_descriptor&gt; in the specctra spec.
  2129. */
  2130. class CLASS : public ELEM
  2131. {
  2132. friend class SPECCTRA_DB;
  2133. std::string class_id;
  2134. STRINGS net_ids;
  2135. /// circuit descriptor list
  2136. STRINGS circuit;
  2137. RULE* rules;
  2138. LAYER_RULES layer_rules;
  2139. TOPOLOGY* topology;
  2140. public:
  2141. CLASS( ELEM* aParent ) :
  2142. ELEM( T_class, aParent )
  2143. {
  2144. rules = 0;
  2145. topology = 0;
  2146. }
  2147. ~CLASS()
  2148. {
  2149. delete rules;
  2150. delete topology;
  2151. }
  2152. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  2153. {
  2154. const char* quote = out->GetQuoteChar( class_id.c_str() );
  2155. int perLine = out->Print( nestLevel, "(%s %s%s%s",
  2156. Name(),
  2157. quote, class_id.c_str(), quote );
  2158. const int RIGHTMARGIN = 72;
  2159. for( STRINGS::iterator i=net_ids.begin(); i!=net_ids.end(); ++i )
  2160. {
  2161. const char* space = " ";
  2162. if( perLine > RIGHTMARGIN )
  2163. {
  2164. out->Print( 0, "\n" );
  2165. perLine = out->Print( nestLevel+1, "%s", "" );
  2166. space = ""; // no space at first net_id of the line
  2167. }
  2168. quote = out->GetQuoteChar( i->c_str() );
  2169. perLine += out->Print( 0, "%s%s%s%s", space, quote, i->c_str(), quote );
  2170. }
  2171. bool newLine = false;
  2172. if( circuit.size() || rules || layer_rules.size() || topology )
  2173. {
  2174. out->Print( 0, "\n" );
  2175. newLine = true;
  2176. }
  2177. if( circuit.size() )
  2178. {
  2179. out->Print( nestLevel+1, "(circuit\n" );
  2180. for( STRINGS::iterator i=circuit.begin(); i!=circuit.end(); ++i )
  2181. out->Print( nestLevel+2, "%s\n", i->c_str() );
  2182. out->Print( nestLevel+1, ")\n" );
  2183. }
  2184. if( rules )
  2185. rules->Format( out, nestLevel+1 );
  2186. for( LAYER_RULES::iterator i=layer_rules.begin(); i!=layer_rules.end(); ++i )
  2187. i->Format( out, nestLevel+1 );
  2188. if( topology )
  2189. topology->Format( out, nestLevel+1 );
  2190. out->Print( newLine ? nestLevel : 0, ")\n" );
  2191. }
  2192. };
  2193. typedef boost::ptr_vector<CLASS> CLASSLIST;
  2194. class NETWORK : public ELEM
  2195. {
  2196. friend class SPECCTRA_DB;
  2197. NETS nets;
  2198. CLASSLIST classes;
  2199. public:
  2200. NETWORK( ELEM* aParent ) :
  2201. ELEM( T_network, aParent )
  2202. {
  2203. }
  2204. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  2205. {
  2206. for( NETS::iterator i=nets.begin(); i!=nets.end(); ++i )
  2207. i->Format( out, nestLevel );
  2208. for( CLASSLIST::iterator i=classes.begin(); i!=classes.end(); ++i )
  2209. i->Format( out, nestLevel );
  2210. }
  2211. };
  2212. class CONNECT : public ELEM
  2213. {
  2214. // @todo not completed.
  2215. public:
  2216. CONNECT( ELEM* aParent ) :
  2217. ELEM( T_connect, aParent ) {}
  2218. };
  2219. /**
  2220. * Class WIRE
  2221. * corresponds to &lt;wire_shape_descriptor&gt; in the specctra dsn spec.
  2222. */
  2223. class WIRE : public ELEM
  2224. {
  2225. friend class SPECCTRA_DB;
  2226. /* <shape_descriptor >::=
  2227. [<rectangle_descriptor> |
  2228. <circle_descriptor> |
  2229. <polygon_descriptor> |
  2230. <path_descriptor> |
  2231. <qarc_descriptor> ]
  2232. */
  2233. ELEM* shape;
  2234. std::string net_id;
  2235. int turret;
  2236. DSN_T wire_type;
  2237. DSN_T attr;
  2238. std::string shield;
  2239. WINDOWS windows;
  2240. CONNECT* connect;
  2241. bool supply;
  2242. public:
  2243. WIRE( ELEM* aParent ) :
  2244. ELEM( T_wire, aParent )
  2245. {
  2246. shape = 0;
  2247. connect = 0;
  2248. turret = -1;
  2249. wire_type = T_NONE;
  2250. attr = T_NONE;
  2251. supply = false;
  2252. }
  2253. ~WIRE()
  2254. {
  2255. delete shape;
  2256. delete connect;
  2257. }
  2258. void SetShape( ELEM* aShape )
  2259. {
  2260. delete shape;
  2261. shape = aShape;
  2262. if( aShape )
  2263. {
  2264. wxASSERT(aShape->Type()==T_rect || aShape->Type()==T_circle
  2265. || aShape->Type()==T_qarc || aShape->Type()==T_path
  2266. || aShape->Type()==T_polygon);
  2267. aShape->SetParent( this );
  2268. }
  2269. }
  2270. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  2271. {
  2272. out->Print( nestLevel, "(%s ", Name() );
  2273. if( shape )
  2274. shape->Format( out, 0 );
  2275. if( net_id.size() )
  2276. {
  2277. const char* quote = out->GetQuoteChar( net_id.c_str() );
  2278. out->Print( 0, "(net %s%s%s)",
  2279. quote, net_id.c_str(), quote );
  2280. }
  2281. if( turret >= 0 )
  2282. out->Print( 0, "(turrent %d)", turret );
  2283. if( wire_type != T_NONE )
  2284. out->Print( 0, "(type %s)", GetTokenText( wire_type ) );
  2285. if( attr != T_NONE )
  2286. out->Print( 0, "(attr %s)", GetTokenText( attr ) );
  2287. if( shield.size() )
  2288. {
  2289. const char* quote = out->GetQuoteChar( shield.c_str() );
  2290. out->Print( 0, "(shield %s%s%s)",
  2291. quote, shield.c_str(), quote );
  2292. }
  2293. if( windows.size() )
  2294. {
  2295. out->Print( 0, "\n" );
  2296. for( WINDOWS::iterator i=windows.begin(); i!=windows.end(); ++i )
  2297. i->Format( out, nestLevel+1 );
  2298. }
  2299. if( connect )
  2300. connect->Format( out, 0 );
  2301. if( supply )
  2302. out->Print( 0, "(supply)" );
  2303. out->Print( 0, ")\n" );
  2304. }
  2305. };
  2306. typedef boost::ptr_vector<WIRE> WIRES;
  2307. /**
  2308. * Class WIRE_VIA
  2309. * corresponds to &lt;wire_via_descriptor&gt; in the specctra dsn spec.
  2310. */
  2311. class WIRE_VIA : public ELEM
  2312. {
  2313. friend class SPECCTRA_DB;
  2314. std::string padstack_id;
  2315. POINTS vertexes;
  2316. std::string net_id;
  2317. int via_number;
  2318. DSN_T via_type;
  2319. DSN_T attr;
  2320. std::string virtual_pin_name;
  2321. STRINGS contact_layers;
  2322. bool supply;
  2323. public:
  2324. WIRE_VIA( ELEM* aParent ) :
  2325. ELEM( T_via, aParent )
  2326. {
  2327. via_number = -1;
  2328. via_type = T_NONE;
  2329. attr = T_NONE;
  2330. supply = false;
  2331. }
  2332. const std::string& GetPadstackId()
  2333. {
  2334. return padstack_id;
  2335. }
  2336. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  2337. {
  2338. const char* quote = out->GetQuoteChar( padstack_id.c_str() );
  2339. const int RIGHTMARGIN = 80;
  2340. int perLine = out->Print( nestLevel, "(%s %s%s%s",
  2341. Name(),
  2342. quote, padstack_id.c_str(), quote );
  2343. for( POINTS::iterator i=vertexes.begin(); i!=vertexes.end(); ++i )
  2344. {
  2345. if( perLine > RIGHTMARGIN )
  2346. {
  2347. out->Print( 0, "\n" );
  2348. perLine = out->Print( nestLevel+1, "%s", "" );
  2349. }
  2350. else
  2351. perLine += out->Print( 0, " " );
  2352. perLine += out->Print( 0, "%.6g %.6g", i->x, i->y );
  2353. }
  2354. if( net_id.size() || via_number!=-1 || via_type!=T_NONE || attr!=T_NONE || supply)
  2355. out->Print( 0, " " );
  2356. if( net_id.size() )
  2357. {
  2358. if( perLine > RIGHTMARGIN )
  2359. {
  2360. out->Print( 0, "\n" );
  2361. perLine = out->Print( nestLevel+1, "%s", "" );
  2362. }
  2363. quote = out->GetQuoteChar( net_id.c_str() );
  2364. perLine += out->Print( 0, "(net %s%s%s)", quote, net_id.c_str(), quote );
  2365. }
  2366. if( via_number != -1 )
  2367. {
  2368. if( perLine > RIGHTMARGIN )
  2369. {
  2370. out->Print( 0, "\n" );
  2371. perLine = out->Print( nestLevel+1, "%s", "" );
  2372. }
  2373. perLine += out->Print( 0, "(via_number %d)", via_number );
  2374. }
  2375. if( via_type != T_NONE )
  2376. {
  2377. if( perLine > RIGHTMARGIN )
  2378. {
  2379. out->Print( 0, "\n" );
  2380. perLine = out->Print( nestLevel+1, "%s", "" );
  2381. }
  2382. perLine += out->Print( 0, "(type %s)", GetTokenText( via_type ) );
  2383. }
  2384. if( attr != T_NONE )
  2385. {
  2386. if( perLine > RIGHTMARGIN )
  2387. {
  2388. out->Print( 0, "\n" );
  2389. perLine = out->Print( nestLevel+1, "%s", "" );
  2390. }
  2391. if( attr == T_virtual_pin )
  2392. {
  2393. quote = out->GetQuoteChar( virtual_pin_name.c_str() );
  2394. perLine += out->Print( 0, "(attr virtual_pin %s%s%s)",
  2395. quote, virtual_pin_name.c_str(), quote );
  2396. }
  2397. else
  2398. perLine += out->Print( 0, "(attr %s)", GetTokenText( attr ) );
  2399. }
  2400. if( supply )
  2401. {
  2402. if( perLine > RIGHTMARGIN )
  2403. {
  2404. out->Print( 0, "\n" );
  2405. perLine = out->Print( nestLevel+1, "%s", "" );
  2406. }
  2407. perLine += out->Print( 0, "(supply)" );
  2408. }
  2409. if( contact_layers.size() )
  2410. {
  2411. out->Print( 0, "\n" );
  2412. out->Print( nestLevel+1, "(contact\n" );
  2413. for( STRINGS::iterator i=contact_layers.begin(); i!=contact_layers.end(); ++i )
  2414. {
  2415. quote = out->GetQuoteChar( i->c_str() );
  2416. out->Print( nestLevel+2, "%s%s%s\n", quote, i->c_str(), quote );
  2417. }
  2418. out->Print( nestLevel+1, "))\n" );
  2419. }
  2420. else
  2421. out->Print( 0, ")\n" );
  2422. }
  2423. };
  2424. typedef boost::ptr_vector<WIRE_VIA> WIRE_VIAS;
  2425. /**
  2426. * Class WIRING
  2427. * corresponds to &lt;wiring_descriptor&gt; in the specctra dsn spec.
  2428. */
  2429. class WIRING : public ELEM
  2430. {
  2431. friend class SPECCTRA_DB;
  2432. UNIT_RES* unit;
  2433. WIRES wires;
  2434. WIRE_VIAS wire_vias;
  2435. public:
  2436. WIRING( ELEM* aParent ) :
  2437. ELEM( T_wiring, aParent )
  2438. {
  2439. unit = 0;
  2440. }
  2441. ~WIRING()
  2442. {
  2443. delete unit;
  2444. }
  2445. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  2446. {
  2447. if( unit )
  2448. unit->Format( out, nestLevel );
  2449. for( WIRES::iterator i=wires.begin(); i!=wires.end(); ++i )
  2450. i->Format( out, nestLevel );
  2451. for( WIRE_VIAS::iterator i=wire_vias.begin(); i!=wire_vias.end(); ++i )
  2452. i->Format( out, nestLevel );
  2453. }
  2454. UNIT_RES* GetUnits() const override
  2455. {
  2456. if( unit )
  2457. return unit;
  2458. return ELEM::GetUnits();
  2459. }
  2460. };
  2461. class PCB : public ELEM
  2462. {
  2463. friend class SPECCTRA_DB;
  2464. std::string pcbname;
  2465. PARSER* parser;
  2466. UNIT_RES* resolution;
  2467. UNIT_RES* unit;
  2468. STRUCTURE* structure;
  2469. PLACEMENT* placement;
  2470. LIBRARY* library;
  2471. NETWORK* network;
  2472. WIRING* wiring;
  2473. public:
  2474. PCB( ELEM* aParent = 0 ) :
  2475. ELEM( T_pcb, aParent )
  2476. {
  2477. parser = 0;
  2478. resolution = 0;
  2479. unit = 0;
  2480. structure = 0;
  2481. placement = 0;
  2482. library = 0;
  2483. network = 0;
  2484. wiring = 0;
  2485. }
  2486. ~PCB()
  2487. {
  2488. delete parser;
  2489. delete resolution;
  2490. delete unit;
  2491. delete structure;
  2492. delete placement;
  2493. delete library;
  2494. delete network;
  2495. delete wiring;
  2496. }
  2497. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  2498. {
  2499. const char* quote = out->GetQuoteChar( pcbname.c_str() );
  2500. out->Print( nestLevel, "(%s %s%s%s\n", Name(),
  2501. quote, pcbname.c_str(), quote );
  2502. if( parser )
  2503. parser->Format( out, nestLevel+1 );
  2504. if( resolution )
  2505. resolution->Format( out, nestLevel+1 );
  2506. if( unit )
  2507. unit->Format( out, nestLevel+1 );
  2508. if( structure )
  2509. structure->Format( out, nestLevel+1 );
  2510. if( placement )
  2511. placement->Format( out, nestLevel+1 );
  2512. if( library )
  2513. library->Format( out, nestLevel+1 );
  2514. if( network )
  2515. network->Format( out, nestLevel+1 );
  2516. if( wiring )
  2517. wiring->Format( out, nestLevel+1 );
  2518. out->Print( nestLevel, ")\n" );
  2519. }
  2520. UNIT_RES* GetUnits() const override
  2521. {
  2522. if( unit )
  2523. return unit;
  2524. if( resolution )
  2525. return resolution->GetUnits();
  2526. return ELEM::GetUnits();
  2527. }
  2528. };
  2529. class ANCESTOR : public ELEM
  2530. {
  2531. friend class SPECCTRA_DB;
  2532. std::string filename;
  2533. std::string comment;
  2534. time_t time_stamp;
  2535. public:
  2536. ANCESTOR( ELEM* aParent ) :
  2537. ELEM( T_ancestor, aParent )
  2538. {
  2539. time_stamp = time(NULL);
  2540. }
  2541. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  2542. {
  2543. char temp[80];
  2544. struct tm* tmp;
  2545. tmp = localtime( &time_stamp );
  2546. strftime( temp, sizeof(temp), "%b %d %H : %M : %S %Y", tmp );
  2547. // format the time first to temp
  2548. // filename may be empty, so quote it just in case.
  2549. out->Print( nestLevel, "(%s \"%s\" (created_time %s)\n",
  2550. Name(),
  2551. filename.c_str(),
  2552. temp );
  2553. if( comment.size() )
  2554. {
  2555. const char* quote = out->GetQuoteChar( comment.c_str() );
  2556. out->Print( nestLevel+1, "(comment %s%s%s)\n",
  2557. quote, comment.c_str(), quote );
  2558. }
  2559. out->Print( nestLevel, ")\n" );
  2560. }
  2561. };
  2562. typedef boost::ptr_vector<ANCESTOR> ANCESTORS;
  2563. class HISTORY : public ELEM
  2564. {
  2565. friend class SPECCTRA_DB;
  2566. ANCESTORS ancestors;
  2567. time_t time_stamp;
  2568. STRINGS comments;
  2569. public:
  2570. HISTORY( ELEM* aParent ) :
  2571. ELEM( T_history, aParent )
  2572. {
  2573. time_stamp = time(NULL);
  2574. }
  2575. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  2576. {
  2577. for( ANCESTORS::iterator i=ancestors.begin(); i!=ancestors.end(); ++i )
  2578. i->Format( out, nestLevel );
  2579. char temp[80];
  2580. struct tm* tmp;
  2581. tmp = localtime( &time_stamp );
  2582. strftime( temp, sizeof(temp), "%b %d %H : %M : %S %Y", tmp );
  2583. // format the time first to temp
  2584. out->Print( nestLevel, "(self (created_time %s)\n", temp );
  2585. for( STRINGS::iterator i=comments.begin(); i!=comments.end(); ++i )
  2586. {
  2587. const char* quote = out->GetQuoteChar( i->c_str() );
  2588. out->Print( nestLevel+1, "(comment %s%s%s)\n",
  2589. quote, i->c_str(), quote );
  2590. }
  2591. out->Print( nestLevel, ")\n" );
  2592. }
  2593. };
  2594. /**
  2595. * Class SUPPLY_PIN
  2596. * corresponds to the &lt;supply_pin_descriptor&gt; in the specctra dsn spec.
  2597. */
  2598. class SUPPLY_PIN : public ELEM
  2599. {
  2600. friend class SPECCTRA_DB;
  2601. PIN_REFS pin_refs;
  2602. std::string net_id;
  2603. public:
  2604. SUPPLY_PIN( ELEM* aParent ) :
  2605. ELEM( T_supply_pin, aParent )
  2606. {
  2607. }
  2608. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  2609. {
  2610. bool singleLine = pin_refs.size() <= 1;
  2611. out->Print( nestLevel, "(%s", Name() );
  2612. if( singleLine )
  2613. {
  2614. out->Print( 0, "%s", " " );
  2615. pin_refs.begin()->Format( out, 0 );
  2616. }
  2617. else
  2618. {
  2619. for( PIN_REFS::iterator i=pin_refs.begin(); i!=pin_refs.end(); ++i )
  2620. i->FormatIt( out, nestLevel+1 );
  2621. }
  2622. if( net_id.size() )
  2623. {
  2624. const char* newline = singleLine ? "" : "\n";
  2625. const char* quote = out->GetQuoteChar( net_id.c_str() );
  2626. out->Print( singleLine ? 0 : nestLevel+1,
  2627. " (net %s%s%s)%s", quote, net_id.c_str(), quote, newline );
  2628. }
  2629. out->Print( singleLine ? 0 : nestLevel, ")\n");
  2630. }
  2631. };
  2632. typedef boost::ptr_vector<SUPPLY_PIN> SUPPLY_PINS;
  2633. /**
  2634. * Class NET_OUT
  2635. * corresponds to the &lt;net_out_descriptor&gt; of the specctra dsn spec.
  2636. */
  2637. class NET_OUT : public ELEM
  2638. {
  2639. friend class SPECCTRA_DB;
  2640. std::string net_id;
  2641. int net_number;
  2642. RULE* rules;
  2643. WIRES wires;
  2644. WIRE_VIAS wire_vias;
  2645. SUPPLY_PINS supply_pins;
  2646. public:
  2647. NET_OUT( ELEM* aParent ) :
  2648. ELEM( T_net_out, aParent )
  2649. {
  2650. rules = 0;
  2651. net_number = -1;
  2652. }
  2653. ~NET_OUT()
  2654. {
  2655. delete rules;
  2656. }
  2657. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  2658. {
  2659. const char* quote = out->GetQuoteChar( net_id.c_str() );
  2660. // cannot use Type() here, it is T_net_out and we need "(net "
  2661. out->Print( nestLevel, "(net %s%s%s\n",
  2662. quote, net_id.c_str(), quote );
  2663. if( net_number>= 0 )
  2664. out->Print( nestLevel+1, "(net_number %d)\n", net_number );
  2665. if( rules )
  2666. rules->Format( out, nestLevel+1 );
  2667. for( WIRES::iterator i=wires.begin(); i!=wires.end(); ++i )
  2668. i->Format( out, nestLevel+1 );
  2669. for( WIRE_VIAS::iterator i=wire_vias.begin(); i!=wire_vias.end(); ++i )
  2670. i->Format( out, nestLevel+1 );
  2671. for( SUPPLY_PINS::iterator i=supply_pins.begin(); i!=supply_pins.end(); ++i )
  2672. i->Format( out, nestLevel+1 );
  2673. out->Print( nestLevel, ")\n" );
  2674. }
  2675. };
  2676. typedef boost::ptr_vector<NET_OUT> NET_OUTS;
  2677. class ROUTE : public ELEM
  2678. {
  2679. friend class SPECCTRA_DB;
  2680. UNIT_RES* resolution;
  2681. PARSER* parser;
  2682. STRUCTURE_OUT* structure_out;
  2683. LIBRARY* library;
  2684. NET_OUTS net_outs;
  2685. // TEST_POINTS* test_points;
  2686. public:
  2687. ROUTE( ELEM* aParent ) :
  2688. ELEM( T_route, aParent )
  2689. {
  2690. resolution = 0;
  2691. parser = 0;
  2692. structure_out = 0;
  2693. library = 0;
  2694. }
  2695. ~ROUTE()
  2696. {
  2697. delete resolution;
  2698. delete parser;
  2699. delete structure_out;
  2700. delete library;
  2701. // delete test_points;
  2702. }
  2703. UNIT_RES* GetUnits() const override
  2704. {
  2705. if( resolution )
  2706. return resolution;
  2707. return ELEM::GetUnits();
  2708. }
  2709. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  2710. {
  2711. if( resolution )
  2712. resolution->Format( out, nestLevel );
  2713. if( parser )
  2714. parser->Format( out, nestLevel );
  2715. if( structure_out )
  2716. structure_out->Format( out, nestLevel );
  2717. if( library )
  2718. library->Format( out, nestLevel );
  2719. if( net_outs.size() )
  2720. {
  2721. out->Print( nestLevel, "(network_out\n" );
  2722. for( NET_OUTS::iterator i=net_outs.begin(); i!=net_outs.end(); ++i )
  2723. i->Format( out, nestLevel+1 );
  2724. out->Print( nestLevel, ")\n" );
  2725. }
  2726. // if( test_poinst )
  2727. // test_points->Format( out, nestLevel );
  2728. }
  2729. };
  2730. /**
  2731. * Struct PIN_PAIR
  2732. * is used within the WAS_IS class below to hold a pair of PIN_REFs and
  2733. * corresponds to the (pins was is) construct within the specctra dsn spec.
  2734. */
  2735. struct PIN_PAIR
  2736. {
  2737. PIN_PAIR( ELEM* aParent = 0 ) :
  2738. was( aParent ),
  2739. is( aParent )
  2740. {
  2741. }
  2742. PIN_REF was;
  2743. PIN_REF is;
  2744. };
  2745. typedef std::vector<PIN_PAIR> PIN_PAIRS;
  2746. /**
  2747. * Class WAS_IS
  2748. * corresponds to the &lt;was_is_descriptor&gt; in the specctra dsn spec.
  2749. */
  2750. class WAS_IS : public ELEM
  2751. {
  2752. friend class SPECCTRA_DB;
  2753. PIN_PAIRS pin_pairs;
  2754. public:
  2755. WAS_IS( ELEM* aParent ) :
  2756. ELEM( T_was_is, aParent )
  2757. {
  2758. }
  2759. void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) override
  2760. {
  2761. for( PIN_PAIRS::iterator i=pin_pairs.begin(); i!=pin_pairs.end(); ++i )
  2762. {
  2763. out->Print( nestLevel, "(pins " );
  2764. i->was.Format( out, 0 );
  2765. out->Print( 0, " " );
  2766. i->is.Format( out, 0 );
  2767. out->Print( 0, ")\n" );
  2768. }
  2769. }
  2770. };
  2771. /**
  2772. * Class SESSION
  2773. * corresponds to the &lt;session_file_descriptor&gt; in the specctra dsn spec.
  2774. */
  2775. class SESSION : public ELEM
  2776. {
  2777. friend class SPECCTRA_DB;
  2778. std::string session_id;
  2779. std::string base_design;
  2780. HISTORY* history;
  2781. STRUCTURE* structure;
  2782. PLACEMENT* placement;
  2783. WAS_IS* was_is;
  2784. ROUTE* route;
  2785. /* not supported:
  2786. FLOOR_PLAN* floor_plan;
  2787. NET_PIN_CHANGES* net_pin_changes;
  2788. SWAP_HISTORY* swap_history;
  2789. */
  2790. public:
  2791. SESSION( ELEM* aParent = 0 ) :
  2792. ELEM( T_session, aParent )
  2793. {
  2794. history = 0;
  2795. structure = 0;
  2796. placement = 0;
  2797. was_is = 0;
  2798. route = 0;
  2799. }
  2800. ~SESSION()
  2801. {
  2802. delete history;
  2803. delete structure;
  2804. delete placement;
  2805. delete was_is;
  2806. delete route;
  2807. }
  2808. void Format( OUTPUTFORMATTER* out, int nestLevel ) override
  2809. {
  2810. const char* quote = out->GetQuoteChar( session_id.c_str() );
  2811. out->Print( nestLevel, "(%s %s%s%s\n", Name(),
  2812. quote, session_id.c_str(), quote );
  2813. out->Print( nestLevel+1, "(base_design \"%s\")\n", base_design.c_str() );
  2814. if( history )
  2815. history->Format( out, nestLevel+1 );
  2816. if( structure )
  2817. structure->Format( out, nestLevel+1 );
  2818. if( placement )
  2819. placement->Format( out, nestLevel+1 );
  2820. if( was_is )
  2821. was_is->Format( out, nestLevel+1 );
  2822. if( route )
  2823. route->Format( out, nestLevel+1 );
  2824. out->Print( nestLevel, ")\n" );
  2825. }
  2826. };
  2827. typedef boost::ptr_set<PADSTACK> PADSTACKSET;
  2828. /**
  2829. * Class SPECCTRA_DB
  2830. * holds a DSN data tree, usually coming from a DSN file. Is essentially a
  2831. * SPECCTRA_PARSER class.
  2832. */
  2833. class SPECCTRA_DB : public SPECCTRA_LEXER
  2834. {
  2835. /// specctra DSN keywords
  2836. static const KEYWORD keywords[];
  2837. static const unsigned keywordCount;
  2838. PCB* pcb;
  2839. SESSION* session;
  2840. wxString filename;
  2841. std::string quote_char;
  2842. bool modulesAreFlipped;
  2843. STRING_FORMATTER sf;
  2844. STRINGS layerIds; ///< indexed by PCB layer number
  2845. /// maps BOARD layer number to PCB layer numbers
  2846. std::vector<int> kicadLayer2pcb;
  2847. /// maps PCB layer number to BOARD layer numbers
  2848. std::vector<PCB_LAYER_ID> pcbLayer2kicad;
  2849. /// used during FromSESSION() only, memory for it is not owned here.
  2850. UNIT_RES* routeResolution;
  2851. /// a copy to avoid passing as an argument, memory for it is not owned here.
  2852. BOARD* sessionBoard;
  2853. static const KICAD_T scanPADs[];
  2854. PADSTACKSET padstackset;
  2855. /// we don't want ownership here permanently, so we don't use boost::ptr_vector
  2856. std::vector<NET*> nets;
  2857. /// specctra cu layers, 0 based index:
  2858. int m_top_via_layer;
  2859. int m_bot_via_layer;
  2860. /**
  2861. * Function buildLayerMaps
  2862. * creates a few data translation structures for layer name and number
  2863. * mapping between the DSN::PCB structure and the KiCad BOARD structure.
  2864. * @param aBoard The BOARD to create the maps for.
  2865. */
  2866. void buildLayerMaps( BOARD* aBoard );
  2867. /**
  2868. * Function findLayerName
  2869. * returns the PCB layer index for a given layer name, within the specctra session
  2870. * file.
  2871. *
  2872. * @return int - the layer index within the specctra session file, or -1 if
  2873. * aLayerName is not found.
  2874. */
  2875. int findLayerName( const std::string& aLayerName ) const;
  2876. /**
  2877. * Function readCOMPnPIN
  2878. * reads a &lt;pin_reference&gt; and splits it into the two parts which are
  2879. * on either side of the hyphen. This function is specialized because
  2880. * pin_reference may or may not be using double quotes. Both of these
  2881. * are legal: U2-14 or "U2"-"14". The lexer treats the first one as a
  2882. * single T_SYMBOL, so in that case we have to split it into two here.
  2883. * <p>
  2884. * The caller should have already read in the first token comprizing the
  2885. * pin_reference and it will be tested through CurTok().
  2886. *
  2887. * @param component_id Where to put the text preceeding the '-' hyphen.
  2888. * @param pid_id Where to put the text which trails the '-'.
  2889. * @throw IO_ERROR, if the next token or two do no make up a pin_reference,
  2890. * or there is an error reading from the input stream.
  2891. */
  2892. void readCOMPnPIN( std::string* component_id, std::string* pid_id );
  2893. /**
  2894. * Function readTIME
  2895. * reads a &lt;time_stamp&gt; which consists of 8 lexer tokens:
  2896. * "month date hour : minute : second year".
  2897. * This function is specialized because time_stamps occur more than
  2898. * once in a session file.
  2899. * <p>
  2900. * The caller should not have already read in the first token comprizing the
  2901. * time stamp.
  2902. *
  2903. * @param time_stamp Where to put the parsed time value.
  2904. * @throw IO_ERROR, if the next token or 8 do no make up a time stamp,
  2905. * or there is an error reading from the input stream.
  2906. */
  2907. void readTIME( time_t* time_stamp );
  2908. void doPCB( PCB* growth );
  2909. void doPARSER( PARSER* growth );
  2910. void doRESOLUTION( UNIT_RES* growth );
  2911. void doUNIT( UNIT_RES* growth );
  2912. void doSTRUCTURE( STRUCTURE* growth );
  2913. void doSTRUCTURE_OUT( STRUCTURE_OUT* growth );
  2914. void doLAYER_NOISE_WEIGHT( LAYER_NOISE_WEIGHT* growth );
  2915. void doSPECCTRA_LAYER_PAIR( SPECCTRA_LAYER_PAIR* growth );
  2916. void doBOUNDARY( BOUNDARY* growth );
  2917. void doRECTANGLE( RECTANGLE* growth );
  2918. void doPATH( PATH* growth );
  2919. void doSTRINGPROP( STRINGPROP* growth );
  2920. void doTOKPROP( TOKPROP* growth );
  2921. void doVIA( VIA* growth );
  2922. void doCONTROL( CONTROL* growth );
  2923. void doLAYER( LAYER* growth );
  2924. void doRULE( RULE* growth );
  2925. void doKEEPOUT( KEEPOUT* growth );
  2926. void doCIRCLE( CIRCLE* growth );
  2927. void doQARC( QARC* growth );
  2928. void doWINDOW( WINDOW* growth );
  2929. void doCONNECT( CONNECT* growth );
  2930. void doREGION( REGION* growth );
  2931. void doCLASS_CLASS( CLASS_CLASS* growth );
  2932. void doLAYER_RULE( LAYER_RULE* growth );
  2933. void doCLASSES( CLASSES* growth );
  2934. void doGRID( GRID* growth );
  2935. void doPLACE( PLACE* growth );
  2936. void doCOMPONENT( COMPONENT* growth );
  2937. void doPLACEMENT( PLACEMENT* growth );
  2938. void doPROPERTIES( PROPERTIES* growth );
  2939. void doPADSTACK( PADSTACK* growth );
  2940. void doSHAPE( SHAPE* growth );
  2941. void doIMAGE( IMAGE* growth );
  2942. void doLIBRARY( LIBRARY* growth );
  2943. void doPIN( PIN* growth );
  2944. void doNET( NET* growth );
  2945. void doNETWORK( NETWORK* growth );
  2946. void doCLASS( CLASS* growth );
  2947. void doTOPOLOGY( TOPOLOGY* growth );
  2948. void doFROMTO( FROMTO* growth );
  2949. void doCOMP_ORDER( COMP_ORDER* growth );
  2950. void doWIRE( WIRE* growth );
  2951. void doWIRE_VIA( WIRE_VIA* growth );
  2952. void doWIRING( WIRING* growth );
  2953. void doSESSION( SESSION* growth );
  2954. void doANCESTOR( ANCESTOR* growth );
  2955. void doHISTORY( HISTORY* growth );
  2956. void doROUTE( ROUTE* growth );
  2957. void doWAS_IS( WAS_IS* growth );
  2958. void doNET_OUT( NET_OUT* growth );
  2959. void doSUPPLY_PIN( SUPPLY_PIN* growth );
  2960. //-----<FromBOARD>-------------------------------------------------------
  2961. /**
  2962. * Function fillBOUNDARY
  2963. * makes the board perimeter for the DSN file by filling the BOUNDARY element
  2964. * in the specctra element tree.
  2965. * @param aBoard The BOARD to get information from in order to make the BOUNDARY.
  2966. * @param aBoundary The empty BOUNDARY to fill in.
  2967. */
  2968. void fillBOUNDARY( BOARD* aBoard, BOUNDARY* aBoundary );
  2969. /**
  2970. * Function makeIMAGE
  2971. * allocates an IMAGE on the heap and creates all the PINs according
  2972. * to the D_PADs in the MODULE.
  2973. * @param aBoard The owner of the MODULE.
  2974. * @param aModule The MODULE from which to build the IMAGE.
  2975. * @return IMAGE* - not tested for duplication yet.
  2976. */
  2977. IMAGE* makeIMAGE( BOARD* aBoard, MODULE* aModule );
  2978. /**
  2979. * Function makePADSTACK
  2980. * creates a PADSTACK which matches the given pad. Only pads which do not
  2981. * satisfy the function isKeepout() should be passed to this function.
  2982. * @param aBoard The owner of the MODULE.
  2983. * @param aPad The D_PAD which needs to be made into a PADSTACK.
  2984. * @return PADSTACK* - The created padstack, including its padstack_id.
  2985. */
  2986. PADSTACK* makePADSTACK( BOARD* aBoard, D_PAD* aPad );
  2987. /**
  2988. * Function makeVia
  2989. * makes a round through hole PADSTACK using the given KiCad diameter in deci-mils.
  2990. * @param aCopperDiameter The diameter of the copper pad.
  2991. * @param aDrillDiameter The drill diameter, used on re-import of the session file.
  2992. * @param aTopLayer The DSN::PCB top most layer index.
  2993. * @param aBotLayer The DSN::PCB bottom most layer index.
  2994. * @return PADSTACK* - The padstack, which is on the heap only, user must save
  2995. * or delete it.
  2996. */
  2997. PADSTACK* makeVia( int aCopperDiameter, int aDrillDiameter,
  2998. int aTopLayer, int aBotLayer );
  2999. /**
  3000. * Function makeVia
  3001. * makes any kind of PADSTACK using the given KiCad VIA.
  3002. * @param aVia The VIA to build the padstack from.
  3003. * @return PADSTACK* - The padstack, which is on the heap only, user must save
  3004. * or delete it.
  3005. */
  3006. PADSTACK* makeVia( const ::VIA* aVia );
  3007. /**
  3008. * Function deleteNETs
  3009. * deletes all the NETs that may be in here.
  3010. */
  3011. void deleteNETs()
  3012. {
  3013. for( unsigned n=0; n<nets.size(); ++n )
  3014. delete nets[n];
  3015. nets.clear();
  3016. }
  3017. /**
  3018. * Function exportNETCLASS
  3019. * exports \a aNetClass to the DSN file.
  3020. */
  3021. void exportNETCLASS( const std::shared_ptr<NETCLASS>& aNetClass, BOARD* aBoard );
  3022. //-----</FromBOARD>------------------------------------------------------
  3023. //-----<FromSESSION>-----------------------------------------------------
  3024. /**
  3025. * Function makeTRACK
  3026. * creates a TRACK form the PATH and BOARD info.
  3027. */
  3028. TRACK* makeTRACK( PATH* aPath, int aPointIndex, int aNetcode );
  3029. /**
  3030. * Function makeVIA
  3031. * instantiates a KiCad VIA on the heap and initializes it with internal
  3032. * values consistent with the given PADSTACK, POINT, and netcode.
  3033. */
  3034. ::VIA* makeVIA( PADSTACK* aPadstack, const POINT& aPoint, int aNetCode, int aViaDrillDefault );
  3035. //-----</FromSESSION>----------------------------------------------------
  3036. public:
  3037. SPECCTRA_DB() :
  3038. SPECCTRA_LEXER( 0 ) // LINE_READER* == NULL, no DSNLEXER::PushReader()
  3039. {
  3040. // The LINE_READER will be pushed from an automatic instantiation,
  3041. // we don't own it:
  3042. wxASSERT( !iOwnReaders );
  3043. pcb = 0;
  3044. session = 0;
  3045. quote_char += '"';
  3046. modulesAreFlipped = false;
  3047. SetSpecctraMode( true );
  3048. // Avoid not initialized members:
  3049. routeResolution = NULL;
  3050. sessionBoard = NULL;
  3051. m_top_via_layer = 0;
  3052. m_bot_via_layer = 0;
  3053. }
  3054. virtual ~SPECCTRA_DB()
  3055. {
  3056. delete pcb;
  3057. delete session;
  3058. deleteNETs();
  3059. }
  3060. /**
  3061. * Function MakePCB
  3062. * makes a PCB with all the default ELEMs and parts on the heap.
  3063. */
  3064. static PCB* MakePCB();
  3065. /**
  3066. * Function SetPCB
  3067. * deletes any existing PCB and replaces it with the given one.
  3068. */
  3069. void SetPCB( PCB* aPcb )
  3070. {
  3071. delete pcb;
  3072. pcb = aPcb;
  3073. }
  3074. PCB* GetPCB() { return pcb; }
  3075. /**
  3076. * Function SetSESSION
  3077. * deletes any existing SESSION and replaces it with the given one.
  3078. */
  3079. void SetSESSION( SESSION* aSession )
  3080. {
  3081. delete session;
  3082. session = aSession;
  3083. }
  3084. SESSION* GetSESSION() { return session; }
  3085. /**
  3086. * Function LoadPCB
  3087. * is a recursive descent parser for a SPECCTRA DSN "design" file.
  3088. * A design file is nearly a full description of a PCB (seems to be
  3089. * missing only the silkscreen stuff).
  3090. *
  3091. * @param aFilename The name of the dsn file to load.
  3092. * @throw IO_ERROR if there is a lexer or parser error.
  3093. */
  3094. void LoadPCB( const wxString& aFilename );
  3095. /**
  3096. * Function LoadSESSION
  3097. * is a recursive descent parser for a SPECCTRA DSN "session" file.
  3098. * A session file is a file that is fed back from the router to the layout
  3099. * tool (Pcbnew) and should be used to update a BOARD object with the new
  3100. * tracks, vias, and component locations.
  3101. *
  3102. * @param aFilename The name of the dsn file to load.
  3103. * @throw IO_ERROR if there is a lexer or parser error.
  3104. */
  3105. void LoadSESSION( const wxString& aFilename );
  3106. /**
  3107. * Function ExportPCB
  3108. * writes the internal PCB instance out as a SPECTRA DSN format file.
  3109. *
  3110. * @param aFilename The file to save to.
  3111. * @param aNameChange If true, causes the pcb's name to change to "aFilename"
  3112. * and also to to be changed in the output file.
  3113. * @throw IO_ERROR, if an i/o error occurs saving the file.
  3114. */
  3115. void ExportPCB( const wxString& aFilename, bool aNameChange=false );
  3116. /**
  3117. * Function FromBOARD
  3118. * adds the entire BOARD to the PCB but does not write it out. Note that
  3119. * the BOARD given to this function must have all the MODULEs on the component
  3120. * side of the BOARD.
  3121. *
  3122. * See void PCB_EDIT_FRAME::ExportToSpecctra( wxCommandEvent& event )
  3123. * for how this can be done before calling this function.
  3124. *
  3125. * @param aBoard The BOARD to convert to a PCB.
  3126. */
  3127. void FromBOARD( BOARD* aBoard );
  3128. /**
  3129. * Function FromSESSION
  3130. * adds the entire SESSION info to a BOARD but does not write it out. The
  3131. * the BOARD given to this function will have all its tracks and via's replaced,
  3132. * and all its components are subject to being moved.
  3133. *
  3134. * @param aBoard The BOARD to merge the SESSION information into.
  3135. */
  3136. void FromSESSION( BOARD* aBoard );
  3137. /**
  3138. * Function ExportSESSION
  3139. * writes the internal SESSION instance out as a SPECTRA DSN format file.
  3140. *
  3141. * @param aFilename The file to save to.
  3142. */
  3143. void ExportSESSION( const wxString& aFilename );
  3144. /**
  3145. * Function FlipMODULEs
  3146. * flips the modules which are on the back side of the board to the front.
  3147. */
  3148. void FlipMODULEs( BOARD* aBoard );
  3149. /**
  3150. * Function RevertMODULEs
  3151. * flips the modules which were on the back side of the board back to the back.
  3152. */
  3153. void RevertMODULEs( BOARD* aBoard );
  3154. };
  3155. } // namespace DSN
  3156. #endif // SPECCTRA_H_
  3157. //EOF