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.

2697 lines
70 KiB

14 years ago
14 years ago
14 years ago
14 years ago
14 years ago
  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2012 CERN
  5. *
  6. * This program is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU General Public License
  8. * as published by the Free Software Foundation; either version 2
  9. * of the License, or (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program; if not, you may find one here:
  18. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  19. * or you may search the http://www.gnu.org website for the version 2 license,
  20. * or you may write to the Free Software Foundation, Inc.,
  21. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  22. */
  23. /**
  24. * @file pcb_parser.cpp
  25. * @brief Pcbnew s-expression file format parser implementation.
  26. */
  27. #include <errno.h>
  28. #include <common.h>
  29. #include <macros.h>
  30. #include <convert_from_iu.h>
  31. #include <trigo.h>
  32. #include <3d_struct.h>
  33. #include <class_title_block.h>
  34. #include <class_board.h>
  35. #include <class_dimension.h>
  36. #include <class_drawsegment.h>
  37. #include <class_edge_mod.h>
  38. #include <class_mire.h>
  39. #include <class_module.h>
  40. #include <class_netclass.h>
  41. #include <class_pad.h>
  42. #include <class_track.h>
  43. #include <class_zone.h>
  44. #include <kicad_plugin.h>
  45. #include <pcb_plot_params.h>
  46. #include <zones.h>
  47. #include <pcb_parser.h>
  48. using namespace std;
  49. void PCB_PARSER::init()
  50. {
  51. m_layerMap.clear();
  52. // Add untranslated default (i.e. english) layernames.
  53. // Some may be overridden later if parsing a board rather than a footprint.
  54. // The english name will survive if parsing only a footprint.
  55. for( int layerNdx = 0; layerNdx < NB_LAYERS; ++layerNdx )
  56. {
  57. wxString untranslated = BOARD::GetDefaultLayerName( layerNdx, false );
  58. m_layerMap[ untranslated ] = layerNdx;
  59. }
  60. }
  61. double PCB_PARSER::parseDouble() throw( IO_ERROR )
  62. {
  63. char* tmp;
  64. errno = 0;
  65. double fval = strtod( CurText(), &tmp );
  66. if( errno )
  67. {
  68. wxString error;
  69. error.Printf( _( "invalid floating point number in\nfile: '%s'\nline: %d\noffset: %d" ),
  70. GetChars( CurSource() ), CurLineNumber(), CurOffset() );
  71. THROW_IO_ERROR( error );
  72. }
  73. if( CurText() == tmp )
  74. {
  75. wxString error;
  76. error.Printf( _( "missing floating point number in\nfile: '%s'\nline: %d\noffset: %d" ),
  77. GetChars( CurSource() ), CurLineNumber(), CurOffset() );
  78. THROW_IO_ERROR( error );
  79. }
  80. return fval;
  81. }
  82. bool PCB_PARSER::parseBool() throw( PARSE_ERROR )
  83. {
  84. T token = NextTok();
  85. if( token == T_yes )
  86. return true;
  87. else if( token == T_no )
  88. return false;
  89. else
  90. Expecting( "yes or no" );
  91. return false;
  92. }
  93. wxPoint PCB_PARSER::parseXY() throw( PARSE_ERROR )
  94. {
  95. if( CurTok() != T_LEFT )
  96. NeedLEFT();
  97. wxPoint pt;
  98. T token = NextTok();
  99. if( token != T_xy )
  100. Expecting( T_xy );
  101. pt.x = parseBoardUnits( "X coordinate" );
  102. pt.y = parseBoardUnits( "Y coordinate" );
  103. NeedRIGHT();
  104. return pt;
  105. }
  106. void PCB_PARSER::parseXY( int* aX, int* aY ) throw( PARSE_ERROR )
  107. {
  108. wxPoint pt = parseXY();
  109. if( aX )
  110. *aX = pt.x;
  111. if( aY )
  112. *aY = pt.y;
  113. }
  114. void PCB_PARSER::parseEDA_TEXT( EDA_TEXT* aText ) throw( PARSE_ERROR )
  115. {
  116. wxCHECK_RET( CurTok() == T_effects,
  117. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as EDA_TEXT." ) );
  118. T token;
  119. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  120. {
  121. if( token != T_LEFT )
  122. Expecting( T_LEFT );
  123. token = NextTok();
  124. switch( token )
  125. {
  126. case T_font:
  127. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  128. {
  129. if( token == T_LEFT )
  130. continue;
  131. switch( token )
  132. {
  133. case T_size:
  134. {
  135. wxSize sz;
  136. sz.SetHeight( parseBoardUnits( "text height" ) );
  137. sz.SetWidth( parseBoardUnits( "text width" ) );
  138. aText->SetSize( sz );
  139. NeedRIGHT();
  140. break;
  141. }
  142. case T_thickness:
  143. aText->SetThickness( parseBoardUnits( "text thickness" ) );
  144. NeedRIGHT();
  145. break;
  146. case T_bold:
  147. aText->SetBold( true );
  148. break;
  149. case T_italic:
  150. aText->SetItalic( true );
  151. break;
  152. default:
  153. Expecting( "size, bold, or italic" );
  154. }
  155. }
  156. break;
  157. case T_justify:
  158. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  159. {
  160. if( token == T_LEFT )
  161. continue;
  162. switch( token )
  163. {
  164. case T_left:
  165. aText->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT );
  166. break;
  167. case T_right:
  168. aText->SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT );
  169. break;
  170. case T_top:
  171. aText->SetVertJustify( GR_TEXT_VJUSTIFY_TOP );
  172. break;
  173. case T_bottom:
  174. aText->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM );
  175. break;
  176. case T_mirror:
  177. aText->SetMirrored( true );
  178. break;
  179. default:
  180. Expecting( "left, right, top, bottom, or mirror" );
  181. }
  182. }
  183. break;
  184. case T_hide:
  185. aText->SetVisible( false );
  186. break;
  187. default:
  188. Expecting( "font, justify, or hide" );
  189. }
  190. }
  191. }
  192. S3D_MASTER* PCB_PARSER::parse3DModel() throw( PARSE_ERROR )
  193. {
  194. wxCHECK_MSG( CurTok() == T_model, NULL,
  195. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as S3D_MASTER." ) );
  196. T token;
  197. auto_ptr< S3D_MASTER > n3D( new S3D_MASTER( NULL ) );
  198. NeedSYMBOL();
  199. n3D->m_Shape3DName = FromUTF8();
  200. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  201. {
  202. if( token != T_LEFT )
  203. Expecting( T_LEFT );
  204. token = NextTok();
  205. switch( token )
  206. {
  207. case T_at:
  208. NeedLEFT();
  209. token = NextTok();
  210. if( token != T_xyz )
  211. Expecting( T_xyz );
  212. n3D->m_MatPosition.x = parseDouble( "x value" );
  213. n3D->m_MatPosition.y = parseDouble( "y value" );
  214. n3D->m_MatPosition.z = parseDouble( "z value" );
  215. NeedRIGHT();
  216. break;
  217. case T_scale:
  218. NeedLEFT();
  219. token = NextTok();
  220. if( token != T_xyz )
  221. Expecting( T_xyz );
  222. n3D->m_MatScale.x = parseDouble( "x value" );
  223. n3D->m_MatScale.y = parseDouble( "y value" );
  224. n3D->m_MatScale.z = parseDouble( "z value" );
  225. NeedRIGHT();
  226. break;
  227. case T_rotate:
  228. NeedLEFT();
  229. token = NextTok();
  230. if( token != T_xyz )
  231. Expecting( T_xyz );
  232. n3D->m_MatRotation.x = parseDouble( "x value" );
  233. n3D->m_MatRotation.y = parseDouble( "y value" );
  234. n3D->m_MatRotation.z = parseDouble( "z value" );
  235. NeedRIGHT();
  236. break;
  237. default:
  238. Expecting( "at, scale, or rotate" );
  239. }
  240. NeedRIGHT();
  241. }
  242. return n3D.release();
  243. }
  244. BOARD_ITEM* PCB_PARSER::Parse() throw( IO_ERROR, PARSE_ERROR )
  245. {
  246. T token;
  247. BOARD_ITEM* item;
  248. LOCALE_IO toggle; // toggles on, then off, the C locale.
  249. token = NextTok();
  250. if( token != T_LEFT )
  251. Expecting( T_LEFT );
  252. switch( NextTok() )
  253. {
  254. case T_kicad_pcb:
  255. if( m_board == NULL )
  256. m_board = new BOARD();
  257. item = (BOARD_ITEM*) parseBOARD();
  258. break;
  259. case T_module:
  260. item = (BOARD_ITEM*) parseMODULE();
  261. break;
  262. default:
  263. wxString err;
  264. err.Printf( _( "unknown token \"%s\"" ), GetChars( FromUTF8() ) );
  265. THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
  266. }
  267. return item;
  268. }
  269. BOARD* PCB_PARSER::parseBOARD() throw( IO_ERROR, PARSE_ERROR )
  270. {
  271. T token;
  272. parseHeader();
  273. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  274. {
  275. if( token != T_LEFT )
  276. Expecting( T_LEFT );
  277. token = NextTok();
  278. switch( token )
  279. {
  280. case T_general:
  281. parseGeneralSection();
  282. break;
  283. case T_page:
  284. parsePAGE_INFO();
  285. break;
  286. case T_title_block:
  287. parseTITLE_BLOCK();
  288. break;
  289. case T_layers:
  290. parseLayers();
  291. break;
  292. case T_setup:
  293. parseSetup();
  294. break;
  295. case T_net:
  296. parseNETINFO_ITEM();
  297. break;
  298. case T_net_class:
  299. parseNETCLASS();
  300. break;
  301. case T_gr_arc:
  302. case T_gr_circle:
  303. case T_gr_curve:
  304. case T_gr_line:
  305. case T_gr_poly:
  306. m_board->Add( parseDRAWSEGMENT(), ADD_APPEND );
  307. break;
  308. case T_gr_text:
  309. m_board->Add( parseTEXTE_PCB(), ADD_APPEND );
  310. break;
  311. case T_dimension:
  312. m_board->Add( parseDIMENSION(), ADD_APPEND );
  313. break;
  314. case T_module:
  315. m_board->Add( parseMODULE(), ADD_APPEND );
  316. break;
  317. case T_segment:
  318. m_board->m_Track.Append( parseTRACK() );
  319. break;
  320. case T_via:
  321. m_board->m_Track.Append( parseSEGVIA() );
  322. break;
  323. case T_zone:
  324. m_board->Add( parseZONE_CONTAINER(), ADD_APPEND );
  325. break;
  326. case T_target:
  327. m_board->Add( parsePCB_TARGET(), ADD_APPEND );
  328. break;
  329. default:
  330. wxString err;
  331. err.Printf( _( "unknown token \"%s\"" ), GetChars( FromUTF8() ) );
  332. THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
  333. }
  334. }
  335. return m_board;
  336. }
  337. void PCB_PARSER::parseHeader() throw( IO_ERROR, PARSE_ERROR )
  338. {
  339. wxCHECK_RET( CurTok() == T_kicad_pcb,
  340. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a header." ) );
  341. T token;
  342. NeedLEFT();
  343. token = NextTok();
  344. if( token != T_version )
  345. Expecting( GetTokenText( T_version ) );
  346. // Get the file version.
  347. m_board->SetFileFormatVersionAtLoad( parseInt( GetTokenText( T_version ) ) );
  348. // Skip the host name and host build version information.
  349. NeedRIGHT();
  350. NeedLEFT();
  351. NeedSYMBOL();
  352. NeedSYMBOL();
  353. NeedSYMBOL();
  354. NeedRIGHT();
  355. }
  356. void PCB_PARSER::parseGeneralSection() throw( IO_ERROR, PARSE_ERROR )
  357. {
  358. wxCHECK_RET( CurTok() == T_general,
  359. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
  360. wxT( " as a general section." ) );
  361. T token;
  362. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  363. {
  364. if( token != T_LEFT )
  365. Expecting( T_LEFT );
  366. token = NextTok();
  367. switch( token )
  368. {
  369. case T_thickness:
  370. m_board->GetDesignSettings().SetBoardThickness( parseBoardUnits( T_thickness ) );
  371. NeedRIGHT();
  372. break;
  373. case T_no_connects:
  374. m_board->m_NbNoconnect = parseInt( "no connect count" );
  375. NeedRIGHT();
  376. break;
  377. default: // Skip everything but the board thickness.
  378. wxLogDebug( wxT( "Skipping general section token %s " ),
  379. GetChars( GetTokenString( token ) ) );
  380. while( ( token = NextTok() ) != T_RIGHT )
  381. {
  382. if( !IsSymbol( token ) && token != T_NUMBER )
  383. Expecting( "symbol or number" );
  384. }
  385. }
  386. }
  387. }
  388. void PCB_PARSER::parsePAGE_INFO() throw( IO_ERROR, PARSE_ERROR )
  389. {
  390. wxCHECK_RET( CurTok() == T_page,
  391. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a PAGE_INFO." ) );
  392. T token;
  393. PAGE_INFO pageInfo;
  394. NeedSYMBOL();
  395. wxString pageType = FromUTF8();
  396. if( !pageInfo.SetType( pageType ) )
  397. {
  398. wxString err;
  399. err.Printf( _( "page type \"%s\" is not valid " ), GetChars( FromUTF8() ) );
  400. THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
  401. }
  402. if( pageType == PAGE_INFO::Custom )
  403. {
  404. double width = parseDouble( "width" ); // width in mm
  405. // Perform some controls to avoid crashes if the size is edited by hands
  406. if( width < 100.0 )
  407. width = 100.0;
  408. else if( width > 1200.0 )
  409. width = 1200.0;
  410. double height = parseDouble( "height" ); // height in mm
  411. if( height < 100.0 )
  412. height = 100.0;
  413. else if( height > 1200.0 )
  414. height = 1200.0;
  415. pageInfo.SetWidthMils( Mm2mils( width ) );
  416. pageInfo.SetHeightMils( Mm2mils( height ) );
  417. }
  418. token = NextTok();
  419. if( token == T_portrait )
  420. {
  421. pageInfo.SetPortrait( true );
  422. NeedRIGHT();
  423. }
  424. else if( token != T_RIGHT )
  425. {
  426. Expecting( "portrait|)" );
  427. }
  428. m_board->SetPageSettings( pageInfo );
  429. }
  430. void PCB_PARSER::parseTITLE_BLOCK() throw( IO_ERROR, PARSE_ERROR )
  431. {
  432. wxCHECK_RET( CurTok() == T_title_block,
  433. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
  434. wxT( " as TITLE_BLOCK." ) );
  435. T token;
  436. TITLE_BLOCK titleBlock;
  437. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  438. {
  439. if( token != T_LEFT )
  440. Expecting( T_LEFT );
  441. token = NextTok();
  442. switch( token )
  443. {
  444. case T_title:
  445. NeedSYMBOL();
  446. titleBlock.SetTitle( FromUTF8() );
  447. break;
  448. case T_date:
  449. NeedSYMBOL();
  450. titleBlock.SetDate( FromUTF8() );
  451. break;
  452. case T_rev:
  453. NextTok();
  454. titleBlock.SetRevision( FromUTF8() );
  455. break;
  456. case T_company:
  457. NextTok();
  458. titleBlock.SetCompany( FromUTF8() );
  459. break;
  460. case T_comment:
  461. {
  462. int commentNumber = parseInt( "comment" );
  463. switch( commentNumber )
  464. {
  465. case 1:
  466. NextTok();
  467. titleBlock.SetComment1( FromUTF8() );
  468. break;
  469. case 2:
  470. NextTok();
  471. titleBlock.SetComment2( FromUTF8() );
  472. break;
  473. case 3:
  474. NextTok();
  475. titleBlock.SetComment3( FromUTF8() );
  476. break;
  477. case 4:
  478. NextTok();
  479. titleBlock.SetComment4( FromUTF8() );
  480. break;
  481. default:
  482. wxString err;
  483. err.Printf( wxT( "%d is not a valid title block comment number" ), commentNumber );
  484. THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
  485. }
  486. break;
  487. }
  488. default:
  489. Expecting( "title, date, rev, company, or comment" );
  490. }
  491. NeedRIGHT();
  492. }
  493. m_board->SetTitleBlock( titleBlock );
  494. }
  495. void PCB_PARSER::parseLayers() throw( IO_ERROR, PARSE_ERROR )
  496. {
  497. wxCHECK_RET( CurTok() == T_layers,
  498. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as layers." ) );
  499. T token;
  500. wxString name;
  501. std::string type;
  502. int layerIndex;
  503. bool isVisible = true;
  504. int visibleLayers = 0;
  505. int enabledLayers = 0;
  506. int copperLayerCount = 0;
  507. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  508. {
  509. if( token != T_LEFT )
  510. Expecting( T_LEFT );
  511. layerIndex = parseInt( "layer index" );
  512. NeedSYMBOL();
  513. name = FromUTF8();
  514. NeedSYMBOL();
  515. type = CurText();
  516. token = NextTok();
  517. if( token == T_hide )
  518. {
  519. isVisible = false;
  520. NeedRIGHT();
  521. }
  522. else if( token == T_RIGHT )
  523. {
  524. isVisible = true;
  525. }
  526. else
  527. {
  528. Expecting( "hide or )" );
  529. }
  530. enabledLayers |= 1 << layerIndex;
  531. if( isVisible )
  532. visibleLayers |= 1 << layerIndex;
  533. enum LAYER_T layerType = LAYER::ParseType( type.c_str() );
  534. LAYER layer( name, layerType, isVisible );
  535. layer.SetFixedListIndex( layerIndex );
  536. m_board->SetLayer( layerIndex, layer );
  537. m_layerMap[ name ] = layerIndex;
  538. wxLogDebug( wxT( "Mapping layer %s to index %d" ),
  539. GetChars( name ), layerIndex );
  540. if( layerType != LT_UNDEFINED )
  541. copperLayerCount++;
  542. }
  543. // We need at least 2 copper layers and there must be an even number of them.
  544. if( (copperLayerCount < 2) || ((copperLayerCount % 2) != 0) )
  545. {
  546. wxString err = wxString::Format(
  547. _( "%d is not a valid layer count" ), copperLayerCount );
  548. THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
  549. }
  550. m_board->SetCopperLayerCount( copperLayerCount );
  551. m_board->SetVisibleLayers( visibleLayers );
  552. m_board->SetEnabledLayers( enabledLayers );
  553. }
  554. int PCB_PARSER::lookUpLayer() throw( PARSE_ERROR, IO_ERROR )
  555. {
  556. wxString name = FromUTF8();
  557. const LAYER_HASH_MAP::iterator it = m_layerMap.find( name );
  558. if( it == m_layerMap.end() )
  559. {
  560. wxString error = wxString::Format(
  561. _( "Layer '%s' in file <%s> at line %d, position %d, was not defined in the layers section" ),
  562. GetChars( name ), GetChars( CurSource() ), CurLineNumber(), CurOffset() );
  563. THROW_IO_ERROR( error );
  564. }
  565. return it->second;
  566. }
  567. int PCB_PARSER::parseBoardItemLayer() throw( PARSE_ERROR, IO_ERROR )
  568. {
  569. wxCHECK_MSG( CurTok() == T_layer, UNDEFINED_LAYER,
  570. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as layer." ) );
  571. NextTok();
  572. int layerIndex = lookUpLayer();
  573. // Handle closing ) in object parser.
  574. return layerIndex;
  575. }
  576. int PCB_PARSER::parseBoardItemLayersAsMask() throw( PARSE_ERROR, IO_ERROR )
  577. {
  578. wxCHECK_MSG( CurTok() == T_layers, 0,
  579. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
  580. wxT( " as item layer mask." ) );
  581. int layerIndex;
  582. int layerMask = 0;
  583. T token;
  584. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  585. {
  586. layerIndex = lookUpLayer();
  587. layerMask |= ( 1 << layerIndex );
  588. }
  589. return layerMask;
  590. }
  591. void PCB_PARSER::parseSetup() throw( IO_ERROR, PARSE_ERROR )
  592. {
  593. wxCHECK_RET( CurTok() == T_setup,
  594. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as setup." ) );
  595. T token;
  596. NETCLASS* defaultNetclass = m_board->m_NetClasses.GetDefault();
  597. BOARD_DESIGN_SETTINGS designSettings = m_board->GetDesignSettings();
  598. ZONE_SETTINGS zoneSettings = m_board->GetZoneSettings();
  599. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  600. {
  601. if( token != T_LEFT )
  602. Expecting( T_LEFT );
  603. token = NextTok();
  604. switch( token )
  605. {
  606. case T_last_trace_width: // not used now
  607. /* lastTraceWidth =*/ parseBoardUnits( T_last_trace_width );
  608. NeedRIGHT();
  609. break;
  610. case T_user_trace_width:
  611. m_board->m_TrackWidthList.push_back( parseBoardUnits( T_user_trace_width ) );
  612. NeedRIGHT();
  613. break;
  614. case T_trace_clearance:
  615. defaultNetclass->SetClearance( parseBoardUnits( T_trace_clearance ) );
  616. NeedRIGHT();
  617. break;
  618. case T_zone_clearance:
  619. zoneSettings.m_ZoneClearance = parseBoardUnits( T_zone_clearance );
  620. NeedRIGHT();
  621. break;
  622. case T_zone_45_only:
  623. zoneSettings.m_Zone_45_Only = parseBool();
  624. NeedRIGHT();
  625. break;
  626. case T_trace_min:
  627. designSettings.m_TrackMinWidth = parseBoardUnits( T_trace_min );
  628. NeedRIGHT();
  629. break;
  630. case T_segment_width:
  631. designSettings.m_DrawSegmentWidth = parseBoardUnits( T_segment_width );
  632. NeedRIGHT();
  633. break;
  634. case T_edge_width:
  635. designSettings.m_EdgeSegmentWidth = parseBoardUnits( T_edge_width );
  636. NeedRIGHT();
  637. break;
  638. case T_via_size:
  639. defaultNetclass->SetViaDiameter( parseBoardUnits( T_via_size ) );
  640. NeedRIGHT();
  641. break;
  642. case T_via_drill:
  643. defaultNetclass->SetViaDrill( parseBoardUnits( T_via_drill ) );
  644. NeedRIGHT();
  645. break;
  646. case T_via_min_size:
  647. designSettings.m_ViasMinSize = parseBoardUnits( T_via_min_size );
  648. NeedRIGHT();
  649. break;
  650. case T_via_min_drill:
  651. designSettings.m_ViasMinDrill = parseBoardUnits( T_via_min_drill );
  652. NeedRIGHT();
  653. break;
  654. case T_user_via:
  655. {
  656. int viaSize = parseBoardUnits( "user via size" );
  657. int viaDrill = parseBoardUnits( "user via drill" );
  658. m_board->m_ViasDimensionsList.push_back( VIA_DIMENSION( viaSize, viaDrill ) );
  659. NeedRIGHT();
  660. }
  661. break;
  662. case T_uvia_size:
  663. defaultNetclass->SetuViaDiameter( parseBoardUnits( T_uvia_size ) );
  664. NeedRIGHT();
  665. break;
  666. case T_uvia_drill:
  667. defaultNetclass->SetuViaDrill( parseBoardUnits( T_uvia_drill ) );
  668. NeedRIGHT();
  669. break;
  670. case T_uvias_allowed:
  671. designSettings.m_MicroViasAllowed = parseBool();
  672. NeedRIGHT();
  673. break;
  674. case T_uvia_min_size:
  675. designSettings.m_MicroViasMinSize = parseBoardUnits( T_uvia_min_size );
  676. NeedRIGHT();
  677. break;
  678. case T_uvia_min_drill:
  679. designSettings.m_MicroViasMinDrill = parseBoardUnits( T_uvia_min_drill );
  680. NeedRIGHT();
  681. break;
  682. case T_pcb_text_width:
  683. designSettings.m_PcbTextWidth = parseBoardUnits( T_pcb_text_width );
  684. NeedRIGHT();
  685. break;
  686. case T_pcb_text_size:
  687. designSettings.m_PcbTextSize.x = parseBoardUnits( "pcb text width" );
  688. designSettings.m_PcbTextSize.y = parseBoardUnits( "pcb text height" );
  689. NeedRIGHT();
  690. break;
  691. case T_mod_edge_width:
  692. designSettings.m_ModuleSegmentWidth = parseBoardUnits( T_mod_edge_width );
  693. NeedRIGHT();
  694. break;
  695. case T_mod_text_size:
  696. designSettings.m_ModuleTextSize.x = parseBoardUnits( "module text width" );
  697. designSettings.m_ModuleTextSize.y = parseBoardUnits( "module text height" );
  698. NeedRIGHT();
  699. break;
  700. case T_mod_text_width:
  701. designSettings.m_ModuleTextWidth = parseBoardUnits( T_mod_text_width );
  702. NeedRIGHT();
  703. break;
  704. case T_pad_size:
  705. {
  706. wxSize sz;
  707. sz.SetWidth( parseBoardUnits( "master pad width" ) );
  708. sz.SetHeight( parseBoardUnits( "master pad height" ) );
  709. designSettings.m_Pad_Master.SetSize( sz );
  710. NeedRIGHT();
  711. break;
  712. }
  713. case T_pad_drill:
  714. {
  715. int drillSize = parseBoardUnits( T_pad_drill );
  716. designSettings.m_Pad_Master.SetDrillSize( wxSize( drillSize, drillSize ) );
  717. NeedRIGHT();
  718. }
  719. break;
  720. case T_pad_to_mask_clearance:
  721. designSettings.m_SolderMaskMargin = parseBoardUnits( T_pad_to_mask_clearance );
  722. NeedRIGHT();
  723. break;
  724. case T_solder_mask_min_width:
  725. designSettings.m_SolderMaskMinWidth = parseBoardUnits( T_solder_mask_min_width );
  726. NeedRIGHT();
  727. break;
  728. case T_pad_to_paste_clearance:
  729. designSettings.m_SolderPasteMargin = parseBoardUnits( T_pad_to_paste_clearance );
  730. NeedRIGHT();
  731. break;
  732. case T_pad_to_paste_clearance_ratio:
  733. designSettings.m_SolderPasteMarginRatio = parseDouble( T_pad_to_paste_clearance_ratio );
  734. NeedRIGHT();
  735. break;
  736. case T_aux_axis_origin:
  737. {
  738. int x = parseBoardUnits( "auxiliary origin X" );
  739. int y = parseBoardUnits( "auxiliary origin Y" );
  740. // x, y are not evaluated left to right, since they are push on stack right to left
  741. m_board->SetOriginAxisPosition( wxPoint( x, y ) );
  742. NeedRIGHT();
  743. break;
  744. }
  745. case T_visible_elements:
  746. designSettings.SetVisibleElements( parseHex() );
  747. NeedRIGHT();
  748. break;
  749. case T_pcbplotparams:
  750. {
  751. PCB_PLOT_PARAMS plotParams;
  752. PCB_PLOT_PARAMS_PARSER parser( reader );
  753. plotParams.Parse( &parser );
  754. m_board->SetPlotOptions( plotParams );
  755. // I don't know why but this seems to fix a problem in PCB_PLOT_PARAMS::Parse().
  756. NextTok();
  757. break;
  758. }
  759. default:
  760. Unexpected( CurText() );
  761. }
  762. }
  763. m_board->SetDesignSettings( designSettings );
  764. m_board->SetZoneSettings( zoneSettings );
  765. // Until such time as the *.brd file does not have the
  766. // global parameters:
  767. // "last_trace_width", "trace_min_width", "via_size", "via_drill",
  768. // "via_min_size", and "via_clearance", put those same global
  769. // values into the default NETCLASS until later board load
  770. // code should override them. *.kicad_brd files which have been
  771. // saved with knowledge of NETCLASSes will override these
  772. // defaults, old boards will not.
  773. //
  774. // @todo: I expect that at some point we can remove said global
  775. // parameters from the *.brd file since the ones in the
  776. // default netclass serve the same purpose. If needed
  777. // at all, the global defaults should go into a preferences
  778. // file instead so they are there to start new board
  779. // projects.
  780. m_board->m_NetClasses.GetDefault()->SetParams();
  781. }
  782. void PCB_PARSER::parseNETINFO_ITEM() throw( IO_ERROR, PARSE_ERROR )
  783. {
  784. wxCHECK_RET( CurTok() == T_net,
  785. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as net." ) );
  786. int number = parseInt( "net number" );
  787. NeedSYMBOLorNUMBER();
  788. wxString name = FromUTF8();
  789. NeedRIGHT();
  790. // net 0 should be already in list, so store this net
  791. // if it is not the net 0, or if the net 0 does not exists.
  792. // (TODO: a better test.)
  793. if( number > 0 || m_board->FindNet( 0 ) == NULL )
  794. {
  795. NETINFO_ITEM* net = new NETINFO_ITEM( m_board );
  796. net->SetNet( number );
  797. net->SetNetname( name );
  798. m_board->AppendNet( net );
  799. }
  800. }
  801. void PCB_PARSER::parseNETCLASS() throw( IO_ERROR, PARSE_ERROR )
  802. {
  803. wxCHECK_RET( CurTok() == T_net_class,
  804. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as net class." ) );
  805. T token;
  806. auto_ptr<NETCLASS> nc( new NETCLASS( m_board, wxEmptyString ) );
  807. NeedSYMBOL();
  808. nc->SetName( FromUTF8() );
  809. NeedSYMBOL();
  810. nc->SetDescription( FromUTF8() );
  811. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  812. {
  813. if( token != T_LEFT )
  814. Expecting( T_LEFT );
  815. token = NextTok();
  816. switch( token )
  817. {
  818. case T_clearance:
  819. nc->SetClearance( parseBoardUnits( T_clearance ) );
  820. break;
  821. case T_trace_width:
  822. nc->SetTrackWidth( parseBoardUnits( T_trace_width ) );
  823. break;
  824. case T_via_dia:
  825. nc->SetViaDiameter( parseBoardUnits( T_via_dia ) );
  826. break;
  827. case T_via_drill:
  828. nc->SetViaDrill( parseBoardUnits( T_via_drill ) );
  829. break;
  830. case T_uvia_dia:
  831. nc->SetuViaDiameter( parseBoardUnits( T_uvia_dia ) );
  832. break;
  833. case T_uvia_drill:
  834. nc->SetuViaDrill( parseBoardUnits( T_uvia_drill ) );
  835. break;
  836. case T_add_net:
  837. NeedSYMBOLorNUMBER();
  838. nc->Add( FromUTF8() );
  839. break;
  840. default:
  841. Expecting( "clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, or add_net" );
  842. }
  843. NeedRIGHT();
  844. }
  845. if( m_board->m_NetClasses.Add( nc.get() ) )
  846. {
  847. nc.release();
  848. }
  849. else
  850. {
  851. // Must have been a name conflict, this is a bad board file.
  852. // User may have done a hand edit to the file.
  853. // auto_ptr will delete nc on this code path
  854. wxString error;
  855. error.Printf( _( "duplicate NETCLASS name '%s' in file %s at line %d, offset %d" ),
  856. nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(), CurOffset() );
  857. THROW_IO_ERROR( error );
  858. }
  859. }
  860. DRAWSEGMENT* PCB_PARSER::parseDRAWSEGMENT() throw( IO_ERROR, PARSE_ERROR )
  861. {
  862. wxCHECK_MSG( CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
  863. CurTok() == T_gr_line || CurTok() == T_gr_poly, NULL,
  864. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as DRAWSEGMENT." ) );
  865. T token;
  866. wxPoint pt;
  867. auto_ptr< DRAWSEGMENT > segment( new DRAWSEGMENT( NULL ) );
  868. switch( CurTok() )
  869. {
  870. case T_gr_arc:
  871. segment->SetShape( S_ARC );
  872. NeedLEFT();
  873. token = NextTok();
  874. if( token != T_start )
  875. Expecting( T_start );
  876. pt.x = parseBoardUnits( "X coordinate" );
  877. pt.y = parseBoardUnits( "Y coordinate" );
  878. segment->SetStart( pt );
  879. NeedRIGHT();
  880. NeedLEFT();
  881. token = NextTok();
  882. if( token != T_end )
  883. Expecting( T_end );
  884. pt.x = parseBoardUnits( "X coordinate" );
  885. pt.y = parseBoardUnits( "Y coordinate" );
  886. segment->SetEnd( pt );
  887. NeedRIGHT();
  888. break;
  889. case T_gr_circle:
  890. segment->SetShape( S_CIRCLE );
  891. NeedLEFT();
  892. token = NextTok();
  893. if( token != T_center )
  894. Expecting( T_center );
  895. pt.x = parseBoardUnits( "X coordinate" );
  896. pt.y = parseBoardUnits( "Y coordinate" );
  897. segment->SetStart( pt );
  898. NeedRIGHT();
  899. NeedLEFT();
  900. token = NextTok();
  901. if( token != T_end )
  902. Expecting( T_end );
  903. pt.x = parseBoardUnits( "X coordinate" );
  904. pt.y = parseBoardUnits( "Y coordinate" );
  905. segment->SetEnd( pt );
  906. NeedRIGHT();
  907. break;
  908. case T_gr_curve:
  909. segment->SetShape( S_CURVE );
  910. NeedLEFT();
  911. token = NextTok();
  912. if( token != T_pts )
  913. Expecting( T_pts );
  914. segment->SetStart( parseXY() );
  915. segment->SetBezControl1( parseXY() );
  916. segment->SetBezControl2( parseXY() );
  917. segment->SetEnd( parseXY() );
  918. NeedRIGHT();
  919. break;
  920. case T_gr_line:
  921. // Default DRAWSEGMENT type is S_SEGMENT.
  922. NeedLEFT();
  923. token = NextTok();
  924. if( token != T_start )
  925. Expecting( T_start );
  926. pt.x = parseBoardUnits( "X coordinate" );
  927. pt.y = parseBoardUnits( "Y coordinate" );
  928. segment->SetStart( pt );
  929. NeedRIGHT();
  930. NeedLEFT();
  931. token = NextTok();
  932. if( token != T_end )
  933. Expecting( T_end );
  934. pt.x = parseBoardUnits( "X coordinate" );
  935. pt.y = parseBoardUnits( "Y coordinate" );
  936. segment->SetEnd( pt );
  937. NeedRIGHT();
  938. break;
  939. case T_gr_poly:
  940. {
  941. segment->SetShape( S_POLYGON );
  942. NeedLEFT();
  943. token = NextTok();
  944. if( token != T_pts )
  945. Expecting( T_pts );
  946. std::vector< wxPoint > pts;
  947. while( (token = NextTok()) != T_RIGHT )
  948. pts.push_back( parseXY() );
  949. segment->SetPolyPoints( pts );
  950. }
  951. break;
  952. default:
  953. Expecting( "gr_arc, gr_circle, gr_curve, gr_line, or gr_poly" );
  954. }
  955. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  956. {
  957. if( token != T_LEFT )
  958. Expecting( T_LEFT );
  959. token = NextTok();
  960. switch( token )
  961. {
  962. case T_angle:
  963. segment->SetAngle( parseDouble( "segment angle" ) * 10.0 );
  964. break;
  965. case T_layer:
  966. segment->SetLayer( parseBoardItemLayer() );
  967. break;
  968. case T_width:
  969. segment->SetWidth( parseBoardUnits( T_width ) );
  970. break;
  971. case T_tstamp:
  972. segment->SetTimeStamp( parseHex() );
  973. break;
  974. case T_status:
  975. segment->SetStatus( parseHex() );
  976. break;
  977. default:
  978. Expecting( "layer, width, tstamp, or status" );
  979. }
  980. NeedRIGHT();
  981. }
  982. return segment.release();
  983. }
  984. TEXTE_PCB* PCB_PARSER::parseTEXTE_PCB() throw( IO_ERROR, PARSE_ERROR )
  985. {
  986. wxCHECK_MSG( CurTok() == T_gr_text, NULL,
  987. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as TEXTE_PCB." ) );
  988. T token;
  989. auto_ptr< TEXTE_PCB > text( new TEXTE_PCB( m_board ) );
  990. NeedSYMBOLorNUMBER();
  991. text->SetText( FromUTF8() );
  992. NeedLEFT();
  993. token = NextTok();
  994. if( token != T_at )
  995. Expecting( T_at );
  996. wxPoint pt;
  997. pt.x = parseBoardUnits( "X coordinate" );
  998. pt.y = parseBoardUnits( "Y coordinate" );
  999. text->SetPosition( pt );
  1000. // If there is no orientation defined, then it is the default value of 0 degrees.
  1001. token = NextTok();
  1002. if( token == T_NUMBER )
  1003. {
  1004. text->SetOrientation( parseDouble() * 10.0 );
  1005. NeedRIGHT();
  1006. }
  1007. else if( token != T_RIGHT )
  1008. {
  1009. Unexpected( CurText() );
  1010. }
  1011. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1012. {
  1013. if( token != T_LEFT )
  1014. Expecting( T_LEFT );
  1015. token = NextTok();
  1016. switch( token )
  1017. {
  1018. case T_layer:
  1019. text->SetLayer( parseBoardItemLayer() );
  1020. NeedRIGHT();
  1021. break;
  1022. case T_tstamp:
  1023. text->SetTimeStamp( parseHex() );
  1024. NeedRIGHT();
  1025. break;
  1026. case T_effects:
  1027. parseEDA_TEXT( (EDA_TEXT*) text.get() );
  1028. break;
  1029. default:
  1030. Expecting( "layer, tstamp or effects" );
  1031. }
  1032. }
  1033. return text.release();
  1034. }
  1035. DIMENSION* PCB_PARSER::parseDIMENSION() throw( IO_ERROR, PARSE_ERROR )
  1036. {
  1037. wxCHECK_MSG( CurTok() == T_dimension, NULL,
  1038. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as DIMENSION." ) );
  1039. T token;
  1040. auto_ptr< DIMENSION > dimension( new DIMENSION( NULL ) );
  1041. dimension->m_Value = parseBoardUnits( "dimension value" );
  1042. NeedLEFT();
  1043. token = NextTok();
  1044. if( token != T_width )
  1045. Expecting( T_width );
  1046. dimension->SetWidth( parseBoardUnits( "dimension width value" ) );
  1047. NeedRIGHT();
  1048. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1049. {
  1050. if( token != T_LEFT )
  1051. Expecting( T_LEFT );
  1052. token = NextTok();
  1053. switch( token )
  1054. {
  1055. case T_layer:
  1056. dimension->SetLayer( parseBoardItemLayer() );
  1057. NeedRIGHT();
  1058. break;
  1059. case T_tstamp:
  1060. dimension->SetTimeStamp( parseHex() );
  1061. NeedRIGHT();
  1062. break;
  1063. case T_gr_text:
  1064. {
  1065. TEXTE_PCB* text = parseTEXTE_PCB();
  1066. dimension->m_Text = *text;
  1067. delete text;
  1068. break;
  1069. }
  1070. case T_feature1:
  1071. NeedLEFT();
  1072. token = NextTok();
  1073. if( token != T_pts )
  1074. Expecting( T_pts );
  1075. parseXY( &dimension->m_featureLineDOx, &dimension->m_featureLineDOy );
  1076. parseXY( &dimension->m_featureLineDFx, &dimension->m_featureLineDFy );
  1077. NeedRIGHT();
  1078. NeedRIGHT();
  1079. break;
  1080. case T_feature2:
  1081. NeedLEFT();
  1082. token = NextTok();
  1083. if( token != T_pts )
  1084. Expecting( T_pts );
  1085. parseXY( &dimension->m_featureLineGOx, &dimension->m_featureLineGOy );
  1086. parseXY( &dimension->m_featureLineGFx, &dimension->m_featureLineGFy );
  1087. NeedRIGHT();
  1088. NeedRIGHT();
  1089. break;
  1090. case T_crossbar:
  1091. NeedLEFT();
  1092. token = NextTok();
  1093. if( token != T_pts )
  1094. Expecting( T_pts );
  1095. parseXY( &dimension->m_crossBarOx, &dimension->m_crossBarOy );
  1096. parseXY( &dimension->m_crossBarFx, &dimension->m_crossBarFy );
  1097. NeedRIGHT();
  1098. NeedRIGHT();
  1099. break;
  1100. case T_arrow1a:
  1101. NeedLEFT();
  1102. token = NextTok();
  1103. if( token != T_pts )
  1104. Expecting( T_pts );
  1105. parseXY( &dimension->m_arrowD1Ox, &dimension->m_arrowD1Oy );
  1106. parseXY( &dimension->m_arrowD1Fx, &dimension->m_arrowD1Fy );
  1107. NeedRIGHT();
  1108. NeedRIGHT();
  1109. break;
  1110. case T_arrow1b:
  1111. NeedLEFT();
  1112. token = NextTok();
  1113. if( token != T_pts )
  1114. Expecting( T_pts );
  1115. parseXY( &dimension->m_arrowD2Ox, &dimension->m_arrowD2Oy );
  1116. parseXY( &dimension->m_arrowD2Fx, &dimension->m_arrowD2Fy );
  1117. NeedRIGHT();
  1118. NeedRIGHT();
  1119. break;
  1120. case T_arrow2a:
  1121. NeedLEFT();
  1122. token = NextTok();
  1123. if( token != T_pts )
  1124. Expecting( T_pts );
  1125. parseXY( &dimension->m_arrowG1Ox, &dimension->m_arrowG1Oy );
  1126. parseXY( &dimension->m_arrowG1Fx, &dimension->m_arrowG1Fy );
  1127. NeedRIGHT();
  1128. NeedRIGHT();
  1129. break;
  1130. case T_arrow2b:
  1131. NeedLEFT();
  1132. token = NextTok();
  1133. if( token != T_pts )
  1134. Expecting( T_pts );
  1135. parseXY( &dimension->m_arrowG2Ox, &dimension->m_arrowG2Oy );
  1136. parseXY( &dimension->m_arrowG2Fx, &dimension->m_arrowG2Fy );
  1137. NeedRIGHT();
  1138. NeedRIGHT();
  1139. break;
  1140. default:
  1141. Expecting( "layer, tstamp, gr_text, feature1, feature2 crossbar, arrow1a, "
  1142. "arrow1b, arrow2a, or arrow2b" );
  1143. }
  1144. }
  1145. return dimension.release();
  1146. }
  1147. MODULE* PCB_PARSER::parseMODULE() throw( IO_ERROR, PARSE_ERROR )
  1148. {
  1149. wxCHECK_MSG( CurTok() == T_module, NULL,
  1150. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as MODULE." ) );
  1151. wxPoint pt;
  1152. T token;
  1153. auto_ptr< MODULE > module( new MODULE( m_board ) );
  1154. NeedSYMBOL();
  1155. module->SetLibRef( FromUTF8() );
  1156. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1157. {
  1158. if( token == T_LEFT )
  1159. token = NextTok();
  1160. switch( token )
  1161. {
  1162. case T_locked:
  1163. module->SetLocked( true );
  1164. break;
  1165. case T_placed:
  1166. module->SetIsPlaced( true );
  1167. break;
  1168. case T_layer:
  1169. module->SetLayer( parseBoardItemLayer() );
  1170. NeedRIGHT();
  1171. break;
  1172. case T_tedit:
  1173. module->SetLastEditTime( parseHex() );
  1174. NeedRIGHT();
  1175. break;
  1176. case T_tstamp:
  1177. module->SetTimeStamp( parseHex() );
  1178. NeedRIGHT();
  1179. break;
  1180. case T_at:
  1181. pt.x = parseBoardUnits( "X coordinate" );
  1182. pt.y = parseBoardUnits( "Y coordinate" );
  1183. module->SetPosition( pt );
  1184. token = NextTok();
  1185. if( token == T_NUMBER )
  1186. {
  1187. module->SetOrientation( parseDouble() * 10.0 );
  1188. NeedRIGHT();
  1189. }
  1190. else if( token != T_RIGHT )
  1191. {
  1192. Expecting( T_RIGHT );
  1193. }
  1194. break;
  1195. case T_descr:
  1196. NeedSYMBOLorNUMBER(); // some symbols can be 0508, so a number is also a symbol here
  1197. module->SetDescription( FromUTF8() );
  1198. NeedRIGHT();
  1199. break;
  1200. case T_tags:
  1201. NeedSYMBOLorNUMBER(); // some symbols can be 0508, so a number is also a symbol here
  1202. module->SetKeywords( FromUTF8() );
  1203. NeedRIGHT();
  1204. break;
  1205. case T_path:
  1206. NeedSYMBOL();
  1207. module->SetPath( FromUTF8() );
  1208. NeedRIGHT();
  1209. break;
  1210. case T_autoplace_cost90:
  1211. module->m_CntRot90 = parseInt( "auto place cost at 90 degrees" );
  1212. NeedRIGHT();
  1213. break;
  1214. case T_autoplace_cost180:
  1215. module->m_CntRot180 = parseInt( "auto place cost at 180 degrees" );
  1216. NeedRIGHT();
  1217. break;
  1218. case T_solder_mask_margin:
  1219. module->SetLocalSolderMaskMargin( parseBoardUnits( "local solder mask margin value" ) );
  1220. NeedRIGHT();
  1221. break;
  1222. case T_solder_paste_margin:
  1223. module->SetLocalSolderPasteMargin(
  1224. parseBoardUnits( "local solder paste margin value" ) );
  1225. NeedRIGHT();
  1226. break;
  1227. case T_solder_paste_ratio:
  1228. module->SetLocalSolderPasteMarginRatio(
  1229. parseDouble( "local solder paste margin ratio value" ) );
  1230. NeedRIGHT();
  1231. break;
  1232. case T_clearance:
  1233. module->SetLocalClearance( parseBoardUnits( "local clearance value" ) );
  1234. NeedRIGHT();
  1235. break;
  1236. case T_zone_connect:
  1237. module->SetZoneConnection( (ZoneConnection) parseInt( "zone connection value" ) );
  1238. NeedRIGHT();
  1239. break;
  1240. case T_thermal_width:
  1241. module->SetThermalWidth( parseBoardUnits( "thermal width value" ) );
  1242. NeedRIGHT();
  1243. break;
  1244. case T_thermal_gap:
  1245. module->SetThermalGap( parseBoardUnits( "thermal gap value" ) );
  1246. NeedRIGHT();
  1247. break;
  1248. case T_attr:
  1249. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1250. {
  1251. switch( token )
  1252. {
  1253. case T_smd:
  1254. module->SetAttributes( module->GetAttributes() | MOD_CMS );
  1255. break;
  1256. case T_virtual:
  1257. module->SetAttributes( module->GetAttributes() | MOD_VIRTUAL );
  1258. break;
  1259. default:
  1260. Expecting( "smd and/or virtual" );
  1261. }
  1262. }
  1263. break;
  1264. case T_fp_text:
  1265. {
  1266. TEXTE_MODULE* text = parseTEXTE_MODULE();
  1267. text->SetParent( module.get() );
  1268. double orientation = text->GetOrientation();
  1269. orientation -= module->GetOrientation();
  1270. text->SetOrientation( orientation );
  1271. text->SetDrawCoord();
  1272. if( text->GetType() == TEXT_is_REFERENCE )
  1273. {
  1274. module->Reference() = *text;
  1275. delete text;
  1276. }
  1277. else if( text->GetType() == TEXT_is_VALUE )
  1278. {
  1279. module->Value() = *text;
  1280. delete text;
  1281. }
  1282. else
  1283. {
  1284. module->m_Drawings.PushBack( text );
  1285. }
  1286. break;
  1287. }
  1288. case T_fp_arc:
  1289. case T_fp_circle:
  1290. case T_fp_curve:
  1291. case T_fp_line:
  1292. case T_fp_poly:
  1293. {
  1294. EDGE_MODULE* em = parseEDGE_MODULE();
  1295. em->SetParent( module.get() );
  1296. em->SetDrawCoord();
  1297. module->m_Drawings.PushBack( em );
  1298. break;
  1299. }
  1300. case T_pad:
  1301. {
  1302. D_PAD* pad = parseD_PAD();
  1303. wxPoint pt = pad->GetPos0();
  1304. RotatePoint( &pt, module->GetOrientation() );
  1305. pad->SetPosition( pt + module->GetPosition() );
  1306. module->AddPad( pad );
  1307. break;
  1308. }
  1309. case T_model:
  1310. module->Add3DModel( parse3DModel() );
  1311. break;
  1312. default:
  1313. Expecting( "locked, placed, tedit, tstamp, at, descr, tags, path, "
  1314. "autoplace_cost90, autoplace_cost180, solder_mask_margin, "
  1315. "solder_paste_margin, solder_paste_ratio, clearance, "
  1316. "zone_connect, thermal_width, thermal_gap, attr, fp_text, "
  1317. "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, pad, or model" );
  1318. }
  1319. }
  1320. module->CalculateBoundingBox();
  1321. return module.release();
  1322. }
  1323. TEXTE_MODULE* PCB_PARSER::parseTEXTE_MODULE() throw( IO_ERROR, PARSE_ERROR )
  1324. {
  1325. wxCHECK_MSG( CurTok() == T_fp_text, NULL,
  1326. wxString::Format( wxT( "Cannot parse %s as TEXTE_MODULE at line %d, offset %d." ),
  1327. GetChars( GetTokenString( CurTok() ) ),
  1328. CurLineNumber(), CurOffset() ) );
  1329. T token = NextTok();
  1330. auto_ptr< TEXTE_MODULE > text( new TEXTE_MODULE( NULL ) );
  1331. switch( token )
  1332. {
  1333. case T_reference:
  1334. text->SetType( TEXT_is_REFERENCE );
  1335. break;
  1336. case T_value:
  1337. text->SetType( TEXT_is_VALUE );
  1338. break;
  1339. case T_user:
  1340. break; // Default type is user text.
  1341. default:
  1342. THROW_IO_ERROR( wxString::Format( _( "cannot handle module text type %s" ),
  1343. GetChars( FromUTF8() ) ) );
  1344. }
  1345. NeedSYMBOLorNUMBER();
  1346. text->SetText( FromUTF8() );
  1347. NeedLEFT();
  1348. token = NextTok();
  1349. if( token != T_at )
  1350. Expecting( T_at );
  1351. wxPoint pt;
  1352. pt.x = parseBoardUnits( "X coordinate" );
  1353. pt.y = parseBoardUnits( "Y coordinate" );
  1354. text->SetPos0( pt );
  1355. token = NextTok();
  1356. // If there is no orientation defined, then it is the default value of 0 degrees.
  1357. if( token == T_NUMBER )
  1358. {
  1359. text->SetOrientation( parseDouble() * 10.0 );
  1360. NeedRIGHT();
  1361. }
  1362. else if( token != T_RIGHT )
  1363. {
  1364. Unexpected( CurText() );
  1365. }
  1366. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1367. {
  1368. if( token == T_LEFT )
  1369. token = NextTok();
  1370. switch( token )
  1371. {
  1372. case T_layer:
  1373. text->SetLayer( parseBoardItemLayer() );
  1374. NeedRIGHT();
  1375. break;
  1376. case T_hide:
  1377. text->SetVisible( false );
  1378. break;
  1379. case T_effects:
  1380. parseEDA_TEXT( (EDA_TEXT*) text.get() );
  1381. break;
  1382. default:
  1383. Expecting( "hide or effects" );
  1384. }
  1385. }
  1386. return text.release();
  1387. }
  1388. EDGE_MODULE* PCB_PARSER::parseEDGE_MODULE() throw( IO_ERROR, PARSE_ERROR )
  1389. {
  1390. wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
  1391. CurTok() == T_fp_line || CurTok() == T_fp_poly, NULL,
  1392. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as EDGE_MODULE." ) );
  1393. wxPoint pt;
  1394. T token;
  1395. auto_ptr< EDGE_MODULE > segment( new EDGE_MODULE( NULL ) );
  1396. switch( CurTok() )
  1397. {
  1398. case T_fp_arc:
  1399. segment->SetShape( S_ARC );
  1400. NeedLEFT();
  1401. token = NextTok();
  1402. if( token != T_start )
  1403. Expecting( T_start );
  1404. pt.x = parseBoardUnits( "X coordinate" );
  1405. pt.y = parseBoardUnits( "Y coordinate" );
  1406. segment->SetStart0( pt );
  1407. NeedRIGHT();
  1408. NeedLEFT();
  1409. token = NextTok();
  1410. if( token != T_end )
  1411. Expecting( T_end );
  1412. pt.x = parseBoardUnits( "X coordinate" );
  1413. pt.y = parseBoardUnits( "Y coordinate" );
  1414. segment->SetEnd0( pt );
  1415. NeedRIGHT();
  1416. NeedLEFT();
  1417. token = NextTok();
  1418. if( token != T_angle )
  1419. Expecting( T_angle );
  1420. segment->SetAngle( parseDouble( "segment angle" ) );
  1421. NeedRIGHT();
  1422. break;
  1423. case T_fp_circle:
  1424. segment->SetShape( S_CIRCLE );
  1425. NeedLEFT();
  1426. token = NextTok();
  1427. if( token != T_center )
  1428. Expecting( T_center );
  1429. pt.x = parseBoardUnits( "X coordinate" );
  1430. pt.y = parseBoardUnits( "Y coordinate" );
  1431. segment->SetStart0( pt );
  1432. NeedRIGHT();
  1433. NeedLEFT();
  1434. token = NextTok();
  1435. if( token != T_end )
  1436. Expecting( T_end );
  1437. pt.x = parseBoardUnits( "X coordinate" );
  1438. pt.y = parseBoardUnits( "Y coordinate" );
  1439. segment->SetEnd0( pt );
  1440. NeedRIGHT();
  1441. break;
  1442. case T_fp_curve:
  1443. segment->SetShape( S_CURVE );
  1444. NeedLEFT();
  1445. token = NextTok();
  1446. if( token != T_pts )
  1447. Expecting( T_pts );
  1448. segment->SetStart0( parseXY() );
  1449. segment->SetBezControl1( parseXY() );
  1450. segment->SetBezControl2( parseXY() );
  1451. segment->SetEnd0( parseXY() );
  1452. NeedRIGHT();
  1453. break;
  1454. case T_fp_line:
  1455. // Default DRAWSEGMENT type is S_SEGMENT.
  1456. NeedLEFT();
  1457. token = NextTok();
  1458. if( token != T_start )
  1459. Expecting( T_start );
  1460. pt.x = parseBoardUnits( "X coordinate" );
  1461. pt.y = parseBoardUnits( "Y coordinate" );
  1462. segment->SetStart0( pt );
  1463. NeedRIGHT();
  1464. NeedLEFT();
  1465. token = NextTok();
  1466. if( token != T_end )
  1467. Expecting( T_end );
  1468. pt.x = parseBoardUnits( "X coordinate" );
  1469. pt.y = parseBoardUnits( "Y coordinate" );
  1470. segment->SetEnd0( pt );
  1471. NeedRIGHT();
  1472. break;
  1473. case T_fp_poly:
  1474. {
  1475. segment->SetShape( S_POLYGON );
  1476. NeedLEFT();
  1477. token = NextTok();
  1478. if( token != T_pts )
  1479. Expecting( T_pts );
  1480. std::vector< wxPoint > pts;
  1481. while( (token = NextTok()) != T_RIGHT )
  1482. pts.push_back( parseXY() );
  1483. segment->SetPolyPoints( pts );
  1484. }
  1485. break;
  1486. default:
  1487. Expecting( "fp_arc, fp_circle, fp_curve, fp_line, or fp_poly" );
  1488. }
  1489. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1490. {
  1491. if( token != T_LEFT )
  1492. Expecting( T_LEFT );
  1493. token = NextTok();
  1494. switch( token )
  1495. {
  1496. case T_layer:
  1497. segment->SetLayer( parseBoardItemLayer() );
  1498. break;
  1499. case T_width:
  1500. segment->SetWidth( parseBoardUnits( T_width ) );
  1501. break;
  1502. case T_tstamp:
  1503. segment->SetTimeStamp( parseHex() );
  1504. break;
  1505. case T_status:
  1506. segment->SetStatus( parseHex() );
  1507. break;
  1508. default:
  1509. Expecting( "layer, width, tstamp, or status" );
  1510. }
  1511. NeedRIGHT();
  1512. }
  1513. return segment.release();
  1514. }
  1515. D_PAD* PCB_PARSER::parseD_PAD() throw( IO_ERROR, PARSE_ERROR )
  1516. {
  1517. wxCHECK_MSG( CurTok() == T_pad, NULL,
  1518. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as D_PAD." ) );
  1519. wxSize sz;
  1520. wxPoint pt;
  1521. auto_ptr< D_PAD > pad( new D_PAD( NULL ) );
  1522. NeedSYMBOLorNUMBER();
  1523. pad->SetPadName( FromUTF8() );
  1524. T token = NextTok();
  1525. switch( token )
  1526. {
  1527. case T_thru_hole:
  1528. pad->SetAttribute( PAD_STANDARD );
  1529. break;
  1530. case T_smd:
  1531. pad->SetAttribute( PAD_SMD );
  1532. break;
  1533. case T_connect:
  1534. pad->SetAttribute( PAD_CONN );
  1535. break;
  1536. case T_np_thru_hole:
  1537. pad->SetAttribute( PAD_HOLE_NOT_PLATED );
  1538. break;
  1539. default:
  1540. Expecting( "thru_hole, smd, connect, or np_thru_hole" );
  1541. }
  1542. token = NextTok();
  1543. switch( token )
  1544. {
  1545. case T_circle:
  1546. pad->SetShape( PAD_CIRCLE );
  1547. break;
  1548. case T_rect:
  1549. pad->SetShape( PAD_RECT );
  1550. break;
  1551. case T_oval:
  1552. pad->SetShape( PAD_OVAL );
  1553. break;
  1554. case T_trapezoid:
  1555. pad->SetShape( PAD_TRAPEZOID );
  1556. break;
  1557. default:
  1558. Expecting( "circle, rectangle, oval, or trapezoid" );
  1559. }
  1560. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1561. {
  1562. if( token != T_LEFT )
  1563. Expecting( T_LEFT );
  1564. token = NextTok();
  1565. switch( token )
  1566. {
  1567. case T_size:
  1568. sz.SetWidth( parseBoardUnits( "width value" ) );
  1569. sz.SetHeight( parseBoardUnits( "height value" ) );
  1570. pad->SetSize( sz );
  1571. NeedRIGHT();
  1572. break;
  1573. case T_at:
  1574. pt.x = parseBoardUnits( "X coordinate" );
  1575. pt.y = parseBoardUnits( "Y coordinate" );
  1576. pad->SetPos0( pt );
  1577. token = NextTok();
  1578. if( token == T_NUMBER )
  1579. {
  1580. pad->SetOrientation( parseDouble() * 10.0 );
  1581. NeedRIGHT();
  1582. }
  1583. else if( token != T_RIGHT )
  1584. {
  1585. Expecting( ") or angle value" );
  1586. }
  1587. break;
  1588. case T_rect_delta:
  1589. {
  1590. wxSize delta;
  1591. delta.SetWidth( parseBoardUnits( "rectangle delta width" ) );
  1592. delta.SetHeight( parseBoardUnits( "rectangle delta height" ) );
  1593. pad->SetDelta( delta );
  1594. NeedRIGHT();
  1595. break;
  1596. }
  1597. case T_drill:
  1598. {
  1599. bool haveWidth = false;
  1600. wxSize drillSize = pad->GetDrillSize();
  1601. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1602. {
  1603. if( token == T_LEFT )
  1604. token = NextTok();
  1605. switch( token )
  1606. {
  1607. case T_oval:
  1608. pad->SetDrillShape( PAD_OVAL );
  1609. break;
  1610. case T_NUMBER:
  1611. {
  1612. if( !haveWidth )
  1613. {
  1614. drillSize.SetWidth( parseBoardUnits() );
  1615. // If height is not defined the width and height are the same.
  1616. drillSize.SetHeight( drillSize.GetWidth() );
  1617. haveWidth = true;
  1618. }
  1619. else
  1620. {
  1621. drillSize.SetHeight( parseBoardUnits() );
  1622. }
  1623. break;
  1624. }
  1625. case T_offset:
  1626. pad->SetOffset( wxPoint( parseBoardUnits( "drill offset x" ),
  1627. parseBoardUnits( "drill offset y" ) ) );
  1628. NeedRIGHT();
  1629. break;
  1630. default:
  1631. Expecting( "oval, size, or offset" );
  1632. }
  1633. }
  1634. pad->SetDrillSize( drillSize );
  1635. break;
  1636. }
  1637. case T_layers:
  1638. {
  1639. int layerMask = parseBoardItemLayersAsMask();
  1640. // Only the layers that are used are saved so we need to enable all the copper
  1641. // layers to prevent any problems with the current design. At some point in
  1642. // the future, the layer handling should be improved.
  1643. if( pad->GetAttribute() == PAD_STANDARD )
  1644. layerMask |= ALL_CU_LAYERS;
  1645. pad->SetLayerMask( layerMask );
  1646. break;
  1647. }
  1648. case T_net:
  1649. pad->SetNet( parseInt( "net number" ) );
  1650. NeedSYMBOLorNUMBER();
  1651. pad->SetNetname( FromUTF8() );
  1652. NeedRIGHT();
  1653. break;
  1654. case T_die_length:
  1655. pad->SetDieLength( parseBoardUnits( T_die_length ) );
  1656. NeedRIGHT();
  1657. break;
  1658. case T_solder_mask_margin:
  1659. pad->SetLocalSolderMaskMargin( parseBoardUnits( T_solder_mask_margin ) );
  1660. NeedRIGHT();
  1661. break;
  1662. case T_solder_paste_margin:
  1663. pad->SetLocalSolderPasteMargin( parseBoardUnits( T_solder_paste_margin ) );
  1664. NeedRIGHT();
  1665. break;
  1666. case T_solder_paste_margin_ratio:
  1667. pad->SetLocalSolderPasteMarginRatio( parseBoardUnits( T_solder_paste_margin_ratio ) );
  1668. NeedRIGHT();
  1669. break;
  1670. case T_clearance:
  1671. pad->SetLocalClearance( parseBoardUnits( "local clearance value" ) );
  1672. NeedRIGHT();
  1673. break;
  1674. case T_zone_connect:
  1675. pad->SetZoneConnection( (ZoneConnection) parseInt( "zone connection value" ) );
  1676. NeedRIGHT();
  1677. break;
  1678. case T_thermal_width:
  1679. pad->SetThermalWidth( parseBoardUnits( T_thermal_width ) );
  1680. NeedRIGHT();
  1681. break;
  1682. case T_thermal_gap:
  1683. pad->SetThermalGap( parseBoardUnits( T_thermal_gap ) );
  1684. NeedRIGHT();
  1685. break;
  1686. default:
  1687. Expecting( "at, drill, layers, net, die_length, solder_mask_margin, "
  1688. "solder_paste_margin, solder_paste_margin_ratio, clearance, "
  1689. "zone_connect, thermal_width, or thermal_gap" );
  1690. }
  1691. }
  1692. return pad.release();
  1693. }
  1694. TRACK* PCB_PARSER::parseTRACK() throw( IO_ERROR, PARSE_ERROR )
  1695. {
  1696. wxCHECK_MSG( CurTok() == T_segment, NULL,
  1697. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as TRACK." ) );
  1698. wxPoint pt;
  1699. T token;
  1700. auto_ptr< TRACK > track( new TRACK( m_board ) );
  1701. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1702. {
  1703. if( token != T_LEFT )
  1704. Expecting( T_LEFT );
  1705. token = NextTok();
  1706. switch( token )
  1707. {
  1708. case T_start:
  1709. pt.x = parseBoardUnits( "start x" );
  1710. pt.y = parseBoardUnits( "start y" );
  1711. track->SetStart( pt );
  1712. break;
  1713. case T_end:
  1714. pt.x = parseBoardUnits( "end x" );
  1715. pt.y = parseBoardUnits( "end y" );
  1716. track->SetEnd( pt );
  1717. break;
  1718. case T_width:
  1719. track->SetWidth( parseBoardUnits( "width" ) );
  1720. break;
  1721. case T_layer:
  1722. track->SetLayer( parseBoardItemLayer() );
  1723. break;
  1724. case T_net:
  1725. track->SetNet( parseInt( "net number" ) );
  1726. break;
  1727. case T_tstamp:
  1728. track->SetTimeStamp( parseHex() );
  1729. break;
  1730. case T_status:
  1731. track->SetStatus( parseHex() );
  1732. break;
  1733. default:
  1734. Expecting( "start, end, width, layer, net, tstamp, or status" );
  1735. }
  1736. NeedRIGHT();
  1737. }
  1738. return track.release();
  1739. }
  1740. SEGVIA* PCB_PARSER::parseSEGVIA() throw( IO_ERROR, PARSE_ERROR )
  1741. {
  1742. wxCHECK_MSG( CurTok() == T_via, NULL,
  1743. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as SEGVIA." ) );
  1744. wxPoint pt;
  1745. T token;
  1746. auto_ptr< SEGVIA > via( new SEGVIA( m_board ) );
  1747. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1748. {
  1749. if( token == T_LEFT )
  1750. token = NextTok();
  1751. switch( token )
  1752. {
  1753. case T_blind:
  1754. via->SetShape( VIA_BLIND_BURIED );
  1755. break;
  1756. case T_micro:
  1757. via->SetShape( VIA_MICROVIA );
  1758. break;
  1759. case T_at:
  1760. pt.x = parseBoardUnits( "start x" );
  1761. pt.y = parseBoardUnits( "start y" );
  1762. via->SetStart( pt );
  1763. via->SetEnd( pt );
  1764. NeedRIGHT();
  1765. break;
  1766. case T_size:
  1767. via->SetWidth( parseBoardUnits( "via width" ) );
  1768. NeedRIGHT();
  1769. break;
  1770. case T_drill:
  1771. via->SetDrill( parseBoardUnits( "drill diameter" ) );
  1772. NeedRIGHT();
  1773. break;
  1774. case T_layers:
  1775. {
  1776. int layer1, layer2;
  1777. NextTok();
  1778. layer1 = lookUpLayer();
  1779. NextTok();
  1780. layer2 = lookUpLayer();
  1781. via->SetLayerPair( layer1, layer2 );
  1782. NeedRIGHT();
  1783. }
  1784. break;
  1785. case T_net:
  1786. via->SetNet( parseInt( "net number" ) );
  1787. NeedRIGHT();
  1788. break;
  1789. case T_tstamp:
  1790. via->SetTimeStamp( parseHex() );
  1791. NeedRIGHT();
  1792. break;
  1793. case T_status:
  1794. via->SetStatus( parseHex() );
  1795. NeedRIGHT();
  1796. break;
  1797. default:
  1798. Expecting( "blind, micro, at, size, drill, layers, net, tstamp, or status" );
  1799. }
  1800. }
  1801. return via.release();
  1802. }
  1803. ZONE_CONTAINER* PCB_PARSER::parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR )
  1804. {
  1805. wxCHECK_MSG( CurTok() == T_zone, NULL,
  1806. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
  1807. wxT( " as ZONE_CONTAINER." ) );
  1808. CPolyLine::HATCH_STYLE hatchStyle = CPolyLine::NO_HATCH;
  1809. int hatchPitch = Mils2iu( CPolyLine::GetDefaultHatchPitchMils() );
  1810. wxPoint pt;
  1811. T token;
  1812. // bigger scope since each filled_polygon is concatenated in here
  1813. std::vector< CPolyPt > pts;
  1814. auto_ptr< ZONE_CONTAINER > zone( new ZONE_CONTAINER( m_board ) );
  1815. zone->SetPriority( 0 );
  1816. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1817. {
  1818. if( token == T_LEFT )
  1819. token = NextTok();
  1820. switch( token )
  1821. {
  1822. case T_net:
  1823. // Init the net code only, not the netname, to be sure
  1824. // the zone net name is the name read in file.
  1825. // (When mismatch, the user will be prompted in DRC, to fix the actual name)
  1826. zone->BOARD_CONNECTED_ITEM::SetNet( parseInt( "net number" ) );
  1827. NeedRIGHT();
  1828. break;
  1829. case T_net_name:
  1830. NeedSYMBOL();
  1831. zone->SetNetName( FromUTF8() );
  1832. NeedRIGHT();
  1833. break;
  1834. case T_layer:
  1835. zone->SetLayer( parseBoardItemLayer() );
  1836. NeedRIGHT();
  1837. break;
  1838. case T_tstamp:
  1839. zone->SetTimeStamp( parseHex() );
  1840. NeedRIGHT();
  1841. break;
  1842. case T_hatch:
  1843. token = NextTok();
  1844. if( token != T_none && token != T_edge && token != T_full )
  1845. Expecting( "none, edge, or full" );
  1846. switch( token )
  1847. {
  1848. default:
  1849. case T_none: hatchStyle = CPolyLine::NO_HATCH; break;
  1850. case T_edge: hatchStyle = CPolyLine::DIAGONAL_EDGE; break;
  1851. case T_full: hatchStyle = CPolyLine::DIAGONAL_FULL;
  1852. }
  1853. hatchPitch = parseBoardUnits( "hatch pitch" );
  1854. NeedRIGHT();
  1855. break;
  1856. case T_priority:
  1857. zone->SetPriority( parseInt( "zone priority" ) );
  1858. NeedRIGHT();
  1859. break;
  1860. case T_connect_pads:
  1861. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1862. {
  1863. if( token == T_LEFT )
  1864. token = NextTok();
  1865. switch( token )
  1866. {
  1867. case T_yes:
  1868. zone->SetPadConnection( PAD_IN_ZONE );
  1869. break;
  1870. case T_no:
  1871. zone->SetPadConnection( PAD_NOT_IN_ZONE );
  1872. break;
  1873. case T_thru_hole_only:
  1874. zone->SetPadConnection( THT_THERMAL );
  1875. break;
  1876. case T_clearance:
  1877. zone->SetZoneClearance( parseBoardUnits( "zone clearance" ) );
  1878. NeedRIGHT();
  1879. break;
  1880. default:
  1881. Expecting( "yes, no, or clearance" );
  1882. }
  1883. }
  1884. break;
  1885. case T_min_thickness:
  1886. zone->SetMinThickness( parseBoardUnits( T_min_thickness ) );
  1887. NeedRIGHT();
  1888. break;
  1889. case T_fill:
  1890. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1891. {
  1892. if( token == T_LEFT )
  1893. token = NextTok();
  1894. switch( token )
  1895. {
  1896. case T_yes:
  1897. zone->SetIsFilled( true );
  1898. break;
  1899. case T_mode:
  1900. token = NextTok();
  1901. if( token != T_segment && token != T_polygon )
  1902. Expecting( "segment or polygon" );
  1903. // @todo Create an enum for fill modes.
  1904. zone->SetFillMode( token == T_polygon ? 0 : 1 );
  1905. break;
  1906. case T_arc_segments:
  1907. zone->SetArcSegCount( parseInt( "arc segment count" ) );
  1908. break;
  1909. case T_thermal_gap:
  1910. zone->SetThermalReliefGap( parseBoardUnits( T_thermal_gap ) );
  1911. break;
  1912. case T_thermal_bridge_width:
  1913. zone->SetThermalReliefCopperBridge( parseBoardUnits( T_thermal_bridge_width ) );
  1914. break;
  1915. case T_smoothing:
  1916. switch( NextTok() )
  1917. {
  1918. case T_none:
  1919. zone->SetCornerSmoothingType( ZONE_SETTINGS::SMOOTHING_NONE );
  1920. break;
  1921. case T_chamfer:
  1922. zone->SetCornerSmoothingType( ZONE_SETTINGS::SMOOTHING_CHAMFER );
  1923. break;
  1924. case T_fillet:
  1925. zone->SetCornerSmoothingType( ZONE_SETTINGS::SMOOTHING_FILLET );
  1926. break;
  1927. default:
  1928. Expecting( "none, chamfer, or fillet" );
  1929. }
  1930. break;
  1931. case T_radius:
  1932. zone->SetCornerRadius( parseBoardUnits( "corner radius" ) );
  1933. break;
  1934. default:
  1935. Expecting( "mode, arc_segments, thermal_gap, thermal_bridge_width, "
  1936. "smoothing, or radius" );
  1937. }
  1938. NeedRIGHT();
  1939. }
  1940. break;
  1941. case T_keepout:
  1942. zone->SetIsKeepout( true );
  1943. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1944. {
  1945. if( token == T_LEFT )
  1946. token = NextTok();
  1947. switch( token )
  1948. {
  1949. case T_tracks:
  1950. token = NextTok();
  1951. if( token != T_allowed && token != T_not_allowed )
  1952. Expecting( "allowed or not_allowed" );
  1953. zone->SetDoNotAllowTracks( token == T_not_allowed );
  1954. break;
  1955. case T_vias:
  1956. token = NextTok();
  1957. if( token != T_allowed && token != T_not_allowed )
  1958. Expecting( "allowed or not_allowed" );
  1959. zone->SetDoNotAllowVias( token == T_not_allowed );
  1960. break;
  1961. case T_copperpour:
  1962. token = NextTok();
  1963. if( token != T_allowed && token != T_not_allowed )
  1964. Expecting( "allowed or not_allowed" );
  1965. zone->SetDoNotAllowCopperPour( token == T_not_allowed );
  1966. break;
  1967. default:
  1968. Expecting( "tracks, vias or copperpour" );
  1969. }
  1970. NeedRIGHT();
  1971. }
  1972. break;
  1973. case T_polygon:
  1974. {
  1975. std::vector< wxPoint > corners;
  1976. NeedLEFT();
  1977. token = NextTok();
  1978. if( token != T_pts )
  1979. Expecting( T_pts );
  1980. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1981. {
  1982. corners.push_back( parseXY() );
  1983. }
  1984. NeedRIGHT();
  1985. zone->AddPolygon( corners );
  1986. }
  1987. break;
  1988. case T_filled_polygon:
  1989. {
  1990. // "(filled_polygon (pts"
  1991. NeedLEFT();
  1992. token = NextTok();
  1993. if( token != T_pts )
  1994. Expecting( T_pts );
  1995. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  1996. {
  1997. pts.push_back( CPolyPt( parseXY() ) );
  1998. }
  1999. NeedRIGHT();
  2000. pts.back().end_contour = true;
  2001. }
  2002. break;
  2003. case T_fill_segments:
  2004. {
  2005. std::vector< SEGMENT > segs;
  2006. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  2007. {
  2008. if( token != T_LEFT )
  2009. Expecting( T_LEFT );
  2010. token = NextTok();
  2011. if( token != T_pts )
  2012. Expecting( T_pts );
  2013. SEGMENT segment( parseXY(), parseXY() );
  2014. NeedRIGHT();
  2015. segs.push_back( segment );
  2016. }
  2017. zone->AddFillSegments( segs );
  2018. }
  2019. break;
  2020. default:
  2021. Expecting( "net, layer, tstamp, hatch, priority, connect_pads, min_thickness, "
  2022. "fill, polygon, filled_polygon, or fill_segments" );
  2023. }
  2024. }
  2025. if( zone->GetNumCorners() > 2 )
  2026. {
  2027. if( !zone->IsOnCopperLayer() )
  2028. {
  2029. zone->SetFillMode( 0 );
  2030. zone->SetNet( 0 );
  2031. }
  2032. // Set hatch here, after outlines corners are read
  2033. zone->m_Poly->SetHatch( hatchStyle, hatchPitch, true );
  2034. }
  2035. if( pts.size() )
  2036. zone->AddFilledPolysList( pts );
  2037. return zone.release();
  2038. }
  2039. PCB_TARGET* PCB_PARSER::parsePCB_TARGET() throw( IO_ERROR, PARSE_ERROR )
  2040. {
  2041. wxCHECK_MSG( CurTok() == T_target, NULL,
  2042. wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as PCB_TARGET." ) );
  2043. wxPoint pt;
  2044. T token;
  2045. auto_ptr< PCB_TARGET > target( new PCB_TARGET( NULL ) );
  2046. for( token = NextTok(); token != T_RIGHT; token = NextTok() )
  2047. {
  2048. if( token == T_LEFT )
  2049. token = NextTok();
  2050. switch( token )
  2051. {
  2052. case T_x:
  2053. target->SetShape( 1 );
  2054. break;
  2055. case T_plus:
  2056. target->SetShape( 0 );
  2057. break;
  2058. case T_at:
  2059. pt.x = parseBoardUnits( "target x position" );
  2060. pt.y = parseBoardUnits( "target y position" );
  2061. target->SetPosition( pt );
  2062. NeedRIGHT();
  2063. break;
  2064. case T_size:
  2065. target->SetSize( parseBoardUnits( "target size" ) );
  2066. NeedRIGHT();
  2067. break;
  2068. case T_width:
  2069. target->SetWidth( parseBoardUnits( "target thickness" ) );
  2070. NeedRIGHT();
  2071. break;
  2072. case T_layer:
  2073. target->SetLayer( parseBoardItemLayer() );
  2074. NeedRIGHT();
  2075. break;
  2076. case T_tstamp:
  2077. target->SetTimeStamp( parseHex() );
  2078. NeedRIGHT();
  2079. break;
  2080. default:
  2081. Expecting( "x, plus, at, size, width, layer or tstamp" );
  2082. }
  2083. }
  2084. return target.release();
  2085. }