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.

3884 lines
100 KiB

18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
18 years ago
  1. /*
  2. * This program source code file is part of KICAD, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2007-2008 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
  5. * Copyright (C) 2007 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. /* This source file implements export and import capabilities to the
  25. specctra dsn file format. The grammar for that file format is documented
  26. fairly well. There are classes for each major type of descriptor in the
  27. spec.
  28. Since there are so many classes in here, it may be helpful to generate
  29. the Doxygen directory:
  30. $ cd <kicadSourceRoot>
  31. $ doxygen
  32. Then you can view the html documentation in the <kicadSourceRoot>/doxygen
  33. directory. The main class in this file is SPECCTRA_DB and its main
  34. functions are LoadPCB(), LoadSESSION(), and ExportPCB().
  35. Wide use is made of boost::ptr_vector<> and std::vector<> template classes.
  36. If the contained object is small, then std::vector tends to be used.
  37. If the contained object is large, variable size, or would require writing
  38. an assignment operator() or copy constructore, then boost::ptr_vector
  39. cannot be beat.
  40. */
  41. #include <cstdarg>
  42. #include <cstdio>
  43. #include "specctra.h"
  44. #include <wx/ffile.h>
  45. // To build the DSN beautifier and unit tester, simply uncomment this and then
  46. // use CMake's makefile to build target "specctra_test".
  47. //#define STANDALONE // define "stand alone, i.e. unit testing"
  48. #if defined(STANDALONE)
  49. #define EDA_BASE // build_version.h behavior
  50. #undef COMMON_GLOBL
  51. #define COMMON_GLOBL // build_version.h behavior
  52. #endif
  53. #include "build_version.h"
  54. namespace DSN {
  55. #define NESTWIDTH 2 ///< how many spaces per nestLevel
  56. //-----<SPECCTRA_DB>-------------------------------------------------
  57. void SPECCTRA_DB::ThrowIOError( const wxChar* fmt, ... ) throw( IOError )
  58. {
  59. wxString errText;
  60. va_list args;
  61. va_start( args, fmt );
  62. errText.PrintfV( fmt, args );
  63. va_end( args );
  64. throw IOError( errText );
  65. }
  66. void SPECCTRA_DB::expecting( DSN_T aTok ) throw( IOError )
  67. {
  68. wxString errText( _("Expecting") );
  69. errText << wxT(" ") << LEXER::GetTokenString( aTok );
  70. lexer->ThrowIOError( errText, lexer->CurOffset() );
  71. }
  72. void SPECCTRA_DB::expecting( const char* text ) throw( IOError )
  73. {
  74. wxString errText( _("Expecting") );
  75. errText << wxT(" '") << CONV_FROM_UTF8(text) << wxT("'");
  76. lexer->ThrowIOError( errText, lexer->CurOffset() );
  77. }
  78. void SPECCTRA_DB::unexpected( DSN_T aTok ) throw( IOError )
  79. {
  80. wxString errText( _("Unexpected") );
  81. errText << wxT(" ") << LEXER::GetTokenString( aTok );
  82. lexer->ThrowIOError( errText, lexer->CurOffset() );
  83. }
  84. void SPECCTRA_DB::unexpected( const char* text ) throw( IOError )
  85. {
  86. wxString errText( _("Unexpected") );
  87. errText << wxT(" '") << CONV_FROM_UTF8(text) << wxT("'");
  88. lexer->ThrowIOError( errText, lexer->CurOffset() );
  89. }
  90. DSN_T SPECCTRA_DB::nextTok()
  91. {
  92. DSN_T ret = lexer->NextTok();
  93. return ret;
  94. }
  95. bool SPECCTRA_DB::isSymbol( DSN_T aTok )
  96. {
  97. // if aTok is >= 0, then it might be a coincidental match to a keyword.
  98. return aTok==T_SYMBOL || aTok==T_STRING || aTok>=0;
  99. }
  100. void SPECCTRA_DB::needLEFT() throw( IOError )
  101. {
  102. DSN_T tok = nextTok();
  103. if( tok != T_LEFT )
  104. expecting( T_LEFT );
  105. }
  106. void SPECCTRA_DB::needRIGHT() throw( IOError )
  107. {
  108. DSN_T tok = nextTok();
  109. if( tok != T_RIGHT )
  110. expecting( T_RIGHT );
  111. }
  112. void SPECCTRA_DB::needSYMBOL() throw( IOError )
  113. {
  114. DSN_T tok = nextTok();
  115. if( !isSymbol( tok ) )
  116. expecting( T_SYMBOL );
  117. }
  118. void SPECCTRA_DB::readCOMPnPIN( std::string* component_id, std::string* pin_id ) throw( IOError )
  119. {
  120. DSN_T tok;
  121. static const char pin_def[] = "<pin_reference>::=<component_id>-<pin_id>";
  122. if( !isSymbol( lexer->CurTok() ) )
  123. expecting( pin_def );
  124. // case for: A12-14, i.e. no wrapping quotes. This should be a single
  125. // token, so split it.
  126. if( lexer->CurTok() != T_STRING )
  127. {
  128. const char* toktext = lexer->CurText();
  129. const char* dash = strchr( toktext, '-' );
  130. if( !dash )
  131. expecting( pin_def );
  132. while( toktext != dash )
  133. *component_id += *toktext++;
  134. ++toktext; // skip the dash
  135. while( *toktext )
  136. *pin_id += *toktext++;
  137. }
  138. // quoted string: "U12"-"14" or "U12"-14, 3 tokens in either case
  139. else
  140. {
  141. *component_id = lexer->CurText();
  142. tok = nextTok();
  143. if( tok!=T_DASH )
  144. expecting( pin_def );
  145. nextTok(); // accept anything after the dash.
  146. *pin_id = lexer->CurText();
  147. }
  148. }
  149. void SPECCTRA_DB::readTIME( time_t* time_stamp ) throw( IOError )
  150. {
  151. DSN_T tok;
  152. struct tm mytime;
  153. static const char time_toks[] = "<month> <day> <hour> : <minute> : <second> <year>";
  154. static const char* months[] = { // index 0 = Jan
  155. "Jan", "Feb", "Mar", "Apr", "May", "Jun",
  156. "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL
  157. };
  158. needSYMBOL(); // month
  159. const char* ptok = lexer->CurText();
  160. mytime.tm_mon = 0; // remains if we don't find a month match.
  161. for( int m=0; months[m]; ++m )
  162. {
  163. if( !stricmp( months[m], ptok ) )
  164. {
  165. mytime.tm_mon = m;
  166. break;
  167. }
  168. }
  169. tok = nextTok(); // day
  170. if( tok != T_NUMBER )
  171. expecting( time_toks );
  172. mytime.tm_mday = atoi( lexer->CurText() );
  173. tok = nextTok(); // hour
  174. if( tok != T_NUMBER )
  175. expecting( time_toks );
  176. mytime.tm_hour = atoi( lexer->CurText() );
  177. // : colon
  178. needSYMBOL();
  179. if( *lexer->CurText() != ':' || strlen( lexer->CurText() )!=1 )
  180. expecting( time_toks );
  181. tok = nextTok(); // minute
  182. if( tok != T_NUMBER )
  183. expecting( time_toks );
  184. mytime.tm_min = atoi( lexer->CurText() );
  185. // : colon
  186. needSYMBOL();
  187. if( *lexer->CurText() != ':' || strlen( lexer->CurText() )!=1 )
  188. expecting( time_toks );
  189. tok = nextTok(); // second
  190. if( tok != T_NUMBER )
  191. expecting( time_toks );
  192. mytime.tm_sec = atoi( lexer->CurText() );
  193. tok = nextTok(); // year
  194. if( tok != T_NUMBER )
  195. expecting( time_toks );
  196. mytime.tm_year = atoi( lexer->CurText() ) - 1900;
  197. *time_stamp = mktime( &mytime );
  198. }
  199. void SPECCTRA_DB::LoadPCB( const wxString& filename ) throw( IOError )
  200. {
  201. wxFFile file;
  202. FILE* fp = wxFopen( filename, wxT("r") );
  203. if( !fp )
  204. {
  205. ThrowIOError( _("Unable to open file \"%s\""), filename.GetData() );
  206. }
  207. file.Attach( fp ); // "exception safe" way to close the file.
  208. delete lexer;
  209. lexer = 0;
  210. lexer = new LEXER( file.fp(), filename );
  211. if( nextTok() != T_LEFT )
  212. expecting( T_LEFT );
  213. if( nextTok() != T_pcb )
  214. expecting( T_pcb );
  215. SetPCB( new PCB() );
  216. doPCB( pcb );
  217. }
  218. void SPECCTRA_DB::LoadSESSION( const wxString& filename ) throw( IOError )
  219. {
  220. wxFFile file;
  221. FILE* fp = wxFopen( filename, wxT("r") );
  222. if( !fp )
  223. {
  224. ThrowIOError( _("Unable to open file \"%s\""), filename.GetData() );
  225. }
  226. file.Attach( fp ); // "exception safe" way to close the file.
  227. delete lexer;
  228. lexer = 0;
  229. lexer = new LEXER( file.fp(), filename );
  230. if( nextTok() != T_LEFT )
  231. expecting( T_LEFT );
  232. if( nextTok() != T_session )
  233. expecting( T_session );
  234. SetSESSION( new SESSION() );
  235. doSESSION( session );
  236. }
  237. void SPECCTRA_DB::doPCB( PCB* growth ) throw( IOError )
  238. {
  239. DSN_T tok;
  240. /* <design_descriptor >::=
  241. (pcb <pcb_id >
  242. [<parser_descriptor> ]
  243. [<capacitance_resolution_descriptor> ]
  244. [<conductance_resolution_descriptor> ]
  245. [<current_resolution_descriptor> ]
  246. [<inductance_resolution_descriptor> ]
  247. [<resistance_resolution_descriptor> ]
  248. [<resolution_descriptor> ]
  249. [<time_resolution_descriptor> ]
  250. [<voltage_resolution_descriptor> ]
  251. [<unit_descriptor> ]
  252. [<structure_descriptor> | <file_descriptor> ]
  253. [<placement_descriptor> | <file_descriptor> ]
  254. [<library_descriptor> | <file_descriptor> ]
  255. [<floor_plan_descriptor> | <file_descriptor> ]
  256. [<part_library_descriptor> | <file_descriptor> ]
  257. [<network_descriptor> | <file_descriptor> ]
  258. [<wiring_descriptor> ]
  259. [<color_descriptor> ]
  260. )
  261. */
  262. needSYMBOL();
  263. growth->pcbname = lexer->CurText();
  264. while( (tok = nextTok()) != T_RIGHT )
  265. {
  266. if( tok != T_LEFT )
  267. expecting( T_LEFT );
  268. tok = nextTok();
  269. switch( tok )
  270. {
  271. case T_parser:
  272. if( growth->parser )
  273. unexpected( tok );
  274. growth->parser = new PARSER( growth );
  275. doPARSER( growth->parser );
  276. break;
  277. case T_unit:
  278. if( growth->unit )
  279. unexpected( tok );
  280. growth->unit = new UNIT_RES( growth, tok );
  281. doUNIT( growth->unit );
  282. break;
  283. case T_resolution:
  284. if( growth->resolution )
  285. unexpected( tok );
  286. growth->resolution = new UNIT_RES( growth, tok );
  287. doRESOLUTION( growth->resolution );
  288. break;
  289. case T_structure:
  290. if( growth->structure )
  291. unexpected( tok );
  292. growth->structure = new STRUCTURE( growth );
  293. doSTRUCTURE( growth->structure );
  294. break;
  295. case T_placement:
  296. if( growth->placement )
  297. unexpected( tok );
  298. growth->placement = new PLACEMENT( growth );
  299. doPLACEMENT( growth->placement );
  300. break;
  301. case T_library:
  302. if( growth->library )
  303. unexpected( tok );
  304. growth->library = new LIBRARY( growth );
  305. doLIBRARY( growth->library );
  306. break;
  307. case T_network:
  308. if( growth->network )
  309. unexpected( tok );
  310. growth->network = new NETWORK( growth );
  311. doNETWORK( growth->network );
  312. break;
  313. case T_wiring:
  314. if( growth->wiring )
  315. unexpected( tok );
  316. growth->wiring = new WIRING( growth );
  317. doWIRING( growth->wiring );
  318. break;
  319. default:
  320. unexpected( lexer->CurText() );
  321. }
  322. }
  323. tok = nextTok();
  324. if( tok != T_EOF )
  325. expecting( T_EOF );
  326. }
  327. void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError )
  328. {
  329. DSN_T tok;
  330. /* <parser_descriptor >::=
  331. (parser
  332. [(string_quote <quote_char >)]
  333. (space_in_quoted_tokens [on | off])
  334. [(host_cad <id >)]
  335. [(host_version <id >)]
  336. [{(constant <id > <id >)}]
  337. [(write_resolution] {<character> <positive_integer >})]
  338. [(routes_include {[testpoint | guides |
  339. image_conductor]})]
  340. [(wires_include testpoint)]
  341. [(case_sensitive [on | off])]
  342. [(via_rotate_first [on | off])]
  343. )
  344. */
  345. while( (tok = nextTok()) != T_RIGHT )
  346. {
  347. if( tok != T_LEFT )
  348. expecting( T_LEFT );
  349. tok = nextTok();
  350. switch( tok )
  351. {
  352. case T_string_quote:
  353. tok = nextTok();
  354. if( tok != T_QUOTE_DEF )
  355. expecting( T_QUOTE_DEF );
  356. lexer->SetStringDelimiter( (unsigned char) *lexer->CurText() );
  357. growth->string_quote = *lexer->CurText();
  358. quote_char = lexer->CurText();
  359. needRIGHT();
  360. break;
  361. case T_space_in_quoted_tokens:
  362. tok = nextTok();
  363. if( tok!=T_on && tok!=T_off )
  364. expecting( "on|off" );
  365. lexer->SetSpaceInQuotedTokens( tok==T_on );
  366. growth->space_in_quoted_tokens = (tok==T_on);
  367. needRIGHT();
  368. break;
  369. case T_host_cad:
  370. needSYMBOL();
  371. growth->host_cad = lexer->CurText();
  372. needRIGHT();
  373. break;
  374. case T_host_version:
  375. needSYMBOL();
  376. growth->host_version = lexer->CurText();
  377. needRIGHT();
  378. break;
  379. case T_constant:
  380. needSYMBOL();
  381. growth->const_id1 = lexer->CurText();
  382. needSYMBOL();
  383. growth->const_id2 = lexer->CurText();
  384. needRIGHT();
  385. break;
  386. case T_write_resolution: // [(writee_resolution {<character> <positive_integer >})]
  387. while( (tok = nextTok()) != T_RIGHT )
  388. {
  389. if( tok!=T_SYMBOL )
  390. expecting( T_SYMBOL );
  391. tok = nextTok();
  392. if( tok!=T_NUMBER )
  393. expecting( T_NUMBER );
  394. // @todo
  395. }
  396. break;
  397. case T_routes_include: // [(routes_include {[testpoint | guides | image_conductor]})]
  398. while( (tok = nextTok()) != T_RIGHT )
  399. {
  400. switch( tok )
  401. {
  402. case T_testpoint:
  403. growth->routes_include_testpoint = true;
  404. break;
  405. case T_guide:
  406. growth->routes_include_guides = true;
  407. break;
  408. case T_image_conductor:
  409. growth->routes_include_image_conductor = true;
  410. break;
  411. default:
  412. expecting( "testpoint|guides|image_conductor" );
  413. }
  414. }
  415. break;
  416. case T_wires_include: // [(wires_include testpoint)]
  417. tok = nextTok();
  418. if( tok != T_testpoint )
  419. expecting( T_testpoint );
  420. growth->routes_include_testpoint = true;
  421. needRIGHT();
  422. break;
  423. case T_case_sensitive:
  424. tok = nextTok();
  425. if( tok!=T_on && tok!=T_off )
  426. expecting( "on|off" );
  427. growth->case_sensitive = (tok==T_on);
  428. needRIGHT();
  429. break;
  430. case T_via_rotate_first: // [(via_rotate_first [on | off])]
  431. tok = nextTok();
  432. if( tok!=T_on && tok!=T_off )
  433. expecting( "on|off" );
  434. growth->via_rotate_first = (tok==T_on);
  435. needRIGHT();
  436. break;
  437. case T_generated_by_freeroute:
  438. growth->generated_by_freeroute = true;
  439. needRIGHT();
  440. break;
  441. default:
  442. unexpected( lexer->CurText() );
  443. }
  444. }
  445. }
  446. void SPECCTRA_DB::doRESOLUTION( UNIT_RES* growth ) throw(IOError)
  447. {
  448. DSN_T tok = nextTok();
  449. switch( tok )
  450. {
  451. case T_inch:
  452. case T_mil:
  453. case T_cm:
  454. case T_mm:
  455. case T_um:
  456. growth->units = tok;
  457. break;
  458. default:
  459. expecting( "inch|mil|cm|mm|um" );
  460. }
  461. tok = nextTok();
  462. if( tok != T_NUMBER )
  463. expecting( T_NUMBER );
  464. growth->value = atoi( lexer->CurText() );
  465. needRIGHT();
  466. }
  467. void SPECCTRA_DB::doUNIT( UNIT_RES* growth ) throw(IOError)
  468. {
  469. DSN_T tok = nextTok();
  470. switch( tok )
  471. {
  472. case T_inch:
  473. case T_mil:
  474. case T_cm:
  475. case T_mm:
  476. case T_um:
  477. growth->units = tok;
  478. break;
  479. default:
  480. expecting( "inch|mil|cm|mm|um" );
  481. }
  482. needRIGHT();
  483. }
  484. void SPECCTRA_DB::doLAYER_PAIR( LAYER_PAIR* growth ) throw( IOError )
  485. {
  486. needSYMBOL();
  487. growth->layer_id0 = lexer->CurText();
  488. needSYMBOL();
  489. growth->layer_id1 = lexer->CurText();
  490. if( nextTok() != T_NUMBER )
  491. expecting( T_NUMBER );
  492. growth->layer_weight = strtod( lexer->CurText(), 0 );
  493. needRIGHT();
  494. }
  495. void SPECCTRA_DB::doLAYER_NOISE_WEIGHT( LAYER_NOISE_WEIGHT* growth ) throw( IOError )
  496. {
  497. DSN_T tok;
  498. while( (tok = nextTok()) != T_RIGHT )
  499. {
  500. if( tok != T_LEFT )
  501. expecting( T_LEFT );
  502. if( nextTok() != T_layer_pair )
  503. expecting( T_layer_pair );
  504. LAYER_PAIR* layer_pair = new LAYER_PAIR( growth );
  505. growth->layer_pairs.push_back( layer_pair );
  506. doLAYER_PAIR( layer_pair );
  507. }
  508. }
  509. void SPECCTRA_DB::doSTRUCTURE( STRUCTURE* growth ) throw(IOError)
  510. {
  511. DSN_T tok;
  512. while( (tok = nextTok()) != T_RIGHT )
  513. {
  514. if( tok != T_LEFT )
  515. expecting( T_LEFT );
  516. tok = nextTok();
  517. switch( tok )
  518. {
  519. case T_unit:
  520. if( growth->unit )
  521. unexpected( tok );
  522. growth->unit = new UNIT_RES( growth, tok );
  523. doUNIT( growth->unit );
  524. break;
  525. case T_resolution:
  526. if( growth->unit )
  527. unexpected( tok );
  528. growth->unit = new UNIT_RES( growth, tok );
  529. doRESOLUTION( growth->unit );
  530. break;
  531. case T_layer_noise_weight:
  532. growth->layer_noise_weight = new LAYER_NOISE_WEIGHT( growth );
  533. doLAYER_NOISE_WEIGHT( growth->layer_noise_weight );
  534. break;
  535. case T_place_boundary:
  536. L_place:
  537. if( growth->place_boundary )
  538. unexpected( tok );
  539. growth->place_boundary = new BOUNDARY( growth, T_place_boundary );
  540. doBOUNDARY( growth->place_boundary );
  541. break;
  542. case T_boundary:
  543. if( growth->boundary )
  544. {
  545. if( growth->place_boundary )
  546. unexpected( tok );
  547. goto L_place;
  548. }
  549. growth->boundary = new BOUNDARY( growth );
  550. doBOUNDARY( growth->boundary );
  551. break;
  552. case T_plane:
  553. COPPER_PLANE* plane;
  554. plane = new COPPER_PLANE( growth );
  555. growth->planes.push_back( plane );
  556. doKEEPOUT( plane );
  557. break;
  558. case T_region:
  559. REGION* region;
  560. region = new REGION( growth );
  561. growth->regions.push_back( region );
  562. doREGION( region );
  563. break;
  564. case T_snap_angle:
  565. STRINGPROP* stringprop;
  566. stringprop = new STRINGPROP( growth, T_snap_angle );
  567. growth->Append( stringprop );
  568. doSTRINGPROP( stringprop );
  569. break;
  570. case T_via:
  571. growth->via = new VIA( growth );
  572. doVIA( growth->via );
  573. break;
  574. case T_control:
  575. growth->control = new CONTROL( growth );
  576. doCONTROL( growth->control );
  577. break;
  578. case T_layer:
  579. LAYER* layer;
  580. layer = new LAYER( growth );
  581. growth->layers.push_back( layer );
  582. doLAYER( layer );
  583. break;
  584. case T_rule:
  585. growth->rules = new RULE( growth, T_rule );
  586. doRULE( growth->rules );
  587. break;
  588. case T_place_rule:
  589. growth->place_rules = new RULE( growth, T_place_rule );
  590. doRULE( growth->place_rules );
  591. break;
  592. case T_keepout:
  593. case T_place_keepout:
  594. case T_via_keepout:
  595. case T_wire_keepout:
  596. case T_bend_keepout:
  597. case T_elongate_keepout:
  598. KEEPOUT* keepout;
  599. keepout = new KEEPOUT( growth, tok );
  600. growth->keepouts.push_back( keepout );
  601. doKEEPOUT( keepout );
  602. break;
  603. case T_grid:
  604. GRID* grid;
  605. grid = new GRID( growth );
  606. growth->grids.push_back( grid );
  607. doGRID( grid );
  608. break;
  609. default:
  610. unexpected( lexer->CurText() );
  611. }
  612. }
  613. }
  614. void SPECCTRA_DB::doKEEPOUT( KEEPOUT* growth ) throw( IOError )
  615. {
  616. DSN_T tok = nextTok();
  617. if( isSymbol(tok) )
  618. {
  619. growth->name = lexer->CurText();
  620. tok = nextTok();
  621. }
  622. if( tok!=T_LEFT )
  623. expecting( T_LEFT );
  624. while( tok != T_RIGHT )
  625. {
  626. if( tok!=T_LEFT )
  627. expecting( T_LEFT );
  628. tok = nextTok();
  629. switch( tok )
  630. {
  631. case T_sequence_number:
  632. if( nextTok() != T_NUMBER )
  633. expecting( T_NUMBER );
  634. growth->sequence_number = atoi( lexer->CurText() );
  635. needRIGHT();
  636. break;
  637. case T_rule:
  638. if( growth->rules )
  639. unexpected( tok );
  640. growth->rules = new RULE( growth, T_rule );
  641. doRULE( growth->rules );
  642. break;
  643. case T_place_rule:
  644. if( growth->place_rules )
  645. unexpected( tok );
  646. growth->place_rules = new RULE( growth, T_place_rule );
  647. doRULE( growth->place_rules );
  648. break;
  649. case T_rect:
  650. if( growth->shape )
  651. unexpected( tok );
  652. growth->shape = new RECTANGLE( growth );
  653. doRECTANGLE( (RECTANGLE*) growth->shape );
  654. break;
  655. case T_circle:
  656. if( growth->shape )
  657. unexpected( tok );
  658. growth->shape = new CIRCLE( growth );
  659. doCIRCLE( (CIRCLE*) growth->shape );
  660. break;
  661. case T_polyline_path:
  662. tok = T_path;
  663. case T_path:
  664. case T_polygon:
  665. if( growth->shape )
  666. unexpected( tok );
  667. growth->shape = new PATH( growth, tok );
  668. doPATH( (PATH*) growth->shape );
  669. break;
  670. case T_qarc:
  671. if( growth->shape )
  672. unexpected( tok );
  673. growth->shape = new QARC( growth );
  674. doQARC( (QARC*) growth->shape );
  675. break;
  676. case T_window:
  677. WINDOW* window;
  678. window = new WINDOW( growth );
  679. growth->windows.push_back( window );
  680. doWINDOW( window );
  681. break;
  682. default:
  683. unexpected( lexer->CurText() );
  684. }
  685. tok = nextTok();
  686. }
  687. }
  688. void SPECCTRA_DB::doWINDOW( WINDOW* growth ) throw( IOError )
  689. {
  690. DSN_T tok = nextTok();
  691. while( tok != T_RIGHT )
  692. {
  693. if( tok!=T_LEFT )
  694. expecting( T_LEFT );
  695. tok = nextTok();
  696. switch( tok )
  697. {
  698. case T_rect:
  699. if( growth->shape )
  700. unexpected( tok );
  701. growth->shape = new RECTANGLE( growth );
  702. doRECTANGLE( (RECTANGLE*) growth->shape );
  703. break;
  704. case T_circle:
  705. if( growth->shape )
  706. unexpected( tok );
  707. growth->shape = new CIRCLE( growth );
  708. doCIRCLE( (CIRCLE*) growth->shape );
  709. break;
  710. case T_polyline_path:
  711. tok = T_path;
  712. case T_path:
  713. case T_polygon:
  714. if( growth->shape )
  715. unexpected( tok );
  716. growth->shape = new PATH( growth, tok );
  717. doPATH( (PATH*) growth->shape );
  718. break;
  719. case T_qarc:
  720. if( growth->shape )
  721. unexpected( tok );
  722. growth->shape = new QARC( growth );
  723. doQARC( (QARC*) growth->shape );
  724. break;
  725. default:
  726. unexpected( lexer->CurText() );
  727. }
  728. tok = nextTok();
  729. }
  730. }
  731. void SPECCTRA_DB::doBOUNDARY( BOUNDARY* growth ) throw( IOError )
  732. {
  733. DSN_T tok = nextTok();
  734. if( tok != T_LEFT )
  735. expecting( T_LEFT );
  736. tok = nextTok();
  737. if( tok == T_rect )
  738. {
  739. if( growth->paths.size() )
  740. unexpected( "rect when path already encountered" );
  741. growth->rectangle = new RECTANGLE( growth );
  742. doRECTANGLE( growth->rectangle );
  743. needRIGHT();
  744. }
  745. else if( tok == T_path )
  746. {
  747. if( growth->rectangle )
  748. unexpected( "path when rect already encountered" );
  749. for(;;)
  750. {
  751. if( tok != T_path )
  752. expecting( T_path );
  753. PATH* path = new PATH( growth, T_path ) ;
  754. growth->paths.push_back( path );
  755. doPATH( path );
  756. tok = nextTok();
  757. if( tok == T_RIGHT )
  758. break;
  759. if( tok != T_LEFT )
  760. expecting(T_LEFT);
  761. tok = nextTok();
  762. }
  763. }
  764. else
  765. expecting( "rect|path" );
  766. }
  767. void SPECCTRA_DB::doPATH( PATH* growth ) throw( IOError )
  768. {
  769. DSN_T tok = nextTok();
  770. if( !isSymbol( tok ) )
  771. expecting( "layer_id" );
  772. growth->layer_id = lexer->CurText();
  773. if( nextTok() != T_NUMBER )
  774. expecting( "aperture_width" );
  775. growth->aperture_width = strtod( lexer->CurText(), NULL );
  776. POINT ptTemp;
  777. tok = nextTok();
  778. do
  779. {
  780. if( tok != T_NUMBER )
  781. expecting( T_NUMBER );
  782. ptTemp.x = strtod( lexer->CurText(), NULL );
  783. if( nextTok() != T_NUMBER )
  784. expecting( T_NUMBER );
  785. ptTemp.y = strtod( lexer->CurText(), NULL );
  786. growth->points.push_back( ptTemp );
  787. } while( (tok = nextTok())!=T_RIGHT && tok!=T_LEFT );
  788. if( tok == T_LEFT )
  789. {
  790. if( nextTok() != T_aperture_type )
  791. expecting( T_aperture_type );
  792. tok = nextTok();
  793. if( tok!=T_round && tok!=T_square )
  794. expecting( "round|square" );
  795. growth->aperture_type = tok;
  796. needRIGHT();
  797. }
  798. }
  799. void SPECCTRA_DB::doRECTANGLE( RECTANGLE* growth ) throw( IOError )
  800. {
  801. needSYMBOL();
  802. growth->layer_id = lexer->CurText();
  803. if( nextTok() != T_NUMBER )
  804. expecting( T_NUMBER );
  805. growth->point0.x = strtod( lexer->CurText(), NULL );
  806. if( nextTok() != T_NUMBER )
  807. expecting( T_NUMBER );
  808. growth->point0.y = strtod( lexer->CurText(), NULL );
  809. if( nextTok() != T_NUMBER )
  810. expecting( T_NUMBER );
  811. growth->point1.x = strtod( lexer->CurText(), NULL );
  812. if( nextTok() != T_NUMBER )
  813. expecting( T_NUMBER );
  814. growth->point1.y = strtod( lexer->CurText(), NULL );
  815. needRIGHT();
  816. }
  817. void SPECCTRA_DB::doCIRCLE( CIRCLE* growth ) throw( IOError )
  818. {
  819. DSN_T tok;
  820. needSYMBOL();
  821. growth->layer_id = lexer->CurText();
  822. if( nextTok() != T_NUMBER )
  823. expecting( T_NUMBER );
  824. growth->diameter = strtod( lexer->CurText(), 0 );
  825. tok = nextTok();
  826. if( tok == T_NUMBER )
  827. {
  828. growth->vertex.x = strtod( lexer->CurText(), 0 );
  829. if( nextTok() != T_NUMBER )
  830. expecting( T_NUMBER );
  831. growth->vertex.y = strtod( lexer->CurText(), 0 );
  832. tok = nextTok();
  833. }
  834. if( tok != T_RIGHT )
  835. expecting( T_RIGHT );
  836. }
  837. void SPECCTRA_DB::doQARC( QARC* growth ) throw( IOError )
  838. {
  839. needSYMBOL();
  840. growth->layer_id = lexer->CurText();
  841. if( nextTok() != T_NUMBER )
  842. expecting( T_NUMBER );
  843. growth->aperture_width = strtod( lexer->CurText(), 0 );
  844. for( int i=0; i<3; ++i )
  845. {
  846. if( nextTok() != T_NUMBER )
  847. expecting( T_NUMBER );
  848. growth->vertex[i].x = strtod( lexer->CurText(), 0 );
  849. if( nextTok() != T_NUMBER )
  850. expecting( T_NUMBER );
  851. growth->vertex[i].y = strtod( lexer->CurText(), 0 );
  852. }
  853. needRIGHT();
  854. }
  855. void SPECCTRA_DB::doSTRINGPROP( STRINGPROP* growth ) throw( IOError )
  856. {
  857. needSYMBOL();
  858. growth->value = lexer->CurText();
  859. needRIGHT();
  860. }
  861. void SPECCTRA_DB::doTOKPROP( TOKPROP* growth ) throw( IOError )
  862. {
  863. DSN_T tok = nextTok();
  864. if( tok<0 )
  865. unexpected( lexer->CurText() );
  866. growth->value = tok;
  867. needRIGHT();
  868. }
  869. void SPECCTRA_DB::doVIA( VIA* growth ) throw( IOError )
  870. {
  871. DSN_T tok;
  872. while( (tok = nextTok()) != T_RIGHT )
  873. {
  874. if( tok == T_LEFT )
  875. {
  876. if( nextTok() != T_spare )
  877. expecting( T_spare );
  878. while( (tok = nextTok()) != T_RIGHT )
  879. {
  880. if( !isSymbol( tok ) )
  881. expecting( T_SYMBOL );
  882. growth->spares.push_back( lexer->CurText() );
  883. }
  884. }
  885. else if( isSymbol( tok ) )
  886. {
  887. growth->padstacks.push_back( lexer->CurText() );
  888. }
  889. else
  890. unexpected( lexer->CurText() );
  891. }
  892. }
  893. void SPECCTRA_DB::doCONTROL( CONTROL* growth ) throw( IOError )
  894. {
  895. DSN_T tok;
  896. while( (tok = nextTok()) != T_RIGHT )
  897. {
  898. if( tok != T_LEFT )
  899. expecting( T_LEFT );
  900. tok = nextTok();
  901. switch( tok )
  902. {
  903. case T_via_at_smd:
  904. tok = nextTok();
  905. if( tok!=T_on && tok!=T_off )
  906. expecting( "on|off" );
  907. growth->via_at_smd = (tok==T_on);
  908. needRIGHT();
  909. break;
  910. case T_off_grid:
  911. case T_route_to_fanout_only:
  912. case T_force_to_terminal_point:
  913. case T_same_net_checking:
  914. case T_checking_trim_by_pin:
  915. case T_noise_calculation:
  916. case T_noise_accumulation:
  917. case T_include_pins_in_crosstalk:
  918. case T_bbv_ctr2ctr:
  919. case T_average_pair_length:
  920. case T_crosstalk_model:
  921. case T_roundoff_rotation:
  922. case T_microvia:
  923. case T_reroute_order_viols:
  924. TOKPROP* tokprop;
  925. tokprop = new TOKPROP( growth, tok ) ;
  926. growth->Append( tokprop );
  927. doTOKPROP( tokprop );
  928. break;
  929. default:
  930. unexpected( lexer->CurText() );
  931. }
  932. }
  933. }
  934. void SPECCTRA_DB::doPROPERTIES( PROPERTIES* growth ) throw( IOError )
  935. {
  936. DSN_T tok;
  937. PROPERTY property; // construct it once here, append multiple times.
  938. while( (tok = nextTok()) != T_RIGHT )
  939. {
  940. if( tok != T_LEFT )
  941. expecting( T_LEFT );
  942. needSYMBOL();
  943. property.name = lexer->CurText();
  944. needSYMBOL();
  945. property.value = lexer->CurText();
  946. growth->push_back( property );
  947. needRIGHT();
  948. }
  949. }
  950. void SPECCTRA_DB::doLAYER( LAYER* growth ) throw( IOError )
  951. {
  952. DSN_T tok = nextTok();
  953. if( !isSymbol(tok) )
  954. expecting(T_SYMBOL);
  955. growth->name = lexer->CurText();
  956. while( (tok = nextTok()) != T_RIGHT )
  957. {
  958. if( tok != T_LEFT )
  959. expecting( T_LEFT );
  960. tok = nextTok();
  961. switch( tok )
  962. {
  963. case T_type:
  964. tok = nextTok();
  965. if( tok!=T_signal && tok!=T_power && tok!=T_mixed && tok!=T_jumper )
  966. expecting( "signal|power|mixed|jumper" );
  967. growth->layer_type = tok;
  968. if( nextTok()!=T_RIGHT )
  969. expecting(T_RIGHT);
  970. break;
  971. case T_rule:
  972. growth->rules = new RULE( growth, T_rule );
  973. doRULE( growth->rules );
  974. break;
  975. case T_property:
  976. doPROPERTIES( &growth->properties );
  977. break;
  978. case T_direction:
  979. tok = nextTok();
  980. switch( tok )
  981. {
  982. case T_horizontal:
  983. case T_vertical:
  984. case T_orthogonal:
  985. case T_positive_diagonal:
  986. case T_negative_diagonal:
  987. case T_diagonal:
  988. case T_off:
  989. growth->direction = tok;
  990. break;
  991. default:
  992. // the spec has an example show an abbreviation of the "horizontal" keyword. Ouch.
  993. if( !strcmp( "hori", lexer->CurText() ) )
  994. {
  995. growth->direction = T_horizontal;
  996. break;
  997. }
  998. else if( !strcmp( "vert", lexer->CurText() ) )
  999. {
  1000. growth->direction = T_vertical;
  1001. break;
  1002. }
  1003. expecting( "horizontal|vertical|orthogonal|positive_diagonal|negative_diagonal|diagonal|off" );
  1004. }
  1005. if( nextTok()!=T_RIGHT )
  1006. expecting(T_RIGHT);
  1007. break;
  1008. case T_cost:
  1009. tok = nextTok();
  1010. switch( tok )
  1011. {
  1012. case T_forbidden:
  1013. case T_high:
  1014. case T_medium:
  1015. case T_low:
  1016. case T_free:
  1017. growth->cost = tok;
  1018. break;
  1019. case T_NUMBER:
  1020. // store as negative so we can differentiate between
  1021. // DSN_T (positive) and T_NUMBER (negative)
  1022. growth->cost = -atoi( lexer->CurText() );
  1023. break;
  1024. default:
  1025. expecting( "forbidden|high|medium|low|free|<positive_integer>|-1" );
  1026. }
  1027. tok = nextTok();
  1028. if( tok == T_LEFT )
  1029. {
  1030. if( nextTok() != T_type )
  1031. unexpected( lexer->CurText() );
  1032. tok = nextTok();
  1033. if( tok!=T_length && tok!=T_way )
  1034. expecting( "length|way" );
  1035. growth->cost_type = tok;
  1036. if( nextTok()!=T_RIGHT )
  1037. expecting(T_RIGHT);
  1038. tok = nextTok();
  1039. }
  1040. if( tok!=T_RIGHT )
  1041. expecting(T_RIGHT);
  1042. break;
  1043. case T_use_net:
  1044. while( (tok = nextTok()) != T_RIGHT )
  1045. {
  1046. if( !isSymbol(tok) )
  1047. expecting( T_SYMBOL );
  1048. growth->use_net.push_back( lexer->CurText() );
  1049. }
  1050. break;
  1051. default:
  1052. unexpected( lexer->CurText() );
  1053. }
  1054. }
  1055. }
  1056. void SPECCTRA_DB::doRULE( RULE* growth ) throw( IOError )
  1057. {
  1058. std::string builder;
  1059. int bracketNesting = 1; // we already saw the opening T_LEFT
  1060. DSN_T tok = T_NONE;
  1061. while( bracketNesting!=0 && tok!=T_EOF )
  1062. {
  1063. tok = nextTok();
  1064. if( tok==T_LEFT)
  1065. ++bracketNesting;
  1066. else if( tok==T_RIGHT )
  1067. --bracketNesting;
  1068. if( bracketNesting >= 1 )
  1069. {
  1070. if( lexer->PrevTok()!=T_LEFT && tok!=T_RIGHT && (tok!=T_LEFT || bracketNesting>2) )
  1071. builder += ' ';
  1072. if( tok==T_STRING )
  1073. builder += quote_char;
  1074. builder += lexer->CurText();
  1075. if( tok==T_STRING )
  1076. builder += quote_char;
  1077. }
  1078. // When the nested rule is closed with a T_RIGHT and we are back down
  1079. // to bracketNesting == 1, (inside the <rule_descriptor> but outside
  1080. // the last rule). Then save the last rule and clear the string builder.
  1081. if( bracketNesting == 1 )
  1082. {
  1083. growth->rules.push_back( builder );
  1084. builder.clear();
  1085. }
  1086. }
  1087. if( tok==T_EOF )
  1088. unexpected( T_EOF );
  1089. }
  1090. #if 0
  1091. void SPECCTRA_DB::doPLACE_RULE( PLACE_RULE* growth, bool expect_object_type ) throw( IOError )
  1092. {
  1093. /* (place_rule [<structure_place_rule_object> ]
  1094. {[<spacing_descriptor> |
  1095. <permit_orient_descriptor> |
  1096. <permit_side_descriptor> |
  1097. <opposite_side_descriptor> ]}
  1098. )
  1099. */
  1100. DSN_T tok = nextTok();
  1101. if( tok!=T_LEFT )
  1102. expecting( T_LEFT );
  1103. tok = nextTok();
  1104. if( tok==T_object_type )
  1105. {
  1106. if( !expect_object_type )
  1107. unexpected( tok );
  1108. /* [(object_type
  1109. [pcb |
  1110. image_set [large | small | discrete | capacitor | resistor]
  1111. [(image_type [smd | pin])]]
  1112. )]
  1113. */
  1114. tok = nextTok();
  1115. switch( tok )
  1116. {
  1117. case T_pcb:
  1118. growth->object_type = tok;
  1119. break;
  1120. case T_image_set:
  1121. tok = nextTok();
  1122. switch( tok )
  1123. {
  1124. case T_large:
  1125. case T_small:
  1126. case T_discrete:
  1127. case T_capacitor:
  1128. case T_resistor:
  1129. growth->object_type = tok;
  1130. break;
  1131. default:
  1132. unexpected( lexer->CurText() );
  1133. }
  1134. break;
  1135. default:
  1136. unexpected( lexer->CurText() );
  1137. }
  1138. tok = nextTok();
  1139. if( tok == T_LEFT )
  1140. {
  1141. tok = nextTok();
  1142. if( tok != T_image_type )
  1143. expecting( T_image_type );
  1144. tok = nextTok();
  1145. if( tok!=T_smd && tok!=T_pin )
  1146. expecting( "smd|pin" );
  1147. needRIGHT();
  1148. tok = nextTok();
  1149. }
  1150. if( tok != T_RIGHT )
  1151. expecting( T_RIGHT );
  1152. tok = nextTok();
  1153. }
  1154. /* {[<spacing_descriptor> |
  1155. <permit_orient_descriptor> |
  1156. <permit_side_descriptor> | <opposite_side_descriptor> ]}
  1157. */
  1158. doRULE( growth );
  1159. }
  1160. #endif
  1161. void SPECCTRA_DB::doREGION( REGION* growth ) throw( IOError )
  1162. {
  1163. DSN_T tok = nextTok();
  1164. if( isSymbol(tok) )
  1165. {
  1166. growth->region_id = lexer->CurText();
  1167. tok = nextTok();
  1168. }
  1169. for(;;)
  1170. {
  1171. if( tok != T_LEFT )
  1172. expecting( T_LEFT );
  1173. tok = nextTok();
  1174. switch( tok )
  1175. {
  1176. case T_rect:
  1177. if( growth->rectangle )
  1178. unexpected( tok );
  1179. growth->rectangle = new RECTANGLE( growth );
  1180. doRECTANGLE( growth->rectangle );
  1181. break;
  1182. case T_polygon:
  1183. if( growth->polygon )
  1184. unexpected( tok );
  1185. growth->polygon = new PATH( growth, T_polygon );
  1186. doPATH( growth->polygon );
  1187. break;
  1188. case T_region_net:
  1189. case T_region_class:
  1190. STRINGPROP* stringprop;
  1191. stringprop = new STRINGPROP( growth, tok );
  1192. growth->Append( stringprop );
  1193. doSTRINGPROP( stringprop );
  1194. break;
  1195. case T_region_class_class:
  1196. CLASS_CLASS* class_class;
  1197. class_class = new CLASS_CLASS( growth, tok );
  1198. growth->Append( class_class );
  1199. doCLASS_CLASS( class_class );
  1200. break;
  1201. case T_rule:
  1202. if( growth->rules )
  1203. unexpected( tok );
  1204. growth->rules = new RULE( growth, T_rule );
  1205. doRULE( growth->rules );
  1206. break;
  1207. default:
  1208. unexpected( lexer->CurText() );
  1209. }
  1210. tok = nextTok();
  1211. if( tok == T_RIGHT )
  1212. {
  1213. if( !growth->rules )
  1214. expecting( T_rule );
  1215. break;
  1216. }
  1217. }
  1218. }
  1219. void SPECCTRA_DB::doCLASS_CLASS( CLASS_CLASS* growth ) throw( IOError )
  1220. {
  1221. DSN_T tok = nextTok();
  1222. if( tok != T_LEFT )
  1223. expecting( T_LEFT );
  1224. while( (tok = nextTok()) != T_RIGHT )
  1225. {
  1226. switch( tok )
  1227. {
  1228. case T_classes:
  1229. if( growth->classes )
  1230. unexpected( tok );
  1231. growth->classes = new CLASSES( growth );
  1232. doCLASSES( growth->classes );
  1233. break;
  1234. case T_rule:
  1235. // only T_class_class takes a T_rule
  1236. if( growth->Type() == T_region_class_class )
  1237. unexpected( tok );
  1238. RULE* rule;
  1239. rule = new RULE( growth, T_rule );
  1240. growth->Append( rule );
  1241. doRULE( rule );
  1242. break;
  1243. case T_layer_rule:
  1244. // only T_class_class takes a T_layer_rule
  1245. if( growth->Type() == T_region_class_class )
  1246. unexpected( tok );
  1247. LAYER_RULE* layer_rule;
  1248. layer_rule = new LAYER_RULE( growth );
  1249. growth->Append( layer_rule );
  1250. doLAYER_RULE( layer_rule );
  1251. break;
  1252. default:
  1253. unexpected( tok );
  1254. }
  1255. }
  1256. }
  1257. void SPECCTRA_DB::doCLASSES( CLASSES* growth ) throw( IOError )
  1258. {
  1259. DSN_T tok = nextTok();
  1260. // require at least 2 class_ids
  1261. if( !isSymbol( tok ) )
  1262. expecting( "class_id" );
  1263. growth->class_ids.push_back( lexer->CurText() );
  1264. do
  1265. {
  1266. tok = nextTok();
  1267. if( !isSymbol( tok ) )
  1268. expecting( "class_id" );
  1269. growth->class_ids.push_back( lexer->CurText() );
  1270. } while( (tok = nextTok()) != T_RIGHT );
  1271. }
  1272. void SPECCTRA_DB::doGRID( GRID* growth ) throw( IOError )
  1273. {
  1274. DSN_T tok = nextTok();
  1275. switch( tok )
  1276. {
  1277. case T_via:
  1278. case T_wire:
  1279. case T_via_keepout:
  1280. case T_snap:
  1281. case T_place:
  1282. growth->grid_type = tok;
  1283. if( nextTok() != T_NUMBER )
  1284. expecting( T_NUMBER );
  1285. growth->dimension = strtod( lexer->CurText(), 0 );
  1286. tok = nextTok();
  1287. if( tok == T_LEFT )
  1288. {
  1289. while( (tok=nextTok()) != T_RIGHT )
  1290. {
  1291. if( tok==T_direction )
  1292. {
  1293. if( growth->grid_type == T_place )
  1294. unexpected( tok );
  1295. tok = nextTok();
  1296. if( tok!=T_x && tok!=T_y )
  1297. unexpected( lexer->CurText() );
  1298. growth->direction = tok;
  1299. if( nextTok() != T_RIGHT )
  1300. expecting(T_RIGHT);
  1301. }
  1302. else if( tok==T_offset )
  1303. {
  1304. if( growth->grid_type == T_place )
  1305. unexpected( tok );
  1306. if( nextTok() != T_NUMBER )
  1307. expecting( T_NUMBER );
  1308. growth->offset = strtod( lexer->CurText(), 0 );
  1309. if( nextTok() != T_RIGHT )
  1310. expecting(T_RIGHT);
  1311. }
  1312. else if( tok==T_image_type )
  1313. {
  1314. if( growth->grid_type != T_place )
  1315. unexpected( tok );
  1316. tok = nextTok();
  1317. if( tok!=T_smd && tok!=T_pin )
  1318. unexpected( lexer->CurText() );
  1319. growth->image_type = tok;
  1320. if( nextTok() != T_RIGHT )
  1321. expecting(T_RIGHT);
  1322. }
  1323. }
  1324. }
  1325. break;
  1326. default:
  1327. unexpected( tok );
  1328. }
  1329. }
  1330. void SPECCTRA_DB::doLAYER_RULE( LAYER_RULE* growth ) throw( IOError )
  1331. {
  1332. DSN_T tok;
  1333. needSYMBOL();
  1334. do
  1335. {
  1336. growth->layer_ids.push_back( lexer->CurText() );
  1337. } while( isSymbol(tok = nextTok()) );
  1338. if( tok != T_LEFT )
  1339. expecting( T_LEFT );
  1340. if( nextTok() != T_rule )
  1341. expecting( T_rule );
  1342. growth->rule = new RULE( growth, T_rule );
  1343. doRULE( growth->rule );
  1344. needRIGHT();
  1345. }
  1346. void SPECCTRA_DB::doPLACE( PLACE* growth ) throw( IOError )
  1347. {
  1348. DSN_T tok = nextTok();
  1349. if( !isSymbol( tok ) )
  1350. expecting( "component_id" );
  1351. growth->component_id = lexer->CurText();
  1352. tok = nextTok();
  1353. if( tok == T_NUMBER )
  1354. {
  1355. POINT point;
  1356. point.x = strtod( lexer->CurText(), 0 );
  1357. if( nextTok() != T_NUMBER )
  1358. expecting( T_NUMBER );
  1359. point.y = strtod( lexer->CurText(), 0 );
  1360. growth->SetVertex( point );
  1361. tok = nextTok();
  1362. if( tok!=T_front && tok!=T_back )
  1363. expecting( "front|back" );
  1364. growth->side = tok;
  1365. if( nextTok() != T_NUMBER )
  1366. expecting( "rotation" );
  1367. growth->SetRotation( strtod( lexer->CurText(), 0) );
  1368. }
  1369. while( (tok = nextTok()) != T_RIGHT )
  1370. {
  1371. if( tok != T_LEFT )
  1372. expecting( T_LEFT );
  1373. tok = nextTok();
  1374. switch( tok )
  1375. {
  1376. case T_mirror:
  1377. tok = nextTok();
  1378. if( tok==T_x || tok==T_y || tok==T_xy || tok==T_off )
  1379. growth->mirror = tok;
  1380. else
  1381. expecting("x|y|xy|off");
  1382. break;
  1383. case T_status:
  1384. tok = nextTok();
  1385. if( tok==T_added || tok==T_deleted || tok==T_substituted )
  1386. growth->status = tok;
  1387. else
  1388. expecting("added|deleted|substituted");
  1389. break;
  1390. case T_logical_part:
  1391. if( growth->logical_part.size() )
  1392. unexpected( tok );
  1393. tok = nextTok();
  1394. if( !isSymbol( tok ) )
  1395. expecting( "logical_part_id");
  1396. growth->logical_part = lexer->CurText();
  1397. break;
  1398. case T_place_rule:
  1399. if( growth->place_rules )
  1400. unexpected( tok );
  1401. growth->place_rules = new RULE( growth, T_place_rule );
  1402. doRULE( growth->place_rules );
  1403. break;
  1404. case T_property:
  1405. if( growth->properties.size() )
  1406. unexpected( tok );
  1407. doPROPERTIES( &growth->properties );
  1408. break;
  1409. case T_lock_type:
  1410. tok = nextTok();
  1411. if( tok==T_position || tok==T_gate || tok==T_subgate || tok==T_pin )
  1412. growth->lock_type = tok;
  1413. else
  1414. expecting("position|gate|subgate|pin");
  1415. break;
  1416. case T_rule:
  1417. if( growth->rules || growth->region )
  1418. unexpected( tok );
  1419. growth->rules = new RULE( growth, T_rule );
  1420. doRULE( growth->rules );
  1421. break;
  1422. case T_region:
  1423. if( growth->rules || growth->region )
  1424. unexpected( tok );
  1425. growth->region = new REGION( growth );
  1426. doREGION( growth->region );
  1427. break;
  1428. case T_pn:
  1429. if( growth->part_number.size() )
  1430. unexpected( tok );
  1431. needSYMBOL();
  1432. growth->part_number = lexer->CurText();
  1433. needRIGHT();
  1434. break;
  1435. default:
  1436. unexpected( tok );
  1437. }
  1438. }
  1439. }
  1440. void SPECCTRA_DB::doCOMPONENT( COMPONENT* growth ) throw( IOError )
  1441. {
  1442. DSN_T tok = nextTok();
  1443. if( !isSymbol( tok ) )
  1444. expecting( "image_id" );
  1445. growth->image_id = lexer->CurText();
  1446. while( (tok = nextTok()) != T_RIGHT )
  1447. {
  1448. if( tok != T_LEFT )
  1449. expecting( T_LEFT );
  1450. tok = nextTok();
  1451. switch( tok )
  1452. {
  1453. case T_place:
  1454. PLACE* place;
  1455. place = new PLACE( growth );
  1456. growth->places.push_back( place );
  1457. doPLACE( place );
  1458. break;
  1459. default:
  1460. unexpected(tok);
  1461. }
  1462. }
  1463. }
  1464. void SPECCTRA_DB::doPLACEMENT( PLACEMENT* growth ) throw( IOError )
  1465. {
  1466. DSN_T tok;
  1467. needLEFT();
  1468. tok = nextTok();
  1469. if( tok==T_unit || tok==T_resolution )
  1470. {
  1471. growth->unit = new UNIT_RES( growth, tok );
  1472. if( tok==T_resolution )
  1473. doRESOLUTION( growth->unit );
  1474. else
  1475. doUNIT( growth->unit );
  1476. if( nextTok() != T_LEFT )
  1477. expecting( T_LEFT );
  1478. tok = nextTok();
  1479. }
  1480. if( tok == T_place_control )
  1481. {
  1482. if( nextTok() != T_LEFT )
  1483. expecting( T_LEFT );
  1484. tok = nextTok();
  1485. if( tok != T_flip_style )
  1486. expecting( T_flip_style );
  1487. tok = nextTok();
  1488. if( tok==T_mirror_first || tok==T_rotate_first )
  1489. growth->flip_style = tok;
  1490. else
  1491. expecting("mirror_first|rotate_first");
  1492. needRIGHT();
  1493. needRIGHT();
  1494. needLEFT();
  1495. tok = nextTok();
  1496. }
  1497. while( tok == T_component )
  1498. {
  1499. COMPONENT* component = new COMPONENT( growth );
  1500. growth->components.push_back( component );
  1501. doCOMPONENT( component );
  1502. tok = nextTok();
  1503. if( tok == T_RIGHT )
  1504. return;
  1505. else if( tok == T_LEFT )
  1506. tok = nextTok();
  1507. }
  1508. unexpected( lexer->CurText() );
  1509. }
  1510. void SPECCTRA_DB::doPADSTACK( PADSTACK* growth ) throw( IOError )
  1511. {
  1512. DSN_T tok = nextTok();
  1513. /* (padstack <padstack_id >
  1514. [<unit_descriptor> ]
  1515. {(shape <shape_descriptor>
  1516. [<reduced_shape_descriptor> ]
  1517. [(connect [on | off])]
  1518. [{<window_descriptor> }]
  1519. )}
  1520. [<attach_descriptor> ]
  1521. [{<pad_via_site_descriptor> }]
  1522. [(rotate [on | off])]
  1523. [(absolute [on | off])]
  1524. [(rule <clearance_descriptor> )])
  1525. */
  1526. // padstack_id may be a number
  1527. if( !isSymbol( tok ) && tok!=T_NUMBER )
  1528. expecting( "padstack_id" );
  1529. growth->padstack_id = lexer->CurText();
  1530. while( (tok = nextTok()) != T_RIGHT )
  1531. {
  1532. if( tok != T_LEFT )
  1533. expecting( T_LEFT );
  1534. tok = nextTok();
  1535. switch( tok )
  1536. {
  1537. case T_unit:
  1538. if( growth->unit )
  1539. unexpected( tok );
  1540. growth->unit = new UNIT_RES( growth, tok );
  1541. doUNIT( growth->unit );
  1542. break;
  1543. case T_rotate:
  1544. tok = nextTok();
  1545. if( tok!=T_on && tok!=T_off )
  1546. expecting( "on|off" );
  1547. growth->rotate = tok;
  1548. needRIGHT();
  1549. break;
  1550. case T_absolute:
  1551. tok = nextTok();
  1552. if( tok!=T_on && tok!=T_off )
  1553. expecting( "on|off" );
  1554. growth->absolute = tok;
  1555. needRIGHT();
  1556. break;
  1557. case T_shape:
  1558. SHAPE* shape;
  1559. shape = new SHAPE( growth );
  1560. growth->Append( shape );
  1561. doSHAPE( shape );
  1562. break;
  1563. case T_attach:
  1564. tok = nextTok();
  1565. if( tok!=T_off && tok!=T_on )
  1566. expecting( "off|on" );
  1567. growth->attach = tok;
  1568. tok = nextTok();
  1569. if( tok == T_LEFT )
  1570. {
  1571. if( nextTok() != T_use_via )
  1572. expecting( T_use_via );
  1573. needSYMBOL();
  1574. growth->via_id = lexer->CurText();
  1575. needRIGHT();
  1576. needRIGHT();
  1577. }
  1578. break;
  1579. /*
  1580. case T_via_site: not supported
  1581. break;
  1582. */
  1583. case T_rule:
  1584. if( growth->rules )
  1585. unexpected( tok );
  1586. growth->rules = new RULE( growth, T_rule );
  1587. doRULE( growth->rules );
  1588. break;
  1589. default:
  1590. unexpected( lexer->CurText() );
  1591. }
  1592. }
  1593. }
  1594. void SPECCTRA_DB::doSHAPE( SHAPE* growth ) throw( IOError )
  1595. {
  1596. DSN_T tok;
  1597. /* (shape <shape_descriptor>
  1598. [<reduced_shape_descriptor> ]
  1599. [(connect [on | off])]
  1600. [{<window_descriptor> }])
  1601. */
  1602. while( (tok = nextTok()) != T_RIGHT )
  1603. {
  1604. if( tok != T_LEFT )
  1605. expecting( T_LEFT );
  1606. tok = nextTok();
  1607. switch( tok )
  1608. {
  1609. case T_polyline_path:
  1610. tok = T_path;
  1611. case T_rect:
  1612. case T_circle:
  1613. case T_path:
  1614. case T_polygon:
  1615. case T_qarc:
  1616. L_done_that:
  1617. if( growth->shape )
  1618. unexpected( tok );
  1619. break;
  1620. default:
  1621. // the example in the spec uses "circ" instead of "circle". Bad!
  1622. if( !strcmp( "circ", lexer->CurText() ) )
  1623. {
  1624. tok = T_circle;
  1625. goto L_done_that;
  1626. }
  1627. }
  1628. switch( tok )
  1629. {
  1630. case T_rect:
  1631. growth->shape = new RECTANGLE( growth );
  1632. doRECTANGLE( (RECTANGLE*) growth->shape );
  1633. break;
  1634. case T_circle:
  1635. growth->shape = new CIRCLE( growth );
  1636. doCIRCLE( (CIRCLE*)growth->shape );
  1637. break;
  1638. case T_path:
  1639. case T_polygon:
  1640. growth->shape = new PATH( growth, tok );
  1641. doPATH( (PATH*)growth->shape );
  1642. break;
  1643. case T_qarc:
  1644. growth->shape = new QARC( growth );
  1645. doQARC( (QARC*)growth->shape );
  1646. break;
  1647. case T_connect:
  1648. tok = nextTok();
  1649. if( tok!=T_on && tok!=T_off )
  1650. expecting( "on|off" );
  1651. growth->connect = tok;
  1652. needRIGHT();
  1653. break;
  1654. case T_window:
  1655. WINDOW* window;
  1656. window = new WINDOW( growth );
  1657. growth->windows.push_back( window );
  1658. doWINDOW( window );
  1659. break;
  1660. default:
  1661. unexpected( lexer->CurText() );
  1662. }
  1663. }
  1664. }
  1665. void SPECCTRA_DB::doIMAGE( IMAGE* growth ) throw( IOError )
  1666. {
  1667. DSN_T tok = nextTok();
  1668. /* <image_descriptor >::=
  1669. (image <image_id >
  1670. [(side [front | back | both])]
  1671. [<unit_descriptor> ]
  1672. [<outline_descriptor> ]
  1673. {(pin <padstack_id > [(rotate <rotation> )]
  1674. [<reference_descriptor> | <pin_array_descriptor> ]
  1675. [<user_property_descriptor> ])}
  1676. [{<conductor_shape_descriptor> }]
  1677. [{<conductor_via_descriptor> }]
  1678. [<rule_descriptor> ]
  1679. [<place_rule_descriptor> ]
  1680. [{<keepout_descriptor> }]
  1681. [<image_property_descriptor> ]
  1682. )
  1683. */
  1684. if( !isSymbol( tok ) )
  1685. expecting( "image_id" );
  1686. growth->image_id = lexer->CurText();
  1687. while( (tok = nextTok()) != T_RIGHT )
  1688. {
  1689. if( tok != T_LEFT )
  1690. expecting( T_LEFT );
  1691. tok = nextTok();
  1692. switch( tok )
  1693. {
  1694. case T_unit:
  1695. if( growth->unit )
  1696. unexpected( tok );
  1697. growth->unit = new UNIT_RES( growth, tok );
  1698. doUNIT( growth->unit );
  1699. break;
  1700. case T_side:
  1701. tok = nextTok();
  1702. if( tok!=T_front && tok!=T_back && tok!=T_both )
  1703. expecting( "front|back|both" );
  1704. growth->side = tok;
  1705. needRIGHT();
  1706. break;
  1707. case T_outline:
  1708. SHAPE* outline;
  1709. outline = new SHAPE( growth, T_outline ); // use SHAPE for T_outline
  1710. growth->Append( outline );
  1711. doSHAPE( outline );
  1712. break;
  1713. case T_pin:
  1714. PIN* pin;
  1715. pin = new PIN( growth );
  1716. growth->pins.push_back( pin );
  1717. doPIN( pin );
  1718. break;
  1719. case T_rule:
  1720. if( growth->rules )
  1721. unexpected( tok );
  1722. growth->rules = new RULE( growth, tok );
  1723. doRULE( growth->rules );
  1724. break;
  1725. case T_place_rule:
  1726. if( growth->place_rules )
  1727. unexpected( tok );
  1728. growth->place_rules = new RULE( growth, tok );
  1729. doRULE( growth->place_rules );
  1730. break;
  1731. case T_keepout:
  1732. case T_place_keepout:
  1733. case T_via_keepout:
  1734. case T_wire_keepout:
  1735. case T_bend_keepout:
  1736. case T_elongate_keepout:
  1737. KEEPOUT* keepout;
  1738. keepout = new KEEPOUT( growth, tok );
  1739. growth->keepouts.push_back( keepout );
  1740. doKEEPOUT( keepout );
  1741. break;
  1742. default:
  1743. unexpected( lexer->CurText() );
  1744. }
  1745. }
  1746. }
  1747. void SPECCTRA_DB::doPIN( PIN* growth ) throw( IOError )
  1748. {
  1749. DSN_T tok = nextTok();
  1750. /* (pin <padstack_id > [(rotate <rotation> )]
  1751. [<reference_descriptor> | <pin_array_descriptor> ]
  1752. [<user_property_descriptor> ])
  1753. */
  1754. // a padstack_id may be a number
  1755. if( !isSymbol( tok ) && tok!=T_NUMBER )
  1756. expecting( "padstack_id" );
  1757. growth->padstack_id = lexer->CurText();
  1758. tok = nextTok();
  1759. if( tok == T_LEFT )
  1760. {
  1761. tok = nextTok();
  1762. if( tok != T_rotate )
  1763. expecting( T_rotate );
  1764. if( nextTok() != T_NUMBER )
  1765. expecting( T_NUMBER );
  1766. growth->SetRotation( strtod( lexer->CurText(), 0 ) );
  1767. needRIGHT();
  1768. tok = nextTok();
  1769. }
  1770. if( !isSymbol(tok) && tok!=T_NUMBER )
  1771. expecting( "pin_id" );
  1772. growth->pin_id = lexer->CurText();
  1773. if( nextTok() != T_NUMBER )
  1774. expecting( T_NUMBER );
  1775. growth->vertex.x = strtod( lexer->CurText(), 0 );
  1776. if( nextTok() != T_NUMBER )
  1777. expecting( T_NUMBER );
  1778. growth->vertex.y = strtod( lexer->CurText(), 0 );
  1779. if( nextTok() != T_RIGHT )
  1780. unexpected( lexer->CurText() );
  1781. }
  1782. void SPECCTRA_DB::doLIBRARY( LIBRARY* growth ) throw( IOError )
  1783. {
  1784. DSN_T tok;
  1785. /* <library_descriptor >::=
  1786. (library
  1787. [<unit_descriptor> ]
  1788. {<image_descriptor> }
  1789. [{<jumper_descriptor> }]
  1790. {<padstack_descriptor> }
  1791. {<via_array_template_descriptor> }
  1792. [<directory_descriptor> ]
  1793. [<extra_image_directory_descriptor> ]
  1794. [{<family_family_descriptor> }]
  1795. [{<image_image_descriptor> }]
  1796. )
  1797. */
  1798. while( (tok = nextTok()) != T_RIGHT )
  1799. {
  1800. if( tok != T_LEFT )
  1801. expecting( T_LEFT );
  1802. tok = nextTok();
  1803. switch( tok )
  1804. {
  1805. case T_unit:
  1806. if( growth->unit )
  1807. unexpected( tok );
  1808. growth->unit = new UNIT_RES( growth, tok );
  1809. doUNIT( growth->unit );
  1810. break;
  1811. case T_padstack:
  1812. PADSTACK* padstack;
  1813. padstack = new PADSTACK( growth );
  1814. growth->padstacks.push_back( padstack );
  1815. doPADSTACK( padstack );
  1816. break;
  1817. case T_image:
  1818. IMAGE* image;
  1819. image = new IMAGE( growth );
  1820. growth->images.push_back( image );
  1821. doIMAGE( image );
  1822. break;
  1823. default:
  1824. unexpected( lexer->CurText() );
  1825. }
  1826. }
  1827. }
  1828. void SPECCTRA_DB::doNET( NET* growth ) throw( IOError )
  1829. {
  1830. DSN_T tok = nextTok();
  1831. /* <net_descriptor >::=
  1832. (net <net_id >
  1833. [(unassigned)]
  1834. [(net_number <integer >)]
  1835. [(pins {<pin_reference> }) | (order {<pin_reference> })]
  1836. [<component_order_descriptor> ]
  1837. [(type [fix | normal])]
  1838. [<user_property_descriptor> ]
  1839. [<circuit_descriptor> ]
  1840. [<rule_descriptor> ]
  1841. [{<layer_rule_descriptor> }]
  1842. [<fromto_descriptor> ]
  1843. [(expose {<pin_reference> })]
  1844. [(noexpose {<pin_reference> })]
  1845. [(source {<pin_reference> })]
  1846. [(load {<pin_reference> })]
  1847. [(terminator {<pin_reference> })]
  1848. [(supply [power | ground])]
  1849. )
  1850. */
  1851. if( !isSymbol( tok ) )
  1852. expecting( "net_id" );
  1853. growth->net_id = lexer->CurText();
  1854. while( (tok = nextTok()) != T_RIGHT )
  1855. {
  1856. if( tok != T_LEFT )
  1857. expecting( T_LEFT );
  1858. tok = nextTok();
  1859. switch( tok )
  1860. {
  1861. case T_unassigned:
  1862. growth->unassigned = true;
  1863. needRIGHT();
  1864. break;
  1865. case T_net_number:
  1866. if( nextTok() != T_NUMBER )
  1867. expecting( T_NUMBER );
  1868. growth->net_number = atoi( lexer->CurText() );
  1869. needRIGHT();
  1870. break;
  1871. case T_pins:
  1872. case T_order:
  1873. growth->pins_type = tok;
  1874. {
  1875. PIN_REF empty( growth );
  1876. while( (tok = nextTok()) != T_RIGHT )
  1877. {
  1878. // copy the empty one, then fill its copy later thru pin_ref.
  1879. growth->pins.push_back( empty );
  1880. PIN_REF* pin_ref = &growth->pins.back();
  1881. readCOMPnPIN( &pin_ref->component_id, &pin_ref->pin_id );
  1882. }
  1883. }
  1884. break;
  1885. case T_comp_order:
  1886. if( growth->comp_order )
  1887. unexpected( tok );
  1888. growth->comp_order = new COMP_ORDER( growth );
  1889. doCOMP_ORDER( growth->comp_order );
  1890. break;
  1891. case T_type:
  1892. tok = nextTok();
  1893. if( tok!=T_fix && tok!=T_normal )
  1894. expecting( "fix|normal" );
  1895. growth->type = tok;
  1896. needRIGHT();
  1897. break;
  1898. /* @todo
  1899. case T_circuit:
  1900. break;
  1901. */
  1902. case T_rule:
  1903. if( growth->rules )
  1904. unexpected( tok );
  1905. growth->rules = new RULE( growth, T_rule );
  1906. doRULE( growth->rules );
  1907. break;
  1908. case T_layer_rule:
  1909. LAYER_RULE* layer_rule;
  1910. layer_rule = new LAYER_RULE( growth );
  1911. growth->layer_rules.push_back( layer_rule );
  1912. doLAYER_RULE( layer_rule );
  1913. break;
  1914. case T_fromto:
  1915. FROMTO* fromto;
  1916. fromto = new FROMTO( growth );
  1917. growth->fromtos.push_back( fromto );
  1918. doFROMTO( fromto );
  1919. break;
  1920. default:
  1921. unexpected( lexer->CurText() );
  1922. }
  1923. }
  1924. }
  1925. void SPECCTRA_DB::doTOPOLOGY( TOPOLOGY* growth ) throw( IOError )
  1926. {
  1927. DSN_T tok;
  1928. /* <topology_descriptor >::=
  1929. (topology {[<fromto_descriptor> |
  1930. <component_order_descriptor> ]})
  1931. */
  1932. while( (tok = nextTok()) != T_RIGHT )
  1933. {
  1934. if( tok != T_LEFT )
  1935. expecting( T_LEFT );
  1936. tok = nextTok();
  1937. switch( tok )
  1938. {
  1939. case T_fromto:
  1940. FROMTO* fromto;
  1941. fromto = new FROMTO( growth );
  1942. growth->fromtos.push_back( fromto );
  1943. doFROMTO( fromto );
  1944. break;
  1945. case T_comp_order:
  1946. COMP_ORDER* comp_order;
  1947. comp_order = new COMP_ORDER( growth );
  1948. growth->comp_orders.push_back( comp_order );
  1949. doCOMP_ORDER( comp_order );
  1950. break;
  1951. default:
  1952. unexpected( lexer->CurText() );
  1953. }
  1954. }
  1955. }
  1956. void SPECCTRA_DB::doCLASS( CLASS* growth ) throw( IOError )
  1957. {
  1958. DSN_T tok;
  1959. /* <class_descriptor >::=
  1960. (class
  1961. <class_id > {[{<net_id >} | {<composite_name_list> }]}
  1962. [<circuit_descriptor> ]
  1963. [<rule_descriptor> ]
  1964. [{<layer_rule_descriptor> }]
  1965. [<topology_descriptor> ]
  1966. )
  1967. */
  1968. needSYMBOL();
  1969. growth->class_id = lexer->CurText();
  1970. // do net_ids, do not support <composite_name_list>s at this time
  1971. while( isSymbol(tok = nextTok()) )
  1972. {
  1973. growth->net_ids.push_back( lexer->CurText() );
  1974. }
  1975. while( tok != T_RIGHT )
  1976. {
  1977. if( tok != T_LEFT )
  1978. expecting( T_LEFT );
  1979. tok = nextTok();
  1980. switch( tok )
  1981. {
  1982. case T_rule:
  1983. if( growth->rules )
  1984. unexpected( tok );
  1985. growth->rules = new RULE( growth, T_rule );
  1986. doRULE( growth->rules );
  1987. break;
  1988. case T_layer_rule:
  1989. LAYER_RULE* layer_rule;
  1990. layer_rule = new LAYER_RULE( growth );
  1991. growth->layer_rules.push_back( layer_rule );
  1992. doLAYER_RULE( layer_rule );
  1993. break;
  1994. case T_topology:
  1995. if( growth->topology )
  1996. unexpected( tok );
  1997. growth->topology = new TOPOLOGY( growth );
  1998. doTOPOLOGY( growth->topology );
  1999. break;
  2000. default: // handle all the circuit_descriptor here as strings
  2001. {
  2002. std::string builder;
  2003. int bracketNesting = 1; // we already saw the opening T_LEFT
  2004. DSN_T tok = T_NONE;
  2005. builder += '(';
  2006. builder += lexer->CurText();
  2007. while( bracketNesting!=0 && tok!=T_EOF )
  2008. {
  2009. tok = nextTok();
  2010. if( tok==T_LEFT)
  2011. ++bracketNesting;
  2012. else if( tok==T_RIGHT )
  2013. --bracketNesting;
  2014. if( bracketNesting >= 1 )
  2015. {
  2016. if( lexer->PrevTok() != T_LEFT && tok!=T_RIGHT )
  2017. builder += ' ';
  2018. if( tok==T_STRING )
  2019. builder += quote_char;
  2020. builder += lexer->CurText();
  2021. if( tok==T_STRING )
  2022. builder += quote_char;
  2023. }
  2024. // When the nested rule is closed with a T_RIGHT and we are back down
  2025. // to bracketNesting == 0, then save the builder and break;
  2026. if( bracketNesting == 0 )
  2027. {
  2028. builder += ')';
  2029. growth->circuit.push_back( builder );
  2030. break;
  2031. }
  2032. }
  2033. if( tok==T_EOF )
  2034. unexpected( T_EOF );
  2035. } // scope bracket
  2036. } // switch
  2037. tok = nextTok();
  2038. } // while
  2039. }
  2040. void SPECCTRA_DB::doNETWORK( NETWORK* growth ) throw( IOError )
  2041. {
  2042. DSN_T tok;
  2043. /* <network_descriptor >::=
  2044. (network
  2045. {<net_descriptor>}
  2046. [{<class_descriptor> }]
  2047. [{<class_class_descriptor> }]
  2048. [{<group_descriptor> }]
  2049. [{<group_set_descriptor> }]
  2050. [{<pair_descriptor> }]
  2051. [{<bundle_descriptor> }]
  2052. )
  2053. */
  2054. while( (tok = nextTok()) != T_RIGHT )
  2055. {
  2056. if( tok != T_LEFT )
  2057. expecting( T_LEFT );
  2058. tok = nextTok();
  2059. switch( tok )
  2060. {
  2061. case T_net:
  2062. NET* net;
  2063. net = new NET( growth );
  2064. growth->nets.push_back( net );
  2065. doNET( net );
  2066. break;
  2067. case T_class:
  2068. CLASS* myclass;
  2069. myclass = new CLASS( growth );
  2070. growth->classes.push_back( myclass );
  2071. doCLASS( myclass );
  2072. break;
  2073. default:
  2074. unexpected( lexer->CurText() );
  2075. }
  2076. }
  2077. }
  2078. void SPECCTRA_DB::doCOMP_ORDER( COMP_ORDER* growth ) throw( IOError )
  2079. {
  2080. DSN_T tok;
  2081. /* <component_order_descriptor >::=
  2082. (comp_order {<placement_id> })
  2083. */
  2084. while( isSymbol(tok = nextTok()) )
  2085. {
  2086. growth->placement_ids.push_back( lexer->CurText() );
  2087. }
  2088. if( tok != T_RIGHT )
  2089. expecting( T_RIGHT );
  2090. }
  2091. void SPECCTRA_DB::doFROMTO( FROMTO* growth ) throw( IOError )
  2092. {
  2093. DSN_T tok;
  2094. /* <fromto_descriptor >::=
  2095. {(fromto
  2096. [<pin_reference> | <virtual_pin_descriptor> ] | <component_id >]
  2097. [<pin_reference> | <virtual_pin_descriptor> | <component_id >]
  2098. [(type [fix | normal | soft])]
  2099. [(net <net_id >)]
  2100. [<rule_descriptor> ]
  2101. [<circuit_descriptor> ]
  2102. [{<layer_rule_descriptor> }]
  2103. )}
  2104. */
  2105. // read the first two grammar items in as 2 single tokens, i.e. do not
  2106. // split apart the <pin_reference>s into 3 separate tokens. Do this by
  2107. // turning off the string delimiter in the lexer.
  2108. int old = lexer->SetStringDelimiter( 0 );
  2109. if( !isSymbol(nextTok() ) )
  2110. {
  2111. lexer->SetStringDelimiter( old );
  2112. expecting( T_SYMBOL );
  2113. }
  2114. growth->fromText = lexer->CurText();
  2115. if( !isSymbol(nextTok() ) )
  2116. {
  2117. lexer->SetStringDelimiter( old );
  2118. expecting( T_SYMBOL );
  2119. }
  2120. growth->toText = lexer->CurText();
  2121. lexer->SetStringDelimiter( old );
  2122. while( (tok = nextTok()) != T_RIGHT )
  2123. {
  2124. if( tok != T_LEFT )
  2125. expecting( T_LEFT );
  2126. tok = nextTok();
  2127. switch( tok )
  2128. {
  2129. case T_type:
  2130. tok = nextTok();
  2131. if( tok!=T_fix && tok!=T_normal && tok!=T_soft )
  2132. expecting( "fix|normal|soft" );
  2133. growth->fromto_type = tok;
  2134. needRIGHT();
  2135. break;
  2136. case T_rule:
  2137. if( growth->rules )
  2138. unexpected( tok );
  2139. growth->rules = new RULE( growth, T_rule );
  2140. doRULE( growth->rules );
  2141. break;
  2142. case T_layer_rule:
  2143. LAYER_RULE* layer_rule;
  2144. layer_rule = new LAYER_RULE( growth );
  2145. growth->layer_rules.push_back( layer_rule );
  2146. doLAYER_RULE( layer_rule );
  2147. break;
  2148. case T_net:
  2149. if( growth->net_id.size() )
  2150. unexpected( tok );
  2151. needSYMBOL();
  2152. growth->net_id = lexer->CurText();
  2153. needRIGHT();
  2154. break;
  2155. // circuit descriptor not supported at this time
  2156. default:
  2157. unexpected( lexer->CurText() );
  2158. }
  2159. }
  2160. }
  2161. void SPECCTRA_DB::doWIRE( WIRE* growth ) throw( IOError )
  2162. {
  2163. DSN_T tok;
  2164. /* <wire_shape_descriptor >::=
  2165. (wire
  2166. <shape_descriptor>
  2167. [(net <net_id >)]
  2168. [(turret <turret#> )]
  2169. [(type [fix | route | normal | protect])]
  2170. [(attr [test | fanout | bus | jumper])]
  2171. [(shield <net_id >)]
  2172. [{<window_descriptor> }]
  2173. [(connect
  2174. (terminal <object_type> [<pin_reference> ])
  2175. (terminal <object_type> [<pin_reference> ])
  2176. )]
  2177. [(supply)]
  2178. )
  2179. */
  2180. while( (tok = nextTok()) != T_RIGHT )
  2181. {
  2182. if( tok != T_LEFT )
  2183. expecting( T_LEFT );
  2184. tok = nextTok();
  2185. switch( tok )
  2186. {
  2187. case T_rect:
  2188. if( growth->shape )
  2189. unexpected( tok );
  2190. growth->shape = new RECTANGLE( growth );
  2191. doRECTANGLE( (RECTANGLE*) growth->shape );
  2192. break;
  2193. case T_circle:
  2194. if( growth->shape )
  2195. unexpected( tok );
  2196. growth->shape = new CIRCLE( growth );
  2197. doCIRCLE( (CIRCLE*) growth->shape );
  2198. break;
  2199. case T_polyline_path:
  2200. tok = T_path;
  2201. case T_path:
  2202. case T_polygon:
  2203. if( growth->shape )
  2204. unexpected( tok );
  2205. growth->shape = new PATH( growth, tok );
  2206. doPATH( (PATH*) growth->shape );
  2207. break;
  2208. case T_qarc:
  2209. if( growth->shape )
  2210. unexpected( tok );
  2211. growth->shape = new QARC( growth );
  2212. doQARC( (QARC*) growth->shape );
  2213. break;
  2214. case T_net:
  2215. needSYMBOL();
  2216. growth->net_id = lexer->CurText();
  2217. needRIGHT();
  2218. break;
  2219. case T_turret:
  2220. if( nextTok() != T_NUMBER )
  2221. expecting( T_NUMBER );
  2222. growth->turret = atoi( lexer->CurText() );
  2223. needRIGHT();
  2224. break;
  2225. case T_type:
  2226. tok = nextTok();
  2227. if( tok!=T_fix && tok!=T_route && tok!=T_normal && tok!=T_protect )
  2228. expecting( "fix|route|normal|protect" );
  2229. growth->wire_type = tok;
  2230. needRIGHT();
  2231. break;
  2232. case T_attr:
  2233. tok = nextTok();
  2234. if( tok!=T_test && tok!=T_fanout && tok!=T_bus && tok!=T_jumper )
  2235. expecting( "test|fanout|bus|jumper" );
  2236. growth->attr = tok;
  2237. needRIGHT();
  2238. break;
  2239. case T_shield:
  2240. needSYMBOL();
  2241. growth->shield = lexer->CurText();
  2242. needRIGHT();
  2243. break;
  2244. case T_window:
  2245. WINDOW* window;
  2246. window = new WINDOW( growth );
  2247. growth->windows.push_back( window );
  2248. doWINDOW( window );
  2249. break;
  2250. case T_connect:
  2251. if( growth->connect )
  2252. unexpected( tok );
  2253. /* @todo
  2254. growth->connect = new CONNECT( growth );
  2255. doCONNECT( growth->connect );
  2256. */
  2257. break;
  2258. case T_supply:
  2259. growth->supply = true;
  2260. needRIGHT();
  2261. break;
  2262. default:
  2263. unexpected( lexer->CurText() );
  2264. }
  2265. }
  2266. }
  2267. void SPECCTRA_DB::doWIRE_VIA( WIRE_VIA* growth ) throw( IOError )
  2268. {
  2269. DSN_T tok;
  2270. POINT point;
  2271. /* <wire_via_descriptor >::=
  2272. (via
  2273. <padstack_id > {<vertex> }
  2274. [(net <net_id >)]
  2275. [(via_number <via#> )]
  2276. [(type [fix | route | normal | protect])]
  2277. [(attr [test | fanout | jumper |
  2278. virtual_pin <virtual_pin_name> ])]
  2279. [(contact {<layer_id >})]
  2280. [(supply)]
  2281. )
  2282. (virtual_pin
  2283. <virtual_pin_name> <vertex> (net <net_id >)
  2284. )
  2285. */
  2286. needSYMBOL();
  2287. growth->padstack_id = lexer->CurText();
  2288. while( (tok = nextTok()) == T_NUMBER )
  2289. {
  2290. point.x = strtod( lexer->CurText(), 0 );
  2291. if( nextTok() != T_NUMBER )
  2292. expecting( "vertex.y" );
  2293. point.y = strtod( lexer->CurText(), 0 );
  2294. growth->vertexes.push_back( point );
  2295. }
  2296. while( tok != T_RIGHT )
  2297. {
  2298. if( tok != T_LEFT )
  2299. expecting( T_LEFT );
  2300. tok = nextTok();
  2301. switch( tok )
  2302. {
  2303. case T_net:
  2304. needSYMBOL();
  2305. growth->net_id = lexer->CurText();
  2306. needRIGHT();
  2307. break;
  2308. case T_via_number:
  2309. if( nextTok() != T_NUMBER )
  2310. expecting( "<via#>" );
  2311. growth->via_number = atoi( lexer->CurText() );
  2312. needRIGHT();
  2313. break;
  2314. case T_type:
  2315. tok = nextTok();
  2316. if( tok!=T_fix && tok!=T_route && tok!=T_normal && tok!=T_protect )
  2317. expecting( "fix|route|normal|protect" );
  2318. growth->via_type = tok;
  2319. needRIGHT();
  2320. break;
  2321. case T_attr:
  2322. tok = nextTok();
  2323. if( tok!=T_test && tok!=T_fanout && tok!=T_jumper && tok!=T_virtual_pin )
  2324. expecting( "test|fanout|jumper|virtual_pin" );
  2325. growth->attr = tok;
  2326. if( tok == T_virtual_pin )
  2327. {
  2328. needSYMBOL();
  2329. growth->virtual_pin_name = lexer->CurText();
  2330. }
  2331. needRIGHT();
  2332. break;
  2333. case T_contact:
  2334. needSYMBOL();
  2335. tok = T_SYMBOL;
  2336. while( isSymbol(tok) )
  2337. {
  2338. growth->contact_layers.push_back( lexer->CurText() );
  2339. tok = nextTok();
  2340. }
  2341. if( tok != T_RIGHT )
  2342. expecting( T_RIGHT );
  2343. break;
  2344. case T_supply:
  2345. growth->supply = true;
  2346. needRIGHT();
  2347. break;
  2348. default:
  2349. unexpected( lexer->CurText() );
  2350. }
  2351. tok = nextTok();
  2352. }
  2353. }
  2354. void SPECCTRA_DB::doWIRING( WIRING* growth ) throw( IOError )
  2355. {
  2356. DSN_T tok;
  2357. /* <wiring_descriptor >::=
  2358. (wiring
  2359. [<unit_descriptor> | <resolution_descriptor> | null]
  2360. {<wire_descriptor> }
  2361. [<test_points_descriptor> ]
  2362. {[<supply_pin_descriptor> ]}
  2363. )
  2364. */
  2365. while( (tok = nextTok()) != T_RIGHT )
  2366. {
  2367. if( tok != T_LEFT )
  2368. expecting( T_LEFT );
  2369. tok = nextTok();
  2370. switch( tok )
  2371. {
  2372. case T_unit:
  2373. if( growth->unit )
  2374. unexpected( tok );
  2375. growth->unit = new UNIT_RES( growth, tok );
  2376. doUNIT( growth->unit );
  2377. break;
  2378. case T_resolution:
  2379. if( growth->unit )
  2380. unexpected( tok );
  2381. growth->unit = new UNIT_RES( growth, tok );
  2382. doRESOLUTION( growth->unit );
  2383. break;
  2384. case T_wire:
  2385. WIRE* wire;
  2386. wire = new WIRE( growth );
  2387. growth->wires.push_back( wire );
  2388. doWIRE( wire );
  2389. break;
  2390. case T_via:
  2391. WIRE_VIA* wire_via;
  2392. wire_via = new WIRE_VIA( growth );
  2393. growth->wire_vias.push_back( wire_via );
  2394. doWIRE_VIA( wire_via );
  2395. break;
  2396. default:
  2397. unexpected( lexer->CurText() );
  2398. }
  2399. }
  2400. }
  2401. void SPECCTRA_DB::doANCESTOR( ANCESTOR* growth ) throw( IOError )
  2402. {
  2403. DSN_T tok;
  2404. /* <ancestor_file_descriptor >::=
  2405. (ancestor <file_path_name> (created_time <time_stamp> )
  2406. [(comment <comment_string> )])
  2407. */
  2408. needSYMBOL();
  2409. growth->filename = lexer->CurText();
  2410. while( (tok = nextTok()) != T_RIGHT )
  2411. {
  2412. if( tok != T_LEFT )
  2413. expecting( T_LEFT );
  2414. tok = nextTok();
  2415. switch( tok )
  2416. {
  2417. case T_created_time:
  2418. readTIME( &growth->time_stamp );
  2419. needRIGHT();
  2420. break;
  2421. case T_comment:
  2422. needSYMBOL();
  2423. growth->comment = lexer->CurText();
  2424. needRIGHT();
  2425. break;
  2426. default:
  2427. unexpected( lexer->CurText() );
  2428. }
  2429. }
  2430. }
  2431. void SPECCTRA_DB::doHISTORY( HISTORY* growth ) throw( IOError )
  2432. {
  2433. DSN_T tok;
  2434. /* <history_descriptor >::=
  2435. (history [{<ancestor_file_descriptor> }] <self_descriptor> )
  2436. */
  2437. while( (tok = nextTok()) != T_RIGHT )
  2438. {
  2439. if( tok != T_LEFT )
  2440. expecting( T_LEFT );
  2441. tok = nextTok();
  2442. switch( tok )
  2443. {
  2444. case T_ancestor:
  2445. ANCESTOR* ancestor;
  2446. ancestor = new ANCESTOR( growth );
  2447. growth->ancestors.push_back( ancestor );
  2448. doANCESTOR( ancestor );
  2449. break;
  2450. case T_self:
  2451. while( (tok = nextTok()) != T_RIGHT )
  2452. {
  2453. if( tok != T_LEFT )
  2454. expecting( T_LEFT );
  2455. tok = nextTok();
  2456. switch( tok )
  2457. {
  2458. case T_created_time:
  2459. readTIME( &growth->time_stamp );
  2460. needRIGHT();
  2461. break;
  2462. case T_comment:
  2463. needSYMBOL();
  2464. growth->comments.push_back( lexer->CurText() );
  2465. needRIGHT();
  2466. break;
  2467. default:
  2468. unexpected( lexer->CurText() );
  2469. }
  2470. }
  2471. break;
  2472. default:
  2473. unexpected( lexer->CurText() );
  2474. }
  2475. }
  2476. }
  2477. void SPECCTRA_DB::doSESSION( SESSION* growth ) throw( IOError )
  2478. {
  2479. DSN_T tok;
  2480. /* <session_file_descriptor >::=
  2481. (session <session_id >
  2482. (base_design <path/filename >)
  2483. [<history_descriptor> ]
  2484. [<session_structure_descriptor> ]
  2485. [<placement_descriptor> ]
  2486. [<floor_plan_descriptor> ]
  2487. [<net_pin_changes_descriptor> ]
  2488. [<was_is_descriptor> ]
  2489. <swap_history_descriptor> ]
  2490. [<route_descriptor> ]
  2491. )
  2492. */
  2493. needSYMBOL();
  2494. growth->session_id = lexer->CurText();
  2495. while( (tok = nextTok()) != T_RIGHT )
  2496. {
  2497. if( tok != T_LEFT )
  2498. expecting( T_LEFT );
  2499. tok = nextTok();
  2500. switch( tok )
  2501. {
  2502. case T_base_design:
  2503. needSYMBOL();
  2504. growth->base_design = lexer->CurText();
  2505. needRIGHT();
  2506. break;
  2507. case T_history:
  2508. if( growth->history )
  2509. unexpected( tok );
  2510. growth->history = new HISTORY( growth );
  2511. doHISTORY( growth->history );
  2512. break;
  2513. case T_structure:
  2514. if( growth->structure )
  2515. unexpected( tok );
  2516. growth->structure = new STRUCTURE( growth );
  2517. doSTRUCTURE( growth->structure );
  2518. break;
  2519. case T_placement:
  2520. if( growth->placement )
  2521. unexpected( tok );
  2522. growth->placement = new PLACEMENT( growth );
  2523. doPLACEMENT( growth->placement );
  2524. break;
  2525. case T_was_is:
  2526. if( growth->was_is )
  2527. unexpected( tok );
  2528. growth->was_is = new WAS_IS( growth );
  2529. doWAS_IS( growth->was_is );
  2530. break;
  2531. case T_routes:
  2532. if( growth->route )
  2533. unexpected( tok );
  2534. growth->route = new ROUTE( growth );
  2535. doROUTE( growth->route );
  2536. break;
  2537. default:
  2538. unexpected( lexer->CurText() );
  2539. }
  2540. }
  2541. }
  2542. void SPECCTRA_DB::doWAS_IS( WAS_IS* growth ) throw( IOError )
  2543. {
  2544. DSN_T tok;
  2545. PIN_PAIR empty( growth );
  2546. PIN_PAIR* pin_pair;
  2547. /* <was_is_descriptor >::=
  2548. (was_is {(pins <pin_reference> <pin_reference> )})
  2549. */
  2550. // none of the pins is ok too
  2551. while( (tok = nextTok()) != T_RIGHT )
  2552. {
  2553. if( tok != T_LEFT )
  2554. expecting( T_LEFT );
  2555. tok = nextTok();
  2556. switch( tok )
  2557. {
  2558. case T_pins:
  2559. // copy the empty one, then fill its copy later thru pin_pair.
  2560. growth->pin_pairs.push_back( empty );
  2561. pin_pair= &growth->pin_pairs.back();
  2562. needSYMBOL(); // readCOMPnPIN() expects 1st token to have been read
  2563. readCOMPnPIN( &pin_pair->was.component_id, &pin_pair->was.pin_id );
  2564. needSYMBOL(); // readCOMPnPIN() expects 1st token to have been read
  2565. readCOMPnPIN( &pin_pair->is.component_id, &pin_pair->is.pin_id );
  2566. needRIGHT();
  2567. break;
  2568. default:
  2569. unexpected( lexer->CurText() );
  2570. }
  2571. }
  2572. }
  2573. void SPECCTRA_DB::doROUTE( ROUTE* growth ) throw( IOError )
  2574. {
  2575. DSN_T tok;
  2576. /* <route_descriptor >::=
  2577. (routes
  2578. <resolution_descriptor>
  2579. <parser_descriptor>
  2580. <structure_out_descriptor>
  2581. <library_out_descriptor>
  2582. <network_out_descriptor>
  2583. <test_points_descriptor>
  2584. )
  2585. */
  2586. while( (tok = nextTok()) != T_RIGHT )
  2587. {
  2588. if( tok != T_LEFT )
  2589. expecting( T_LEFT );
  2590. tok = nextTok();
  2591. switch( tok )
  2592. {
  2593. case T_resolution:
  2594. if( growth->resolution )
  2595. unexpected( tok );
  2596. growth->resolution = new UNIT_RES( growth, tok );
  2597. doRESOLUTION( growth->resolution );
  2598. break;
  2599. case T_parser:
  2600. if( growth->parser )
  2601. unexpected( tok );
  2602. growth->parser = new PARSER( growth );
  2603. doPARSER( growth->parser );
  2604. break;
  2605. case T_structure:
  2606. if( growth->structure )
  2607. unexpected( tok );
  2608. growth->structure = new STRUCTURE( growth );
  2609. doSTRUCTURE( growth->structure );
  2610. break;
  2611. case T_library_out:
  2612. if( growth->library )
  2613. unexpected( tok );
  2614. growth->library = new LIBRARY( growth, tok );
  2615. doLIBRARY( growth->library );
  2616. break;
  2617. case T_network_out:
  2618. while( (tok = nextTok()) != T_RIGHT )
  2619. {
  2620. if( tok != T_LEFT )
  2621. expecting( T_LEFT );
  2622. tok = nextTok();
  2623. if( tok != T_net ) // it is class NET_OUT, but token T_net
  2624. unexpected( lexer->CurText() );
  2625. NET_OUT* net_out;
  2626. net_out = new NET_OUT( growth );
  2627. growth->net_outs.push_back( net_out );
  2628. doNET_OUT( net_out );
  2629. }
  2630. break;
  2631. default:
  2632. unexpected( lexer->CurText() );
  2633. }
  2634. }
  2635. }
  2636. void SPECCTRA_DB::doNET_OUT( NET_OUT* growth ) throw( IOError )
  2637. {
  2638. DSN_T tok;
  2639. /* <net_out_descriptor >::=
  2640. (net <net_id >
  2641. [(net_number <integer >)]
  2642. [<rule_descriptor> ]
  2643. {[<wire_shape_descriptor> | <wire_guide_descriptor> |
  2644. <wire_via_descriptor> | <bond_shape_descriptor> ]}
  2645. {[<supply_pin_descriptor> ]}
  2646. )
  2647. */
  2648. needSYMBOL();
  2649. growth->net_id = lexer->CurText();
  2650. while( (tok = nextTok()) != T_RIGHT )
  2651. {
  2652. if( tok != T_LEFT )
  2653. expecting( T_LEFT );
  2654. tok = nextTok();
  2655. switch( tok )
  2656. {
  2657. case T_net_number:
  2658. tok = nextTok();
  2659. if( tok!= T_NUMBER )
  2660. expecting( T_NUMBER );
  2661. growth->net_number = atoi( lexer->CurText() );
  2662. needRIGHT();
  2663. break;
  2664. case T_rule:
  2665. if( growth->rules )
  2666. unexpected( tok );
  2667. growth->rules = new RULE( growth, tok );
  2668. doRULE( growth->rules );
  2669. break;
  2670. case T_wire:
  2671. WIRE* wire;
  2672. wire = new WIRE( growth );
  2673. growth->wires.push_back( wire );
  2674. doWIRE( wire );
  2675. break;
  2676. case T_via:
  2677. WIRE_VIA* wire_via;
  2678. wire_via = new WIRE_VIA( growth );
  2679. growth->wire_vias.push_back( wire_via );
  2680. doWIRE_VIA( wire_via );
  2681. break;
  2682. case T_supply_pin:
  2683. SUPPLY_PIN* supply_pin;
  2684. supply_pin = new SUPPLY_PIN( growth );
  2685. growth->supply_pins.push_back( supply_pin );
  2686. doSUPPLY_PIN( supply_pin );
  2687. break;
  2688. default:
  2689. unexpected( lexer->CurText() );
  2690. }
  2691. }
  2692. }
  2693. void SPECCTRA_DB::doSUPPLY_PIN( SUPPLY_PIN* growth ) throw( IOError )
  2694. {
  2695. DSN_T tok;
  2696. PIN_REF empty(growth);
  2697. /* <supply_pin_descriptor >::=
  2698. (supply_pin {<pin_reference> } [(net <net_id >)])
  2699. */
  2700. needSYMBOL();
  2701. growth->net_id = lexer->CurText();
  2702. while( (tok = nextTok()) != T_RIGHT )
  2703. {
  2704. if( isSymbol(tok) )
  2705. {
  2706. growth->pin_refs.push_back( empty );
  2707. PIN_REF* pin_ref = &growth->pin_refs.back();
  2708. readCOMPnPIN( &pin_ref->component_id, &pin_ref->pin_id );
  2709. }
  2710. else if( tok == T_LEFT )
  2711. {
  2712. tok = nextTok();
  2713. if( tok != T_net )
  2714. expecting( T_net );
  2715. growth->net_id = lexer->CurText();
  2716. needRIGHT();
  2717. }
  2718. else
  2719. unexpected( lexer->CurText() );
  2720. }
  2721. }
  2722. int SPECCTRA_DB::Print( int nestLevel, const char* fmt, ... ) throw( IOError )
  2723. {
  2724. va_list args;
  2725. va_start( args, fmt );
  2726. int result = 0;
  2727. int total = 0;
  2728. for( int i=0; i<nestLevel; ++i )
  2729. {
  2730. result = fprintf( fp, "%*c", NESTWIDTH, ' ' );
  2731. if( result < 0 )
  2732. break;
  2733. total += result;
  2734. }
  2735. if( result<0 || (result=vfprintf( fp, fmt, args ))<0 )
  2736. ThrowIOError( _("System file error writing to file \"%s\""), filename.GetData() );
  2737. va_end( args );
  2738. total += result;
  2739. return total;
  2740. }
  2741. // factor out a common GetQuoteChar
  2742. const char* OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, const char* quote_char )
  2743. {
  2744. // I include '#' so a symbol is not confused with a comment. We intend
  2745. // to wrap any symbol starting with a '#'.
  2746. // Our LEXER class handles comments, and comments appear to be an extension
  2747. // to the SPECCTRA DSN specification.
  2748. if( *wrapee == '#' )
  2749. return quote_char;
  2750. if( strlen(wrapee)==0 )
  2751. return quote_char;
  2752. bool isNumber = true;
  2753. for( ; *wrapee; ++wrapee )
  2754. {
  2755. // if the string to be wrapped (wrapee) has a delimiter in it,
  2756. // return the quote_char so caller wraps the wrapee.
  2757. if( strchr( "\t ()", *wrapee ) )
  2758. return quote_char;
  2759. if( !strchr( "01234567890.-+", *wrapee ) )
  2760. isNumber = false;
  2761. }
  2762. if( isNumber )
  2763. return quote_char;
  2764. return ""; // can use an unwrapped string.
  2765. }
  2766. const char* SPECCTRA_DB::GetQuoteChar( const char* wrapee )
  2767. {
  2768. return OUTPUTFORMATTER::GetQuoteChar( wrapee, quote_char.c_str() );
  2769. }
  2770. void SPECCTRA_DB::ExportPCB( wxString filename, bool aNameChange ) throw( IOError )
  2771. {
  2772. fp = wxFopen( filename, wxT("w") );
  2773. if( !fp )
  2774. {
  2775. ThrowIOError( _("Unable to open file \"%s\""), filename.GetData() );
  2776. }
  2777. if( pcb )
  2778. {
  2779. if( aNameChange )
  2780. pcb->pcbname = CONV_TO_UTF8(filename);
  2781. pcb->Format( this, 0 );
  2782. }
  2783. // if an exception is thrown by Format, then ~SPECCTRA_DB() will close
  2784. // the file.
  2785. fclose( fp );
  2786. fp = 0;
  2787. }
  2788. void SPECCTRA_DB::ExportSESSION( wxString filename )
  2789. {
  2790. fp = wxFopen( filename, wxT("w") );
  2791. if( !fp )
  2792. {
  2793. ThrowIOError( _("Unable to open file \"%s\""), filename.GetData() );
  2794. }
  2795. if( session )
  2796. session->Format( this, 0 );
  2797. fclose( fp );
  2798. fp = 0;
  2799. }
  2800. PCB* SPECCTRA_DB::MakePCB()
  2801. {
  2802. PCB* pcb = new PCB();
  2803. pcb->parser = new PARSER( pcb );
  2804. pcb->resolution = new UNIT_RES( pcb, T_resolution );
  2805. pcb->unit = new UNIT_RES( pcb, T_unit );
  2806. pcb->structure = new STRUCTURE( pcb );
  2807. pcb->structure->boundary = new BOUNDARY( pcb->structure );
  2808. pcb->structure->via = new VIA( pcb->structure );
  2809. pcb->structure->rules = new RULE( pcb->structure, T_rule );
  2810. pcb->placement = new PLACEMENT( pcb );
  2811. //pcb->placement->flip_style = T_mirror_first;
  2812. pcb->library = new LIBRARY( pcb );
  2813. pcb->network = new NETWORK( pcb );
  2814. pcb->wiring = new WIRING( pcb );
  2815. return pcb;
  2816. }
  2817. //-----<STRINGFORMATTER>----------------------------------------------------
  2818. const char* STRINGFORMATTER::GetQuoteChar( const char* wrapee )
  2819. {
  2820. // for what we are using STRINGFORMATTER for at this time, we can return the nul string
  2821. // always.
  2822. return "";
  2823. // return OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, "\"" );
  2824. }
  2825. int STRINGFORMATTER::vprint( const char* fmt, va_list ap )
  2826. {
  2827. int ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
  2828. if( ret >= (int) buffer.size() )
  2829. {
  2830. buffer.reserve( ret+200 );
  2831. ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
  2832. }
  2833. if( ret > 0 )
  2834. mystring.append( (const char*) &buffer[0] );
  2835. return ret;
  2836. }
  2837. int STRINGFORMATTER::sprint( const char* fmt, ... )
  2838. {
  2839. va_list args;
  2840. va_start( args, fmt );
  2841. int ret = vprint( fmt, args);
  2842. va_end( args );
  2843. return ret;
  2844. }
  2845. int STRINGFORMATTER::Print( int nestLevel, const char* fmt, ... ) throw( IOError )
  2846. {
  2847. va_list args;
  2848. va_start( args, fmt );
  2849. int result = 0;
  2850. int total = 0;
  2851. for( int i=0; i<nestLevel; ++i )
  2852. {
  2853. result = sprint( "%*c", NESTWIDTH, ' ' );
  2854. if( result < 0 )
  2855. break;
  2856. total += result;
  2857. }
  2858. if( result<0 || (result=vprint( fmt, args ))<0 )
  2859. {
  2860. throw IOError( _("Error writing to STRINGFORMATTER") );
  2861. }
  2862. va_end( args );
  2863. total += result;
  2864. return total;
  2865. }
  2866. void STRINGFORMATTER::StripUseless()
  2867. {
  2868. for( std::string::iterator i=mystring.begin(); i!=mystring.end(); )
  2869. {
  2870. if( isspace( *i ) || *i==')' || *i=='(' )
  2871. mystring.erase(i);
  2872. else
  2873. ++i;
  2874. }
  2875. }
  2876. //-----<ELEM>---------------------------------------------------------------
  2877. ELEM::ELEM( DSN_T aType, ELEM* aParent ) :
  2878. type( aType ),
  2879. parent( aParent )
  2880. {
  2881. }
  2882. ELEM::~ELEM()
  2883. {
  2884. }
  2885. void ELEM::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
  2886. {
  2887. out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) );
  2888. FormatContents( out, nestLevel+1 );
  2889. out->Print( nestLevel, ")\n" );
  2890. }
  2891. void ELEM_HOLDER::FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
  2892. {
  2893. for( int i=0; i<Length(); ++i )
  2894. {
  2895. At(i)->Format( out, nestLevel );
  2896. }
  2897. }
  2898. int ELEM_HOLDER::FindElem( DSN_T aType, int instanceNum )
  2899. {
  2900. int repeats=0;
  2901. for( unsigned i=0; i<kids.size(); ++i )
  2902. {
  2903. if( kids[i].Type() == aType )
  2904. {
  2905. if( repeats == instanceNum )
  2906. return i;
  2907. ++repeats;
  2908. }
  2909. }
  2910. return -1;
  2911. }
  2912. //-----<PADSTACK>---------------------------------------------------------
  2913. int PADSTACK::Compare( PADSTACK* lhs, PADSTACK* rhs )
  2914. {
  2915. if( !lhs->hash.size() )
  2916. lhs->hash = lhs->makeHash();
  2917. if( !rhs->hash.size() )
  2918. rhs->hash = rhs->makeHash();
  2919. int result = lhs->hash.compare( rhs->hash );
  2920. return result;
  2921. }
  2922. //-----<IMAGE>------------------------------------------------------------
  2923. int IMAGE::Compare( IMAGE* lhs, IMAGE* rhs )
  2924. {
  2925. if( !lhs->hash.size() )
  2926. lhs->hash = lhs->makeHash();
  2927. if( !rhs->hash.size() )
  2928. rhs->hash = rhs->makeHash();
  2929. int result = lhs->hash.compare( rhs->hash );
  2930. // printf("\"%s\" \"%s\" ret=%d\n", lhs->hash.c_str(), rhs->hash.c_str(), result );
  2931. return result;
  2932. }
  2933. //-----<COMPONENT>--------------------------------------------------------
  2934. /*
  2935. int COMPONENT::Compare( COMPONENT* lhs, COMPONENT* rhs )
  2936. {
  2937. if( !lhs->hash.size() )
  2938. lhs->hash = lhs->makeHash();
  2939. if( !rhs->hash.size() )
  2940. rhs->hash = rhs->makeHash();
  2941. int result = lhs->hash.compare( rhs->hash );
  2942. return result;
  2943. }
  2944. */
  2945. //-----<PARSER>-----------------------------------------------------------
  2946. PARSER::PARSER( ELEM* aParent ) :
  2947. ELEM( T_parser, aParent )
  2948. {
  2949. string_quote = '"';
  2950. space_in_quoted_tokens = false;
  2951. case_sensitive = false;
  2952. wires_include_testpoint = false;
  2953. routes_include_testpoint = false;
  2954. routes_include_guides = false;
  2955. routes_include_image_conductor = false;
  2956. via_rotate_first = true;
  2957. generated_by_freeroute = false;
  2958. host_cad = "Kicad's PCBNEW";
  2959. host_version = CONV_TO_UTF8(g_BuildVersion);
  2960. }
  2961. void PARSER::FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
  2962. {
  2963. out->Print( nestLevel, "(string_quote %c)\n", string_quote );
  2964. out->Print( nestLevel, "(space_in_quoted_tokens %s)\n", space_in_quoted_tokens ? "on" : "off" );
  2965. out->Print( nestLevel, "(host_cad \"%s\")\n", host_cad.c_str() );
  2966. out->Print( nestLevel, "(host_version \"%s\")\n", host_version.c_str() );
  2967. if( const_id1.length()>0 || const_id2.length()>0 )
  2968. out->Print( nestLevel, "(constant %c%s%c %c%s%c)\n",
  2969. string_quote, const_id1.c_str(), string_quote,
  2970. string_quote, const_id2.c_str(), string_quote );
  2971. if( routes_include_testpoint || routes_include_guides || routes_include_image_conductor )
  2972. out->Print( nestLevel, "(routes_include%s%s%s)\n",
  2973. routes_include_testpoint ? " testpoint" : "",
  2974. routes_include_guides ? " guides" : "",
  2975. routes_include_image_conductor ? " image_conductor" : "");
  2976. if( wires_include_testpoint )
  2977. out->Print( nestLevel, "(wires_include testpoint)\n" );
  2978. if( !via_rotate_first )
  2979. out->Print( nestLevel, "(via_rotate_first off)\n" );
  2980. if( case_sensitive )
  2981. out->Print( nestLevel, "(case_sensitive %s)\n", case_sensitive ? "on" : "off" );
  2982. }
  2983. void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
  2984. {
  2985. bool useMultiLine;
  2986. const char* quote = out->GetQuoteChar( component_id.c_str() );
  2987. if( place_rules || properties.size() || rules || region )
  2988. {
  2989. useMultiLine = true;
  2990. out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ),
  2991. quote, component_id.c_str(), quote );
  2992. out->Print( nestLevel+1, "%s", "" );
  2993. }
  2994. else
  2995. {
  2996. useMultiLine = false;
  2997. out->Print( nestLevel, "(%s %s%s%s", LEXER::GetTokenText( Type() ),
  2998. quote, component_id.c_str(), quote );
  2999. }
  3000. if( hasVertex )
  3001. {
  3002. out->Print( 0, " %.6g %.6g", vertex.x, vertex.y );
  3003. out->Print( 0, " %s", LEXER::GetTokenText( side ) );
  3004. out->Print( 0, " %.6g", rotation );
  3005. }
  3006. const char* space = " "; // one space, as c string.
  3007. if( mirror != T_NONE )
  3008. {
  3009. out->Print( 0, "%s(mirror %s)", space, LEXER::GetTokenText( mirror ) );
  3010. space = "";
  3011. }
  3012. if( status != T_NONE )
  3013. {
  3014. out->Print( 0, "%s(status %s)", space, LEXER::GetTokenText( status ) );
  3015. space = "";
  3016. }
  3017. if( logical_part.size() )
  3018. {
  3019. quote = out->GetQuoteChar( logical_part.c_str() );
  3020. out->Print( 0, "%s(logical_part %s%s%s)", space,
  3021. quote, logical_part.c_str(), quote );
  3022. space = "";
  3023. }
  3024. if( useMultiLine )
  3025. {
  3026. out->Print( 0, "\n" );
  3027. if( place_rules )
  3028. {
  3029. place_rules->Format( out, nestLevel+1 );
  3030. }
  3031. if( properties.size() )
  3032. {
  3033. out->Print( nestLevel+1, "(property \n" );
  3034. for( PROPERTIES::const_iterator i = properties.begin();
  3035. i != properties.end(); ++i )
  3036. {
  3037. i->Format( out, nestLevel+2 );
  3038. }
  3039. out->Print( nestLevel+1, ")\n" );
  3040. }
  3041. if( lock_type != T_NONE )
  3042. out->Print( nestLevel+1, "(lock_type %s)\n",
  3043. LEXER::GetTokenText(lock_type) );
  3044. if( rules )
  3045. rules->Format( out, nestLevel+1 );
  3046. if( region )
  3047. region->Format( out, nestLevel+1 );
  3048. if( part_number.size() )
  3049. {
  3050. const char* quote = out->GetQuoteChar( part_number.c_str() );
  3051. out->Print( nestLevel+1, "(PN %s%s%s)\n",
  3052. quote, part_number.c_str(), quote );
  3053. }
  3054. }
  3055. else
  3056. {
  3057. if( lock_type != T_NONE )
  3058. {
  3059. out->Print( 0, "%s(lock_type %s)", space,
  3060. LEXER::GetTokenText(lock_type) );
  3061. space = "";
  3062. }
  3063. if( part_number.size() )
  3064. {
  3065. const char* quote = out->GetQuoteChar( part_number.c_str() );
  3066. out->Print( 0, "%s(PN %s%s%s)", space,
  3067. quote, part_number.c_str(), quote );
  3068. }
  3069. }
  3070. out->Print( 0, ")\n" );
  3071. }
  3072. } // namespace DSN
  3073. // unit test this source file
  3074. #if defined(STANDALONE)
  3075. using namespace DSN;
  3076. int main( int argc, char** argv )
  3077. {
  3078. // wxString filename( wxT("/tmp/fpcroute/Sample_1sided/demo_1sided.dsn") );
  3079. // wxString filename( wxT("/tmp/testdesigns/test.dsn") );
  3080. // wxString filename( wxT("/tmp/testdesigns/test.ses") );
  3081. wxString filename( wxT("/tmp/specctra_big.dsn") );
  3082. SPECCTRA_DB db;
  3083. bool failed = false;
  3084. if( argc == 2 )
  3085. {
  3086. filename = CONV_FROM_UTF8( argv[1] );
  3087. }
  3088. try
  3089. {
  3090. db.LoadPCB( filename );
  3091. // db.LoadSESSION( filename );
  3092. }
  3093. catch( IOError ioe )
  3094. {
  3095. fprintf( stderr, "%s\n", CONV_TO_UTF8(ioe.errorText) );
  3096. failed = true;
  3097. }
  3098. if( !failed )
  3099. fprintf( stderr, "loaded OK\n" );
  3100. // export what we read in, making this test program basically a beautifier
  3101. // db.ExportSESSION( wxT("/tmp/export.ses") );
  3102. // db.ExportPCB( wxT("/tmp/export.dsn") );
  3103. DSN::PCB* pcb = db.GetPCB();
  3104. // hose the beautified DSN file to stdout.
  3105. db.SetFILE( stdout );
  3106. pcb->Format( &db, 0 );
  3107. }
  3108. #endif
  3109. //EOF