KiCad PCB EDA Suite
PCB_PARSER Class Reference

Class PCB_PARSER reads a Pcbnew s-expression formatted LINE_READER object and returns the appropriate BOARD_ITEM object. More...

#include <pcb_parser.h>

Inheritance diagram for PCB_PARSER:
CLIPBOARD_PARSER

Public Member Functions

 PCB_PARSER (LINE_READER *aReader=NULL)
 
LINE_READERSetLineReader (LINE_READER *aReader)
 Function SetLineReader sets aLineReader into the parser, and returns the previous one, if any. More...
 
void SetBoard (BOARD *aBoard)
 
BOARD_ITEMParse ()
 
MODULEparseMODULE (wxArrayString *aInitialComments=0)
 Function parseMODULE. More...
 
bool IsTooRecent ()
 Return whether a version number, if any was parsed, was too recent. More...
 
wxString GetRequiredVersion ()
 Return a string representing the version of kicad required to open this file. More...
 

Private Types

typedef std::unordered_map< std::string, PCB_LAYER_IDLAYER_ID_MAP
 
typedef std::unordered_map< std::string, LSETLSET_MAP
 

Private Member Functions

int getNetCode (int aNetCode)
 

Converts net code using the mapping table if available, otherwise returns unchanged net code if < 0 or if is is out of range

More...
 
void pushValueIntoMap (int aIndex, int aValue)
 function pushValueIntoMap Add aValue value in netcode mapping (m_netCodes) at index aIndex ensure there is room in m_netCodes for that, and add room if needed. More...
 
void init ()
 Function init clears and re-establishes m_layerMap with the default layer names. More...
 
void parseHeader ()
 
void parseGeneralSection ()
 
void parsePAGE_INFO ()
 
void parseTITLE_BLOCK ()
 
void parseLayers ()
 
void parseLayer (LAYER *aLayer)
 
void parseSetup ()
 
void parseNETINFO_ITEM ()
 
void parseNETCLASS ()
 
DRAWSEGMENTparseDRAWSEGMENT (bool aAllowCirclesZeroWidth=false)
 Read a DRAWSEGMENT description. More...
 
TEXTE_PCBparseTEXTE_PCB ()
 
DIMENSIONparseDIMENSION ()
 
MODULEparseMODULE_unchecked (wxArrayString *aInitialComments=0)
 Function parseMODULE_unchecked Parse a module, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR automatically. More...
 
TEXTE_MODULEparseTEXTE_MODULE ()
 
EDGE_MODULEparseEDGE_MODULE ()
 
D_PADparseD_PAD (MODULE *aParent=NULL)
 
bool parseD_PAD_option (D_PAD *aPad)
 
TRACKparseTRACK ()
 
VIAparseVIA ()
 
ZONE_CONTAINERparseZONE_CONTAINER ()
 
PCB_TARGETparsePCB_TARGET ()
 
BOARDparseBOARD ()
 
BOARDparseBOARD_unchecked ()
 Function parseBOARD_unchecked Parse a module, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR automatically. More...
 
template<class T , class M >
lookUpLayer (const M &aMap)
 Function lookUpLayer parses the current token for the layer definition of a BOARD_ITEM object. More...
 
PCB_LAYER_ID parseBoardItemLayer ()
 Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object. More...
 
LSET parseBoardItemLayersAsMask ()
 Function parseBoardItemLayersAsMask parses the layers definition of a BOARD_ITEM object. More...
 
wxPoint parseXY ()
 Function parseXY parses a coordinate pair (xy X Y) in board units (mm). More...
 
void parseXY (int *aX, int *aY)
 
void parseEDA_TEXT (EDA_TEXT *aText)
 Function parseEDA_TEXT parses the common settings for any object derived from EDA_TEXT. More...
 
MODULE_3D_SETTINGSparse3DModel ()
 
double parseDouble ()
 Function parseDouble parses the current token as an ASCII numeric string with possible leading whitespace into a double precision floating point number. More...
 
double parseDouble (const char *aExpected)
 
double parseDouble (PCB_KEYS_T::T aToken)
 
int parseBoardUnits ()
 
int parseBoardUnits (const char *aExpected)
 
int parseBoardUnits (PCB_KEYS_T::T aToken)
 
int parseInt ()
 
int parseInt (const char *aExpected)
 
long parseHex ()
 
bool parseBool ()
 
int parseVersion ()
 Parse a format version tag like (version 20160417) return the version. More...
 

Private Attributes

BOARDm_board
 
LAYER_ID_MAP m_layerIndices
 map layer name to it's index More...
 
LSET_MAP m_layerMasks
 map layer names to their masks More...
 
std::set< wxString > m_undefinedLayers
 set of layers not defined in layers section More...
 
std::vector< int > m_netCodes
 net codes mapping for boards being loaded More...
 
bool m_tooRecent
 true if version parses as later than supported More...
 
int m_requiredVersion
 set to the KiCad format version this board requires More...
 

Detailed Description

Class PCB_PARSER reads a Pcbnew s-expression formatted LINE_READER object and returns the appropriate BOARD_ITEM object.

Definition at line 65 of file pcb_parser.h.

Member Typedef Documentation

◆ LAYER_ID_MAP

typedef std::unordered_map< std::string, PCB_LAYER_ID > PCB_PARSER::LAYER_ID_MAP
private

Definition at line 67 of file pcb_parser.h.

◆ LSET_MAP

typedef std::unordered_map< std::string, LSET > PCB_PARSER::LSET_MAP
private

Definition at line 68 of file pcb_parser.h.

Constructor & Destructor Documentation

◆ PCB_PARSER()

PCB_PARSER::PCB_PARSER ( LINE_READER aReader = NULL)
inline

Definition at line 293 of file pcb_parser.h.

293  :
294  PCB_LEXER( aReader ),
295  m_board( 0 )
296  {
297  init();
298  }
BOARD * m_board
Definition: pcb_parser.h:70
void init()
Function init clears and re-establishes m_layerMap with the default layer names.
Definition: pcb_parser.cpp:57

References init().

Member Function Documentation

◆ getNetCode()

int PCB_PARSER::getNetCode ( int  aNetCode)
inlineprivate

Converts net code using the mapping table if available, otherwise returns unchanged net code if < 0 or if is is out of range

Definition at line 80 of file pcb_parser.h.

81  {
82  if( ( aNetCode >= 0 ) && ( aNetCode < (int) m_netCodes.size() ) )
83  return m_netCodes[aNetCode];
84 
85  return aNetCode;
86  }
std::vector< int > m_netCodes
net codes mapping for boards being loaded
Definition: pcb_parser.h:74

References m_netCodes.

◆ GetRequiredVersion()

wxString PCB_PARSER::GetRequiredVersion ( )

Return a string representing the version of kicad required to open this file.

Not particularly meaningful if IsTooRecent() returns false.

Definition at line 183 of file pcb_parser.cpp.

184 {
185  int year, month, day;
186 
187  year = m_requiredVersion / 10000;
188  month = ( m_requiredVersion / 100 ) - ( year * 100 );
189  day = m_requiredVersion - ( year * 10000 ) - ( month * 100 );
190 
191  // wx throws an assertion, not a catchable exception, when the date is invalid.
192  // User input shouldn't give wx asserts, so check manually and throw a proper
193  // error instead
194  if( day <= 0 || month <= 0 || month > 12 ||
195  day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
196  {
197  wxString err;
198  err.Printf( _( "Cannot interpret date code %d" ), m_requiredVersion );
199  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
200  }
201 
202  wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
203  return date.FormatDate();
204 }
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
string & err
Definition: json11.cpp:598
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:76

References err, and THROW_PARSE_ERROR.

Referenced by CLIPBOARD_IO::Load(), PCB_IO::Load(), and PCB_IO::Parse().

◆ init()

void PCB_PARSER::init ( )
private

Function init clears and re-establishes m_layerMap with the default layer names.

m_layerMap will have some of its entries overwritten whenever a (new) board is encountered.

Definition at line 57 of file pcb_parser.cpp.

58 {
59  m_tooRecent = false;
61  m_layerIndices.clear();
62  m_layerMasks.clear();
63 
64  // Add untranslated default (i.e. english) layernames.
65  // Some may be overridden later if parsing a board rather than a footprint.
66  // The english name will survive if parsing only a footprint.
67  for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
68  {
69  std::string untranslated = TO_UTF8( wxString( LSET::Name( PCB_LAYER_ID( layer ) ) ) );
70 
71  m_layerIndices[ untranslated ] = PCB_LAYER_ID( layer );
72  m_layerMasks[ untranslated ] = LSET( PCB_LAYER_ID( layer ) );
73  }
74 
75  m_layerMasks[ "*.Cu" ] = LSET::AllCuMask();
76  m_layerMasks[ "F&B.Cu" ] = LSET( 2, F_Cu, B_Cu );
77  m_layerMasks[ "*.Adhes" ] = LSET( 2, B_Adhes, F_Adhes );
78  m_layerMasks[ "*.Paste" ] = LSET( 2, B_Paste, F_Paste );
79  m_layerMasks[ "*.Mask" ] = LSET( 2, B_Mask, F_Mask );
80  m_layerMasks[ "*.SilkS" ] = LSET( 2, B_SilkS, F_SilkS );
81  m_layerMasks[ "*.Fab" ] = LSET( 2, B_Fab, F_Fab );
82  m_layerMasks[ "*.CrtYd" ] = LSET( 2, B_CrtYd, F_CrtYd );
83 
84  // This is for the first pretty & *.kicad_pcb formats, which had
85  // Inner1_Cu - Inner14_Cu with the numbering sequence
86  // reversed from the subsequent format's In1_Cu - In30_Cu numbering scheme.
87  // The newer format brought in an additional 16 Cu layers and flipped the cu stack but
88  // kept the gap between one of the outside layers and the last cu internal.
89 
90  for( int i=1; i<=14; ++i )
91  {
92  std::string key = StrPrintf( "Inner%d.Cu", i );
93 
94  m_layerMasks[ key ] = LSET( PCB_LAYER_ID( In15_Cu - i ) );
95  }
96 
97 #if defined(DEBUG) && 0
98  printf( "m_layerMasks:\n" );
99  for( LSET_MAP::const_iterator it = m_layerMasks.begin(); it != m_layerMasks.end(); ++it )
100  {
101  printf( " [%s] == 0x%s\n", it->first.c_str(), it->second.FmtHex().c_str() );
102  }
103 
104  printf( "m_layerIndices:\n" );
105  for( LAYER_ID_MAP::const_iterator it = m_layerIndices.begin(); it != m_layerIndices.end(); ++it )
106  {
107  printf( " [%s] == %d\n", it->first.c_str(), it->second );
108  }
109 #endif
110 
111 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Function AllCuMask returns a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:676
int StrPrintf(std::string *aResult, const char *aFormat,...)
Function StrPrintf is like sprintf() but the output is appended to a std::string instead of to a char...
Definition: richio.cpp:74
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:75
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:47
PCB_LAYER_ID
A quick note on layer IDs:
Class LSET is a set of PCB_LAYER_IDs.
static const wxChar * Name(PCB_LAYER_ID aLayerId)
Function Name returns the fixed name association with aLayerId.
Definition: lset.cpp:73
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:76
size_t i
Definition: json11.cpp:597
LAYER_ID_MAP m_layerIndices
map layer name to it's index
Definition: pcb_parser.h:71
LSET_MAP m_layerMasks
map layer names to their masks
Definition: pcb_parser.h:72

References LSET::AllCuMask(), B_Adhes, B_CrtYd, B_Cu, B_Fab, B_Mask, B_Paste, B_SilkS, F_Adhes, F_CrtYd, F_Cu, F_Fab, F_Mask, F_Paste, F_SilkS, i, In15_Cu, LSET::Name(), PCB_LAYER_ID_COUNT, numEval::StrPrintf(), and TO_UTF8.

Referenced by PCB_PARSER(), and SetBoard().

◆ IsTooRecent()

bool PCB_PARSER::IsTooRecent ( )
inline

Return whether a version number, if any was parsed, was too recent.

Definition at line 333 of file pcb_parser.h.

334  {
335  return m_tooRecent;
336  }
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:75

References m_tooRecent.

Referenced by CLIPBOARD_IO::Load(), PCB_IO::Load(), and PCB_IO::Parse().

◆ lookUpLayer()

template<class T , class M >
T PCB_PARSER::lookUpLayer ( const M &  aMap)
private

Function lookUpLayer parses the current token for the layer definition of a BOARD_ITEM object.

Parameters
aMapis the LAYER_{NUM|MSK}_MAP to use for the lookup.
Exceptions
IO_ERRORif the layer is not valid.
PARSE_ERRORif the layer syntax is incorrect.
Returns
int - The result of the parsed BOARD_ITEM layer or set designator.

Definition at line 1046 of file pcb_parser.cpp.

1047 {
1048  // avoid constructing another std::string, use lexer's directly
1049  typename M::const_iterator it = aMap.find( curText );
1050 
1051  if( it == aMap.end() )
1052  {
1053 #if 0 && defined(DEBUG)
1054  // dump the whole darn table, there's something wrong with it.
1055  for( it = aMap.begin(); it != aMap.end(); ++it )
1056  {
1057  wxLogDebug( &aMap == (void*)&m_layerIndices ? wxT( "lm[%s] = %d" ) :
1058  wxT( "lm[%s] = %08X" ), it->first.c_str(), it->second );
1059  }
1060 #endif
1061 
1062  m_undefinedLayers.insert( curText );
1063  return Rescue;
1064  }
1065 
1066  return it->second;
1067 }
LAYER_ID_MAP m_layerIndices
map layer name to it's index
Definition: pcb_parser.h:71
std::set< wxString > m_undefinedLayers
set of layers not defined in layers section
Definition: pcb_parser.h:73

References Rescue.

◆ Parse()

BOARD_ITEM * PCB_PARSER::Parse ( )

Definition at line 443 of file pcb_parser.cpp.

444 {
445  T token;
446  BOARD_ITEM* item;
447  LOCALE_IO toggle;
448 
449  // MODULEs can be prefixed with an initial block of single line comments and these
450  // are kept for Format() so they round trip in s-expression form. BOARDs might
451  // eventually do the same, but currently do not.
452  std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
453 
454  token = CurTok();
455 
456  if( token != T_LEFT )
457  Expecting( T_LEFT );
458 
459  switch( NextTok() )
460  {
461  case T_kicad_pcb:
462  if( m_board == NULL )
463  m_board = new BOARD();
464 
465  item = (BOARD_ITEM*) parseBOARD();
466  break;
467 
468  case T_module:
469  item = (BOARD_ITEM*) parseMODULE( initial_comments.release() );
470  break;
471 
472  default:
473  wxString err;
474  err.Printf( _( "Unknown token \"%s\"" ), GetChars( FromUTF8() ) );
475  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
476  }
477 
478  return item;
479 }
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: common.h:180
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
BOARD * parseBOARD()
Definition: pcb_parser.cpp:482
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
string & err
Definition: json11.cpp:598
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:171
BOARD * m_board
Definition: pcb_parser.h:70
MODULE * parseMODULE(wxArrayString *aInitialComments=0)
Function parseMODULE.

References err, GetChars(), and THROW_PARSE_ERROR.

Referenced by GITHUB_PLUGIN::FootprintLoad(), CLIPBOARD_IO::Load(), PCB_IO::Load(), FP_CACHE::Load(), and PCB_IO::Parse().

◆ parse3DModel()

MODULE_3D_SETTINGS * PCB_PARSER::parse3DModel ( )
private

Definition at line 351 of file pcb_parser.cpp.

352 {
353  wxCHECK_MSG( CurTok() == T_model, NULL,
354  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as MODULE_3D_SETTINGS." ) );
355 
356  T token;
357 
359  NeedSYMBOLorNUMBER();
360  n3D->m_Filename = FromUTF8();
361 
362  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
363  {
364  if( token != T_LEFT )
365  Expecting( T_LEFT );
366 
367  token = NextTok();
368 
369  switch( token )
370  {
371  case T_at:
372  NeedLEFT();
373  token = NextTok();
374 
375  if( token != T_xyz )
376  Expecting( T_xyz );
377 
378  /* Note:
379  * Prior to KiCad v5, model offset was designated by "at",
380  * and the units were in inches.
381  * Now we use mm, but support reading of legacy files
382  */
383 
384  n3D->m_Offset.x = parseDouble( "x value" ) * 25.4f;
385  n3D->m_Offset.y = parseDouble( "y value" ) * 25.4f;
386  n3D->m_Offset.z = parseDouble( "z value" ) * 25.4f;
387  NeedRIGHT();
388  break;
389 
390  case T_offset:
391  NeedLEFT();
392  token = NextTok();
393 
394  if( token != T_xyz )
395  Expecting( T_xyz );
396 
397  /*
398  * 3D model offset is in mm
399  */
400  n3D->m_Offset.x = parseDouble( "x value" );
401  n3D->m_Offset.y = parseDouble( "y value" );
402  n3D->m_Offset.z = parseDouble( "z value" );
403  NeedRIGHT();
404  break;
405 
406  case T_scale:
407  NeedLEFT();
408  token = NextTok();
409 
410  if( token != T_xyz )
411  Expecting( T_xyz );
412 
413  n3D->m_Scale.x = parseDouble( "x value" );
414  n3D->m_Scale.y = parseDouble( "y value" );
415  n3D->m_Scale.z = parseDouble( "z value" );
416  NeedRIGHT();
417  break;
418 
419  case T_rotate:
420  NeedLEFT();
421  token = NextTok();
422 
423  if( token != T_xyz )
424  Expecting( T_xyz );
425 
426  n3D->m_Rotation.x = parseDouble( "x value" );
427  n3D->m_Rotation.y = parseDouble( "y value" );
428  n3D->m_Rotation.z = parseDouble( "z value" );
429  NeedRIGHT();
430  break;
431 
432  default:
433  Expecting( "at, offset, scale, or rotate" );
434  }
435 
436  NeedRIGHT();
437  }
438 
439  return n3D;
440 }
VECTOR3D m_Offset
3D model offset (mm)
Definition: class_module.h:101
wxString m_Filename
The 3D shape filename in 3D library.
Definition: class_module.h:102
VECTOR3D m_Rotation
3D model rotation (degrees)
Definition: class_module.h:100
VECTOR3D m_Scale
3D model scaling factor (dimensionless)
Definition: class_module.h:99
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:125

References MODULE_3D_SETTINGS::m_Filename, MODULE_3D_SETTINGS::m_Offset, MODULE_3D_SETTINGS::m_Rotation, MODULE_3D_SETTINGS::m_Scale, parseDouble(), MODULE_3D_SETTINGS::VECTOR3D::x, MODULE_3D_SETTINGS::VECTOR3D::y, and MODULE_3D_SETTINGS::VECTOR3D::z.

◆ parseBOARD()

BOARD * PCB_PARSER::parseBOARD ( )
private

Definition at line 482 of file pcb_parser.cpp.

483 {
484  try
485  {
486  return parseBOARD_unchecked();
487  }
488  catch( const PARSE_ERROR& parse_error )
489  {
490  if( m_tooRecent )
491  throw FUTURE_FORMAT_ERROR( parse_error, GetRequiredVersion() );
492  else
493  throw;
494  }
495 }
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:75
wxString GetRequiredVersion()
Return a string representing the version of kicad required to open this file.
Definition: pcb_parser.cpp:183
BOARD * parseBOARD_unchecked()
Function parseBOARD_unchecked Parse a module, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR...
Definition: pcb_parser.cpp:498
Struct PARSE_ERROR contains a filename or source description, a problem input line,...
Definition: ki_exception.h:123
Struct FUTURE_FORMAT_ERROR variant of PARSE_ERROR indicating that a syntax or related error was likel...
Definition: ki_exception.h:172

◆ parseBOARD_unchecked()

BOARD * PCB_PARSER::parseBOARD_unchecked ( )
private

Function parseBOARD_unchecked Parse a module, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR automatically.

Definition at line 498 of file pcb_parser.cpp.

499 {
500  T token;
501 
502  parseHeader();
503 
504  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
505  {
506  if( token != T_LEFT )
507  Expecting( T_LEFT );
508 
509  token = NextTok();
510 
511  switch( token )
512  {
513  case T_general:
515  break;
516 
517  case T_page:
518  parsePAGE_INFO();
519  break;
520 
521  case T_title_block:
523  break;
524 
525  case T_layers:
526  parseLayers();
527  break;
528 
529  case T_setup:
530  parseSetup();
531  break;
532 
533  case T_net:
535  break;
536 
537  case T_net_class:
538  parseNETCLASS();
539  break;
540 
541  case T_gr_arc:
542  case T_gr_circle:
543  case T_gr_curve:
544  case T_gr_line:
545  case T_gr_poly:
547  break;
548 
549  case T_gr_text:
551  break;
552 
553  case T_dimension:
555  break;
556 
557  case T_module:
559  break;
560 
561  case T_segment:
563  break;
564 
565  case T_via:
567  break;
568 
569  case T_zone:
571  break;
572 
573  case T_target:
575  break;
576 
577  default:
578  wxString err;
579  err.Printf( _( "Unknown token \"%s\"" ), GetChars( FromUTF8() ) );
580  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
581  }
582  }
583 
584  if( m_undefinedLayers.size() > 0 )
585  {
586  bool deleteItems;
587  std::vector<BOARD_ITEM*> deleteList;
588  wxString msg = wxString::Format( _( "Items found on undefined layers. Do you wish to\n"
589  "rescue them to the Cmts.User layer?" ) );
590  wxString details = wxString::Format( _( "Undefined layers:" ) );
591 
592  for( const wxString& undefinedLayer : m_undefinedLayers )
593  details += wxT( "\n " ) + undefinedLayer;
594 
595  wxRichMessageDialog dlg( nullptr, msg, _( "Warning" ),
596  wxYES_NO | wxCANCEL | wxCENTRE | wxICON_WARNING | wxSTAY_ON_TOP );
597  dlg.ShowDetailedText( details );
598  dlg.SetYesNoCancelLabels( _( "Rescue" ), _( "Delete" ), _( "Cancel" ) );
599 
600  switch( dlg.ShowModal() )
601  {
602  case wxID_YES: deleteItems = false; break;
603  case wxID_NO: deleteItems = true; break;
604  case wxID_CANCEL:
605  default: THROW_IO_ERROR( wxT( "CANCEL" ) );
606  }
607 
608  auto visitItem = [&]( BOARD_ITEM* item )
609  {
610  if( item->GetLayer() == Rescue )
611  {
612  if( deleteItems )
613  deleteList.push_back( item );
614  else
615  item->SetLayer( Cmts_User );
616  }
617  };
618 
619  for( TRACK* segm = m_board->m_Track; segm; segm = segm->Next() )
620  {
621  if( segm->Type() == PCB_VIA_T )
622  {
623  VIA* via = (VIA*) segm;
624  PCB_LAYER_ID top_layer, bottom_layer;
625 
626  if( via->GetViaType() == VIA_THROUGH )
627  continue;
628 
629  via->LayerPair( &top_layer, &bottom_layer );
630 
631  if( top_layer == Rescue || bottom_layer == Rescue )
632  {
633  if( deleteItems )
634  deleteList.push_back( via );
635  else
636  {
637  if( top_layer == Rescue )
638  top_layer = F_Cu;
639 
640  if( bottom_layer == Rescue )
641  bottom_layer = B_Cu;
642 
643  via->SetLayerPair( top_layer, bottom_layer );
644  }
645  }
646  }
647  else
648  visitItem( segm );
649  }
650 
651  for( TRACK* segm = m_board->m_SegZoneDeprecated; segm; segm = segm->Next() )
652  visitItem( segm );
653 
654  for( BOARD_ITEM* zone : m_board->Zones() )
655  visitItem( zone );
656 
657  for( BOARD_ITEM* drawing : m_board->Drawings() )
658  visitItem( drawing );
659 
660  for( BOARD_ITEM* item : deleteList )
661  m_board->Delete( item );
662 
663  m_undefinedLayers.clear();
664  }
665 
666  return m_board;
667 }
void parseHeader()
Definition: pcb_parser.cpp:670
void LayerPair(PCB_LAYER_ID *top_layer, PCB_LAYER_ID *bottom_layer) const
Function LayerPair Return the 2 layers used by the via (the via actually uses all layers between thes...
DRAWSEGMENT * parseDRAWSEGMENT(bool aAllowCirclesZeroWidth=false)
Read a DRAWSEGMENT description.
Class BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
TRACK * parseTRACK()
VIA * parseVIA()
void parseNETINFO_ITEM()
DIMENSION * parseDIMENSION()
void parseTITLE_BLOCK()
Definition: pcb_parser.cpp:808
void parseLayers()
Definition: pcb_parser.cpp:933
void parsePAGE_INFO()
Definition: pcb_parser.cpp:752
PCB_LAYER_ID
A quick note on layer IDs:
DLIST< SEGZONE > m_SegZoneDeprecated
Definition: class_board.h:251
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_INSERT) override
Adds an item to the container.
PCB_TARGET * parsePCB_TARGET()
VIATYPE_T GetViaType() const
Definition: class_track.h:461
TEXTE_PCB * parseTEXTE_PCB()
void SetLayerPair(PCB_LAYER_ID aTopLayer, PCB_LAYER_ID aBottomLayer)
Function SetLayerPair For a via m_Layer contains the top layer, the other layer is in m_BottomLayer.
#define THROW_IO_ERROR(msg)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
void parseNETCLASS()
string & err
Definition: json11.cpp:598
ZONE_CONTAINER * parseZONE_CONTAINER()
ZONE_CONTAINERS & Zones()
Definition: class_board.h:257
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
BOARD * m_board
Definition: pcb_parser.h:70
void parseGeneralSection()
Definition: pcb_parser.cpp:706
virtual void Delete(BOARD_ITEM *aItem)
Removes an item from the containter and deletes it.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:96
DLIST< TRACK > m_Track
Definition: class_board.h:250
MODULE * parseMODULE(wxArrayString *aInitialComments=0)
Function parseMODULE.
void parseSetup()
DLIST_ITERATOR_WRAPPER< BOARD_ITEM > Drawings()
Definition: class_board.h:256
std::set< wxString > m_undefinedLayers
set of layers not defined in layers section
Definition: pcb_parser.h:73

References ADD_APPEND, ADD_INSERT, B_Cu, Cmts_User, err, F_Cu, Format(), GetChars(), VIA::GetViaType(), VIA::LayerPair(), TRACK::Next(), PCB_VIA_T, Rescue, VIA::SetLayerPair(), THROW_IO_ERROR, THROW_PARSE_ERROR, and VIA_THROUGH.

◆ parseBoardItemLayer()

PCB_LAYER_ID PCB_PARSER::parseBoardItemLayer ( )
private

Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.

Exceptions
IO_ERRORif the layer is not valid.
PARSE_ERRORif the layer syntax is incorrect.
Returns
The index the parsed BOARD_ITEM layer.

Definition at line 1070 of file pcb_parser.cpp.

1071 {
1072  wxCHECK_MSG( CurTok() == T_layer, UNDEFINED_LAYER,
1073  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as layer." ) );
1074 
1075  NextTok();
1076 
1077  PCB_LAYER_ID layerIndex = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
1078 
1079  // Handle closing ) in object parser.
1080 
1081  return layerIndex;
1082 }
PCB_LAYER_ID
A quick note on layer IDs:
LAYER_ID_MAP m_layerIndices
map layer name to it's index
Definition: pcb_parser.h:71

References UNDEFINED_LAYER.

◆ parseBoardItemLayersAsMask()

LSET PCB_PARSER::parseBoardItemLayersAsMask ( )
private

Function parseBoardItemLayersAsMask parses the layers definition of a BOARD_ITEM object.

Exceptions
IO_ERRORif any of the layers is not valid.
PARSE_ERRORif the layers syntax is incorrect.
Returns
The mask of layers the parsed BOARD_ITEM is on.

Definition at line 1085 of file pcb_parser.cpp.

1086 {
1087  wxCHECK_MSG( CurTok() == T_layers, LSET(),
1088  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1089  wxT( " as item layer mask." ) );
1090 
1091  LSET layerMask;
1092 
1093  for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
1094  {
1095  LSET mask = lookUpLayer<LSET>( m_layerMasks );
1096  layerMask |= mask;
1097  }
1098 
1099  return layerMask;
1100 }
Class LSET is a set of PCB_LAYER_IDs.
LSET_MAP m_layerMasks
map layer names to their masks
Definition: pcb_parser.h:72

◆ parseBoardUnits() [1/3]

int PCB_PARSER::parseBoardUnits ( )
inlineprivate

Definition at line 228 of file pcb_parser.h.

229  {
230  // There should be no major rounding issues here, since the values in
231  // the file are in mm and get converted to nano-meters.
232  // See test program tools/test-nm-biu-to-ascii-mm-round-tripping.cpp
233  // to confirm or experiment. Use a similar strategy in both places, here
234  // and in the test program. Make that program with:
235  // $ make test-nm-biu-to-ascii-mm-round-tripping
236  auto retval = parseDouble() * IU_PER_MM;
237 
238  // N.B. we currently represent board units as integers. Any values that are
239  // larger or smaller than those board units represent undefined behavior for
240  // the system. We limit values to the largest that is visible on the screen
241  // This is the diagonal distance of the full screen ~1.5m
242  double int_limit = std::numeric_limits<int>::max() * 0.7071; // 0.7071 = roughly 1/sqrt(2)
243  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
244  }
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:121
#define max(a, b)
Definition: auxiliary.h:86
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:125

References KiROUND(), max, and parseDouble().

Referenced by parseBoardUnits().

◆ parseBoardUnits() [2/3]

int PCB_PARSER::parseBoardUnits ( const char *  aExpected)
inlineprivate

Definition at line 246 of file pcb_parser.h.

247  {
248  auto retval = parseDouble( aExpected ) * IU_PER_MM;
249 
250  // N.B. we currently represent board units as integers. Any values that are
251  // larger or smaller than those board units represent undefined behavior for
252  // the system. We limit values to the largest that is visible on the screen
253  double int_limit = std::numeric_limits<int>::max() * 0.7071;
254 
255  // Use here KiROUND, not KIROUND (see comments about them)
256  // when having a function as argument, because it will be called twice
257  // with KIROUND
258  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
259  }
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:121
#define max(a, b)
Definition: auxiliary.h:86
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:125

References KiROUND(), max, and parseDouble().

◆ parseBoardUnits() [3/3]

int PCB_PARSER::parseBoardUnits ( PCB_KEYS_T::T  aToken)
inlineprivate

Definition at line 261 of file pcb_parser.h.

262  {
263  return parseBoardUnits( GetTokenText( aToken ) );
264  }
int parseBoardUnits()
Definition: pcb_parser.h:228
const char * GetTokenText(T aTok)
Function GetTokenText is in the DSN namespace and returns the C string representing a SPECCTRA_DB::ke...
Definition: specctra.cpp:69

References DSN::GetTokenText(), and parseBoardUnits().

◆ parseBool()

bool PCB_PARSER::parseBool ( )
private

Definition at line 155 of file pcb_parser.cpp.

156 {
157  T token = NextTok();
158 
159  if( token == T_yes )
160  return true;
161  else if( token == T_no )
162  return false;
163  else
164  Expecting( "yes or no" );
165 
166  return false;
167 }

◆ parseD_PAD()

D_PAD * PCB_PARSER::parseD_PAD ( MODULE aParent = NULL)
private

Definition at line 2393 of file pcb_parser.cpp.

2394 {
2395  wxCHECK_MSG( CurTok() == T_pad, NULL,
2396  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as D_PAD." ) );
2397 
2398  wxSize sz;
2399  wxPoint pt;
2400 
2401  std::unique_ptr< D_PAD > pad( new D_PAD( aParent ) );
2402 
2403  NeedSYMBOLorNUMBER();
2404  pad->SetName( FromUTF8() );
2405 
2406  T token = NextTok();
2407 
2408  switch( token )
2409  {
2410  case T_thru_hole:
2411  pad->SetAttribute( PAD_ATTRIB_STANDARD );
2412  break;
2413 
2414  case T_smd:
2415  pad->SetAttribute( PAD_ATTRIB_SMD );
2416 
2417  // Default D_PAD object is thru hole with drill.
2418  // SMD pads have no hole
2419  pad->SetDrillSize( wxSize( 0, 0 ) );
2420  break;
2421 
2422  case T_connect:
2423  pad->SetAttribute( PAD_ATTRIB_CONN );
2424 
2425  // Default D_PAD object is thru hole with drill.
2426  // CONN pads have no hole
2427  pad->SetDrillSize( wxSize( 0, 0 ) );
2428  break;
2429 
2430  case T_np_thru_hole:
2431  pad->SetAttribute( PAD_ATTRIB_HOLE_NOT_PLATED );
2432  break;
2433 
2434  default:
2435  Expecting( "thru_hole, smd, connect, or np_thru_hole" );
2436  }
2437 
2438  token = NextTok();
2439 
2440  switch( token )
2441  {
2442  case T_circle:
2443  pad->SetShape( PAD_SHAPE_CIRCLE );
2444  break;
2445 
2446  case T_rect:
2447  pad->SetShape( PAD_SHAPE_RECT );
2448  break;
2449 
2450  case T_oval:
2451  pad->SetShape( PAD_SHAPE_OVAL );
2452  break;
2453 
2454  case T_trapezoid:
2455  pad->SetShape( PAD_SHAPE_TRAPEZOID );
2456  break;
2457 
2458  case T_roundrect:
2459  // Note: the shape can be PAD_SHAPE_ROUNDRECT or PAD_SHAPE_CHAMFERED_RECT
2460  // (if champfer parameters are found later in pad descr.)
2461  pad->SetShape( PAD_SHAPE_ROUNDRECT );
2462  break;
2463 
2464  case T_custom:
2465  pad->SetShape( PAD_SHAPE_CUSTOM );
2466  break;
2467 
2468  default:
2469  Expecting( "circle, rectangle, roundrect, oval, trapezoid or custom" );
2470  }
2471 
2472  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2473  {
2474  if( token != T_LEFT )
2475  Expecting( T_LEFT );
2476 
2477  token = NextTok();
2478 
2479  switch( token )
2480  {
2481  case T_size:
2482  sz.SetWidth( parseBoardUnits( "width value" ) );
2483  sz.SetHeight( parseBoardUnits( "height value" ) );
2484  pad->SetSize( sz );
2485  NeedRIGHT();
2486  break;
2487 
2488  case T_at:
2489  pt.x = parseBoardUnits( "X coordinate" );
2490  pt.y = parseBoardUnits( "Y coordinate" );
2491  pad->SetPos0( pt );
2492  token = NextTok();
2493 
2494  if( token == T_NUMBER )
2495  {
2496  pad->SetOrientation( parseDouble() * 10.0 );
2497  NeedRIGHT();
2498  }
2499  else if( token != T_RIGHT )
2500  {
2501  Expecting( ") or angle value" );
2502  }
2503 
2504  break;
2505 
2506  case T_rect_delta:
2507  {
2508  wxSize delta;
2509  delta.SetWidth( parseBoardUnits( "rectangle delta width" ) );
2510  delta.SetHeight( parseBoardUnits( "rectangle delta height" ) );
2511  pad->SetDelta( delta );
2512  NeedRIGHT();
2513  }
2514  break;
2515 
2516  case T_drill:
2517  {
2518  bool haveWidth = false;
2519  wxSize drillSize = pad->GetDrillSize();
2520 
2521  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2522  {
2523  if( token == T_LEFT )
2524  token = NextTok();
2525 
2526  switch( token )
2527  {
2528  case T_oval:
2529  pad->SetDrillShape( PAD_DRILL_SHAPE_OBLONG );
2530  break;
2531 
2532  case T_NUMBER:
2533  {
2534  if( !haveWidth )
2535  {
2536  drillSize.SetWidth( parseBoardUnits() );
2537 
2538  // If height is not defined the width and height are the same.
2539  drillSize.SetHeight( drillSize.GetWidth() );
2540  haveWidth = true;
2541  }
2542  else
2543  {
2544  drillSize.SetHeight( parseBoardUnits() );
2545  }
2546 
2547  }
2548  break;
2549 
2550  case T_offset:
2551  pt.x = parseBoardUnits( "drill offset x" );
2552  pt.y = parseBoardUnits( "drill offset y" );
2553  pad->SetOffset( pt );
2554  NeedRIGHT();
2555  break;
2556 
2557  default:
2558  Expecting( "oval, size, or offset" );
2559  }
2560  }
2561 
2562  // This fixes a bug caused by setting the default D_PAD drill size to a value
2563  // other than 0 used to fix a bunch of debug assertions even though it is defined
2564  // as a through hole pad. Wouldn't a though hole pad with no drill be a surface
2565  // mount pad (or a conn pad which is a smd pad with no solder paste)?
2566  if( ( pad->GetAttribute() != PAD_ATTRIB_SMD ) && ( pad->GetAttribute() != PAD_ATTRIB_CONN ) )
2567  pad->SetDrillSize( drillSize );
2568  else
2569  pad->SetDrillSize( wxSize( 0, 0 ) );
2570 
2571  }
2572  break;
2573 
2574  case T_layers:
2575  {
2576  LSET layerMask = parseBoardItemLayersAsMask();
2577  pad->SetLayerSet( layerMask );
2578  }
2579  break;
2580 
2581  case T_net:
2582  if( ! pad->SetNetCode( getNetCode( parseInt( "net number" ) ), /* aNoAssert */ true ) )
2584  wxString::Format( _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
2585  GetChars( CurSource() ), CurLineNumber(), CurOffset() )
2586  );
2587  NeedSYMBOLorNUMBER();
2588  if( m_board && FromUTF8() != m_board->FindNet( pad->GetNetCode() )->GetNetname() )
2590  wxString::Format( _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
2591  GetChars( CurSource() ), CurLineNumber(), CurOffset() )
2592  );
2593  NeedRIGHT();
2594  break;
2595 
2596  case T_die_length:
2597  pad->SetPadToDieLength( parseBoardUnits( T_die_length ) );
2598  NeedRIGHT();
2599  break;
2600 
2601  case T_solder_mask_margin:
2602  pad->SetLocalSolderMaskMargin( parseBoardUnits( T_solder_mask_margin ) );
2603  NeedRIGHT();
2604  break;
2605 
2606  case T_solder_paste_margin:
2607  pad->SetLocalSolderPasteMargin( parseBoardUnits( T_solder_paste_margin ) );
2608  NeedRIGHT();
2609  break;
2610 
2611  case T_solder_paste_margin_ratio:
2612  pad->SetLocalSolderPasteMarginRatio(
2613  parseDouble( "pad local solder paste margin ratio value" ) );
2614  NeedRIGHT();
2615  break;
2616 
2617  case T_clearance:
2618  pad->SetLocalClearance( parseBoardUnits( "local clearance value" ) );
2619  NeedRIGHT();
2620  break;
2621 
2622  case T_zone_connect:
2623  pad->SetZoneConnection( (ZoneConnection) parseInt( "zone connection value" ) );
2624  NeedRIGHT();
2625  break;
2626 
2627  case T_thermal_width:
2628  pad->SetThermalWidth( parseBoardUnits( T_thermal_width ) );
2629  NeedRIGHT();
2630  break;
2631 
2632  case T_thermal_gap:
2633  pad->SetThermalGap( parseBoardUnits( T_thermal_gap ) );
2634  NeedRIGHT();
2635  break;
2636 
2637  case T_roundrect_rratio:
2638  pad->SetRoundRectRadiusRatio( parseDouble( "roundrect radius ratio" ) );
2639  NeedRIGHT();
2640  break;
2641 
2642  case T_chamfer_ratio:
2643  pad->SetChamferRectRatio( parseDouble( "chamfer ratio" ) );
2644 
2645  if( pad->GetChamferRectRatio() > 0 )
2646  pad->SetShape( PAD_SHAPE_CHAMFERED_RECT );
2647 
2648  NeedRIGHT();
2649  break;
2650 
2651  case T_chamfer:
2652  {
2653  int chamfers = 0;
2654  bool end_list = false;
2655 
2656  while( !end_list )
2657  {
2658  token = NextTok();
2659  switch( token )
2660  {
2661  case T_top_left:
2662  chamfers |= RECT_CHAMFER_TOP_LEFT;
2663  break;
2664 
2665  case T_top_right:
2666  chamfers |= RECT_CHAMFER_TOP_RIGHT;
2667  break;
2668 
2669  case T_bottom_left:
2670  chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
2671  break;
2672 
2673  case T_bottom_right:
2674  chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
2675  break;
2676 
2677  case T_RIGHT:
2678  pad->SetChamferPositions( chamfers );
2679  end_list = true;
2680  break;
2681 
2682  default:
2683  Expecting( "chamfer_top_left chamfer_top_right chamfer_bottom_left or chamfer_bottom_right" );
2684  }
2685  }
2686 
2687  if( pad->GetChamferPositions() != RECT_NO_CHAMFER )
2688  pad->SetShape( PAD_SHAPE_CHAMFERED_RECT );
2689  }
2690  break;
2691 
2692  case T_options:
2693  parseD_PAD_option( pad.get() );
2694  break;
2695 
2696  case T_primitives:
2697  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2698  {
2699  if( token == T_LEFT )
2700  token = NextTok();
2701 
2702  // Currently, I am using parseDRAWSEGMENT() to read basic shapes parameters,
2703  // because they are the same as a DRAWSEGMENT.
2704  // However it could be better to write a specific parser, to avoid possible issues
2705  // if the DRAWSEGMENT parser is modified.
2706  DRAWSEGMENT* dummysegm = NULL;
2707 
2708  switch( token )
2709  {
2710  case T_gr_arc:
2711  dummysegm = parseDRAWSEGMENT();
2712  pad->AddPrimitive( dummysegm->GetCenter(), dummysegm->GetArcStart(),
2713  dummysegm->GetAngle(), dummysegm->GetWidth() );
2714  break;
2715 
2716  case T_gr_line:
2717  dummysegm = parseDRAWSEGMENT();
2718  pad->AddPrimitive( dummysegm->GetStart(), dummysegm->GetEnd(),
2719  dummysegm->GetWidth() );
2720  break;
2721 
2722  case T_gr_circle:
2723  dummysegm = parseDRAWSEGMENT( true ); // Circles with 0 thickness are allowed
2724  // ( filled circles )
2725  pad->AddPrimitive( dummysegm->GetCenter(), dummysegm->GetRadius(),
2726  dummysegm->GetWidth() );
2727  break;
2728 
2729  case T_gr_poly:
2730  dummysegm = parseDRAWSEGMENT();
2731  pad->AddPrimitive( dummysegm->BuildPolyPointsList(), dummysegm->GetWidth() );
2732  break;
2733 
2734  default:
2735  Expecting( "gr_line, gr_arc, gr_circle or gr_poly" );
2736  break;
2737  }
2738 
2739  delete dummysegm;
2740  }
2741  break;
2742 
2743  default:
2744  Expecting( "at, drill, layers, net, die_length, solder_mask_margin, roundrect_rratio,\n"
2745  "solder_paste_margin, solder_paste_margin_ratio, clearance,\n"
2746  "zone_connect, fp_poly, primitives, thermal_width, or thermal_gap" );
2747  }
2748  }
2749 
2750  // Be sure the custom shape polygon is built:
2751  if( pad->GetShape() == PAD_SHAPE_CUSTOM )
2752  pad->MergePrimitivesAsPolygon();
2753 
2754  return pad.release();
2755 }
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
DRAWSEGMENT * parseDRAWSEGMENT(bool aAllowCirclesZeroWidth=false)
Read a DRAWSEGMENT description.
LSET parseBoardItemLayersAsMask()
Function parseBoardItemLayersAsMask parses the layers definition of a BOARD_ITEM object.
like PAD_STANDARD, but not plated mechanical use only, no connection allowed
Definition: pad_shapes.h:66
const wxPoint GetCenter() const override
Function GetCenter()
ZoneConnection
How pads are covered by copper in zone.
Definition: zones.h:50
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:62
bool parseD_PAD_option(D_PAD *aPad)
const std::vector< wxPoint > BuildPolyPointsList() const
Build and return the list of corners in a std::vector<wxPoint> It must be used only to convert the SH...
const wxPoint & GetEnd() const
Function GetEnd returns the ending point of the graphic.
static const int delta[8][2]
Definition: solve.cpp:112
int parseBoardUnits()
Definition: pcb_parser.h:228
Class LSET is a set of PCB_LAYER_IDs.
const wxPoint & GetArcStart() const
#define THROW_IO_ERROR(msg)
int GetRadius() const
Function GetRadius returns the radius of this item Has meaning only for arc and circle.
Like smd, does not appear on the solder paste layer (default) note also has a special attribute in Ge...
Definition: pad_shapes.h:63
int GetWidth() const
double GetAngle() const
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
int getNetCode(int aNetCode)
Converts net code using the mapping table if available, otherwise returns unchanged net code if < 0 o...
Definition: pcb_parser.h:80
BOARD * m_board
Definition: pcb_parser.h:70
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:125
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
int parseInt()
Definition: pcb_parser.h:266

References DRAWSEGMENT::BuildPolyPointsList(), delta, Format(), DRAWSEGMENT::GetAngle(), DRAWSEGMENT::GetArcStart(), DRAWSEGMENT::GetCenter(), GetChars(), DRAWSEGMENT::GetEnd(), DRAWSEGMENT::GetRadius(), DRAWSEGMENT::GetStart(), DRAWSEGMENT::GetWidth(), PAD_ATTRIB_CONN, PAD_ATTRIB_HOLE_NOT_PLATED, PAD_ATTRIB_SMD, PAD_ATTRIB_STANDARD, PAD_DRILL_SHAPE_OBLONG, PAD_SHAPE_CHAMFERED_RECT, PAD_SHAPE_CIRCLE, PAD_SHAPE_CUSTOM, PAD_SHAPE_OVAL, PAD_SHAPE_RECT, PAD_SHAPE_ROUNDRECT, PAD_SHAPE_TRAPEZOID, parseDouble(), parseInt(), RECT_CHAMFER_BOTTOM_LEFT, RECT_CHAMFER_BOTTOM_RIGHT, RECT_CHAMFER_TOP_LEFT, RECT_CHAMFER_TOP_RIGHT, RECT_NO_CHAMFER, and THROW_IO_ERROR.

◆ parseD_PAD_option()

bool PCB_PARSER::parseD_PAD_option ( D_PAD aPad)
private

Definition at line 2758 of file pcb_parser.cpp.

2759 {
2760  // Parse only the (option ...) inside a pad description
2761  for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2762  {
2763  if( token != T_LEFT )
2764  Expecting( T_LEFT );
2765 
2766  token = NextTok();
2767 
2768  switch( token )
2769  {
2770  case T_anchor:
2771  token = NextTok();
2772  // Custom shaped pads have a "anchor pad", which is the reference
2773  // for connection calculations.
2774  // Because this is an anchor, only the 2 very basic shapes are managed:
2775  // circle and rect. The default is circle
2776  switch( token )
2777  {
2778  case T_circle: // default
2779  break;
2780 
2781  case T_rect:
2783  break;
2784 
2785  default:
2786  // Currently, because pad options is a moving target
2787  // just skip unknown keywords
2788  break;
2789  }
2790  NeedRIGHT();
2791  break;
2792 
2793  case T_clearance:
2794  token = NextTok();
2795  // Custom shaped pads have a clearance area that is the pad shape
2796  // (like usual pads) or the convew hull of the pad shape.
2797  switch( token )
2798  {
2799  case T_outline:
2801  break;
2802 
2803  case T_convexhull:
2805  break;
2806 
2807  default:
2808  // Currently, because pad options is a moving target
2809  // just skip unknown keywords
2810  break;
2811  }
2812  NeedRIGHT();
2813  break;
2814 
2815  default:
2816  // Currently, because pad options is a moving target
2817  // just skip unknown keywords
2818  while( (token = NextTok() ) != T_RIGHT )
2819  {}
2820  break;
2821  }
2822  }
2823 
2824  return true;
2825 }
void SetAnchorPadShape(PAD_SHAPE_T aShape)
Function SetAnchorPadShape Set the shape of the anchor pad for custm shped pads.
Definition: class_pad.h:253
void SetCustomShapeInZoneOpt(CUST_PAD_SHAPE_IN_ZONE aOption)
Set the option for the custom pad shape to use as clearance area in copper zones.
Definition: class_pad.h:242

References CUST_PAD_SHAPE_IN_ZONE_CONVEXHULL, CUST_PAD_SHAPE_IN_ZONE_OUTLINE, PAD_SHAPE_RECT, D_PAD::SetAnchorPadShape(), and D_PAD::SetCustomShapeInZoneOpt().

◆ parseDIMENSION()

DIMENSION * PCB_PARSER::parseDIMENSION ( )
private

Definition at line 1697 of file pcb_parser.cpp.

1698 {
1699  wxCHECK_MSG( CurTok() == T_dimension, NULL,
1700  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as DIMENSION." ) );
1701 
1702  T token;
1703 
1704  std::unique_ptr<DIMENSION> dimension( new DIMENSION( NULL ) );
1705 
1706  dimension->SetValue( parseBoardUnits( "dimension value" ) );
1707  NeedLEFT();
1708  token = NextTok();
1709 
1710  if( token != T_width )
1711  Expecting( T_width );
1712 
1713  dimension->SetWidth( parseBoardUnits( "dimension width value" ) );
1714  NeedRIGHT();
1715 
1716  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1717  {
1718  if( token != T_LEFT )
1719  Expecting( T_LEFT );
1720 
1721  token = NextTok();
1722 
1723  switch( token )
1724  {
1725  case T_layer:
1726  dimension->SetLayer( parseBoardItemLayer() );
1727  NeedRIGHT();
1728  break;
1729 
1730  case T_tstamp:
1731  dimension->SetTimeStamp( parseHex() );
1732  NeedRIGHT();
1733  break;
1734 
1735  case T_gr_text:
1736  {
1737  TEXTE_PCB* text = parseTEXTE_PCB();
1738 
1739  // This copy (using the copy constructor) rebuild the text timestamp,
1740  // that is not what we want.
1741  dimension->Text() = *text;
1742  // reinitialises the text time stamp to the right value (the dimension time stamp)
1743  dimension->Text().SetTimeStamp( dimension->GetTimeStamp() );
1744  dimension->SetPosition( text->GetTextPos() );
1745 
1746  EDA_UNITS_T units = INCHES;
1747  bool useMils = false;
1748  FetchUnitsFromString( text->GetText(), units, useMils );
1749  dimension->SetUnits( units, useMils );
1750 
1751  delete text;
1752  break;
1753  }
1754 
1755  case T_feature1:
1756  NeedLEFT();
1757  token = NextTok();
1758 
1759  if( token != T_pts )
1760  Expecting( T_pts );
1761 
1762  parseXY( &dimension->m_featureLineDO.x, &dimension->m_featureLineDO.y );
1763  parseXY( &dimension->m_featureLineDF.x, &dimension->m_featureLineDF.y );
1764  dimension->UpdateHeight();
1765  NeedRIGHT();
1766  NeedRIGHT();
1767  break;
1768 
1769  case T_feature2:
1770  NeedLEFT();
1771  token = NextTok();
1772 
1773  if( token != T_pts )
1774  Expecting( T_pts );
1775 
1776  parseXY( &dimension->m_featureLineGO.x, &dimension->m_featureLineGO.y );
1777  parseXY( &dimension->m_featureLineGF.x, &dimension->m_featureLineGF.y );
1778  dimension->UpdateHeight();
1779  NeedRIGHT();
1780  NeedRIGHT();
1781  break;
1782 
1783 
1784  case T_crossbar:
1785  NeedLEFT();
1786  token = NextTok();
1787 
1788  if( token != T_pts )
1789  Expecting( T_pts );
1790 
1791  parseXY( &dimension->m_crossBarO.x, &dimension->m_crossBarO.y );
1792  parseXY( &dimension->m_crossBarF.x, &dimension->m_crossBarF.y );
1793  dimension->UpdateHeight();
1794  NeedRIGHT();
1795  NeedRIGHT();
1796  break;
1797 
1798  case T_arrow1a:
1799  NeedLEFT();
1800  token = NextTok();
1801 
1802  if( token != T_pts )
1803  Expecting( T_pts );
1804 
1805  parseXY( &dimension->m_crossBarF.x, &dimension->m_crossBarF.y );
1806  parseXY( &dimension->m_arrowD1F.x, &dimension->m_arrowD1F.y );
1807  NeedRIGHT();
1808  NeedRIGHT();
1809  break;
1810 
1811  case T_arrow1b:
1812  NeedLEFT();
1813  token = NextTok();
1814 
1815  if( token != T_pts )
1816  Expecting( T_pts );
1817 
1818  parseXY( &dimension->m_crossBarF.x, &dimension->m_crossBarF.y );
1819  parseXY( &dimension->m_arrowD2F.x, &dimension->m_arrowD2F.y );
1820  NeedRIGHT();
1821  NeedRIGHT();
1822  break;
1823 
1824  case T_arrow2a:
1825  NeedLEFT();
1826  token = NextTok();
1827 
1828  if( token != T_pts )
1829  Expecting( T_pts );
1830 
1831  parseXY( &dimension->m_crossBarO.x, &dimension->m_crossBarO.y );
1832  parseXY( &dimension->m_arrowG1F.x, &dimension->m_arrowG1F.y );
1833  NeedRIGHT();
1834  NeedRIGHT();
1835  break;
1836 
1837  case T_arrow2b:
1838  NeedLEFT();
1839  token = NextTok();
1840 
1841  if( token != T_pts )
1842  Expecting( T_pts );
1843 
1844  parseXY( &dimension->m_crossBarO.x, &dimension->m_crossBarO.y );
1845  parseXY( &dimension->m_arrowG2F.x, &dimension->m_arrowG2F.y );
1846  NeedRIGHT();
1847  NeedRIGHT();
1848  break;
1849 
1850  default:
1851  Expecting( "layer, tstamp, gr_text, feature1, feature2 crossbar, arrow1a, "
1852  "arrow1b, arrow2a, or arrow2b" );
1853  }
1854  }
1855 
1856  return dimension.release();
1857 }
wxPoint parseXY()
Function parseXY parses a coordinate pair (xy X Y) in board units (mm).
Definition: pcb_parser.cpp:207
void FetchUnitsFromString(const wxString &aTextValue, EDA_UNITS_T &aUnits, bool &aUseMils)
Function FetchUnitsFromString writes any unit info found in the string to aUnits and aUseMils.
Definition: base_units.cpp:370
int parseBoardUnits()
Definition: pcb_parser.h:228
const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:143
Definition: common.h:161
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
TEXTE_PCB * parseTEXTE_PCB()
const wxPoint & GetTextPos() const
Definition: eda_text.h:237
long parseHex()
Definition: pcb_parser.h:277
EDA_UNITS_T
Definition: common.h:160
Class DIMENSION.
void SetTimeStamp(timestamp_t aNewTimeStamp)
Definition: base_struct.h:206

References FetchUnitsFromString(), EDA_TEXT::GetText(), EDA_TEXT::GetTextPos(), INCHES, parseHex(), and EDA_ITEM::SetTimeStamp().

◆ parseDouble() [1/3]

double PCB_PARSER::parseDouble ( )
private

Function parseDouble parses the current token as an ASCII numeric string with possible leading whitespace into a double precision floating point number.

Exceptions
IO_ERRORif an error occurs attempting to convert the current token.
Returns
The result of the parsed token.

Definition at line 125 of file pcb_parser.cpp.

126 {
127  char* tmp;
128 
129  errno = 0;
130 
131  double fval = strtod( CurText(), &tmp );
132 
133  if( errno )
134  {
135  wxString error;
136  error.Printf( _( "Invalid floating point number in\nfile: \"%s\"\nline: %d\noffset: %d" ),
137  GetChars( CurSource() ), CurLineNumber(), CurOffset() );
138 
139  THROW_IO_ERROR( error );
140  }
141 
142  if( CurText() == tmp )
143  {
144  wxString error;
145  error.Printf( _( "Missing floating point number in\nfile: \"%s\"\nline: %d\noffset: %d" ),
146  GetChars( CurSource() ), CurLineNumber(), CurOffset() );
147 
148  THROW_IO_ERROR( error );
149  }
150 
151  return fval;
152 }
#define THROW_IO_ERROR(msg)
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92

References GetChars(), and THROW_IO_ERROR.

Referenced by parseBoardUnits(), and parseDouble().

◆ parseDouble() [2/3]

double PCB_PARSER::parseDouble ( const char *  aExpected)
inlineprivate

Definition at line 217 of file pcb_parser.h.

218  {
219  NeedNUMBER( aExpected );
220  return parseDouble();
221  }
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:125

References parseDouble().

◆ parseDouble() [3/3]

double PCB_PARSER::parseDouble ( PCB_KEYS_T::T  aToken)
inlineprivate

Definition at line 223 of file pcb_parser.h.

224  {
225  return parseDouble( GetTokenText( aToken ) );
226  }
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:125
const char * GetTokenText(T aTok)
Function GetTokenText is in the DSN namespace and returns the C string representing a SPECCTRA_DB::ke...
Definition: specctra.cpp:69

References DSN::GetTokenText(), and parseDouble().

◆ parseDRAWSEGMENT()

DRAWSEGMENT * PCB_PARSER::parseDRAWSEGMENT ( bool  aAllowCirclesZeroWidth = false)
private

Read a DRAWSEGMENT description.

Parameters
aAllowCirclesZeroWidth= true to allow items with 0 width Only used in custom pad shapes for filled circles.

Definition at line 1456 of file pcb_parser.cpp.

1457 {
1458  wxCHECK_MSG( CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
1459  CurTok() == T_gr_line || CurTok() == T_gr_poly, NULL,
1460  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as DRAWSEGMENT." ) );
1461 
1462  T token;
1463  wxPoint pt;
1464  std::unique_ptr< DRAWSEGMENT > segment( new DRAWSEGMENT( NULL ) );
1465 
1466  switch( CurTok() )
1467  {
1468  case T_gr_arc:
1469  segment->SetShape( S_ARC );
1470  NeedLEFT();
1471  token = NextTok();
1472 
1473  // the start keyword actually gives the arc center
1474  // Allows also T_center for future change
1475  if( token != T_start && token != T_center )
1476  Expecting( T_start );
1477 
1478  pt.x = parseBoardUnits( "X coordinate" );
1479  pt.y = parseBoardUnits( "Y coordinate" );
1480  segment->SetCenter( pt );
1481  NeedRIGHT();
1482  NeedLEFT();
1483  token = NextTok();
1484 
1485  if( token != T_end ) // the end keyword actually gives the starting point of the arc
1486  Expecting( T_end );
1487 
1488  pt.x = parseBoardUnits( "X coordinate" );
1489  pt.y = parseBoardUnits( "Y coordinate" );
1490  segment->SetArcStart( pt );
1491  NeedRIGHT();
1492  break;
1493 
1494  case T_gr_circle:
1495  segment->SetShape( S_CIRCLE );
1496  NeedLEFT();
1497  token = NextTok();
1498 
1499  if( token != T_center )
1500  Expecting( T_center );
1501 
1502  pt.x = parseBoardUnits( "X coordinate" );
1503  pt.y = parseBoardUnits( "Y coordinate" );
1504  segment->SetCenter( pt );
1505  NeedRIGHT();
1506  NeedLEFT();
1507 
1508  token = NextTok();
1509 
1510  if( token != T_end )
1511  Expecting( T_end );
1512 
1513  pt.x = parseBoardUnits( "X coordinate" );
1514  pt.y = parseBoardUnits( "Y coordinate" );
1515  segment->SetEnd( pt );
1516  NeedRIGHT();
1517  break;
1518 
1519  case T_gr_curve:
1520  segment->SetShape( S_CURVE );
1521  NeedLEFT();
1522  token = NextTok();
1523 
1524  if( token != T_pts )
1525  Expecting( T_pts );
1526 
1527  segment->SetStart( parseXY() );
1528  segment->SetBezControl1( parseXY() );
1529  segment->SetBezControl2( parseXY() );
1530  segment->SetEnd( parseXY() );
1531  NeedRIGHT();
1532  break;
1533 
1534  case T_gr_line:
1535  // Default DRAWSEGMENT type is S_SEGMENT.
1536  NeedLEFT();
1537  token = NextTok();
1538 
1539  if( token != T_start )
1540  Expecting( T_start );
1541 
1542  pt.x = parseBoardUnits( "X coordinate" );
1543  pt.y = parseBoardUnits( "Y coordinate" );
1544  segment->SetStart( pt );
1545  NeedRIGHT();
1546  NeedLEFT();
1547  token = NextTok();
1548 
1549  if( token != T_end )
1550  Expecting( T_end );
1551 
1552  pt.x = parseBoardUnits( "X coordinate" );
1553  pt.y = parseBoardUnits( "Y coordinate" );
1554  segment->SetEnd( pt );
1555  NeedRIGHT();
1556  break;
1557 
1558  case T_gr_poly:
1559  {
1560  segment->SetShape( S_POLYGON );
1561  segment->SetWidth( 0 ); // this is the default value. will be (perhaps) modified later
1562  NeedLEFT();
1563  token = NextTok();
1564 
1565  if( token != T_pts )
1566  Expecting( T_pts );
1567 
1568  std::vector< wxPoint > pts;
1569 
1570  while( (token = NextTok()) != T_RIGHT )
1571  pts.push_back( parseXY() );
1572 
1573  segment->SetPolyPoints( pts );
1574  }
1575  break;
1576 
1577  default:
1578  Expecting( "gr_arc, gr_circle, gr_curve, gr_line, or gr_poly" );
1579  }
1580 
1581  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1582  {
1583  if( token != T_LEFT )
1584  Expecting( T_LEFT );
1585 
1586  token = NextTok();
1587 
1588  switch( token )
1589  {
1590  case T_angle:
1591  segment->SetAngle( parseDouble( "segment angle" ) * 10.0 );
1592  break;
1593 
1594  case T_layer:
1595  segment->SetLayer( parseBoardItemLayer() );
1596  break;
1597 
1598  case T_width:
1599  segment->SetWidth( parseBoardUnits( T_width ) );
1600  break;
1601 
1602  case T_tstamp:
1603  segment->SetTimeStamp( parseHex() );
1604  break;
1605 
1606  case T_status:
1607  segment->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
1608  break;
1609 
1610  default:
1611  Expecting( "layer, width, tstamp, or status" );
1612  }
1613 
1614  NeedRIGHT();
1615  }
1616 
1617  // Only filled polygons may have a zero-line width
1618  // This is not permitted in KiCad but some external tools generate invalid
1619  // files.
1620  // However in custom pad shapes, zero-line width is allowed for filled circles
1621  if( segment->GetShape() != S_POLYGON && segment->GetWidth() == 0 &&
1622  !( segment->GetShape() == S_CIRCLE && aAllowCirclesZeroWidth ) )
1623  segment->SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) );
1624 
1625  return segment.release();
1626 }
polygon (not yet used for tracks, but could be in microwave apps)
wxPoint parseXY()
Function parseXY parses a coordinate pair (xy X Y) in board units (mm).
Definition: pcb_parser.cpp:207
#define DEFAULT_LINE_WIDTH
int parseBoardUnits()
Definition: pcb_parser.h:228
Arcs (with rounded ends)
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
Bezier Curve.
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:125
long parseHex()
Definition: pcb_parser.h:277

References DEFAULT_LINE_WIDTH, parseDouble(), parseHex(), S_ARC, S_CIRCLE, S_CURVE, and S_POLYGON.

◆ parseEDA_TEXT()

void PCB_PARSER::parseEDA_TEXT ( EDA_TEXT aText)
private

Function parseEDA_TEXT parses the common settings for any object derived from EDA_TEXT.

Exceptions
PARSE_ERRORif the text syntax is not valid.
Parameters
aTextA point to the EDA_TEXT object to save the parsed settings into.

Definition at line 239 of file pcb_parser.cpp.

240 {
241  wxCHECK_RET( CurTok() == T_effects,
242  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as EDA_TEXT." ) );
243 
244  T token;
245 
246  // Prior to v5.0 text size was omitted from file format if equal to 60mils
247  // Now, it is always explicitly written to file
248  bool foundTextSize = false;
249 
250  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
251  {
252  if( token == T_LEFT )
253  token = NextTok();
254 
255  switch( token )
256  {
257  case T_font:
258  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
259  {
260  if( token == T_LEFT )
261  continue;
262 
263  switch( token )
264  {
265  case T_size:
266  {
267  wxSize sz;
268  sz.SetHeight( parseBoardUnits( "text height" ) );
269  sz.SetWidth( parseBoardUnits( "text width" ) );
270  aText->SetTextSize( sz );
271  NeedRIGHT();
272 
273  foundTextSize = true;
274  }
275  break;
276 
277  case T_thickness:
278  aText->SetThickness( parseBoardUnits( "text thickness" ) );
279  NeedRIGHT();
280  break;
281 
282  case T_bold:
283  aText->SetBold( true );
284  break;
285 
286  case T_italic:
287  aText->SetItalic( true );
288  break;
289 
290  default:
291  Expecting( "size, bold, or italic" );
292  }
293  }
294  break;
295 
296  case T_justify:
297  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
298  {
299  if( token == T_LEFT )
300  continue;
301 
302  switch( token )
303  {
304  case T_left:
306  break;
307 
308  case T_right:
310  break;
311 
312  case T_top:
314  break;
315 
316  case T_bottom:
318  break;
319 
320  case T_mirror:
321  aText->SetMirrored( true );
322  break;
323 
324  default:
325  Expecting( "left, right, top, bottom, or mirror" );
326  }
327 
328  }
329  break;
330 
331  case T_hide:
332  aText->SetVisible( false );
333  break;
334 
335  default:
336  Expecting( "font, justify, or hide" );
337  }
338  }
339 
340  // Text size was not specified in file, force legacy default units
341  // 60mils is 1.524mm
342  if( !foundTextSize )
343  {
344  const float defaultTextSize = 1.524f * IU_PER_MM;
345 
346  aText->SetTextSize( wxSize( defaultTextSize, defaultTextSize ) );
347  }
348 }
void SetMirrored(bool isMirrored)
Definition: eda_text.h:191
void SetItalic(bool isItalic)
Definition: eda_text.h:182
void SetVisible(bool aVisible)
Definition: eda_text.h:188
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:227
int parseBoardUnits()
Definition: pcb_parser.h:228
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:207
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:206
void SetBold(bool aBold)
Definition: eda_text.h:185
void SetThickness(int aNewThickness)
Function SetThickness sets pen width.
Definition: eda_text.h:161

References GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_HJUSTIFY_RIGHT, GR_TEXT_VJUSTIFY_BOTTOM, GR_TEXT_VJUSTIFY_TOP, EDA_TEXT::SetBold(), EDA_TEXT::SetHorizJustify(), EDA_TEXT::SetItalic(), EDA_TEXT::SetMirrored(), EDA_TEXT::SetTextSize(), EDA_TEXT::SetThickness(), EDA_TEXT::SetVertJustify(), and EDA_TEXT::SetVisible().

◆ parseEDGE_MODULE()

EDGE_MODULE * PCB_PARSER::parseEDGE_MODULE ( )
private

Definition at line 2218 of file pcb_parser.cpp.

2219 {
2220  wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
2221  CurTok() == T_fp_line || CurTok() == T_fp_poly, NULL,
2222  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as EDGE_MODULE." ) );
2223 
2224  wxPoint pt;
2225  T token;
2226 
2227  std::unique_ptr< EDGE_MODULE > segment( new EDGE_MODULE( NULL ) );
2228 
2229  switch( CurTok() )
2230  {
2231  case T_fp_arc:
2232  segment->SetShape( S_ARC );
2233  NeedLEFT();
2234  token = NextTok();
2235 
2236  // the start keyword actually gives the arc center
2237  // Allows also T_center for future change
2238  if( token != T_start && token != T_center )
2239  Expecting( T_start );
2240 
2241  pt.x = parseBoardUnits( "X coordinate" );
2242  pt.y = parseBoardUnits( "Y coordinate" );
2243  segment->SetStart0( pt );
2244  NeedRIGHT();
2245  NeedLEFT();
2246  token = NextTok();
2247 
2248  if( token != T_end ) // end keyword actually gives the starting point of the arc
2249  Expecting( T_end );
2250 
2251  pt.x = parseBoardUnits( "X coordinate" );
2252  pt.y = parseBoardUnits( "Y coordinate" );
2253  segment->SetEnd0( pt );
2254  NeedRIGHT();
2255  NeedLEFT();
2256  token = NextTok();
2257 
2258  if( token != T_angle )
2259  Expecting( T_angle );
2260 
2261  segment->SetAngle( parseDouble( "segment angle" ) * 10.0 );
2262  NeedRIGHT();
2263  break;
2264 
2265  case T_fp_circle:
2266  segment->SetShape( S_CIRCLE );
2267  NeedLEFT();
2268  token = NextTok();
2269 
2270  if( token != T_center )
2271  Expecting( T_center );
2272 
2273  pt.x = parseBoardUnits( "X coordinate" );
2274  pt.y = parseBoardUnits( "Y coordinate" );
2275  segment->SetStart0( pt );
2276  NeedRIGHT();
2277  NeedLEFT();
2278  token = NextTok();
2279 
2280  if( token != T_end )
2281  Expecting( T_end );
2282 
2283  pt.x = parseBoardUnits( "X coordinate" );
2284  pt.y = parseBoardUnits( "Y coordinate" );
2285  segment->SetEnd0( pt );
2286  NeedRIGHT();
2287  break;
2288 
2289  case T_fp_curve:
2290  segment->SetShape( S_CURVE );
2291  NeedLEFT();
2292  token = NextTok();
2293 
2294  if( token != T_pts )
2295  Expecting( T_pts );
2296 
2297  segment->SetStart0( parseXY() );
2298  segment->SetBezier0_C1( parseXY() );
2299  segment->SetBezier0_C2( parseXY() );
2300  segment->SetEnd0( parseXY() );
2301  NeedRIGHT();
2302  break;
2303 
2304  case T_fp_line:
2305  // Default DRAWSEGMENT type is S_SEGMENT.
2306  NeedLEFT();
2307  token = NextTok();
2308 
2309  if( token != T_start )
2310  Expecting( T_start );
2311 
2312  pt.x = parseBoardUnits( "X coordinate" );
2313  pt.y = parseBoardUnits( "Y coordinate" );
2314  segment->SetStart0( pt );
2315 
2316  NeedRIGHT();
2317  NeedLEFT();
2318  token = NextTok();
2319 
2320  if( token != T_end )
2321  Expecting( T_end );
2322 
2323  pt.x = parseBoardUnits( "X coordinate" );
2324  pt.y = parseBoardUnits( "Y coordinate" );
2325  segment->SetEnd0( pt );
2326  NeedRIGHT();
2327  break;
2328 
2329  case T_fp_poly:
2330  {
2331  segment->SetShape( S_POLYGON );
2332  NeedLEFT();
2333  token = NextTok();
2334 
2335  if( token != T_pts )
2336  Expecting( T_pts );
2337 
2338  std::vector< wxPoint > pts;
2339 
2340  while( (token = NextTok()) != T_RIGHT )
2341  pts.push_back( parseXY() );
2342 
2343  segment->SetPolyPoints( pts );
2344  }
2345  break;
2346 
2347  default:
2348  Expecting( "fp_arc, fp_circle, fp_curve, fp_line, or fp_poly" );
2349  }
2350 
2351  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2352  {
2353  if( token != T_LEFT )
2354  Expecting( T_LEFT );
2355 
2356  token = NextTok();
2357 
2358  switch( token )
2359  {
2360  case T_layer:
2361  segment->SetLayer( parseBoardItemLayer() );
2362  break;
2363 
2364  case T_width:
2365  segment->SetWidth( parseBoardUnits( T_width ) );
2366  break;
2367 
2368  case T_tstamp:
2369  segment->SetTimeStamp( parseHex() );
2370  break;
2371 
2372  case T_status:
2373  segment->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
2374  break;
2375 
2376  default:
2377  Expecting( "layer or width" );
2378  }
2379 
2380  NeedRIGHT();
2381  }
2382 
2383  // Only filled polygons may have a zero-line width
2384  // This is not permitted in KiCad but some external tools generate invalid
2385  // files.
2386  if( segment->GetShape() != S_POLYGON && segment->GetWidth() == 0 )
2387  segment->SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) );
2388 
2389  return segment.release();
2390 }
polygon (not yet used for tracks, but could be in microwave apps)
wxPoint parseXY()
Function parseXY parses a coordinate pair (xy X Y) in board units (mm).
Definition: pcb_parser.cpp:207
#define DEFAULT_LINE_WIDTH
int parseBoardUnits()
Definition: pcb_parser.h:228
Arcs (with rounded ends)
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
Bezier Curve.
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:125
long parseHex()
Definition: pcb_parser.h:277

References DEFAULT_LINE_WIDTH, parseDouble(), parseHex(), S_ARC, S_CIRCLE, S_CURVE, and S_POLYGON.

◆ parseGeneralSection()

void PCB_PARSER::parseGeneralSection ( )
private

Definition at line 706 of file pcb_parser.cpp.

707 {
708  wxCHECK_RET( CurTok() == T_general,
709  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
710  wxT( " as a general section." ) );
711 
712  T token;
713 
714  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
715  {
716  if( token != T_LEFT )
717  Expecting( T_LEFT );
718 
719  token = NextTok();
720 
721  switch( token )
722  {
723  case T_thickness:
725  NeedRIGHT();
726  break;
727 
728  case T_nets:
729  m_netCodes.resize( parseInt( "nets number" ) );
730  NeedRIGHT();
731  break;
732 
733  case T_no_connects:
734  // ignore
735  parseInt( "no connect count" );
736  NeedRIGHT();
737  break;
738 
739  default: // Skip everything but the board thickness.
740  //wxLogDebug( wxT( "Skipping general section token %s " ), GetChars( GetTokenString( token ) ) );
741 
742  while( ( token = NextTok() ) != T_RIGHT )
743  {
744  if( !IsSymbol( token ) && token != T_NUMBER )
745  Expecting( "symbol or number" );
746  }
747  }
748  }
749 }
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:539
void SetBoardThickness(int aThickness)
int parseBoardUnits()
Definition: pcb_parser.h:228
std::vector< int > m_netCodes
net codes mapping for boards being loaded
Definition: pcb_parser.h:74
BOARD * m_board
Definition: pcb_parser.h:70
int parseInt()
Definition: pcb_parser.h:266

References parseInt().

◆ parseHeader()

void PCB_PARSER::parseHeader ( )
private

Definition at line 670 of file pcb_parser.cpp.

671 {
672  wxCHECK_RET( CurTok() == T_kicad_pcb,
673  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a header." ) );
674 
675  NeedLEFT();
676 
677  T tok = NextTok();
678  if( tok == T_version )
679  {
680  m_requiredVersion = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
682  NeedRIGHT();
683 
684  // Skip the host name and host build version information.
685  NeedLEFT();
686  NeedSYMBOL();
687  NeedSYMBOL();
688  NeedSYMBOL();
689  NeedRIGHT();
690  }
691  else
692  {
695 
696  // Skip the host name and host build version information.
697  NeedSYMBOL();
698  NeedSYMBOL();
699  NeedRIGHT();
700  }
701 
703 }
void SetFileFormatVersionAtLoad(int aVersion)
Definition: class_board.h:281
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:75
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:76
BOARD * m_board
Definition: pcb_parser.h:70
int parseInt()
Definition: pcb_parser.h:266

References parseInt(), and SEXPR_BOARD_FILE_VERSION.

◆ parseHex()

long PCB_PARSER::parseHex ( )
inlineprivate

Definition at line 277 of file pcb_parser.h.

278  {
279  NextTok();
280  return strtol( CurText(), NULL, 16 );
281  }

◆ parseInt() [1/2]

int PCB_PARSER::parseInt ( )
inlineprivate

Definition at line 266 of file pcb_parser.h.

267  {
268  return (int)strtol( CurText(), NULL, 10 );
269  }

Referenced by parseInt().

◆ parseInt() [2/2]

int PCB_PARSER::parseInt ( const char *  aExpected)
inlineprivate

Definition at line 271 of file pcb_parser.h.

272  {
273  NeedNUMBER( aExpected );
274  return parseInt();
275  }
int parseInt()
Definition: pcb_parser.h:266

References parseInt().

◆ parseLayer()

void PCB_PARSER::parseLayer ( LAYER aLayer)
private

Definition at line 891 of file pcb_parser.cpp.

892 {
893  T token;
894 
895  std::string name;
896  std::string type;
897  bool isVisible = true;
898 
899  aLayer->clear();
900 
901  if( CurTok() != T_LEFT )
902  Expecting( T_LEFT );
903 
904  // this layer_num is not used, we DO depend on LAYER_T however.
905  LAYER_NUM layer_num = parseInt( "layer index" );
906 
907  NeedSYMBOLorNUMBER();
908  name = CurText();
909 
910  NeedSYMBOL();
911  type = CurText();
912 
913  token = NextTok();
914 
915  if( token == T_hide )
916  {
917  isVisible = false;
918  NeedRIGHT();
919  }
920  else if( token != T_RIGHT )
921  {
922  Expecting( "hide or )" );
923  }
924 
925  aLayer->m_name = FROM_UTF8( name.c_str() );
926  aLayer->m_type = LAYER::ParseType( type.c_str() );
927  aLayer->m_number = layer_num;
928  aLayer->m_visible = isVisible;
929 }
static wxString FROM_UTF8(const char *cstring)
function FROM_UTF8 converts a UTF8 encoded C string to a wxString for all wxWidgets build modes.
Definition: macros.h:53
wxString m_name
The name of the layer, there should be no spaces in this name.
Definition: class_board.h:113
LAYER_T m_type
The type of the layer.
Definition: class_board.h:115
bool m_visible
Definition: class_board.h:117
static LAYER_T ParseType(const char *aType)
Function ParseType converts a string to a LAYER_T.
int LAYER_NUM
Type LAYER_NUM can be replaced with int and removed.
void clear()
Definition: class_board.h:94
const char * name
Definition: DXF_plotter.cpp:61
int m_number
Definition: class_board.h:119
int parseInt()
Definition: pcb_parser.h:266

References LAYER::clear(), FROM_UTF8(), LAYER::m_name, LAYER::m_number, LAYER::m_type, LAYER::m_visible, name, parseInt(), and LAYER::ParseType().

◆ parseLayers()

void PCB_PARSER::parseLayers ( )
private

Definition at line 933 of file pcb_parser.cpp.

934 {
935  wxCHECK_RET( CurTok() == T_layers,
936  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as layers." ) );
937 
938  T token;
939  LSET visibleLayers;
940  LSET enabledLayers;
941  int copperLayerCount = 0;
942  LAYER layer;
943 
944  std::vector<LAYER> cu;
945 
946  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
947  {
948  parseLayer( &layer );
949 
950  if( layer.m_type == LT_UNDEFINED ) // it's a non-copper layer
951  break;
952 
953  cu.push_back( layer ); // it's copper
954  }
955 
956  // All Cu layers are parsed, but not the non-cu layers here.
957 
958  // The original *.kicad_pcb file format and the inverted
959  // Cu stack format both have all the Cu layers first, so use this
960  // trick to handle either. The layer number in the (layers ..)
961  // s-expression element are ignored.
962  if( cu.size() )
963  {
964  // Rework the layer numbers, which changed when the Cu stack
965  // was flipped. So we instead use position in the list.
966  cu[cu.size()-1].m_number = B_Cu;
967 
968  for( unsigned i=0; i < cu.size()-1; ++i )
969  {
970  cu[i].m_number = i;
971  }
972 
973  for( std::vector<LAYER>::const_iterator it = cu.begin(); it<cu.end(); ++it )
974  {
975  enabledLayers.set( it->m_number );
976 
977  if( it->m_visible )
978  visibleLayers.set( it->m_number );
979 
980  m_board->SetLayerDescr( PCB_LAYER_ID( it->m_number ), *it );
981 
982  UTF8 name = it->m_name;
983 
984  m_layerIndices[ name ] = PCB_LAYER_ID( it->m_number );
985  m_layerMasks[ name ] = LSET( PCB_LAYER_ID( it->m_number ) );
986  }
987 
988  copperLayerCount = cu.size();
989  }
990 
991  // process non-copper layers
992  while( token != T_RIGHT )
993  {
994  LAYER_ID_MAP::const_iterator it = m_layerIndices.find( UTF8( layer.m_name ) );
995 
996  if( it == m_layerIndices.end() )
997  {
998  wxString error = wxString::Format(
999  _( "Layer \"%s\" in file \"%s\" at line %d, is not in fixed layer hash" ),
1000  GetChars( layer.m_name ),
1001  GetChars( CurSource() ),
1002  CurLineNumber(),
1003  CurOffset()
1004  );
1005 
1006  THROW_IO_ERROR( error );
1007  }
1008 
1009  layer.m_number = it->second;
1010 
1011  enabledLayers.set( layer.m_number );
1012 
1013  if( layer.m_visible )
1014  visibleLayers.set( layer.m_number );
1015 
1016  // DBG( printf( "aux m_visible:%s\n", layer.m_visible ? "true" : "false" );)
1017 
1018  m_board->SetLayerDescr( it->second, layer );
1019 
1020  token = NextTok();
1021 
1022  if( token != T_LEFT )
1023  break;
1024 
1025  parseLayer( &layer );
1026  }
1027 
1028  // We need at least 2 copper layers and there must be an even number of them.
1029  if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
1030  {
1031  wxString err = wxString::Format(
1032  _( "%d is not a valid layer count" ), copperLayerCount );
1033 
1034  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
1035  }
1036 
1037  m_board->SetCopperLayerCount( copperLayerCount );
1038  m_board->SetEnabledLayers( enabledLayers );
1039 
1040  // call SetEnabledLayers before SetVisibleLayers()
1041  m_board->SetVisibleLayers( visibleLayers );
1042 }
Class UTF8 is an 8 bit string that is assuredly encoded in UTF8, and supplies special conversion supp...
Definition: utf8.h:73
wxString m_name
The name of the layer, there should be no spaces in this name.
Definition: class_board.h:113
LAYER_T m_type
The type of the layer.
Definition: class_board.h:115
void SetCopperLayerCount(int aCount)
#define cu(a)
Definition: auxiliary.h:88
PCB_LAYER_ID
A quick note on layer IDs:
Class LSET is a set of PCB_LAYER_IDs.
void SetVisibleLayers(LSET aLayerMask)
Function SetVisibleLayers is a proxy function that calls the correspondent function in m_BoardSetting...
bool SetLayerDescr(PCB_LAYER_ID aIndex, const LAYER &aLayer)
Function SetLayerDescr returns the type of the copper layer given by aLayer.
bool m_visible
Definition: class_board.h:117
#define THROW_IO_ERROR(msg)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
string & err
Definition: json11.cpp:598
void parseLayer(LAYER *aLayer)
Definition: pcb_parser.cpp:891
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
const char * name
Definition: DXF_plotter.cpp:61
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
Class LAYER holds information pertinent to a layer of a BOARD.
Definition: class_board.h:87
BOARD * m_board
Definition: pcb_parser.h:70
size_t i
Definition: json11.cpp:597
LAYER_ID_MAP m_layerIndices
map layer name to it's index
Definition: pcb_parser.h:71
int m_number
Definition: class_board.h:119
void SetEnabledLayers(LSET aLayerMask)
Function SetEnabledLayers is a proxy function that calls the correspondent function in m_BoardSetting...
LSET_MAP m_layerMasks
map layer names to their masks
Definition: pcb_parser.h:72

References B_Cu, cu, err, Format(), GetChars(), i, LT_UNDEFINED, LAYER::m_name, LAYER::m_number, LAYER::m_type, LAYER::m_visible, name, THROW_IO_ERROR, and THROW_PARSE_ERROR.

◆ parseMODULE()

MODULE * PCB_PARSER::parseMODULE ( wxArrayString *  aInitialComments = 0)

Function parseMODULE.

Parameters
aInitialCommentsmay be a pointer to a heap allocated initial comment block or NULL. If not NULL, then caller has given ownership of a wxArrayString to this function and care must be taken to delete it even on exception.

Definition at line 1860 of file pcb_parser.cpp.

1861 {
1862  try
1863  {
1864  return parseMODULE_unchecked( aInitialComments );
1865  }
1866  catch( const PARSE_ERROR& parse_error )
1867  {
1868  if( m_tooRecent )
1869  throw FUTURE_FORMAT_ERROR( parse_error, GetRequiredVersion() );
1870  else
1871  throw;
1872  }
1873 }
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:75
wxString GetRequiredVersion()
Return a string representing the version of kicad required to open this file.
Definition: pcb_parser.cpp:183
MODULE * parseMODULE_unchecked(wxArrayString *aInitialComments=0)
Function parseMODULE_unchecked Parse a module, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERRO...
Struct PARSE_ERROR contains a filename or source description, a problem input line,...
Definition: ki_exception.h:123
Struct FUTURE_FORMAT_ERROR variant of PARSE_ERROR indicating that a syntax or related error was likel...
Definition: ki_exception.h:172

Referenced by CLIPBOARD_PARSER::parseMODULE().

◆ parseMODULE_unchecked()

MODULE * PCB_PARSER::parseMODULE_unchecked ( wxArrayString *  aInitialComments = 0)
private

Function parseMODULE_unchecked Parse a module, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR automatically.

Definition at line 1876 of file pcb_parser.cpp.

1877 {
1878  wxCHECK_MSG( CurTok() == T_module, NULL,
1879  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as MODULE." ) );
1880 
1881  wxString name;
1882  wxPoint pt;
1883  T token;
1884  LIB_ID fpid;
1885 
1886  std::unique_ptr<MODULE> module( new MODULE( m_board ) );
1887 
1888  module->SetInitialComments( aInitialComments );
1889 
1890  token = NextTok();
1891 
1892  if( !IsSymbol( token ) && token != T_NUMBER )
1893  Expecting( "symbol|number" );
1894 
1895  name = FromUTF8();
1896 
1897  if( !name.IsEmpty() && fpid.Parse( name, LIB_ID::ID_PCB, true ) >= 0 )
1898  {
1899  wxString error;
1900  error.Printf( _( "Invalid footprint ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1901  GetChars( CurSource() ), CurLineNumber(), CurOffset() );
1902  THROW_IO_ERROR( error );
1903  }
1904 
1905  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1906  {
1907  if( token == T_LEFT )
1908  token = NextTok();
1909 
1910  switch( token )
1911  {
1912  case T_version:
1913  {
1914  // Theoretically a module nested in a PCB could declare its own version, though
1915  // as of writing this comment we don't do that. Just in case, take the greater
1916  // version.
1917  int this_version = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
1918  NeedRIGHT();
1919  m_requiredVersion = std::max( m_requiredVersion, this_version );
1921  break;
1922  }
1923 
1924  case T_locked:
1925  module->SetLocked( true );
1926  break;
1927 
1928  case T_placed:
1929  module->SetIsPlaced( true );
1930  break;
1931 
1932  case T_layer:
1933  {
1934  // Footprints can be only on the front side or the back side.
1935  // but because we can find some stupid layer in file, ensure a
1936  // acceptable layer is set for the footprint
1938  module->SetLayer( layer == B_Cu ? B_Cu : F_Cu );
1939  }
1940  NeedRIGHT();
1941  break;
1942 
1943  case T_tedit:
1944  module->SetLastEditTime( parseHex() );
1945  NeedRIGHT();
1946  break;
1947 
1948  case T_tstamp:
1949  module->SetTimeStamp( parseHex() );
1950  NeedRIGHT();
1951  break;
1952 
1953  case T_at:
1954  pt.x = parseBoardUnits( "X coordinate" );
1955  pt.y = parseBoardUnits( "Y coordinate" );
1956  module->SetPosition( pt );
1957  token = NextTok();
1958 
1959  if( token == T_NUMBER )
1960  {
1961  module->SetOrientation( parseDouble() * 10.0 );
1962  NeedRIGHT();
1963  }
1964  else if( token != T_RIGHT )
1965  {
1966  Expecting( T_RIGHT );
1967  }
1968 
1969  break;
1970 
1971  case T_descr:
1972  NeedSYMBOLorNUMBER(); // some symbols can be 0508, so a number is also a symbol here
1973  module->SetDescription( FromUTF8() );
1974  NeedRIGHT();
1975  break;
1976 
1977  case T_tags:
1978  NeedSYMBOLorNUMBER(); // some symbols can be 0508, so a number is also a symbol here
1979  module->SetKeywords( FromUTF8() );
1980  NeedRIGHT();
1981  break;
1982 
1983  case T_path:
1984  NeedSYMBOLorNUMBER(); // Paths can be numerical so a number is also a symbol here
1985  module->SetPath( FromUTF8() );
1986  NeedRIGHT();
1987  break;
1988 
1989  case T_autoplace_cost90:
1990  module->SetPlacementCost90( parseInt( "auto place cost at 90 degrees" ) );
1991  NeedRIGHT();
1992  break;
1993 
1994  case T_autoplace_cost180:
1995  module->SetPlacementCost180( parseInt( "auto place cost at 180 degrees" ) );
1996  NeedRIGHT();
1997  break;
1998 
1999  case T_solder_mask_margin:
2000  module->SetLocalSolderMaskMargin( parseBoardUnits( "local solder mask margin value" ) );
2001  NeedRIGHT();
2002  break;
2003 
2004  case T_solder_paste_margin:
2005  module->SetLocalSolderPasteMargin(
2006  parseBoardUnits( "local solder paste margin value" ) );
2007  NeedRIGHT();
2008  break;
2009 
2010  case T_solder_paste_ratio:
2011  module->SetLocalSolderPasteMarginRatio(
2012  parseDouble( "local solder paste margin ratio value" ) );
2013  NeedRIGHT();
2014  break;
2015 
2016  case T_clearance:
2017  module->SetLocalClearance( parseBoardUnits( "local clearance value" ) );
2018  NeedRIGHT();
2019  break;
2020 
2021  case T_zone_connect:
2022  module->SetZoneConnection( (ZoneConnection) parseInt( "zone connection value" ) );
2023  NeedRIGHT();
2024  break;
2025 
2026  case T_thermal_width:
2027  module->SetThermalWidth( parseBoardUnits( "thermal width value" ) );
2028  NeedRIGHT();
2029  break;
2030 
2031  case T_thermal_gap:
2032  module->SetThermalGap( parseBoardUnits( "thermal gap value" ) );
2033  NeedRIGHT();
2034  break;
2035 
2036  case T_attr:
2037  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2038  {
2039  switch( token )
2040  {
2041  case T_smd:
2042  module->SetAttributes( module->GetAttributes() | MOD_CMS );
2043  break;
2044 
2045  case T_virtual:
2046  module->SetAttributes( module->GetAttributes() | MOD_VIRTUAL );
2047  break;
2048 
2049  default:
2050  Expecting( "smd and/or virtual" );
2051  }
2052  }
2053  break;
2054 
2055  case T_fp_text:
2056  {
2057  TEXTE_MODULE* text = parseTEXTE_MODULE();
2058  text->SetParent( module.get() );
2059  double orientation = text->GetTextAngle();
2060  orientation -= module->GetOrientation();
2061  text->SetTextAngle( orientation );
2062  text->SetDrawCoord();
2063 
2064  switch( text->GetType() )
2065  {
2067  module->Reference() = *text;
2068  delete text;
2069  break;
2070 
2072  module->Value() = *text;
2073  delete text;
2074  break;
2075 
2076  default:
2077  module->GraphicalItemsList().PushBack( text );
2078  }
2079  }
2080  break;
2081 
2082  case T_fp_arc:
2083  case T_fp_circle:
2084  case T_fp_curve:
2085  case T_fp_line:
2086  case T_fp_poly:
2087  {
2088  EDGE_MODULE* em = parseEDGE_MODULE();
2089  em->SetParent( module.get() );
2090  em->SetDrawCoord();
2091  module->GraphicalItemsList().PushBack( em );
2092  }
2093  break;
2094 
2095  case T_pad:
2096  {
2097  D_PAD* pad = parseD_PAD( module.get() );
2098  pt = pad->GetPos0();
2099 
2100  RotatePoint( &pt, module->GetOrientation() );
2101  pad->SetPosition( pt + module->GetPosition() );
2102  module->Add( pad, ADD_APPEND );
2103  }
2104  break;
2105 
2106  case T_model:
2107  module->Add3DModel( parse3DModel() );
2108  break;
2109 
2110  default:
2111  Expecting( "locked, placed, tedit, tstamp, at, descr, tags, path, "
2112  "autoplace_cost90, autoplace_cost180, solder_mask_margin, "
2113  "solder_paste_margin, solder_paste_ratio, clearance, "
2114  "zone_connect, thermal_width, thermal_gap, attr, fp_text, "
2115  "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, pad, or model" );
2116  }
2117  }
2118 
2119  module->SetFPID( fpid );
2120  module->CalculateBoundingBox();
2121 
2122  return module.release();
2123 }
const wxPoint & GetPos0() const
Definition: class_pad.h:263
ZoneConnection
How pads are covered by copper in zone.
Definition: zones.h:50
Set for modules listed in the automatic insertion list (usually SMD footprints)
Definition: class_module.h:76
#define SEXPR_BOARD_FILE_VERSION
Current s-expression file format version. 2 was the last legacy format version.
double GetTextAngle() const
Definition: eda_text.h:177
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:219
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:75
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:216
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
int parseBoardUnits()
Definition: pcb_parser.h:228
PCB_LAYER_ID
A quick note on layer IDs:
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:216
TEXT_TYPE GetType() const
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
#define THROW_IO_ERROR(msg)
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:76
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
EDGE_MODULE * parseEDGE_MODULE()
const char * name
Definition: DXF_plotter.cpp:61
#define max(a, b)
Definition: auxiliary.h:86
BOARD * m_board
Definition: pcb_parser.h:70
Virtual component: when created by copper shapes on board (Like edge card connectors,...
Definition: class_module.h:78
void SetDrawCoord()
Set absolute coordinates.
void SetDrawCoord()
Set draw coordinates (absolute values ) from relative coordinates.
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:125
void SetTextAngle(double aAngle)
TEXTE_MODULE * parseTEXTE_MODULE()
D_PAD * parseD_PAD(MODULE *aParent=NULL)
long parseHex()
Definition: pcb_parser.h:277
int parseInt()
Definition: pcb_parser.h:266
int Parse(const UTF8 &aId, LIB_ID_TYPE aType, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:122
MODULE_3D_SETTINGS * parse3DModel()
Definition: pcb_parser.cpp:351

References ADD_APPEND, B_Cu, F_Cu, GetChars(), D_PAD::GetPos0(), EDA_TEXT::GetTextAngle(), TEXTE_MODULE::GetType(), LIB_ID::ID_PCB, max, MOD_CMS, MOD_VIRTUAL, name, LIB_ID::Parse(), parseDouble(), parseHex(), parseInt(), RotatePoint(), EDGE_MODULE::SetDrawCoord(), TEXTE_MODULE::SetDrawCoord(), EDA_ITEM::SetParent(), D_PAD::SetPosition(), TEXTE_MODULE::SetTextAngle(), SEXPR_BOARD_FILE_VERSION, TEXTE_MODULE::TEXT_is_REFERENCE, TEXTE_MODULE::TEXT_is_VALUE, and THROW_IO_ERROR.

◆ parseNETCLASS()

void PCB_PARSER::parseNETCLASS ( )
private

Definition at line 1373 of file pcb_parser.cpp.

1374 {
1375  wxCHECK_RET( CurTok() == T_net_class,
1376  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as net class." ) );
1377 
1378  T token;
1379 
1380  NETCLASSPTR nc = std::make_shared<NETCLASS>( wxEmptyString );
1381 
1382  // Read netclass name (can be a name or just a number like track width)
1383  NeedSYMBOLorNUMBER();
1384  nc->SetName( FromUTF8() );
1385  NeedSYMBOL();
1386  nc->SetDescription( FromUTF8() );
1387 
1388  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1389  {
1390  if( token != T_LEFT )
1391  Expecting( T_LEFT );
1392 
1393  token = NextTok();
1394 
1395  switch( token )
1396  {
1397  case T_clearance:
1398  nc->SetClearance( parseBoardUnits( T_clearance ) );
1399  break;
1400 
1401  case T_trace_width:
1402  nc->SetTrackWidth( parseBoardUnits( T_trace_width ) );
1403  break;
1404 
1405  case T_via_dia:
1406  nc->SetViaDiameter( parseBoardUnits( T_via_dia ) );
1407  break;
1408 
1409  case T_via_drill:
1410  nc->SetViaDrill( parseBoardUnits( T_via_drill ) );
1411  break;
1412 
1413  case T_uvia_dia:
1414  nc->SetuViaDiameter( parseBoardUnits( T_uvia_dia ) );
1415  break;
1416 
1417  case T_uvia_drill:
1418  nc->SetuViaDrill( parseBoardUnits( T_uvia_drill ) );
1419  break;
1420 
1421  case T_diff_pair_width:
1422  nc->SetDiffPairWidth( parseBoardUnits( T_diff_pair_width ) );
1423  break;
1424 
1425  case T_diff_pair_gap:
1426  nc->SetDiffPairGap( parseBoardUnits( T_diff_pair_gap ) );
1427  break;
1428 
1429  case T_add_net:
1430  NeedSYMBOLorNUMBER();
1431  nc->Add( FromUTF8() );
1432  break;
1433 
1434  default:
1435  Expecting( "clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, diff_pair_width, diff_pair_gap or add_net" );
1436  }
1437 
1438  NeedRIGHT();
1439  }
1440 
1441  if( !m_board->GetDesignSettings().m_NetClasses.Add( nc ) )
1442  {
1443  // Must have been a name conflict, this is a bad board file.
1444  // User may have done a hand edit to the file.
1445 
1446  // unique_ptr will delete nc on this code path
1447 
1448  wxString error;
1449  error.Printf( _( "Duplicate NETCLASS name \"%s\" in file \"%s\" at line %d, offset %d" ),
1450  nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(), CurOffset() );
1451  THROW_IO_ERROR( error );
1452  }
1453 }
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:539
int parseBoardUnits()
Definition: pcb_parser.h:228
#define THROW_IO_ERROR(msg)
bool Add(const NETCLASSPTR &aNetclass)
Function Add takes aNetclass and puts it into this NETCLASSES container.
Definition: netclass.cpp:99
BOARD * m_board
Definition: pcb_parser.h:70

References THROW_IO_ERROR.

◆ parseNETINFO_ITEM()

void PCB_PARSER::parseNETINFO_ITEM ( )
private

Definition at line 1347 of file pcb_parser.cpp.

1348 {
1349  wxCHECK_RET( CurTok() == T_net,
1350  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as net." ) );
1351 
1352  int netCode = parseInt( "net number" );
1353 
1354  NeedSYMBOLorNUMBER();
1355  wxString name = FromUTF8();
1356 
1357  NeedRIGHT();
1358 
1359  // net 0 should be already in list, so store this net
1360  // if it is not the net 0, or if the net 0 does not exists.
1361  // (TODO: a better test.)
1363  {
1364  NETINFO_ITEM* net = new NETINFO_ITEM( m_board, name, netCode );
1365  m_board->Add( net );
1366 
1367  // Store the new code mapping
1368  pushValueIntoMap( netCode, net->GetNet() );
1369  }
1370 }
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_INSERT) override
Adds an item to the container.
Class NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:69
const char * name
Definition: DXF_plotter.cpp:61
int GetNet() const
Function GetNet.
Definition: netinfo.h:231
BOARD * m_board
Definition: pcb_parser.h:70
void pushValueIntoMap(int aIndex, int aValue)
function pushValueIntoMap Add aValue value in netcode mapping (m_netCodes) at index aIndex ensure the...
Definition: pcb_parser.cpp:114
int parseInt()
Definition: pcb_parser.h:266
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:469

References NETINFO_ITEM::GetNet(), name, parseInt(), and NETINFO_LIST::UNCONNECTED.

◆ parsePAGE_INFO()

void PCB_PARSER::parsePAGE_INFO ( )
private

Definition at line 752 of file pcb_parser.cpp.

753 {
754  wxCHECK_RET( CurTok() == T_page,
755  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a PAGE_INFO." ) );
756 
757  T token;
758  PAGE_INFO pageInfo;
759 
760  NeedSYMBOL();
761 
762  wxString pageType = FromUTF8();
763 
764  if( !pageInfo.SetType( pageType ) )
765  {
766  wxString err;
767  err.Printf( _( "Page type \"%s\" is not valid " ), GetChars( FromUTF8() ) );
768  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
769  }
770 
771  if( pageType == PAGE_INFO::Custom )
772  {
773  double width = parseDouble( "width" ); // width in mm
774 
775  // Perform some controls to avoid crashes if the size is edited by hands
776  if( width < 100.0 )
777  width = 100.0;
778  else if( width > 1200.0 )
779  width = 1200.0;
780 
781  double height = parseDouble( "height" ); // height in mm
782 
783  if( height < 100.0 )
784  height = 100.0;
785  else if( height > 1200.0 )
786  height = 1200.0;
787 
788  pageInfo.SetWidthMils( Mm2mils( width ) );
789  pageInfo.SetHeightMils( Mm2mils( height ) );
790  }
791 
792  token = NextTok();
793 
794  if( token == T_portrait )
795  {
796  pageInfo.SetPortrait( true );
797  NeedRIGHT();
798  }
799  else if( token != T_RIGHT )
800  {
801  Expecting( "portrait|)" );
802  }
803 
804  m_board->SetPageSettings( pageInfo );
805 }
int Mm2mils(double x)
Convert mm to mils.
Definition: base_units.h:51
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: class_board.h:555
bool SetType(const wxString &aStandardPageDescriptionName, bool aIsPortrait=false)
Function SetType sets the name of the page type and also the sizes and margins commonly associated wi...
Definition: page_info.cpp:117
static const wxChar Custom[]
"User" defined page type
Definition: page_info.h:78
Class PAGE_INFO describes the page size and margins of a paper page on which to eventually print or p...
Definition: page_info.h:54
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
string & err
Definition: json11.cpp:598
void SetHeightMils(int aHeightInMils)
Definition: page_info.cpp:253
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
BOARD * m_board
Definition: pcb_parser.h:70
void SetWidthMils(int aWidthInMils)
Definition: page_info.cpp:239
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:125
void SetPortrait(bool aIsPortrait)
Function SetPortrait will rotate the paper page 90 degrees.
Definition: page_info.cpp:182

References PAGE_INFO::Custom, err, GetChars(), Mm2mils(), parseDouble(), PAGE_INFO::SetHeightMils(), PAGE_INFO::SetPortrait(), PAGE_INFO::SetType(), PAGE_INFO::SetWidthMils(), and THROW_PARSE_ERROR.

◆ parsePCB_TARGET()

PCB_TARGET * PCB_PARSER::parsePCB_TARGET ( )
private

Definition at line 3357 of file pcb_parser.cpp.

3358 {
3359  wxCHECK_MSG( CurTok() == T_target, NULL,
3360  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as PCB_TARGET." ) );
3361 
3362  wxPoint pt;
3363  T token;
3364 
3365  std::unique_ptr< PCB_TARGET > target( new PCB_TARGET( NULL ) );
3366 
3367  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3368  {
3369  if( token == T_LEFT )
3370  token = NextTok();
3371 
3372  switch( token )
3373  {
3374  case T_x:
3375  target->SetShape( 1 );
3376  break;
3377 
3378  case T_plus:
3379  target->SetShape( 0 );
3380  break;
3381 
3382  case T_at:
3383  pt.x = parseBoardUnits( "target x position" );
3384  pt.y = parseBoardUnits( "target y position" );
3385  target->SetPosition( pt );
3386  NeedRIGHT();
3387  break;
3388 
3389  case T_size:
3390  target->SetSize( parseBoardUnits( "target size" ) );
3391  NeedRIGHT();
3392  break;
3393 
3394  case T_width:
3395  target->SetWidth( parseBoardUnits( "target thickness" ) );
3396  NeedRIGHT();
3397  break;
3398 
3399  case T_layer:
3400  target->SetLayer( parseBoardItemLayer() );
3401  NeedRIGHT();
3402  break;
3403 
3404  case T_tstamp:
3405  target->SetTimeStamp( parseHex() );
3406  NeedRIGHT();
3407  break;
3408 
3409  default:
3410  Expecting( "x, plus, at, size, width, layer or tstamp" );
3411  }
3412  }
3413 
3414  return target.release();
3415 }
int parseBoardUnits()
Definition: pcb_parser.h:228
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
long parseHex()
Definition: pcb_parser.h:277

References parseHex().

◆ parseSetup()

void PCB_PARSER::parseSetup ( )
private

Definition at line 1103 of file pcb_parser.cpp.

1104 {
1105  wxCHECK_RET( CurTok() == T_setup,
1106  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as setup." ) );
1107 
1108  T token;
1109  NETCLASSPTR defaultNetClass = m_board->GetDesignSettings().GetDefault();
1110  // TODO Orson: is it really necessary to first operate on a copy and then apply it?
1111  // would not it be better to use reference here and apply all the changes instantly?
1112  BOARD_DESIGN_SETTINGS designSettings = m_board->GetDesignSettings();
1113  ZONE_SETTINGS zoneSettings = m_board->GetZoneSettings();
1114 
1115  // Missing soldermask min width value means that the user has set the value to 0 and
1116  // not the default value (0.25mm)
1117  designSettings.m_SolderMaskMinWidth = 0;
1118 
1119  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1120  {
1121  if( token != T_LEFT )
1122  Expecting( T_LEFT );
1123 
1124  token = NextTok();
1125 
1126  switch( token )
1127  {
1128  case T_last_trace_width: // not used now
1129  /* lastTraceWidth =*/ parseBoardUnits( T_last_trace_width );
1130  NeedRIGHT();
1131  break;
1132 
1133  case T_user_trace_width:
1134  designSettings.m_TrackWidthList.push_back( parseBoardUnits( T_user_trace_width ) );
1135  NeedRIGHT();
1136  break;
1137 
1138  case T_trace_clearance:
1139  defaultNetClass->SetClearance( parseBoardUnits( T_trace_clearance ) );
1140  NeedRIGHT();
1141  break;
1142 
1143  case T_zone_clearance:
1144  zoneSettings.m_ZoneClearance = parseBoardUnits( T_zone_clearance );
1145  NeedRIGHT();
1146  break;
1147 
1148  case T_zone_45_only:
1149  zoneSettings.m_Zone_45_Only = parseBool();
1150  NeedRIGHT();
1151  break;
1152 
1153  case T_trace_min:
1154  designSettings.m_TrackMinWidth = parseBoardUnits( T_trace_min );
1155  NeedRIGHT();
1156  break;
1157 
1158  case T_via_size:
1159  defaultNetClass->SetViaDiameter( parseBoardUnits( T_via_size ) );
1160  NeedRIGHT();
1161  break;
1162 
1163  case T_via_drill:
1164  defaultNetClass->SetViaDrill( parseBoardUnits( T_via_drill ) );
1165  NeedRIGHT();
1166  break;
1167 
1168  case T_via_min_size:
1169  designSettings.m_ViasMinSize = parseBoardUnits( T_via_min_size );
1170  NeedRIGHT();
1171  break;
1172 
1173  case T_via_min_drill:
1174  designSettings.m_ViasMinDrill = parseBoardUnits( T_via_min_drill );
1175  NeedRIGHT();
1176  break;
1177 
1178  case T_user_via:
1179  {
1180  int viaSize = parseBoardUnits( "user via size" );
1181  int viaDrill = parseBoardUnits( "user via drill" );
1182  designSettings.m_ViasDimensionsList.push_back( VIA_DIMENSION( viaSize, viaDrill ) );
1183  NeedRIGHT();
1184  }
1185  break;
1186 
1187  case T_uvia_size:
1188  defaultNetClass->SetuViaDiameter( parseBoardUnits( T_uvia_size ) );
1189  NeedRIGHT();
1190  break;
1191 
1192  case T_uvia_drill:
1193  defaultNetClass->SetuViaDrill( parseBoardUnits( T_uvia_drill ) );
1194  NeedRIGHT();
1195  break;
1196 
1197  case T_uvias_allowed:
1198  designSettings.m_MicroViasAllowed = parseBool();
1199  NeedRIGHT();
1200  break;
1201 
1202  case T_blind_buried_vias_allowed:
1203  designSettings.m_BlindBuriedViaAllowed = parseBool();
1204  NeedRIGHT();
1205  break;
1206 
1207  case T_uvia_min_size:
1208  designSettings.m_MicroViasMinSize = parseBoardUnits( T_uvia_min_size );
1209  NeedRIGHT();
1210  break;
1211 
1212  case T_uvia_min_drill:
1213  designSettings.m_MicroViasMinDrill = parseBoardUnits( T_uvia_min_drill );
1214  NeedRIGHT();
1215  break;
1216 
1217  // 6.0 TODO: change these names, or leave them?
1218  // 6.0 TODO: add LAYER_CLASS_OTHERS read/write
1219  // 6.0 TODO: add m_TextItalic read/write
1220  // 6.0 TODO: add m_TextUpright read/write
1221 
1222  case T_segment_width:
1223  designSettings.m_LineThickness[ LAYER_CLASS_COPPER ] = parseBoardUnits( T_segment_width );
1224  NeedRIGHT();
1225  break;
1226 
1227  case T_edge_width:
1228  designSettings.m_LineThickness[ LAYER_CLASS_EDGES ] = parseBoardUnits( T_edge_width );
1229  NeedRIGHT();
1230  break;
1231 
1232  case T_mod_edge_width:
1233  designSettings.m_LineThickness[ LAYER_CLASS_SILK ] = parseBoardUnits( T_mod_edge_width );
1234  NeedRIGHT();
1235  break;
1236 
1237  case T_pcb_text_width:
1238  designSettings.m_TextThickness[ LAYER_CLASS_COPPER ] = parseBoardUnits( T_pcb_text_width );
1239  NeedRIGHT();
1240  break;
1241 
1242  case T_mod_text_width:
1243  designSettings.m_TextThickness[ LAYER_CLASS_SILK ] = parseBoardUnits( T_mod_text_width );
1244  NeedRIGHT();
1245  break;
1246 
1247  case T_pcb_text_size:
1248  designSettings.m_TextSize[ LAYER_CLASS_COPPER ].x = parseBoardUnits( "pcb text width" );
1249  designSettings.m_TextSize[ LAYER_CLASS_COPPER ].y = parseBoardUnits( "pcb text height" );
1250  NeedRIGHT();
1251  break;
1252 
1253  case T_mod_text_size:
1254  designSettings.m_TextSize[ LAYER_CLASS_SILK ].x = parseBoardUnits( "module text width" );
1255  designSettings.m_TextSize[ LAYER_CLASS_SILK ].y = parseBoardUnits( "module text height" );
1256  NeedRIGHT();
1257  break;
1258 
1259  case T_pad_size:
1260  {
1261  wxSize sz;
1262  sz.SetWidth( parseBoardUnits( "master pad width" ) );
1263  sz.SetHeight( parseBoardUnits( "master pad height" ) );
1264  designSettings.m_Pad_Master.SetSize( sz );
1265  NeedRIGHT();
1266  }
1267  break;
1268 
1269  case T_pad_drill:
1270  {
1271  int drillSize = parseBoardUnits( T_pad_drill );
1272  designSettings.m_Pad_Master.SetDrillSize( wxSize( drillSize, drillSize ) );
1273  NeedRIGHT();
1274  }
1275  break;
1276 
1277  case T_pad_to_mask_clearance:
1278  designSettings.m_SolderMaskMargin = parseBoardUnits( T_pad_to_mask_clearance );
1279  NeedRIGHT();
1280  break;
1281 
1282  case T_solder_mask_min_width:
1283  designSettings.m_SolderMaskMinWidth = parseBoardUnits( T_solder_mask_min_width );
1284  NeedRIGHT();
1285  break;
1286 
1287  case T_pad_to_paste_clearance:
1288  designSettings.m_SolderPasteMargin = parseBoardUnits( T_pad_to_paste_clearance );
1289  NeedRIGHT();
1290  break;
1291 
1292  case T_pad_to_paste_clearance_ratio:
1293  designSettings.m_SolderPasteMarginRatio = parseDouble( T_pad_to_paste_clearance_ratio );
1294  NeedRIGHT();
1295  break;
1296 
1297  case T_aux_axis_origin:
1298  {
1299  int x = parseBoardUnits( "auxiliary origin X" );
1300  int y = parseBoardUnits( "auxiliary origin Y" );
1301  // m_board->SetAuxOrigin( wxPoint( x, y ) ); gets overwritten via SetDesignSettings below
1302  designSettings.m_AuxOrigin = wxPoint( x, y );
1303  NeedRIGHT();
1304  }
1305  break;
1306 
1307  case T_grid_origin:
1308  {
1309  int x = parseBoardUnits( "grid origin X" );
1310  int y = parseBoardUnits( "grid origin Y" );
1311  // m_board->SetGridOrigin( wxPoint( x, y ) ); gets overwritten SetDesignSettings below
1312  designSettings.m_GridOrigin = wxPoint( x, y );
1313  NeedRIGHT();
1314  }
1315  break;
1316 
1317  case T_visible_elements:
1318  designSettings.SetVisibleElements( parseHex() | MIN_VISIBILITY_MASK );
1319  NeedRIGHT();
1320  break;
1321 
1322  case T_pcbplotparams:
1323  {
1324  PCB_PLOT_PARAMS plotParams;
1325  PCB_PLOT_PARAMS_PARSER parser( reader );
1326  // parser must share the same current line as our current PCB parser
1327  // synchronize it.
1328  parser.SyncLineReaderWith( *this );
1329 
1330  plotParams.Parse( &parser );
1331  SyncLineReaderWith( parser );
1332 
1333  m_board->SetPlotOptions( plotParams );
1334  }
1335  break;
1336 
1337  default:
1338  Unexpected( CurText() );
1339  }
1340  }
1341 
1342  m_board->SetDesignSettings( designSettings );
1343  m_board->SetZoneSettings( zoneSettings );
1344 }
int m_SolderMaskMargin
Solder mask margin.
Struct VIA_DIMENSION is a small helper container to handle a stock of specific vias each with unique ...
void SetZoneSettings(const ZONE_SETTINGS &aSettings)
Definition: class_board.h:564
wxPoint m_GridOrigin
origin for grid offsets
int m_SolderPasteMargin
Solder paste margin absolute value.
Class PCB_PLOT_PARAMS_PARSER is the parser class for PCB_PLOT_PARAMS.
std::vector< int > m_TrackWidthList
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:539
void SetDrillSize(const wxSize &aSize)
Definition: class_pad.h:274
int parseBoardUnits()
Definition: pcb_parser.h:228
wxSize m_TextSize[LAYER_CLASS_COUNT]
bool parseBool()
Definition: pcb_parser.cpp:155
int m_TextThickness[LAYER_CLASS_COUNT]
#define MIN_VISIBILITY_MASK
int m_TrackMinWidth
track min value for width ((min copper size value
int m_ViasMinSize
vias (not micro vias) min diameter
int m_ViasMinDrill
vias (not micro vias) min drill diameter
void SetSize(const wxSize &aSize)
Definition: class_pad.h:268
int m_ZoneClearance
Clearance value.
Definition: zone_settings.h:63
void SetDesignSettings(const BOARD_DESIGN_SETTINGS &aDesignSettings)
Function SetDesignSettings.
Definition: class_board.h:549
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
void SetPlotOptions(const PCB_PLOT_PARAMS &aOptions)
Definition: class_board.h:558
int m_MicroViasMinSize
micro vias (not vias) min diameter
Class PCB_PLOT_PARAMS handles plot parameters and options when plotting/printing a board.
int m_LineThickness[LAYER_CLASS_COUNT]
Class ZONE_SETTINGS handles zones parameters.
Definition: zone_settings.h:48
NETCLASSPTR GetDefault() const
Function GetDefault.
BOARD * m_board
Definition: pcb_parser.h:70
D_PAD m_Pad_Master
A dummy pad to store all default parameters.
void SetVisibleElements(int aMask)
Function SetVisibleElements changes the bit-mask of visible element categories.
const ZONE_SETTINGS & GetZoneSettings() const
Definition: class_board.h:563
std::vector< VIA_DIMENSION > m_ViasDimensionsList
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:125
bool m_MicroViasAllowed
true to allow micro vias
int m_MicroViasMinDrill
micro vias (not vias) min drill diameter
long parseHex()
Definition: pcb_parser.h:277
double m_SolderPasteMarginRatio
Solder pask margin ratio value of pad size The final margin is the sum of these 2 values.
void Parse(PCB_PLOT_PARAMS_PARSER *aParser)
wxPoint m_AuxOrigin
origin for plot exports
int m_SolderMaskMinWidth
Solder mask min width.
Class BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.

References LAYER_CLASS_COPPER, LAYER_CLASS_EDGES, LAYER_CLASS_SILK, BOARD_DESIGN_SETTINGS::m_AuxOrigin, BOARD_DESIGN_SETTINGS::m_BlindBuriedViaAllowed, BOARD_DESIGN_SETTINGS::m_GridOrigin, BOARD_DESIGN_SETTINGS::m_LineThickness, BOARD_DESIGN_SETTINGS::m_MicroViasAllowed, BOARD_DESIGN_SETTINGS::m_MicroViasMinDrill, BOARD_DESIGN_SETTINGS::m_MicroViasMinSize, BOARD_DESIGN_SETTINGS::m_Pad_Master, BOARD_DESIGN_SETTINGS::m_SolderMaskMargin, BOARD_DESIGN_SETTINGS::m_SolderMaskMinWidth, BOARD_DESIGN_SETTINGS::m_SolderPasteMargin, BOARD_DESIGN_SETTINGS::m_SolderPasteMarginRatio, BOARD_DESIGN_SETTINGS::m_TextSize, BOARD_DESIGN_SETTINGS::m_TextThickness, BOARD_DESIGN_SETTINGS::m_TrackMinWidth, BOARD_DESIGN_SETTINGS::m_TrackWidthList, BOARD_DESIGN_SETTINGS::m_ViasDimensionsList, BOARD_DESIGN_SETTINGS::m_ViasMinDrill, BOARD_DESIGN_SETTINGS::m_ViasMinSize, ZONE_SETTINGS::m_Zone_45_Only, ZONE_SETTINGS::m_ZoneClearance, MIN_VISIBILITY_MASK, PCB_PLOT_PARAMS::Parse(), parseDouble(), parseHex(), D_PAD::SetDrillSize(), D_PAD::SetSize(), and BOARD_DESIGN_SETTINGS::SetVisibleElements().

◆ parseTEXTE_MODULE()

TEXTE_MODULE * PCB_PARSER::parseTEXTE_MODULE ( )
private

Definition at line 2126 of file pcb_parser.cpp.

2127 {
2128  wxCHECK_MSG( CurTok() == T_fp_text, NULL,
2129  wxString::Format( wxT( "Cannot parse %s as TEXTE_MODULE at line %d, offset %d." ),
2130  GetChars( GetTokenString( CurTok() ) ),
2131  CurLineNumber(), CurOffset() ) );
2132 
2133  T token = NextTok();
2134 
2135  std::unique_ptr<TEXTE_MODULE> text( new TEXTE_MODULE( NULL ) );
2136 
2137  switch( token )
2138  {
2139  case T_reference:
2140  text->SetType( TEXTE_MODULE::TEXT_is_REFERENCE );
2141  break;
2142 
2143  case T_value:
2144  text->SetType( TEXTE_MODULE::TEXT_is_VALUE );
2145  break;
2146 
2147  case T_user:
2148  break; // Default type is user text.
2149 
2150  default:
2151  THROW_IO_ERROR( wxString::Format( _( "Cannot handle footprint text type %s" ),
2152  GetChars( FromUTF8() ) ) );
2153  }
2154 
2155  NeedSYMBOLorNUMBER();
2156 
2157  text->SetText( FromUTF8() );
2158  NeedLEFT();
2159  token = NextTok();
2160 
2161  if( token != T_at )
2162  Expecting( T_at );
2163 
2164  wxPoint pt;
2165 
2166  pt.x = parseBoardUnits( "X coordinate" );
2167  pt.y = parseBoardUnits( "Y coordinate" );
2168  text->SetPos0( pt );
2169 
2170  NextTok();
2171 
2172  if( CurTok() == T_NUMBER )
2173  {
2174  text->SetTextAngle( parseDouble() * 10.0 );
2175  NextTok();
2176  }
2177 
2178  if( CurTok() == T_unlocked )
2179  {
2180  text->SetKeepUpright( false );
2181  NextTok();
2182  }
2183 
2184  if( CurTok() != T_RIGHT )
2185  {
2186  Unexpected( CurText() );
2187  }
2188 
2189  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2190  {
2191  if( token == T_LEFT )
2192  token = NextTok();
2193 
2194  switch( token )
2195  {
2196  case T_layer:
2197  text->SetLayer( parseBoardItemLayer() );
2198  NeedRIGHT();
2199  break;
2200 
2201  case T_hide:
2202  text->SetVisible( false );
2203  break;
2204 
2205  case T_effects:
2206  parseEDA_TEXT( (EDA_TEXT*) text.get() );
2207  break;
2208 
2209  default:
2210  Expecting( "hide or effects" );
2211  }
2212  }
2213 
2214  return text.release();
2215 }
void parseEDA_TEXT(EDA_TEXT *aText)
Function parseEDA_TEXT parses the common settings for any object derived from EDA_TEXT.
Definition: pcb_parser.cpp:239
int parseBoardUnits()
Definition: pcb_parser.h:228
Class EDA_TEXT is a mix-in class (via multiple inheritance) that handles texts such as labels,...
Definition: eda_text.h:127
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
#define THROW_IO_ERROR(msg)
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:125

References Format(), GetChars(), parseDouble(), TEXTE_MODULE::TEXT_is_REFERENCE, TEXTE_MODULE::TEXT_is_VALUE, and THROW_IO_ERROR.

◆ parseTEXTE_PCB()

TEXTE_PCB * PCB_PARSER::parseTEXTE_PCB ( )
private

Definition at line 1629 of file pcb_parser.cpp.

1630 {
1631  wxCHECK_MSG( CurTok() == T_gr_text, NULL,
1632  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as TEXTE_PCB." ) );
1633 
1634  T token;
1635 
1636  std::unique_ptr<TEXTE_PCB> text( new TEXTE_PCB( m_board ) );
1637  NeedSYMBOLorNUMBER();
1638 
1639  text->SetText( FromUTF8() );
1640  NeedLEFT();
1641  token = NextTok();
1642 
1643  if( token != T_at )
1644  Expecting( T_at );
1645 
1646  wxPoint pt;
1647 
1648  pt.x = parseBoardUnits( "X coordinate" );
1649  pt.y = parseBoardUnits( "Y coordinate" );
1650  text->SetTextPos( pt );
1651 
1652  // If there is no orientation defined, then it is the default value of 0 degrees.
1653  token = NextTok();
1654 
1655  if( token == T_NUMBER )
1656  {
1657  text->SetTextAngle( parseDouble() * 10.0 );
1658  NeedRIGHT();
1659  }
1660  else if( token != T_RIGHT )
1661  {
1662  Unexpected( CurText() );
1663  }
1664 
1665  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1666  {
1667  if( token != T_LEFT )
1668  Expecting( T_LEFT );
1669 
1670  token = NextTok();
1671 
1672  switch( token )
1673  {
1674  case T_layer:
1675  text->SetLayer( parseBoardItemLayer() );
1676  NeedRIGHT();
1677  break;
1678 
1679  case T_tstamp:
1680  text->SetTimeStamp( parseHex() );
1681  NeedRIGHT();
1682  break;
1683 
1684  case T_effects:
1685  parseEDA_TEXT( (EDA_TEXT*) text.get() );
1686  break;
1687 
1688  default:
1689  Expecting( "layer, tstamp or effects" );
1690  }
1691  }
1692 
1693  return text.release();
1694 }
void parseEDA_TEXT(EDA_TEXT *aText)
Function parseEDA_TEXT parses the common settings for any object derived from EDA_TEXT.
Definition: pcb_parser.cpp:239
int parseBoardUnits()
Definition: pcb_parser.h:228
Class EDA_TEXT is a mix-in class (via multiple inheritance) that handles texts such as labels,...
Definition: eda_text.h:127
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
BOARD * m_board
Definition: pcb_parser.h:70
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:125
long parseHex()
Definition: pcb_parser.h:277

References parseDouble(), and parseHex().

◆ parseTITLE_BLOCK()

void PCB_PARSER::parseTITLE_BLOCK ( )
private

Definition at line 808 of file pcb_parser.cpp.

809 {
810  wxCHECK_RET( CurTok() == T_title_block,
811  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
812  wxT( " as TITLE_BLOCK." ) );
813 
814  T token;
815  TITLE_BLOCK titleBlock;
816 
817  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
818  {
819  if( token != T_LEFT )
820  Expecting( T_LEFT );
821 
822  token = NextTok();
823 
824  switch( token )
825  {
826  case T_title:
827  NextTok();
828  titleBlock.SetTitle( FromUTF8() );
829  break;
830 
831  case T_date:
832  NextTok();
833  titleBlock.SetDate( FromUTF8() );
834  break;
835 
836  case T_rev:
837  NextTok();
838  titleBlock.SetRevision( FromUTF8() );
839  break;
840 
841  case T_company:
842  NextTok();
843  titleBlock.SetCompany( FromUTF8() );
844  break;
845 
846  case T_comment:
847  {
848  int commentNumber = parseInt( "comment" );
849 
850  switch( commentNumber )
851  {
852  case 1:
853  NextTok();
854  titleBlock.SetComment1( FromUTF8() );
855  break;
856 
857  case 2:
858  NextTok();
859  titleBlock.SetComment2( FromUTF8() );
860  break;
861 
862  case 3:
863  NextTok();
864  titleBlock.SetComment3( FromUTF8() );
865  break;
866 
867  case 4:
868  NextTok();
869  titleBlock.SetComment4( FromUTF8() );
870  break;
871 
872  default:
873  wxString err;
874  err.Printf( wxT( "%d is not a valid title block comment number" ), commentNumber );
875  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
876  }
877  }
878  break;
879 
880  default:
881  Expecting( "title, date, rev, company, or comment" );
882  }
883 
884  NeedRIGHT();
885  }
886 
887  m_board->SetTitleBlock( titleBlock );
888 }
void SetComment1(const wxString &aComment)
Definition: title_block.h:117
void SetRevision(const wxString &aRevision)
Definition: title_block.h:84
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition: class_board.h:561
void SetDate(const wxString &aDate)
Function SetDate sets the date field, and defaults to the current time and date.
Definition: title_block.h:74
Class TITLE_BLOCK holds the information shown in the lower right corner of a plot,...
Definition: title_block.h:40
void SetComment4(const wxString &aComment)
Definition: title_block.h:120
void SetCompany(const wxString &aCompany)
Definition: title_block.h:94
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
void SetTitle(const wxString &aTitle)
Definition: title_block.h:60
string & err
Definition: json11.cpp:598
void SetComment2(const wxString &aComment)
Definition: title_block.h:118
BOARD * m_board
Definition: pcb_parser.h:70
void SetComment3(const wxString &aComment)
Definition: title_block.h:119
int parseInt()
Definition: pcb_parser.h:266

References err, parseInt(), TITLE_BLOCK::SetComment1(), TITLE_BLOCK::SetComment2(), TITLE_BLOCK::SetComment3(), TITLE_BLOCK::SetComment4(), TITLE_BLOCK::SetCompany(), TITLE_BLOCK::SetDate(), TITLE_BLOCK::SetRevision(), TITLE_BLOCK::SetTitle(), and THROW_PARSE_ERROR.

◆ parseTRACK()

TRACK * PCB_PARSER::parseTRACK ( )
private

Definition at line 2828 of file pcb_parser.cpp.

2829 {
2830  wxCHECK_MSG( CurTok() == T_segment, NULL,
2831  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as TRACK." ) );
2832 
2833  wxPoint pt;
2834  T token;
2835 
2836  std::unique_ptr< TRACK > track( new TRACK( m_board ) );
2837 
2838  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2839  {
2840  if( token != T_LEFT )
2841  Expecting( T_LEFT );
2842 
2843  token = NextTok();
2844 
2845  switch( token )
2846  {
2847  case T_start:
2848  pt.x = parseBoardUnits( "start x" );
2849  pt.y = parseBoardUnits( "start y" );
2850  track->SetStart( pt );
2851  break;
2852 
2853  case T_end:
2854  pt.x = parseBoardUnits( "end x" );
2855  pt.y = parseBoardUnits( "end y" );
2856  track->SetEnd( pt );
2857  break;
2858 
2859  case T_width:
2860  track->SetWidth( parseBoardUnits( "width" ) );
2861  break;
2862 
2863  case T_layer:
2864  track->SetLayer( parseBoardItemLayer() );
2865  break;
2866 
2867  case T_net:
2868  if( ! track->SetNetCode( getNetCode( parseInt( "net number" ) ), /* aNoAssert */ true ) )
2870  wxString::Format( _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
2871  GetChars( CurSource() ), CurLineNumber(), CurOffset() )
2872  );
2873  break;
2874 
2875  case T_tstamp:
2876  track->SetTimeStamp( parseHex() );
2877  break;
2878 
2879  case T_status:
2880  track->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
2881  break;
2882 
2883  default:
2884  Expecting( "start, end, width, layer, net, tstamp, or status" );
2885  }
2886 
2887  NeedRIGHT();
2888  }
2889 
2890  return track.release();
2891 }
int parseBoardUnits()
Definition: pcb_parser.h:228
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
#define THROW_IO_ERROR(msg)
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
int getNetCode(int aNetCode)
Converts net code using the mapping table if available, otherwise returns unchanged net code if < 0 o...
Definition: pcb_parser.h:80
BOARD * m_board
Definition: pcb_parser.h:70
long parseHex()
Definition: pcb_parser.h:277
int parseInt()
Definition: pcb_parser.h:266

References Format(), GetChars(), parseHex(), parseInt(), and THROW_IO_ERROR.

◆ parseVersion()

int PCB_PARSER::parseVersion ( )
private

Parse a format version tag like (version 20160417) return the version.

Expects to start on 'version', and eats the closing paren.

Definition at line 170 of file pcb_parser.cpp.

171 {
172  if( NextTok() != T_version )
173  Expecting( GetTokenText( T_version ) );
174 
175  int pcb_version = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
176 
177  NeedRIGHT();
178 
179  return pcb_version;
180 }
const char * GetTokenText(T aTok)
Function GetTokenText is in the DSN namespace and returns the C string representing a SPECCTRA_DB::ke...
Definition: specctra.cpp:69
int parseInt()
Definition: pcb_parser.h:266

References DSN::GetTokenText(), and parseInt().

◆ parseVIA()

VIA * PCB_PARSER::parseVIA ( )
private

Definition at line 2894 of file pcb_parser.cpp.

2895 {
2896  wxCHECK_MSG( CurTok() == T_via, NULL,
2897  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as VIA." ) );
2898 
2899  wxPoint pt;
2900  T token;
2901 
2902  std::unique_ptr< VIA > via( new VIA( m_board ) );
2903 
2904  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2905  {
2906  if( token == T_LEFT )
2907  token = NextTok();
2908 
2909  switch( token )
2910  {
2911  case T_blind:
2912  via->SetViaType( VIA_BLIND_BURIED );
2913  break;
2914 
2915  case T_micro:
2916  via->SetViaType( VIA_MICROVIA );
2917  break;
2918 
2919  case T_at:
2920  pt.x = parseBoardUnits( "start x" );
2921  pt.y = parseBoardUnits( "start y" );
2922  via->SetStart( pt );
2923  via->SetEnd( pt );
2924  NeedRIGHT();
2925  break;
2926 
2927  case T_size:
2928  via->SetWidth( parseBoardUnits( "via width" ) );
2929  NeedRIGHT();
2930  break;
2931 
2932  case T_drill:
2933  via->SetDrill( parseBoardUnits( "drill diameter" ) );
2934  NeedRIGHT();
2935  break;
2936 
2937  case T_layers:
2938  {
2939  PCB_LAYER_ID layer1, layer2;
2940  NextTok();
2941  layer1 = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
2942  NextTok();
2943  layer2 = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
2944  via->SetLayerPair( layer1, layer2 );
2945  NeedRIGHT();
2946  }
2947  break;
2948 
2949  case T_net:
2950  if(! via->SetNetCode( getNetCode( parseInt( "net number" ) ), /* aNoAssert */ true))
2952  wxString::Format( _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
2953  GetChars( CurSource() ), CurLineNumber(), CurOffset() )
2954  );
2955  NeedRIGHT();
2956  break;
2957 
2958  case T_tstamp:
2959  via->SetTimeStamp( parseHex() );
2960  NeedRIGHT();
2961  break;
2962 
2963  case T_status:
2964  via->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
2965  NeedRIGHT();
2966  break;
2967 
2968  default:
2969  Expecting( "blind, micro, at, size, drill, layers, net, tstamp, or status" );
2970  }
2971  }
2972 
2973  return via.release();
2974 }
int parseBoardUnits()
Definition: pcb_parser.h:228
PCB_LAYER_ID
A quick note on layer IDs:
#define THROW_IO_ERROR(msg)
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
int getNetCode(int aNetCode)
Converts net code using the mapping table if available, otherwise returns unchanged net code if < 0 o...
Definition: pcb_parser.h:80
BOARD * m_board
Definition: pcb_parser.h:70
LAYER_ID_MAP m_layerIndices
map layer name to it's index
Definition: pcb_parser.h:71
long parseHex()
Definition: pcb_parser.h:277
int parseInt()
Definition: pcb_parser.h:266

References Format(), GetChars(), parseHex(), parseInt(), THROW_IO_ERROR, VIA, VIA_BLIND_BURIED, and VIA_MICROVIA.

◆ parseXY() [1/2]

wxPoint PCB_PARSER::parseXY ( )
private

Function parseXY parses a coordinate pair (xy X Y) in board units (mm).

The parser checks if the previous token was T_LEFT and parses the remainder of the token syntax. This is used when parsing a list of coordinate points. This way the parser can be used in either case.

Exceptions
PARSE_ERRORif the coordinate pair syntax is incorrect.
Returns
A wxPoint object containing the coordinate pair.

Definition at line 207 of file pcb_parser.cpp.

208 {
209  if( CurTok() != T_LEFT )
210  NeedLEFT();
211 
212  wxPoint pt;
213  T token = NextTok();
214 
215  if( token != T_xy )
216  Expecting( T_xy );
217 
218  pt.x = parseBoardUnits( "X coordinate" );
219  pt.y = parseBoardUnits( "Y coordinate" );
220 
221  NeedRIGHT();
222 
223  return pt;
224 }
int parseBoardUnits()
Definition: pcb_parser.h:228

◆ parseXY() [2/2]

void PCB_PARSER::parseXY ( int *  aX,
int *  aY 
)
private

Definition at line 227 of file pcb_parser.cpp.

228 {
229  wxPoint pt = parseXY();
230 
231  if( aX )
232  *aX = pt.x;
233 
234  if( aY )
235  *aY = pt.y;
236 }
wxPoint parseXY()
Function parseXY parses a coordinate pair (xy X Y) in board units (mm).
Definition: pcb_parser.cpp:207

◆ parseZONE_CONTAINER()

ZONE_CONTAINER * PCB_PARSER::parseZONE_CONTAINER ( )
private

Definition at line 2977 of file pcb_parser.cpp.

2978 {
2979  wxCHECK_MSG( CurTok() == T_zone, NULL,
2980  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
2981  wxT( " as ZONE_CONTAINER." ) );
2982 
2984 
2985  int hatchPitch = ZONE_CONTAINER::GetDefaultHatchPitch();
2986  wxPoint pt;
2987  T token;
2988  int tmp;
2989  wxString netnameFromfile; // the zone net name find in file
2990 
2991  // bigger scope since each filled_polygon is concatenated in here
2992  SHAPE_POLY_SET pts;
2993 
2994  std::unique_ptr< ZONE_CONTAINER > zone( new ZONE_CONTAINER( m_board ) );
2995 
2996  zone->SetPriority( 0 );
2997 
2998  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2999  {
3000  if( token == T_LEFT )
3001  token = NextTok();
3002 
3003  switch( token )
3004  {
3005  case T_net:
3006  // Init the net code only, not the netname, to be sure
3007  // the zone net name is the name read in file.
3008  // (When mismatch, the user will be prompted in DRC, to fix the actual name)
3009  tmp = getNetCode( parseInt( "net number" ) );
3010 
3011  if( tmp < 0 )
3012  tmp = 0;
3013 
3014  if( ! zone->SetNetCode( tmp, /* aNoAssert */ true ) )
3016  wxString::Format( _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
3017  GetChars( CurSource() ), CurLineNumber(), CurOffset() )
3018  );
3019 
3020  NeedRIGHT();
3021  break;
3022 
3023  case T_net_name:
3024  NeedSYMBOLorNUMBER();
3025  netnameFromfile = FromUTF8();
3026  NeedRIGHT();
3027  break;
3028 
3029  case T_layer: // keyword for zones that are on only one layer
3030  zone->SetLayer( parseBoardItemLayer() );
3031  NeedRIGHT();
3032  break;
3033 
3034  case T_layers: // keyword for zones that can live on a set of layer
3035  // currently: keepout zones
3036  zone->SetLayerSet( parseBoardItemLayersAsMask() );
3037  break;
3038 
3039  case T_tstamp:
3040  zone->SetTimeStamp( parseHex() );
3041  NeedRIGHT();
3042  break;
3043 
3044  case T_hatch:
3045  token = NextTok();
3046 
3047  if( token != T_none && token != T_edge && token != T_full )
3048  Expecting( "none, edge, or full" );
3049 
3050  switch( token )
3051  {
3052  default:
3053  case T_none: hatchStyle = ZONE_CONTAINER::NO_HATCH; break;
3054  case T_edge: hatchStyle = ZONE_CONTAINER::DIAGONAL_EDGE; break;
3055  case T_full: hatchStyle = ZONE_CONTAINER::DIAGONAL_FULL;
3056  }
3057 
3058  hatchPitch = parseBoardUnits( "hatch pitch" );
3059  NeedRIGHT();
3060  break;
3061 
3062  case T_priority:
3063  zone->SetPriority( parseInt( "zone priority" ) );
3064  NeedRIGHT();
3065  break;
3066 
3067  case T_connect_pads:
3068  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3069  {
3070  if( token == T_LEFT )
3071  token = NextTok();
3072 
3073  switch( token )
3074  {
3075  case T_yes:
3076  zone->SetPadConnection( PAD_ZONE_CONN_FULL );
3077  break;
3078 
3079  case T_no:
3080  zone->SetPadConnection( PAD_ZONE_CONN_NONE );
3081  break;
3082 
3083  case T_thru_hole_only:
3084  zone->SetPadConnection( PAD_ZONE_CONN_THT_THERMAL );
3085  break;
3086 
3087  case T_clearance:
3088  zone->SetZoneClearance( parseBoardUnits( "zone clearance" ) );
3089  NeedRIGHT();
3090  break;
3091 
3092  default:
3093  Expecting( "yes, no, or clearance" );
3094  }
3095  }
3096 
3097  break;
3098 
3099  case T_min_thickness:
3100  zone->SetMinThickness( parseBoardUnits( T_min_thickness ) );
3101  NeedRIGHT();
3102  break;
3103 
3104  case T_fill:
3105  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3106  {
3107  if( token == T_LEFT )
3108  token = NextTok();
3109 
3110  switch( token )
3111  {
3112  case T_yes:
3113  zone->SetIsFilled( true );
3114  break;
3115 
3116  case T_mode:
3117  token = NextTok();
3118 
3119  if( token != T_segment && token != T_polygon )
3120  Expecting( "segment or polygon" );
3121 
3122  // @todo Create an enum for fill modes.
3123  zone->SetFillMode( token == T_polygon ? ZFM_POLYGONS : ZFM_SEGMENTS );
3124  NeedRIGHT();
3125  break;
3126 
3127  case T_arc_segments:
3128  zone->SetArcSegmentCount( parseInt( "arc segment count" ) );
3129  NeedRIGHT();
3130  break;
3131 
3132  case T_thermal_gap:
3133  zone->SetThermalReliefGap( parseBoardUnits( T_thermal_gap ) );
3134  NeedRIGHT();
3135  break;
3136 
3137  case T_thermal_bridge_width:
3138  zone->SetThermalReliefCopperBridge( parseBoardUnits( T_thermal_bridge_width ) );
3139  NeedRIGHT();
3140  break;
3141 
3142  case T_smoothing:
3143  switch( NextTok() )
3144  {
3145  case T_none:
3146  zone->SetCornerSmoothingType( ZONE_SETTINGS::SMOOTHING_NONE );
3147  break;
3148 
3149  case T_chamfer:
3150  if( !zone->GetIsKeepout() ) // smoothing has meaning only for filled zones
3151  zone->SetCornerSmoothingType( ZONE_SETTINGS::SMOOTHING_CHAMFER );
3152  break;
3153 
3154  case T_fillet:
3155  if( !zone->GetIsKeepout() ) // smoothing has meaning only for filled zones
3156  zone->SetCornerSmoothingType( ZONE_SETTINGS::SMOOTHING_FILLET );
3157  break;
3158 
3159  default:
3160  Expecting( "none, chamfer, or fillet" );
3161  }
3162  NeedRIGHT();
3163  break;
3164 
3165  case T_radius:
3166  tmp = parseBoardUnits( "corner radius" );
3167  if( !zone->GetIsKeepout() ) // smoothing has meaning only for filled zones
3168  zone->SetCornerRadius( tmp );
3169  NeedRIGHT();
3170  break;
3171 
3172  default:
3173  Expecting( "mode, arc_segments, thermal_gap, thermal_bridge_width, "
3174  "smoothing, or radius" );
3175  }
3176  }
3177  break;
3178 
3179  case T_keepout:
3180  zone->SetIsKeepout( true );
3181 
3182  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3183  {
3184  if( token == T_LEFT )
3185  token = NextTok();
3186 
3187  switch( token )
3188  {
3189  case T_tracks:
3190  token = NextTok();
3191 
3192  if( token != T_allowed && token != T_not_allowed )
3193  Expecting( "allowed or not_allowed" );
3194  zone->SetDoNotAllowTracks( token == T_not_allowed );
3195  break;
3196 
3197  case T_vias:
3198  token = NextTok();
3199 
3200  if( token != T_allowed && token != T_not_allowed )
3201  Expecting( "allowed or not_allowed" );
3202  zone->SetDoNotAllowVias( token == T_not_allowed );
3203  break;
3204 
3205  case T_copperpour:
3206  token = NextTok();
3207 
3208  if( token != T_allowed && token != T_not_allowed )
3209  Expecting( "allowed or not_allowed" );
3210  zone->SetDoNotAllowCopperPour( token == T_not_allowed );
3211  break;
3212 
3213  default:
3214  Expecting( "tracks, vias or copperpour" );
3215  }
3216 
3217  NeedRIGHT();
3218  }
3219 
3220  break;
3221 
3222  case T_polygon:
3223  {
3224  std::vector< wxPoint > corners;
3225 
3226  NeedLEFT();
3227  token = NextTok();
3228 
3229  if( token != T_pts )
3230  Expecting( T_pts );
3231 
3232  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3233  {
3234  corners.push_back( parseXY() );
3235  }
3236 
3237  NeedRIGHT();
3238 
3239  // Remark: The first polygon is the main outline.
3240  // Others are holes inside the main outline.
3241  zone->AddPolygon( corners );
3242  }
3243  break;
3244 
3245  case T_filled_polygon:
3246  {
3247  // "(filled_polygon (pts"
3248  NeedLEFT();
3249  token = NextTok();
3250 
3251  if( token != T_pts )
3252  Expecting( T_pts );
3253 
3254  pts.NewOutline();
3255 
3256  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3257  {
3258  pts.Append( parseXY() );
3259  }
3260 
3261  NeedRIGHT();
3262  }
3263  break;
3264 
3265  case T_fill_segments:
3266  {
3267  ZONE_SEGMENT_FILL segs;
3268 
3269  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3270  {
3271  if( token != T_LEFT )
3272  Expecting( T_LEFT );
3273 
3274  token = NextTok();
3275 
3276  if( token != T_pts )
3277  Expecting( T_pts );
3278 
3279  SEG segment( parseXY(), parseXY() );
3280  NeedRIGHT();
3281  segs.push_back( segment );
3282  }
3283 
3284  zone->SetFillSegments( segs );
3285  }
3286  break;
3287 
3288  default:
3289  Expecting( "net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
3290  "fill, polygon, filled_polygon, or fill_segments" );
3291  }
3292  }
3293 
3294  if( zone->GetNumCorners() > 2 )
3295  {
3296  if( !zone->IsOnCopperLayer() )
3297  {
3298  zone->SetFillMode( ZFM_POLYGONS );
3299  zone->SetNetCode( NETINFO_LIST::UNCONNECTED );
3300  }
3301 
3302  // Set hatch here, after outlines corners are read
3303  zone->SetHatch( hatchStyle, hatchPitch, true );
3304  }
3305 
3306  if( !pts.IsEmpty() )
3307  zone->SetFilledPolysList( pts );
3308 
3309  // Ensure keepout and non copper zones do not have a net
3310  // (which have no sense for these zones)
3311  // the netcode 0 is used for these zones
3312  bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsKeepout();
3313 
3314  if( !zone_has_net )
3315  zone->SetNetCode( NETINFO_LIST::UNCONNECTED );
3316 
3317  // Ensure the zone net name is valid, and matches the net code, for copper zones
3318  if( zone_has_net && ( zone->GetNet()->GetNetname() != netnameFromfile ) )
3319  {
3320  // Can happens which old boards, with nonexistent nets ...
3321  // or after being edited by hand
3322  // We try to fix the mismatch.
3323  NETINFO_ITEM* net = m_board->FindNet( netnameFromfile );
3324 
3325  if( net ) // An existing net has the same net name. use it for the zone
3326  zone->SetNetCode( net->GetNet() );
3327  else // Not existing net: add a new net to keep trace of the zone netname
3328  {
3329  int newnetcode = m_board->GetNetCount();
3330  net = new NETINFO_ITEM( m_board, netnameFromfile, newnetcode );
3331  m_board->Add( net );
3332 
3333  // Store the new code mapping
3334  pushValueIntoMap( newnetcode, net->GetNet() );
3335  // and update the zone netcode
3336  zone->SetNetCode( net->GetNet() );
3337 
3338  // FIXME: a call to any GUI item is not allowed in io plugins:
3339  // Change this code to generate a warning message outside this plugin
3340  // Prompt the user
3341  wxString msg;
3342  msg.Printf( _( "There is a zone that belongs to a not existing net\n"
3343  "\"%s\"\n"
3344  "you should verify and edit it (run DRC test)." ),
3345  GetChars( netnameFromfile ) );
3346  DisplayError( NULL, msg );
3347  }
3348  }
3349 
3350  // Clear flags used in zone edition:
3351  zone->SetNeedRefill( false );
3352 
3353  return zone.release();
3354 }
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:59
std::vector< SEG > ZONE_SEGMENT_FILL
Definition: class_zone.h:49
LSET parseBoardItemLayersAsMask()
Function parseBoardItemLayersAsMask parses the layers definition of a BOARD_ITEM object.
bool IsEmpty() const
Returns true if the set is empty (no polygons at all)
wxPoint parseXY()
Function parseXY parses a coordinate pair (xy X Y) in board units (mm).
Definition: pcb_parser.cpp:207
static int GetDefaultHatchPitch()
Function GetDefaultHatchPitchMils.
int parseBoardUnits()
Definition: pcb_parser.h:228
Pads are not covered.
Definition: zones.h:52
unsigned GetNetCount() const
Function GetNetCount.
Definition: class_board.h:785
Class SHAPE_POLY_SET.
void SetNetCode(int aNetCode)
Definition: netinfo.h:233
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_INSERT) override
Adds an item to the container.
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
#define THROW_IO_ERROR(msg)
HATCH_STYLE
Zone hatch styles.
Definition: class_zone.h:66
int NewOutline()
Creates a new empty polygon in the set and returns its index
Thermal relief only for THT pads.
Definition: zones.h:55
Definition: seg.h:36
Class NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:69
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:92
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, CPTREE &aTree)
Function Format outputs a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:205
int GetNet() const
Function GetNet.
Definition: netinfo.h:231
int getNetCode(int aNetCode)
Converts net code using the mapping table if available, otherwise returns unchanged net code if < 0 o...
Definition: pcb_parser.h:80
BOARD * m_board
Definition: pcb_parser.h:70
void pushValueIntoMap(int aIndex, int aValue)
function pushValueIntoMap Add aValue value in netcode mapping (m_netCodes) at index aIndex ensure the...
Definition: pcb_parser.cpp:114
long parseHex()
Definition: pcb_parser.h:277
int parseInt()
Definition: pcb_parser.h:266
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Function DisplayError displays an error or warning message box with aMessage.
Definition: confirm.cpp:243
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:469
pads are covered by copper
Definition: zones.h:54
int Append(int x, int y, int aOutline=-1, int aHole=-1, bool aAllowDuplication=false)
Appends a vertex at the end of the given outline/hole (default: the last outline)

References SHAPE_POLY_SET::Append(), ZONE_CONTAINER::DIAGONAL_EDGE, ZONE_CONTAINER::DIAGONAL_FULL, DisplayError(), Format(), GetChars(), ZONE_CONTAINER::GetDefaultHatchPitch(), NETINFO_ITEM::GetNet(), SHAPE_POLY_SET::IsEmpty(), SHAPE_POLY_SET::NewOutline(), ZONE_CONTAINER::NO_HATCH, PAD_ZONE_CONN_FULL, PAD_ZONE_CONN_NONE, PAD_ZONE_CONN_THT_THERMAL, parseHex(), parseInt(), NETINFO_ITEM::SetNetCode(), ZONE_SETTINGS::SMOOTHING_CHAMFER, ZONE_SETTINGS::SMOOTHING_FILLET, ZONE_SETTINGS::SMOOTHING_NONE, THROW_IO_ERROR, NETINFO_LIST::UNCONNECTED, ZFM_POLYGONS, and ZFM_SEGMENTS.

◆ pushValueIntoMap()

void PCB_PARSER::pushValueIntoMap ( int  aIndex,
int  aValue 
)
private

function pushValueIntoMap Add aValue value in netcode mapping (m_netCodes) at index aIndex ensure there is room in m_netCodes for that, and add room if needed.

Parameters
aIndex= the index ( expected >=0 )of the location to use in m_netCodes
aValue= the netcode value to map

Definition at line 114 of file pcb_parser.cpp.

115 {
116  // Add aValue in netcode mapping (m_netCodes) at index aNetCode
117  // ensure there is room in m_netCodes for that, and add room if needed.
118 
119  if( (int)m_netCodes.size() <= aIndex )
120  m_netCodes.resize( aIndex+1 );
121 
122  m_netCodes[aIndex] = aValue;
123 }
std::vector< int > m_netCodes
net codes mapping for boards being loaded
Definition: pcb_parser.h:74

◆ SetBoard()

void PCB_PARSER::SetBoard ( BOARD aBoard)
inline

Definition at line 315 of file pcb_parser.h.

316  {
317  init();
318  m_board = aBoard;
319  }
BOARD * m_board
Definition: pcb_parser.h:70
void init()
Function init clears and re-establishes m_layerMap with the default layer names.
Definition: pcb_parser.cpp:57

References init(), and m_board.

Referenced by CLIPBOARD_IO::Load(), and PCB_IO::Load().

◆ SetLineReader()

LINE_READER* PCB_PARSER::SetLineReader ( LINE_READER aReader)
inline

Function SetLineReader sets aLineReader into the parser, and returns the previous one, if any.

Parameters
aReaderis what to read from for tokens, no ownership is received.
Returns
LINE_READER* - previous LINE_READER or NULL if none.

Definition at line 308 of file pcb_parser.h.

309  {
310  LINE_READER* ret = PopReader();
311  PushReader( aReader );
312  return ret;
313  }
Class LINE_READER is an abstract class from which implementation specific LINE_READERs may be derived...
Definition: richio.h:81

Referenced by GITHUB_PLUGIN::FootprintLoad(), CLIPBOARD_IO::Load(), PCB_IO::Load(), FP_CACHE::Load(), and PCB_IO::Parse().

Member Data Documentation

◆ m_board

BOARD* PCB_PARSER::m_board
private

Definition at line 70 of file pcb_parser.h.

Referenced by SetBoard().

◆ m_layerIndices

LAYER_ID_MAP PCB_PARSER::m_layerIndices
private

map layer name to it's index

Definition at line 71 of file pcb_parser.h.

◆ m_layerMasks

LSET_MAP PCB_PARSER::m_layerMasks
private

map layer names to their masks

Definition at line 72 of file pcb_parser.h.

◆ m_netCodes

std::vector<int> PCB_PARSER::m_netCodes
private

net codes mapping for boards being loaded

Definition at line 74 of file pcb_parser.h.

Referenced by getNetCode().

◆ m_requiredVersion

int PCB_PARSER::m_requiredVersion
private

set to the KiCad format version this board requires

Definition at line 76 of file pcb_parser.h.

◆ m_tooRecent

bool PCB_PARSER::m_tooRecent
private

true if version parses as later than supported

Definition at line 75 of file pcb_parser.h.

Referenced by IsTooRecent().

◆ m_undefinedLayers

std::set<wxString> PCB_PARSER::m_undefinedLayers
private

set of layers not defined in layers section

Definition at line 73 of file pcb_parser.h.


The documentation for this class was generated from the following files: