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 createOldLayerMapping (std::unordered_map< std::string, std::string > &aMap)
 Creates a mapping from the (short-lived) bug where layer names were translated TODO: Remove this once we support custom layer names. More...
 
void parseHeader ()
 
void parseGeneralSection ()
 
void parsePAGE_INFO ()
 
void parseTITLE_BLOCK ()
 
void parseLayers ()
 
void parseLayer (LAYER *aLayer)
 
void parseSetup ()
 
void parseDefaults (BOARD_DESIGN_SETTINGS &aSettings)
 
void parseDefaultTextDims (BOARD_DESIGN_SETTINGS &aSettings, int aLayer)
 
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...
 
bool m_showLegacyZoneWarning
 

Detailed Description

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

Definition at line 66 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 68 of file pcb_parser.h.

◆ LSET_MAP

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

Definition at line 69 of file pcb_parser.h.

Constructor & Destructor Documentation

◆ PCB_PARSER()

PCB_PARSER::PCB_PARSER ( LINE_READER aReader = NULL)
inline

Definition at line 306 of file pcb_parser.h.

306  :
307  PCB_LEXER( aReader ),
308  m_board( 0 )
309  {
310  init();
311  }
BOARD * m_board
Definition: pcb_parser.h:71
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

◆ createOldLayerMapping()

void PCB_PARSER::createOldLayerMapping ( std::unordered_map< std::string, std::string > &  aMap)
private

Creates a mapping from the (short-lived) bug where layer names were translated TODO: Remove this once we support custom layer names.

Parameters
aMapstring mapping from translated to English layer names

Definition at line 930 of file pcb_parser.cpp.

931 {
932  // N.B. This mapping only includes Italian, Polish and French as they were the only languages that
933  // mapped the layer names as of cc2022b1ac739aa673d2a0b7a2047638aa7a47b3 (kicad-i18n) when the
934  // bug was fixed in KiCad source.
935 
936  // Italian
937  aMap["Adesivo.Retro"] = "B.Adhes";
938  aMap["Adesivo.Fronte"] = "F.Adhes";
939  aMap["Pasta.Retro"] = "B.Paste";
940  aMap["Pasta.Fronte"] = "F.Paste";
941  aMap["Serigrafia.Retro"] = "B.SilkS";
942  aMap["Serigrafia.Fronte"] = "F.SilkS";
943  aMap["Maschera.Retro"] = "B.Mask";
944  aMap["Maschera.Fronte"] = "F.Mask";
945  aMap["Grafica"] = "Dwgs.User";
946  aMap["Commenti"] = "Cmts.User";
947  aMap["Eco1"] = "Eco1.User";
948  aMap["Eco2"] = "Eco2.User";
949  aMap["Contorno.scheda"] = "Edge.Cuts";
950 
951  // Polish
952  aMap["Kleju_Dolna"] = "B.Adhes";
953  aMap["Kleju_Gorna"] = "F.Adhes";
954  aMap["Pasty_Dolna"] = "B.Paste";
955  aMap["Pasty_Gorna"] = "F.Paste";
956  aMap["Opisowa_Dolna"] = "B.SilkS";
957  aMap["Opisowa_Gorna"] = "F.SilkS";
958  aMap["Maski_Dolna"] = "B.Mask";
959  aMap["Maski_Gorna"] = "F.Mask";
960  aMap["Rysunkowa"] = "Dwgs.User";
961  aMap["Komentarzy"] = "Cmts.User";
962  aMap["ECO1"] = "Eco1.User";
963  aMap["ECO2"] = "Eco2.User";
964  aMap["Krawedziowa"] = "Edge.Cuts";
965 
966  // French
967  aMap["Dessous.Adhes"] = "B.Adhes";
968  aMap["Dessus.Adhes"] = "F.Adhes";
969  aMap["Dessous.Pate"] = "B.Paste";
970  aMap["Dessus.Pate"] = "F.Paste";
971  aMap["Dessous.SilkS"] = "B.SilkS";
972  aMap["Dessus.SilkS"] = "F.SilkS";
973  aMap["Dessous.Masque"] = "B.Mask";
974  aMap["Dessus.Masque"] = "F.Mask";
975  aMap["Dessin.User"] = "Dwgs.User";
976  aMap["Contours.Ci"] = "Edge.Cuts";
977 }

◆ 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 83 of file pcb_parser.h.

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

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 184 of file pcb_parser.cpp.

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

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 {
60  m_tooRecent = false;
62  m_layerIndices.clear();
63  m_layerMasks.clear();
64 
65  // Add untranslated default (i.e. english) layernames.
66  // Some may be overridden later if parsing a board rather than a footprint.
67  // The english name will survive if parsing only a footprint.
68  for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
69  {
70  std::string untranslated = TO_UTF8( wxString( LSET::Name( PCB_LAYER_ID( layer ) ) ) );
71 
72  m_layerIndices[ untranslated ] = PCB_LAYER_ID( layer );
73  m_layerMasks[ untranslated ] = LSET( PCB_LAYER_ID( layer ) );
74  }
75 
76  m_layerMasks[ "*.Cu" ] = LSET::AllCuMask();
77  m_layerMasks[ "F&B.Cu" ] = LSET( 2, F_Cu, B_Cu );
78  m_layerMasks[ "*.Adhes" ] = LSET( 2, B_Adhes, F_Adhes );
79  m_layerMasks[ "*.Paste" ] = LSET( 2, B_Paste, F_Paste );
80  m_layerMasks[ "*.Mask" ] = LSET( 2, B_Mask, F_Mask );
81  m_layerMasks[ "*.SilkS" ] = LSET( 2, B_SilkS, F_SilkS );
82  m_layerMasks[ "*.Fab" ] = LSET( 2, B_Fab, F_Fab );
83  m_layerMasks[ "*.CrtYd" ] = LSET( 2, B_CrtYd, F_CrtYd );
84 
85  // This is for the first pretty & *.kicad_pcb formats, which had
86  // Inner1_Cu - Inner14_Cu with the numbering sequence
87  // reversed from the subsequent format's In1_Cu - In30_Cu numbering scheme.
88  // The newer format brought in an additional 16 Cu layers and flipped the cu stack but
89  // kept the gap between one of the outside layers and the last cu internal.
90 
91  for( int i=1; i<=14; ++i )
92  {
93  std::string key = StrPrintf( "Inner%d.Cu", i );
94 
95  m_layerMasks[ key ] = LSET( PCB_LAYER_ID( In15_Cu - i ) );
96  }
97 
98 #if defined(DEBUG) && 0
99  printf( "m_layerMasks:\n" );
100  for( LSET_MAP::const_iterator it = m_layerMasks.begin(); it != m_layerMasks.end(); ++it )
101  {
102  printf( " [%s] == 0x%s\n", it->first.c_str(), it->second.FmtHex().c_str() );
103  }
104 
105  printf( "m_layerIndices:\n" );
106  for( LAYER_ID_MAP::const_iterator it = m_layerIndices.begin(); it != m_layerIndices.end(); ++it )
107  {
108  printf( " [%s] == %d\n", it->first.c_str(), it->second );
109  }
110 #endif
111 
112 }
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:76
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:48
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
bool m_showLegacyZoneWarning
Definition: pcb_parser.h:79
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:77
size_t i
Definition: json11.cpp:597
LAYER_ID_MAP m_layerIndices
map layer name to it's index
Definition: pcb_parser.h:72
LSET_MAP m_layerMasks
map layer names to their masks
Definition: pcb_parser.h:73

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 346 of file pcb_parser.h.

347  {
348  return m_tooRecent;
349  }
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:76

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 1107 of file pcb_parser.cpp.

1108 {
1109  // avoid constructing another std::string, use lexer's directly
1110  typename M::const_iterator it = aMap.find( curText );
1111 
1112  if( it == aMap.end() )
1113  {
1114 #if 0 && defined(DEBUG)
1115  // dump the whole darn table, there's something wrong with it.
1116  for( it = aMap.begin(); it != aMap.end(); ++it )
1117  {
1118  wxLogDebug( &aMap == (void*)&m_layerIndices ? wxT( "lm[%s] = %d" ) :
1119  wxT( "lm[%s] = %08X" ), it->first.c_str(), it->second );
1120  }
1121 #endif
1122 
1123  m_undefinedLayers.insert( curText );
1124  return Rescue;
1125  }
1126 
1127  return it->second;
1128 }
LAYER_ID_MAP m_layerIndices
map layer name to it's index
Definition: pcb_parser.h:72
std::set< wxString > m_undefinedLayers
set of layers not defined in layers section
Definition: pcb_parser.h:74

References Rescue.

◆ Parse()

BOARD_ITEM * PCB_PARSER::Parse ( )

Definition at line 444 of file pcb_parser.cpp.

445 {
446  T token;
447  BOARD_ITEM* item;
448  LOCALE_IO toggle;
449 
450  // MODULEs can be prefixed with an initial block of single line comments and these
451  // are kept for Format() so they round trip in s-expression form. BOARDs might
452  // eventually do the same, but currently do not.
453  std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
454 
455  token = CurTok();
456 
457  if( token != T_LEFT )
458  Expecting( T_LEFT );
459 
460  switch( NextTok() )
461  {
462  case T_kicad_pcb:
463  if( m_board == NULL )
464  m_board = new BOARD();
465 
466  item = (BOARD_ITEM*) parseBOARD();
467  break;
468 
469  case T_module:
470  item = (BOARD_ITEM*) parseMODULE( initial_comments.release() );
471  break;
472 
473  default:
474  wxString err;
475  err.Printf( _( "Unknown token \"%s\"" ), GetChars( FromUTF8() ) );
476  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
477  }
478 
479  return item;
480 }
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: common.h:175
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:483
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
#define _(s)
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:101
Class BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:161
BOARD * m_board
Definition: pcb_parser.h:71
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 352 of file pcb_parser.cpp.

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

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 483 of file pcb_parser.cpp.

484 {
485  try
486  {
487  return parseBOARD_unchecked();
488  }
489  catch( const PARSE_ERROR& parse_error )
490  {
491  if( m_tooRecent )
492  throw FUTURE_FORMAT_ERROR( parse_error, GetRequiredVersion() );
493  else
494  throw;
495  }
496 }
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:76
wxString GetRequiredVersion()
Return a string representing the version of kicad required to open this file.
Definition: pcb_parser.cpp:184
BOARD * parseBOARD_unchecked()
Function parseBOARD_unchecked Parse a module, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR...
Definition: pcb_parser.cpp:499
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 499 of file pcb_parser.cpp.

500 {
501  T token;
502 
503  parseHeader();
504 
505  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
506  {
507  if( token != T_LEFT )
508  Expecting( T_LEFT );
509 
510  token = NextTok();
511 
512  switch( token )
513  {
514  case T_general:
516  break;
517 
518  case T_page:
519  parsePAGE_INFO();
520  break;
521 
522  case T_title_block:
524  break;
525 
526  case T_layers:
527  parseLayers();
528  break;
529 
530  case T_setup:
531  parseSetup();
532  break;
533 
534  case T_net:
536  break;
537 
538  case T_net_class:
539  parseNETCLASS();
540  break;
541 
542  case T_gr_arc:
543  case T_gr_circle:
544  case T_gr_curve:
545  case T_gr_line:
546  case T_gr_poly:
548  break;
549 
550  case T_gr_text:
552  break;
553 
554  case T_dimension:
556  break;
557 
558  case T_module:
560  break;
561 
562  case T_segment:
564  break;
565 
566  case T_via:
568  break;
569 
570  case T_zone:
572  break;
573 
574  case T_target:
576  break;
577 
578  default:
579  wxString err;
580  err.Printf( _( "Unknown token \"%s\"" ), GetChars( FromUTF8() ) );
581  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
582  }
583  }
584 
585  if( m_undefinedLayers.size() > 0 )
586  {
587  bool deleteItems;
588  std::vector<BOARD_ITEM*> deleteList;
589  wxString msg = wxString::Format( _( "Items found on undefined layers. Do you wish to\n"
590  "rescue them to the Cmts.User layer?" ) );
591  wxString details = wxString::Format( _( "Undefined layers:" ) );
592 
593  for( const wxString& undefinedLayer : m_undefinedLayers )
594  details += wxT( "\n " ) + undefinedLayer;
595 
596  wxRichMessageDialog dlg( nullptr, msg, _( "Warning" ),
597  wxYES_NO | wxCANCEL | wxCENTRE | wxICON_WARNING | wxSTAY_ON_TOP );
598  dlg.ShowDetailedText( details );
599  dlg.SetYesNoCancelLabels( _( "Rescue" ), _( "Delete" ), _( "Cancel" ) );
600 
601  switch( dlg.ShowModal() )
602  {
603  case wxID_YES: deleteItems = false; break;
604  case wxID_NO: deleteItems = true; break;
605  case wxID_CANCEL:
606  default: THROW_IO_ERROR( wxT( "CANCEL" ) );
607  }
608 
609  auto visitItem = [&]( BOARD_ITEM* item )
610  {
611  if( item->GetLayer() == Rescue )
612  {
613  if( deleteItems )
614  deleteList.push_back( item );
615  else
616  item->SetLayer( Cmts_User );
617  }
618  };
619 
620  for( auto segm : m_board->Tracks() )
621  {
622  if( segm->Type() == PCB_VIA_T )
623  {
624  VIA* via = (VIA*) segm;
625  PCB_LAYER_ID top_layer, bottom_layer;
626 
627  if( via->GetViaType() == VIA_THROUGH )
628  continue;
629 
630  via->LayerPair( &top_layer, &bottom_layer );
631 
632  if( top_layer == Rescue || bottom_layer == Rescue )
633  {
634  if( deleteItems )
635  deleteList.push_back( via );
636  else
637  {
638  if( top_layer == Rescue )
639  top_layer = F_Cu;
640 
641  if( bottom_layer == Rescue )
642  bottom_layer = B_Cu;
643 
644  via->SetLayerPair( top_layer, bottom_layer );
645  }
646  }
647  }
648  else
649  visitItem( segm );
650  }
651 
652  for( BOARD_ITEM* zone : m_board->Zones() )
653  visitItem( zone );
654 
655  for( BOARD_ITEM* drawing : m_board->Drawings() )
656  visitItem( drawing );
657 
658  for( BOARD_ITEM* item : deleteList )
659  m_board->Delete( item );
660 
661  m_undefinedLayers.clear();
662  }
663 
664  return m_board;
665 }
void parseHeader()
Definition: pcb_parser.cpp:668
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:806
void parseLayers()
Definition: pcb_parser.cpp:980
void parsePAGE_INFO()
Definition: pcb_parser.cpp:750
PCB_LAYER_ID
A quick note on layer IDs:
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:346
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()
#define _(s)
string & err
Definition: json11.cpp:598
ZONE_CONTAINER * parseZONE_CONTAINER()
ZONE_CONTAINERS & Zones()
Definition: class_board.h:250
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:101
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:71
void parseGeneralSection()
Definition: pcb_parser.cpp:704
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
MODULE * parseMODULE(wxArrayString *aInitialComments=0)
Function parseMODULE.
DRAWINGS & Drawings()
Definition: class_board.h:245
TRACKS & Tracks()
Definition: class_board.h:227
void parseSetup()
std::set< wxString > m_undefinedLayers
set of layers not defined in layers section
Definition: pcb_parser.h:74

References _, ADD_APPEND, ADD_INSERT, B_Cu, Cmts_User, err, F_Cu, Format(), GetChars(), VIA::GetViaType(), VIA::LayerPair(), 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 1131 of file pcb_parser.cpp.

1132 {
1133  wxCHECK_MSG( CurTok() == T_layer, UNDEFINED_LAYER,
1134  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as layer." ) );
1135 
1136  NextTok();
1137 
1138  PCB_LAYER_ID layerIndex = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
1139 
1140  // Handle closing ) in object parser.
1141 
1142  return layerIndex;
1143 }
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:72

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 1146 of file pcb_parser.cpp.

1147 {
1148  wxCHECK_MSG( CurTok() == T_layers, LSET(),
1149  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1150  wxT( " as item layer mask." ) );
1151 
1152  LSET layerMask;
1153 
1154  for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
1155  {
1156  LSET mask = lookUpLayer<LSET>( m_layerMasks );
1157  layerMask |= mask;
1158  }
1159 
1160  return layerMask;
1161 }
Class LSET is a set of PCB_LAYER_IDs.
LSET_MAP m_layerMasks
map layer names to their masks
Definition: pcb_parser.h:73

◆ parseBoardUnits() [1/3]

int PCB_PARSER::parseBoardUnits ( )
inlineprivate

Definition at line 241 of file pcb_parser.h.

242  {
243  // There should be no major rounding issues here, since the values in
244  // the file are in mm and get converted to nano-meters.
245  // See test program tools/test-nm-biu-to-ascii-mm-round-tripping.cpp
246  // to confirm or experiment. Use a similar strategy in both places, here
247  // and in the test program. Make that program with:
248  // $ make test-nm-biu-to-ascii-mm-round-tripping
249  auto retval = parseDouble() * IU_PER_MM;
250 
251  // N.B. we currently represent board units as integers. Any values that are
252  // larger or smaller than those board units represent undefined behavior for
253  // the system. We limit values to the largest that is visible on the screen
254  // This is the diagonal distance of the full screen ~1.5m
255  double int_limit = std::numeric_limits<int>::max() * 0.7071; // 0.7071 = roughly 1/sqrt(2)
256  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
257  }
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:115
#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:126

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

Referenced by parseBoardUnits().

◆ parseBoardUnits() [2/3]

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

Definition at line 259 of file pcb_parser.h.

260  {
261  auto retval = parseDouble( aExpected ) * IU_PER_MM;
262 
263  // N.B. we currently represent board units as integers. Any values that are
264  // larger or smaller than those board units represent undefined behavior for
265  // the system. We limit values to the largest that is visible on the screen
266  double int_limit = std::numeric_limits<int>::max() * 0.7071;
267 
268  // Use here KiROUND, not KIROUND (see comments about them)
269  // when having a function as argument, because it will be called twice
270  // with KIROUND
271  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
272  }
static int KiROUND(double v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: common.h:115
#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:126

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

◆ parseBoardUnits() [3/3]

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

Definition at line 274 of file pcb_parser.h.

275  {
276  return parseBoardUnits( GetTokenText( aToken ) );
277  }
int parseBoardUnits()
Definition: pcb_parser.h:241
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 156 of file pcb_parser.cpp.

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

◆ parseD_PAD()

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

Definition at line 2572 of file pcb_parser.cpp.

2573 {
2574  wxCHECK_MSG( CurTok() == T_pad, NULL,
2575  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as D_PAD." ) );
2576 
2577  wxSize sz;
2578  wxPoint pt;
2579 
2580  std::unique_ptr< D_PAD > pad( new D_PAD( aParent ) );
2581 
2582  NeedSYMBOLorNUMBER();
2583  pad->SetName( FromUTF8() );
2584 
2585  T token = NextTok();
2586 
2587  switch( token )
2588  {
2589  case T_thru_hole:
2590  pad->SetAttribute( PAD_ATTRIB_STANDARD );
2591  break;
2592 
2593  case T_smd:
2594  pad->SetAttribute( PAD_ATTRIB_SMD );
2595 
2596  // Default D_PAD object is thru hole with drill.
2597  // SMD pads have no hole
2598  pad->SetDrillSize( wxSize( 0, 0 ) );
2599  break;
2600 
2601  case T_connect:
2602  pad->SetAttribute( PAD_ATTRIB_CONN );
2603 
2604  // Default D_PAD object is thru hole with drill.
2605  // CONN pads have no hole
2606  pad->SetDrillSize( wxSize( 0, 0 ) );
2607  break;
2608 
2609  case T_np_thru_hole:
2610  pad->SetAttribute( PAD_ATTRIB_HOLE_NOT_PLATED );
2611  break;
2612 
2613  default:
2614  Expecting( "thru_hole, smd, connect, or np_thru_hole" );
2615  }
2616 
2617  token = NextTok();
2618 
2619  switch( token )
2620  {
2621  case T_circle:
2622  pad->SetShape( PAD_SHAPE_CIRCLE );
2623  break;
2624 
2625  case T_rect:
2626  pad->SetShape( PAD_SHAPE_RECT );
2627  break;
2628 
2629  case T_oval:
2630  pad->SetShape( PAD_SHAPE_OVAL );
2631  break;
2632 
2633  case T_trapezoid:
2634  pad->SetShape( PAD_SHAPE_TRAPEZOID );
2635  break;
2636 
2637  case T_roundrect:
2638  // Note: the shape can be PAD_SHAPE_ROUNDRECT or PAD_SHAPE_CHAMFERED_RECT
2639  // (if champfer parameters are found later in pad descr.)
2640  pad->SetShape( PAD_SHAPE_ROUNDRECT );
2641  break;
2642 
2643  case T_custom:
2644  pad->SetShape( PAD_SHAPE_CUSTOM );
2645  break;
2646 
2647  default:
2648  Expecting( "circle, rectangle, roundrect, oval, trapezoid or custom" );
2649  }
2650 
2651  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2652  {
2653  if( token != T_LEFT )
2654  Expecting( T_LEFT );
2655 
2656  token = NextTok();
2657 
2658  switch( token )
2659  {
2660  case T_size:
2661  sz.SetWidth( parseBoardUnits( "width value" ) );
2662  sz.SetHeight( parseBoardUnits( "height value" ) );
2663  pad->SetSize( sz );
2664  NeedRIGHT();
2665  break;
2666 
2667  case T_at:
2668  pt.x = parseBoardUnits( "X coordinate" );
2669  pt.y = parseBoardUnits( "Y coordinate" );
2670  pad->SetPos0( pt );
2671  token = NextTok();
2672 
2673  if( token == T_NUMBER )
2674  {
2675  pad->SetOrientation( parseDouble() * 10.0 );
2676  NeedRIGHT();
2677  }
2678  else if( token != T_RIGHT )
2679  {
2680  Expecting( ") or angle value" );
2681  }
2682 
2683  break;
2684 
2685  case T_rect_delta:
2686  {
2687  wxSize delta;
2688  delta.SetWidth( parseBoardUnits( "rectangle delta width" ) );
2689  delta.SetHeight( parseBoardUnits( "rectangle delta height" ) );
2690  pad->SetDelta( delta );
2691  NeedRIGHT();
2692  }
2693  break;
2694 
2695  case T_drill:
2696  {
2697  bool haveWidth = false;
2698  wxSize drillSize = pad->GetDrillSize();
2699 
2700  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2701  {
2702  if( token == T_LEFT )
2703  token = NextTok();
2704 
2705  switch( token )
2706  {
2707  case T_oval:
2708  pad->SetDrillShape( PAD_DRILL_SHAPE_OBLONG );
2709  break;
2710 
2711  case T_NUMBER:
2712  {
2713  if( !haveWidth )
2714  {
2715  drillSize.SetWidth( parseBoardUnits() );
2716 
2717  // If height is not defined the width and height are the same.
2718  drillSize.SetHeight( drillSize.GetWidth() );
2719  haveWidth = true;
2720  }
2721  else
2722  {
2723  drillSize.SetHeight( parseBoardUnits() );
2724  }
2725 
2726  }
2727  break;
2728 
2729  case T_offset:
2730  pt.x = parseBoardUnits( "drill offset x" );
2731  pt.y = parseBoardUnits( "drill offset y" );
2732  pad->SetOffset( pt );
2733  NeedRIGHT();
2734  break;
2735 
2736  default:
2737  Expecting( "oval, size, or offset" );
2738  }
2739  }
2740 
2741  // This fixes a bug caused by setting the default D_PAD drill size to a value
2742  // other than 0 used to fix a bunch of debug assertions even though it is defined
2743  // as a through hole pad. Wouldn't a though hole pad with no drill be a surface
2744  // mount pad (or a conn pad which is a smd pad with no solder paste)?
2745  if( ( pad->GetAttribute() != PAD_ATTRIB_SMD ) && ( pad->GetAttribute() != PAD_ATTRIB_CONN ) )
2746  pad->SetDrillSize( drillSize );
2747  else
2748  pad->SetDrillSize( wxSize( 0, 0 ) );
2749 
2750  }
2751  break;
2752 
2753  case T_layers:
2754  {
2755  LSET layerMask = parseBoardItemLayersAsMask();
2756  pad->SetLayerSet( layerMask );
2757  }
2758  break;
2759 
2760  case T_net:
2761  if( ! pad->SetNetCode( getNetCode( parseInt( "net number" ) ), /* aNoAssert */ true ) )
2763  wxString::Format( _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
2764  CurSource(), CurLineNumber(), CurOffset() )
2765  );
2766 
2767  NeedSYMBOLorNUMBER();
2768 
2769  // Test validity of the netname in file for netcodes expected having a net name
2770  if( m_board && pad->GetNetCode() > 0 &&
2771  FromUTF8() != m_board->FindNet( pad->GetNetCode() )->GetNetname() )
2773  wxString::Format( _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
2774  CurSource(), CurLineNumber(), CurOffset() )
2775  );
2776 
2777  NeedRIGHT();
2778  break;
2779 
2780  case T_die_length:
2781  pad->SetPadToDieLength( parseBoardUnits( T_die_length ) );
2782  NeedRIGHT();
2783  break;
2784 
2785  case T_solder_mask_margin:
2786  pad->SetLocalSolderMaskMargin( parseBoardUnits( T_solder_mask_margin ) );
2787  NeedRIGHT();
2788  break;
2789 
2790  case T_solder_paste_margin:
2791  pad->SetLocalSolderPasteMargin( parseBoardUnits( T_solder_paste_margin ) );
2792  NeedRIGHT();
2793  break;
2794 
2795  case T_solder_paste_margin_ratio:
2796  pad->SetLocalSolderPasteMarginRatio(
2797  parseDouble( "pad local solder paste margin ratio value" ) );
2798  NeedRIGHT();
2799  break;
2800 
2801  case T_clearance:
2802  pad->SetLocalClearance( parseBoardUnits( "local clearance value" ) );
2803  NeedRIGHT();
2804  break;
2805 
2806  case T_zone_connect:
2807  pad->SetZoneConnection( (ZoneConnection) parseInt( "zone connection value" ) );
2808  NeedRIGHT();
2809  break;
2810 
2811  case T_thermal_width:
2812  pad->SetThermalWidth( parseBoardUnits( T_thermal_width ) );
2813  NeedRIGHT();
2814  break;
2815 
2816  case T_thermal_gap:
2817  pad->SetThermalGap( parseBoardUnits( T_thermal_gap ) );
2818  NeedRIGHT();
2819  break;
2820 
2821  case T_roundrect_rratio:
2822  pad->SetRoundRectRadiusRatio( parseDouble( "roundrect radius ratio" ) );
2823  NeedRIGHT();
2824  break;
2825 
2826  case T_chamfer_ratio:
2827  pad->SetChamferRectRatio( parseDouble( "chamfer ratio" ) );
2828 
2829  if( pad->GetChamferRectRatio() > 0 )
2830  pad->SetShape( PAD_SHAPE_CHAMFERED_RECT );
2831 
2832  NeedRIGHT();
2833  break;
2834 
2835  case T_chamfer:
2836  {
2837  int chamfers = 0;
2838  bool end_list = false;
2839 
2840  while( !end_list )
2841  {
2842  token = NextTok();
2843  switch( token )
2844  {
2845  case T_top_left:
2846  chamfers |= RECT_CHAMFER_TOP_LEFT;
2847  break;
2848 
2849  case T_top_right:
2850  chamfers |= RECT_CHAMFER_TOP_RIGHT;
2851  break;
2852 
2853  case T_bottom_left:
2854  chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
2855  break;
2856 
2857  case T_bottom_right:
2858  chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
2859  break;
2860 
2861  case T_RIGHT:
2862  pad->SetChamferPositions( chamfers );
2863  end_list = true;
2864  break;
2865 
2866  default:
2867  Expecting( "chamfer_top_left chamfer_top_right chamfer_bottom_left or chamfer_bottom_right" );
2868  }
2869  }
2870 
2871  if( pad->GetChamferPositions() != RECT_NO_CHAMFER )
2872  pad->SetShape( PAD_SHAPE_CHAMFERED_RECT );
2873  }
2874  break;
2875 
2876  case T_options:
2877  parseD_PAD_option( pad.get() );
2878  break;
2879 
2880  case T_primitives:
2881  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2882  {
2883  if( token == T_LEFT )
2884  token = NextTok();
2885 
2886  // Currently, I am using parseDRAWSEGMENT() to read basic shapes parameters,
2887  // because they are the same as a DRAWSEGMENT.
2888  // However it could be better to write a specific parser, to avoid possible issues
2889  // if the DRAWSEGMENT parser is modified.
2890  DRAWSEGMENT* dummysegm = NULL;
2891 
2892  switch( token )
2893  {
2894  case T_gr_arc:
2895  dummysegm = parseDRAWSEGMENT();
2896  pad->AddPrimitive( dummysegm->GetCenter(), dummysegm->GetArcStart(),
2897  dummysegm->GetAngle(), dummysegm->GetWidth() );
2898  break;
2899 
2900  case T_gr_line:
2901  dummysegm = parseDRAWSEGMENT();
2902  pad->AddPrimitive( dummysegm->GetStart(), dummysegm->GetEnd(),
2903  dummysegm->GetWidth() );
2904  break;
2905 
2906  case T_gr_circle:
2907  dummysegm = parseDRAWSEGMENT( true ); // Circles with 0 thickness are allowed
2908  // ( filled circles )
2909  pad->AddPrimitive( dummysegm->GetCenter(), dummysegm->GetRadius(),
2910  dummysegm->GetWidth() );
2911  break;
2912 
2913  case T_gr_poly:
2914  dummysegm = parseDRAWSEGMENT();
2915  pad->AddPrimitive( dummysegm->BuildPolyPointsList(), dummysegm->GetWidth() );
2916  break;
2917 
2918  case T_gr_curve:
2919  dummysegm = parseDRAWSEGMENT();
2920  pad->AddPrimitive( dummysegm->GetStart(), dummysegm->GetEnd(),
2921  dummysegm->GetBezControl1(), dummysegm->GetBezControl2(),
2922  dummysegm->GetWidth() );
2923  break;
2924 
2925  default:
2926  Expecting( "gr_line, gr_arc, gr_circle, gr_curve or gr_poly" );
2927  break;
2928  }
2929 
2930  delete dummysegm;
2931  }
2932  break;
2933 
2934  default:
2935  Expecting( "at, drill, layers, net, die_length, solder_mask_margin, roundrect_rratio,\n"
2936  "solder_paste_margin, solder_paste_margin_ratio, clearance,\n"
2937  "zone_connect, fp_poly, primitives, thermal_width, or thermal_gap" );
2938  }
2939  }
2940 
2941  // Be sure the custom shape polygon is built:
2942  if( pad->GetShape() == PAD_SHAPE_CUSTOM )
2943  pad->MergePrimitivesAsPolygon();
2944 
2945  return pad.release();
2946 }
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.
int parseBoardUnits()
Definition: pcb_parser.h:241
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
#define _(s)
int GetWidth() const
double GetAngle() const
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:83
BOARD * m_board
Definition: pcb_parser.h:71
const wxPoint & GetBezControl2() const
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:126
const wxPoint & GetBezControl1() const
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
int parseInt()
Definition: pcb_parser.h:279

References _, DRAWSEGMENT::BuildPolyPointsList(), Format(), DRAWSEGMENT::GetAngle(), DRAWSEGMENT::GetArcStart(), DRAWSEGMENT::GetBezControl1(), DRAWSEGMENT::GetBezControl2(), DRAWSEGMENT::GetCenter(), 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 2949 of file pcb_parser.cpp.

2950 {
2951  // Parse only the (option ...) inside a pad description
2952  for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
2953  {
2954  if( token != T_LEFT )
2955  Expecting( T_LEFT );
2956 
2957  token = NextTok();
2958 
2959  switch( token )
2960  {
2961  case T_anchor:
2962  token = NextTok();
2963  // Custom shaped pads have a "anchor pad", which is the reference
2964  // for connection calculations.
2965  // Because this is an anchor, only the 2 very basic shapes are managed:
2966  // circle and rect. The default is circle
2967  switch( token )
2968  {
2969  case T_circle: // default
2970  break;
2971 
2972  case T_rect:
2974  break;
2975 
2976  default:
2977  // Currently, because pad options is a moving target
2978  // just skip unknown keywords
2979  break;
2980  }
2981  NeedRIGHT();
2982  break;
2983 
2984  case T_clearance:
2985  token = NextTok();
2986  // Custom shaped pads have a clearance area that is the pad shape
2987  // (like usual pads) or the convew hull of the pad shape.
2988  switch( token )
2989  {
2990  case T_outline:
2992  break;
2993 
2994  case T_convexhull:
2996  break;
2997 
2998  default:
2999  // Currently, because pad options is a moving target
3000  // just skip unknown keywords
3001  break;
3002  }
3003  NeedRIGHT();
3004  break;
3005 
3006  default:
3007  // Currently, because pad options is a moving target
3008  // just skip unknown keywords
3009  while( (token = NextTok() ) != T_RIGHT )
3010  {}
3011  break;
3012  }
3013  }
3014 
3015  return true;
3016 }
void SetAnchorPadShape(PAD_SHAPE_T aShape)
Function SetAnchorPadShape Set the shape of the anchor pad for custm shped pads.
Definition: class_pad.h:258
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:247

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

◆ parseDefaults()

void PCB_PARSER::parseDefaults ( BOARD_DESIGN_SETTINGS aSettings)
private

Definition at line 1427 of file pcb_parser.cpp.

1428 {
1429  T token;
1430 
1431  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1432  {
1433  if( token != T_LEFT )
1434  Expecting( T_LEFT );
1435 
1436  token = NextTok();
1437 
1438  switch( token )
1439  {
1440  case T_edge_clearance:
1441  designSettings.m_CopperEdgeClearance = parseBoardUnits( T_edge_clearance );
1442  NeedRIGHT();
1443  break;
1444 
1445  case T_copper_line_width:
1446  designSettings.m_LineThickness[ LAYER_CLASS_COPPER ] = parseBoardUnits( token );
1447  NeedRIGHT();
1448  break;
1449 
1450  case T_copper_text_dims:
1451  parseDefaultTextDims( designSettings, LAYER_CLASS_COPPER );
1452  break;
1453 
1454  case T_courtyard_line_width:
1455  designSettings.m_LineThickness[ LAYER_CLASS_COURTYARD ] = parseBoardUnits( token );
1456  NeedRIGHT();
1457  break;
1458 
1459  case T_edge_cuts_line_width:
1460  designSettings.m_LineThickness[ LAYER_CLASS_EDGES ] = parseBoardUnits( token );
1461  NeedRIGHT();
1462  break;
1463 
1464  case T_silk_line_width:
1465  designSettings.m_LineThickness[ LAYER_CLASS_SILK ] = parseBoardUnits( token );
1466  NeedRIGHT();
1467  break;
1468 
1469  case T_silk_text_dims:
1470  parseDefaultTextDims( designSettings, LAYER_CLASS_SILK );
1471  break;
1472 
1473  case T_other_layers_line_width:
1474  designSettings.m_LineThickness[ LAYER_CLASS_OTHERS ] = parseBoardUnits( token );
1475  NeedRIGHT();
1476  break;
1477 
1478  case T_other_layers_text_dims:
1479  parseDefaultTextDims( designSettings, LAYER_CLASS_OTHERS );
1480  break;
1481 
1482  default:
1483  Unexpected( CurText() );
1484  }
1485  }
1486 }
int parseBoardUnits()
Definition: pcb_parser.h:241
void parseDefaultTextDims(BOARD_DESIGN_SETTINGS &aSettings, int aLayer)

References LAYER_CLASS_COPPER, LAYER_CLASS_COURTYARD, LAYER_CLASS_EDGES, LAYER_CLASS_OTHERS, LAYER_CLASS_SILK, BOARD_DESIGN_SETTINGS::m_CopperEdgeClearance, and BOARD_DESIGN_SETTINGS::m_LineThickness.

◆ parseDefaultTextDims()

void PCB_PARSER::parseDefaultTextDims ( BOARD_DESIGN_SETTINGS aSettings,
int  aLayer 
)
private

Definition at line 1489 of file pcb_parser.cpp.

1490 {
1491  T token;
1492 
1493  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1494  {
1495  if( token == T_LEFT )
1496  token = NextTok();
1497 
1498  switch( token )
1499  {
1500  case T_size:
1501  aSettings.m_TextSize[ aLayer ].x = parseBoardUnits( "default text size X" );
1502  aSettings.m_TextSize[ aLayer ].y = parseBoardUnits( "default text size Y" );
1503  NeedRIGHT();
1504  break;
1505 
1506  case T_thickness:
1507  aSettings.m_TextThickness[ aLayer ] = parseBoardUnits( "default text width" );
1508  NeedRIGHT();
1509  break;
1510 
1511  case T_italic:
1512  aSettings.m_TextItalic[ aLayer ] = true;
1513  break;
1514 
1515  case T_keep_upright:
1516  aSettings.m_TextUpright[ aLayer ] = true;
1517  break;
1518 
1519  default:
1520  Expecting( "size, thickness, italic or keep_upright" );
1521  }
1522  }
1523 }
int parseBoardUnits()
Definition: pcb_parser.h:241
wxSize m_TextSize[LAYER_CLASS_COUNT]
int m_TextThickness[LAYER_CLASS_COUNT]
bool m_TextItalic[LAYER_CLASS_COUNT]
bool m_TextUpright[LAYER_CLASS_COUNT]

References BOARD_DESIGN_SETTINGS::m_TextItalic, BOARD_DESIGN_SETTINGS::m_TextSize, BOARD_DESIGN_SETTINGS::m_TextThickness, and BOARD_DESIGN_SETTINGS::m_TextUpright.

◆ parseDIMENSION()

DIMENSION * PCB_PARSER::parseDIMENSION ( )
private

Definition at line 1876 of file pcb_parser.cpp.

1877 {
1878  wxCHECK_MSG( CurTok() == T_dimension, NULL,
1879  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as DIMENSION." ) );
1880 
1881  T token;
1882 
1883  std::unique_ptr<DIMENSION> dimension( new DIMENSION( NULL ) );
1884 
1885  dimension->SetValue( parseBoardUnits( "dimension value" ) );
1886  NeedLEFT();
1887  token = NextTok();
1888 
1889  if( token != T_width )
1890  Expecting( T_width );
1891 
1892  dimension->SetWidth( parseBoardUnits( "dimension width value" ) );
1893  NeedRIGHT();
1894 
1895  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1896  {
1897  if( token != T_LEFT )
1898  Expecting( T_LEFT );
1899 
1900  token = NextTok();
1901 
1902  switch( token )
1903  {
1904  case T_layer:
1905  dimension->SetLayer( parseBoardItemLayer() );
1906  NeedRIGHT();
1907  break;
1908 
1909  case T_tstamp:
1910  dimension->SetTimeStamp( parseHex() );
1911  NeedRIGHT();
1912  break;
1913 
1914  case T_gr_text:
1915  {
1916  TEXTE_PCB* text = parseTEXTE_PCB();
1917 
1918  // This copy (using the copy constructor) rebuild the text timestamp,
1919  // that is not what we want.
1920  dimension->Text() = *text;
1921  // reinitialises the text time stamp to the right value (the dimension time stamp)
1922  dimension->Text().SetTimeStamp( dimension->GetTimeStamp() );
1923  dimension->SetPosition( text->GetTextPos() );
1924 
1925  EDA_UNITS_T units = INCHES;
1926  bool useMils = false;
1927  FetchUnitsFromString( text->GetText(), units, useMils );
1928  dimension->SetUnits( units, useMils );
1929 
1930  delete text;
1931  break;
1932  }
1933 
1934  case T_feature1:
1935  NeedLEFT();
1936  token = NextTok();
1937 
1938  if( token != T_pts )
1939  Expecting( T_pts );
1940 
1941  parseXY( &dimension->m_featureLineDO.x, &dimension->m_featureLineDO.y );
1942  parseXY( &dimension->m_featureLineDF.x, &dimension->m_featureLineDF.y );
1943  dimension->UpdateHeight();
1944  NeedRIGHT();
1945  NeedRIGHT();
1946  break;
1947 
1948  case T_feature2:
1949  NeedLEFT();
1950  token = NextTok();
1951 
1952  if( token != T_pts )
1953  Expecting( T_pts );
1954 
1955  parseXY( &dimension->m_featureLineGO.x, &dimension->m_featureLineGO.y );
1956  parseXY( &dimension->m_featureLineGF.x, &dimension->m_featureLineGF.y );
1957  dimension->UpdateHeight();
1958  NeedRIGHT();
1959  NeedRIGHT();
1960  break;
1961 
1962 
1963  case T_crossbar:
1964  NeedLEFT();
1965  token = NextTok();
1966 
1967  if( token != T_pts )
1968  Expecting( T_pts );
1969 
1970  parseXY( &dimension->m_crossBarO.x, &dimension->m_crossBarO.y );
1971  parseXY( &dimension->m_crossBarF.x, &dimension->m_crossBarF.y );
1972  dimension->UpdateHeight();
1973  NeedRIGHT();
1974  NeedRIGHT();
1975  break;
1976 
1977  case T_arrow1a:
1978  NeedLEFT();
1979  token = NextTok();
1980 
1981  if( token != T_pts )
1982  Expecting( T_pts );
1983 
1984  parseXY( &dimension->m_crossBarF.x, &dimension->m_crossBarF.y );
1985  parseXY( &dimension->m_arrowD1F.x, &dimension->m_arrowD1F.y );
1986  NeedRIGHT();
1987  NeedRIGHT();
1988  break;
1989 
1990  case T_arrow1b:
1991  NeedLEFT();
1992  token = NextTok();
1993 
1994  if( token != T_pts )
1995  Expecting( T_pts );
1996 
1997  parseXY( &dimension->m_crossBarF.x, &dimension->m_crossBarF.y );
1998  parseXY( &dimension->m_arrowD2F.x, &dimension->m_arrowD2F.y );
1999  NeedRIGHT();
2000  NeedRIGHT();
2001  break;
2002 
2003  case T_arrow2a:
2004  NeedLEFT();
2005  token = NextTok();
2006 
2007  if( token != T_pts )
2008  Expecting( T_pts );
2009 
2010  parseXY( &dimension->m_crossBarO.x, &dimension->m_crossBarO.y );
2011  parseXY( &dimension->m_arrowG1F.x, &dimension->m_arrowG1F.y );
2012  NeedRIGHT();
2013  NeedRIGHT();
2014  break;
2015 
2016  case T_arrow2b:
2017  NeedLEFT();
2018  token = NextTok();
2019 
2020  if( token != T_pts )
2021  Expecting( T_pts );
2022 
2023  parseXY( &dimension->m_crossBarO.x, &dimension->m_crossBarO.y );
2024  parseXY( &dimension->m_arrowG2F.x, &dimension->m_arrowG2F.y );
2025  NeedRIGHT();
2026  NeedRIGHT();
2027  break;
2028 
2029  default:
2030  Expecting( "layer, tstamp, gr_text, feature1, feature2 crossbar, arrow1a, "
2031  "arrow1b, arrow2a, or arrow2b" );
2032  }
2033  }
2034 
2035  return dimension.release();
2036 }
wxPoint parseXY()
Function parseXY parses a coordinate pair (xy X Y) in board units (mm).
Definition: pcb_parser.cpp:208
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:375
int parseBoardUnits()
Definition: pcb_parser.h:241
Definition: common.h:155
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:230
long parseHex()
Definition: pcb_parser.h:290
virtual const wxString & GetText() const
Function GetText returns the string associated with the text object.
Definition: eda_text.h:124
EDA_UNITS_T
Definition: common.h:154
Class DIMENSION.
void SetTimeStamp(timestamp_t aNewTimeStamp)
Definition: base_struct.h:215

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 126 of file pcb_parser.cpp.

127 {
128  char* tmp;
129 
130  errno = 0;
131 
132  double fval = strtod( CurText(), &tmp );
133 
134  if( errno )
135  {
136  wxString error;
137  error.Printf( _( "Invalid floating point number in\nfile: \"%s\"\nline: %d\noffset: %d" ),
138  GetChars( CurSource() ), CurLineNumber(), CurOffset() );
139 
140  THROW_IO_ERROR( error );
141  }
142 
143  if( CurText() == tmp )
144  {
145  wxString error;
146  error.Printf( _( "Missing floating point number in\nfile: \"%s\"\nline: %d\noffset: %d" ),
147  GetChars( CurSource() ), CurLineNumber(), CurOffset() );
148 
149  THROW_IO_ERROR( error );
150  }
151 
152  return fval;
153 }
#define THROW_IO_ERROR(msg)
#define _(s)
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:101

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 230 of file pcb_parser.h.

231  {
232  NeedNUMBER( aExpected );
233  return parseDouble();
234  }
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:126

References parseDouble().

◆ parseDouble() [3/3]

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

Definition at line 236 of file pcb_parser.h.

237  {
238  return parseDouble( GetTokenText( aToken ) );
239  }
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:126
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 1635 of file pcb_parser.cpp.

1636 {
1637  wxCHECK_MSG( CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
1638  CurTok() == T_gr_line || CurTok() == T_gr_poly, NULL,
1639  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as DRAWSEGMENT." ) );
1640 
1641  T token;
1642  wxPoint pt;
1643  std::unique_ptr< DRAWSEGMENT > segment( new DRAWSEGMENT( NULL ) );
1644 
1645  switch( CurTok() )
1646  {
1647  case T_gr_arc:
1648  segment->SetShape( S_ARC );
1649  NeedLEFT();
1650  token = NextTok();
1651 
1652  // the start keyword actually gives the arc center
1653  // Allows also T_center for future change
1654  if( token != T_start && token != T_center )
1655  Expecting( T_start );
1656 
1657  pt.x = parseBoardUnits( "X coordinate" );
1658  pt.y = parseBoardUnits( "Y coordinate" );
1659  segment->SetCenter( pt );
1660  NeedRIGHT();
1661  NeedLEFT();
1662  token = NextTok();
1663 
1664  if( token != T_end ) // the end keyword actually gives the starting point of the arc
1665  Expecting( T_end );
1666 
1667  pt.x = parseBoardUnits( "X coordinate" );
1668  pt.y = parseBoardUnits( "Y coordinate" );
1669  segment->SetArcStart( pt );
1670  NeedRIGHT();
1671  break;
1672 
1673  case T_gr_circle:
1674  segment->SetShape( S_CIRCLE );
1675  NeedLEFT();
1676  token = NextTok();
1677 
1678  if( token != T_center )
1679  Expecting( T_center );
1680 
1681  pt.x = parseBoardUnits( "X coordinate" );
1682  pt.y = parseBoardUnits( "Y coordinate" );
1683  segment->SetCenter( pt );
1684  NeedRIGHT();
1685  NeedLEFT();
1686 
1687  token = NextTok();
1688 
1689  if( token != T_end )
1690  Expecting( T_end );
1691 
1692  pt.x = parseBoardUnits( "X coordinate" );
1693  pt.y = parseBoardUnits( "Y coordinate" );
1694  segment->SetEnd( pt );
1695  NeedRIGHT();
1696  break;
1697 
1698  case T_gr_curve:
1699  segment->SetShape( S_CURVE );
1700  NeedLEFT();
1701  token = NextTok();
1702 
1703  if( token != T_pts )
1704  Expecting( T_pts );
1705 
1706  segment->SetStart( parseXY() );
1707  segment->SetBezControl1( parseXY() );
1708  segment->SetBezControl2( parseXY() );
1709  segment->SetEnd( parseXY() );
1710  NeedRIGHT();
1711  break;
1712 
1713  case T_gr_line:
1714  // Default DRAWSEGMENT type is S_SEGMENT.
1715  NeedLEFT();
1716  token = NextTok();
1717 
1718  if( token != T_start )
1719  Expecting( T_start );
1720 
1721  pt.x = parseBoardUnits( "X coordinate" );
1722  pt.y = parseBoardUnits( "Y coordinate" );
1723  segment->SetStart( pt );
1724  NeedRIGHT();
1725  NeedLEFT();
1726  token = NextTok();
1727 
1728  if( token != T_end )
1729  Expecting( T_end );
1730 
1731  pt.x = parseBoardUnits( "X coordinate" );
1732  pt.y = parseBoardUnits( "Y coordinate" );
1733  segment->SetEnd( pt );
1734  NeedRIGHT();
1735  break;
1736 
1737  case T_gr_poly:
1738  {
1739  segment->SetShape( S_POLYGON );
1740  segment->SetWidth( 0 ); // this is the default value. will be (perhaps) modified later
1741  NeedLEFT();
1742  token = NextTok();
1743 
1744  if( token != T_pts )
1745  Expecting( T_pts );
1746 
1747  std::vector< wxPoint > pts;
1748 
1749  while( (token = NextTok()) != T_RIGHT )
1750  pts.push_back( parseXY() );
1751 
1752  segment->SetPolyPoints( pts );
1753  }
1754  break;
1755 
1756  default:
1757  Expecting( "gr_arc, gr_circle, gr_curve, gr_line, or gr_poly" );
1758  }
1759 
1760  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1761  {
1762  if( token != T_LEFT )
1763  Expecting( T_LEFT );
1764 
1765  token = NextTok();
1766 
1767  switch( token )
1768  {
1769  case T_angle:
1770  segment->SetAngle( parseDouble( "segment angle" ) * 10.0 );
1771  break;
1772 
1773  case T_layer:
1774  segment->SetLayer( parseBoardItemLayer() );
1775  break;
1776 
1777  case T_width:
1778  segment->SetWidth( parseBoardUnits( T_width ) );
1779  break;
1780 
1781  case T_tstamp:
1782  segment->SetTimeStamp( parseHex() );
1783  break;
1784 
1785  case T_status:
1786  segment->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
1787  break;
1788 
1789  default:
1790  Expecting( "layer, width, tstamp, or status" );
1791  }
1792 
1793  NeedRIGHT();
1794  }
1795 
1796  // Only filled polygons may have a zero-line width
1797  // This is not permitted in KiCad but some external tools generate invalid
1798  // files.
1799  // However in custom pad shapes, zero-line width is allowed for filled circles
1800  if( segment->GetShape() != S_POLYGON && segment->GetWidth() == 0 &&
1801  !( segment->GetShape() == S_CIRCLE && aAllowCirclesZeroWidth ) )
1802  segment->SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) );
1803 
1804  return segment.release();
1805 }
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:208
#define DEFAULT_LINE_WIDTH
int parseBoardUnits()
Definition: pcb_parser.h:241
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:126
long parseHex()
Definition: pcb_parser.h:290

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 240 of file pcb_parser.cpp.

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

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 2397 of file pcb_parser.cpp.

2398 {
2399  wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
2400  CurTok() == T_fp_line || CurTok() == T_fp_poly, NULL,
2401  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as EDGE_MODULE." ) );
2402 
2403  wxPoint pt;
2404  T token;
2405 
2406  std::unique_ptr< EDGE_MODULE > segment( new EDGE_MODULE( NULL ) );
2407 
2408  switch( CurTok() )
2409  {
2410  case T_fp_arc:
2411  segment->SetShape( S_ARC );
2412  NeedLEFT();
2413  token = NextTok();
2414 
2415  // the start keyword actually gives the arc center
2416  // Allows also T_center for future change
2417  if( token != T_start && token != T_center )
2418  Expecting( T_start );
2419 
2420  pt.x = parseBoardUnits( "X coordinate" );
2421  pt.y = parseBoardUnits( "Y coordinate" );
2422  segment->SetStart0( pt );
2423  NeedRIGHT();
2424  NeedLEFT();
2425  token = NextTok();
2426 
2427  if( token != T_end ) // end keyword actually gives the starting point of the arc
2428  Expecting( T_end );
2429 
2430  pt.x = parseBoardUnits( "X coordinate" );
2431  pt.y = parseBoardUnits( "Y coordinate" );
2432  segment->SetEnd0( pt );
2433  NeedRIGHT();
2434  NeedLEFT();
2435  token = NextTok();
2436 
2437  if( token != T_angle )
2438  Expecting( T_angle );
2439 
2440  segment->SetAngle( parseDouble( "segment angle" ) * 10.0 );
2441  NeedRIGHT();
2442  break;
2443 
2444  case T_fp_circle:
2445  segment->SetShape( S_CIRCLE );
2446  NeedLEFT();
2447  token = NextTok();
2448 
2449  if( token != T_center )
2450  Expecting( T_center );
2451 
2452  pt.x = parseBoardUnits( "X coordinate" );
2453  pt.y = parseBoardUnits( "Y coordinate" );
2454  segment->SetStart0( pt );
2455  NeedRIGHT();
2456  NeedLEFT();
2457  token = NextTok();
2458 
2459  if( token != T_end )
2460  Expecting( T_end );
2461 
2462  pt.x = parseBoardUnits( "X coordinate" );
2463  pt.y = parseBoardUnits( "Y coordinate" );
2464  segment->SetEnd0( pt );
2465  NeedRIGHT();
2466  break;
2467 
2468  case T_fp_curve:
2469  segment->SetShape( S_CURVE );
2470  NeedLEFT();
2471  token = NextTok();
2472 
2473  if( token != T_pts )
2474  Expecting( T_pts );
2475 
2476  segment->SetStart0( parseXY() );
2477  segment->SetBezier0_C1( parseXY() );
2478  segment->SetBezier0_C2( parseXY() );
2479  segment->SetEnd0( parseXY() );
2480  NeedRIGHT();
2481  break;
2482 
2483  case T_fp_line:
2484  // Default DRAWSEGMENT type is S_SEGMENT.
2485  NeedLEFT();
2486  token = NextTok();
2487 
2488  if( token != T_start )
2489  Expecting( T_start );
2490 
2491  pt.x = parseBoardUnits( "X coordinate" );
2492  pt.y = parseBoardUnits( "Y coordinate" );
2493  segment->SetStart0( pt );
2494 
2495  NeedRIGHT();
2496  NeedLEFT();
2497  token = NextTok();
2498 
2499  if( token != T_end )
2500  Expecting( T_end );
2501 
2502  pt.x = parseBoardUnits( "X coordinate" );
2503  pt.y = parseBoardUnits( "Y coordinate" );
2504  segment->SetEnd0( pt );
2505  NeedRIGHT();
2506  break;
2507 
2508  case T_fp_poly:
2509  {
2510  segment->SetShape( S_POLYGON );
2511  NeedLEFT();
2512  token = NextTok();
2513 
2514  if( token != T_pts )
2515  Expecting( T_pts );
2516 
2517  std::vector< wxPoint > pts;
2518 
2519  while( (token = NextTok()) != T_RIGHT )
2520  pts.push_back( parseXY() );
2521 
2522  segment->SetPolyPoints( pts );
2523  }
2524  break;
2525 
2526  default:
2527  Expecting( "fp_arc, fp_circle, fp_curve, fp_line, or fp_poly" );
2528  }
2529 
2530  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2531  {
2532  if( token != T_LEFT )
2533  Expecting( T_LEFT );
2534 
2535  token = NextTok();
2536 
2537  switch( token )
2538  {
2539  case T_layer:
2540  segment->SetLayer( parseBoardItemLayer() );
2541  break;
2542 
2543  case T_width:
2544  segment->SetWidth( parseBoardUnits( T_width ) );
2545  break;
2546 
2547  case T_tstamp:
2548  segment->SetTimeStamp( parseHex() );
2549  break;
2550 
2551  case T_status:
2552  segment->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
2553  break;
2554 
2555  default:
2556  Expecting( "layer or width" );
2557  }
2558 
2559  NeedRIGHT();
2560  }
2561 
2562  // Only filled polygons may have a zero-line width
2563  // This is not permitted in KiCad but some external tools generate invalid
2564  // files.
2565  if( segment->GetShape() != S_POLYGON && segment->GetWidth() == 0 )
2566  segment->SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) );
2567 
2568  return segment.release();
2569 }
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:208
#define DEFAULT_LINE_WIDTH
int parseBoardUnits()
Definition: pcb_parser.h:241
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:126
long parseHex()
Definition: pcb_parser.h:290

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

◆ parseGeneralSection()

void PCB_PARSER::parseGeneralSection ( )
private

Definition at line 704 of file pcb_parser.cpp.

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

References parseInt().

◆ parseHeader()

void PCB_PARSER::parseHeader ( )
private

Definition at line 668 of file pcb_parser.cpp.

669 {
670  wxCHECK_RET( CurTok() == T_kicad_pcb,
671  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a header." ) );
672 
673  NeedLEFT();
674 
675  T tok = NextTok();
676  if( tok == T_version )
677  {
678  m_requiredVersion = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
680  NeedRIGHT();
681 
682  // Skip the host name and host build version information.
683  NeedLEFT();
684  NeedSYMBOL();
685  NeedSYMBOL();
686  NeedSYMBOL();
687  NeedRIGHT();
688  }
689  else
690  {
693 
694  // Skip the host name and host build version information.
695  NeedSYMBOL();
696  NeedSYMBOL();
697  NeedRIGHT();
698  }
699 
701 }
void SetFileFormatVersionAtLoad(int aVersion)
Definition: class_board.h:274
#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:76
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:77
BOARD * m_board
Definition: pcb_parser.h:71
int parseInt()
Definition: pcb_parser.h:279

References parseInt(), and SEXPR_BOARD_FILE_VERSION.

◆ parseHex()

long PCB_PARSER::parseHex ( )
inlineprivate

Definition at line 290 of file pcb_parser.h.

291  {
292  NextTok();
293  return strtol( CurText(), NULL, 16 );
294  }

◆ parseInt() [1/2]

int PCB_PARSER::parseInt ( )
inlineprivate

Definition at line 279 of file pcb_parser.h.

280  {
281  return (int)strtol( CurText(), NULL, 10 );
282  }

Referenced by parseInt().

◆ parseInt() [2/2]

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

Definition at line 284 of file pcb_parser.h.

285  {
286  NeedNUMBER( aExpected );
287  return parseInt();
288  }
int parseInt()
Definition: pcb_parser.h:279

References parseInt().

◆ parseLayer()

void PCB_PARSER::parseLayer ( LAYER aLayer)
private

Definition at line 889 of file pcb_parser.cpp.

890 {
891  T token;
892 
893  std::string name;
894  std::string type;
895  bool isVisible = true;
896 
897  aLayer->clear();
898 
899  if( CurTok() != T_LEFT )
900  Expecting( T_LEFT );
901 
902  // this layer_num is not used, we DO depend on LAYER_T however.
903  LAYER_NUM layer_num = parseInt( "layer index" );
904 
905  NeedSYMBOLorNUMBER();
906  name = CurText();
907 
908  NeedSYMBOL();
909  type = CurText();
910 
911  token = NextTok();
912 
913  if( token == T_hide )
914  {
915  isVisible = false;
916  NeedRIGHT();
917  }
918  else if( token != T_RIGHT )
919  {
920  Expecting( "hide or )" );
921  }
922 
923  aLayer->m_name = FROM_UTF8( name.c_str() );
924  aLayer->m_type = LAYER::ParseType( type.c_str() );
925  aLayer->m_number = layer_num;
926  aLayer->m_visible = isVisible;
927 }
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:62
wxString m_name
The name of the layer, there should be no spaces in this name.
Definition: class_board.h:106
LAYER_T m_type
The type of the layer.
Definition: class_board.h:107
bool m_visible
Definition: class_board.h:108
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:87
const char * name
Definition: DXF_plotter.cpp:61
int m_number
Definition: class_board.h:109
int parseInt()
Definition: pcb_parser.h:279

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 980 of file pcb_parser.cpp.

981 {
982  wxCHECK_RET( CurTok() == T_layers,
983  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as layers." ) );
984 
985  T token;
986  LSET visibleLayers;
987  LSET enabledLayers;
988  int copperLayerCount = 0;
989  LAYER layer;
990 
991  std::unordered_map< std::string, std::string > v3_layer_names;
992  std::vector<LAYER> cu;
993 
994  createOldLayerMapping( v3_layer_names );
995 
996  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
997  {
998  parseLayer( &layer );
999 
1000  if( layer.m_type == LT_UNDEFINED ) // it's a non-copper layer
1001  break;
1002 
1003  cu.push_back( layer ); // it's copper
1004  }
1005 
1006  // All Cu layers are parsed, but not the non-cu layers here.
1007 
1008  // The original *.kicad_pcb file format and the inverted
1009  // Cu stack format both have all the Cu layers first, so use this
1010  // trick to handle either. The layer number in the (layers ..)
1011  // s-expression element are ignored.
1012  if( cu.size() )
1013  {
1014  // Rework the layer numbers, which changed when the Cu stack
1015  // was flipped. So we instead use position in the list.
1016  cu[cu.size()-1].m_number = B_Cu;
1017 
1018  for( unsigned i=0; i < cu.size()-1; ++i )
1019  {
1020  cu[i].m_number = i;
1021  }
1022 
1023  for( std::vector<LAYER>::const_iterator it = cu.begin(); it<cu.end(); ++it )
1024  {
1025  enabledLayers.set( it->m_number );
1026 
1027  if( it->m_visible )
1028  visibleLayers.set( it->m_number );
1029 
1030  m_board->SetLayerDescr( PCB_LAYER_ID( it->m_number ), *it );
1031 
1032  UTF8 name = it->m_name;
1033 
1034  m_layerIndices[ name ] = PCB_LAYER_ID( it->m_number );
1035  m_layerMasks[ name ] = LSET( PCB_LAYER_ID( it->m_number ) );
1036  }
1037 
1038  copperLayerCount = cu.size();
1039  }
1040 
1041  // process non-copper layers
1042  while( token != T_RIGHT )
1043  {
1044  LAYER_ID_MAP::const_iterator it = m_layerIndices.find( UTF8( layer.m_name ) );
1045 
1046  if( it == m_layerIndices.end() )
1047  {
1048  auto new_layer_it = v3_layer_names.find( layer.m_name.ToStdString() );
1049 
1050  if( new_layer_it != v3_layer_names.end() )
1051  it = m_layerIndices.find( new_layer_it->second );
1052 
1053  if( it == m_layerIndices.end() )
1054  {
1055  wxString error = wxString::Format(
1056  _( "Layer \"%s\" in file \"%s\" at line %d, is not in fixed layer hash" ),
1057  GetChars( layer.m_name ),
1058  GetChars( CurSource() ),
1059  CurLineNumber(),
1060  CurOffset()
1061  );
1062 
1063  THROW_IO_ERROR( error );
1064  }
1065 
1066  // If we are here, then we have found a translated layer name. Put it in the maps so that
1067  // items on this layer get the appropriate layer ID number
1068  m_layerIndices[ UTF8( layer.m_name ) ] = it->second;
1069  m_layerMasks[ UTF8( layer.m_name ) ] = it->second;
1070  layer.m_name = it->first;
1071  }
1072 
1073  layer.m_number = it->second;
1074  enabledLayers.set( layer.m_number );
1075 
1076  if( layer.m_visible )
1077  visibleLayers.set( layer.m_number );
1078 
1079  m_board->SetLayerDescr( it->second, layer );
1080 
1081  token = NextTok();
1082 
1083  if( token != T_LEFT )
1084  break;
1085 
1086  parseLayer( &layer );
1087  }
1088 
1089  // We need at least 2 copper layers and there must be an even number of them.
1090  if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
1091  {
1092  wxString err = wxString::Format(
1093  _( "%d is not a valid layer count" ), copperLayerCount );
1094 
1095  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
1096  }
1097 
1098  m_board->SetCopperLayerCount( copperLayerCount );
1099  m_board->SetEnabledLayers( enabledLayers );
1100 
1101  // call SetEnabledLayers before SetVisibleLayers()
1102  m_board->SetVisibleLayers( visibleLayers );
1103 }
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:106
LAYER_T m_type
The type of the layer.
Definition: class_board.h:107
void createOldLayerMapping(std::unordered_map< std::string, std::string > &aMap)
Creates a mapping from the (short-lived) bug where layer names were translated TODO: Remove this once...
Definition: pcb_parser.cpp:930
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:108
#define THROW_IO_ERROR(msg)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
#define _(s)
string & err
Definition: json11.cpp:598
void parseLayer(LAYER *aLayer)
Definition: pcb_parser.cpp:889
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:101
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:80
BOARD * m_board
Definition: pcb_parser.h:71
size_t i
Definition: json11.cpp:597
LAYER_ID_MAP m_layerIndices
map layer name to it's index
Definition: pcb_parser.h:72
int m_number
Definition: class_board.h:109
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:73

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 2039 of file pcb_parser.cpp.

2040 {
2041  try
2042  {
2043  return parseMODULE_unchecked( aInitialComments );
2044  }
2045  catch( const PARSE_ERROR& parse_error )
2046  {
2047  if( m_tooRecent )
2048  throw FUTURE_FORMAT_ERROR( parse_error, GetRequiredVersion() );
2049  else
2050  throw;
2051  }
2052 }
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:76
wxString GetRequiredVersion()
Return a string representing the version of kicad required to open this file.
Definition: pcb_parser.cpp:184
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 2055 of file pcb_parser.cpp.

2056 {
2057  wxCHECK_MSG( CurTok() == T_module, NULL,
2058  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as MODULE." ) );
2059 
2060  wxString name;
2061  wxPoint pt;
2062  T token;
2063  LIB_ID fpid;
2064 
2065  std::unique_ptr<MODULE> module( new MODULE( m_board ) );
2066 
2067  module->SetInitialComments( aInitialComments );
2068 
2069  token = NextTok();
2070 
2071  if( !IsSymbol( token ) && token != T_NUMBER )
2072  Expecting( "symbol|number" );
2073 
2074  name = FromUTF8();
2075 
2076  if( !name.IsEmpty() && fpid.Parse( name, LIB_ID::ID_PCB, true ) >= 0 )
2077  {
2078  wxString error;
2079  error.Printf( _( "Invalid footprint ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
2080  GetChars( CurSource() ), CurLineNumber(), CurOffset() );
2081  THROW_IO_ERROR( error );
2082  }
2083 
2084  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2085  {
2086  if( token == T_LEFT )
2087  token = NextTok();
2088 
2089  switch( token )
2090  {
2091  case T_version:
2092  {
2093  // Theoretically a module nested in a PCB could declare its own version, though
2094  // as of writing this comment we don't do that. Just in case, take the greater
2095  // version.
2096  int this_version = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
2097  NeedRIGHT();
2098  m_requiredVersion = std::max( m_requiredVersion, this_version );
2100  break;
2101  }
2102 
2103  case T_locked:
2104  module->SetLocked( true );
2105  break;
2106 
2107  case T_placed:
2108  module->SetIsPlaced( true );
2109  break;
2110 
2111  case T_layer:
2112  {
2113  // Footprints can be only on the front side or the back side.
2114  // but because we can find some stupid layer in file, ensure a
2115  // acceptable layer is set for the footprint
2117  module->SetLayer( layer == B_Cu ? B_Cu : F_Cu );
2118  }
2119  NeedRIGHT();
2120  break;
2121 
2122  case T_tedit:
2123  module->SetLastEditTime( parseHex() );
2124  NeedRIGHT();
2125  break;
2126 
2127  case T_tstamp:
2128  module->SetTimeStamp( parseHex() );
2129  NeedRIGHT();
2130  break;
2131 
2132  case T_at:
2133  pt.x = parseBoardUnits( "X coordinate" );
2134  pt.y = parseBoardUnits( "Y coordinate" );
2135  module->SetPosition( pt );
2136  token = NextTok();
2137 
2138  if( token == T_NUMBER )
2139  {
2140  module->SetOrientation( parseDouble() * 10.0 );
2141  NeedRIGHT();
2142  }
2143  else if( token != T_RIGHT )
2144  {
2145  Expecting( T_RIGHT );
2146  }
2147 
2148  break;
2149 
2150  case T_descr:
2151  NeedSYMBOLorNUMBER(); // some symbols can be 0508, so a number is also a symbol here
2152  module->SetDescription( FromUTF8() );
2153  NeedRIGHT();
2154  break;
2155 
2156  case T_tags:
2157  NeedSYMBOLorNUMBER(); // some symbols can be 0508, so a number is also a symbol here
2158  module->SetKeywords( FromUTF8() );
2159  NeedRIGHT();
2160  break;
2161 
2162  case T_path:
2163  NeedSYMBOLorNUMBER(); // Paths can be numerical so a number is also a symbol here
2164  module->SetPath( FromUTF8() );
2165  NeedRIGHT();
2166  break;
2167 
2168  case T_autoplace_cost90:
2169  module->SetPlacementCost90( parseInt( "auto place cost at 90 degrees" ) );
2170  NeedRIGHT();
2171  break;
2172 
2173  case T_autoplace_cost180:
2174  module->SetPlacementCost180( parseInt( "auto place cost at 180 degrees" ) );
2175  NeedRIGHT();
2176  break;
2177 
2178  case T_solder_mask_margin:
2179  module->SetLocalSolderMaskMargin( parseBoardUnits( "local solder mask margin value" ) );
2180  NeedRIGHT();
2181  break;
2182 
2183  case T_solder_paste_margin:
2184  module->SetLocalSolderPasteMargin(
2185  parseBoardUnits( "local solder paste margin value" ) );
2186  NeedRIGHT();
2187  break;
2188 
2189  case T_solder_paste_ratio:
2190  module->SetLocalSolderPasteMarginRatio(
2191  parseDouble( "local solder paste margin ratio value" ) );
2192  NeedRIGHT();
2193  break;
2194 
2195  case T_clearance:
2196  module->SetLocalClearance( parseBoardUnits( "local clearance value" ) );
2197  NeedRIGHT();
2198  break;
2199 
2200  case T_zone_connect:
2201  module->SetZoneConnection( (ZoneConnection) parseInt( "zone connection value" ) );
2202  NeedRIGHT();
2203  break;
2204 
2205  case T_thermal_width:
2206  module->SetThermalWidth( parseBoardUnits( "thermal width value" ) );
2207  NeedRIGHT();
2208  break;
2209 
2210  case T_thermal_gap:
2211  module->SetThermalGap( parseBoardUnits( "thermal gap value" ) );
2212  NeedRIGHT();
2213  break;
2214 
2215  case T_attr:
2216  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2217  {
2218  switch( token )
2219  {
2220  case T_smd:
2221  module->SetAttributes( module->GetAttributes() | MOD_CMS );
2222  break;
2223 
2224  case T_virtual:
2225  module->SetAttributes( module->GetAttributes() | MOD_VIRTUAL );
2226  break;
2227 
2228  default:
2229  Expecting( "smd and/or virtual" );
2230  }
2231  }
2232  break;
2233 
2234  case T_fp_text:
2235  {
2236  TEXTE_MODULE* text = parseTEXTE_MODULE();
2237  text->SetParent( module.get() );
2238  double orientation = text->GetTextAngle();
2239  orientation -= module->GetOrientation();
2240  text->SetTextAngle( orientation );
2241  text->SetDrawCoord();
2242 
2243  switch( text->GetType() )
2244  {
2246  module->Reference() = *text;
2247  delete text;
2248  break;
2249 
2251  module->Value() = *text;
2252  delete text;
2253  break;
2254 
2255  default:
2256  module->Add( text );
2257  }
2258  }
2259  break;
2260 
2261  case T_fp_arc:
2262  case T_fp_circle:
2263  case T_fp_curve:
2264  case T_fp_line:
2265  case T_fp_poly:
2266  {
2267  EDGE_MODULE* em = parseEDGE_MODULE();
2268  em->SetParent( module.get() );
2269  em->SetDrawCoord();
2270  module->Add( em );
2271  }
2272  break;
2273 
2274  case T_pad:
2275  {
2276  D_PAD* pad = parseD_PAD( module.get() );
2277  pt = pad->GetPos0();
2278 
2279  RotatePoint( &pt, module->GetOrientation() );
2280  pad->SetPosition( pt + module->GetPosition() );
2281  module->Add( pad, ADD_APPEND );
2282  }
2283  break;
2284 
2285  case T_model:
2286  module->Add3DModel( parse3DModel() );
2287  break;
2288 
2289  default:
2290  Expecting( "locked, placed, tedit, tstamp, at, descr, tags, path, "
2291  "autoplace_cost90, autoplace_cost180, solder_mask_margin, "
2292  "solder_paste_margin, solder_paste_ratio, clearance, "
2293  "zone_connect, thermal_width, thermal_gap, attr, fp_text, "
2294  "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, pad, or model" );
2295  }
2296  }
2297 
2298  module->SetFPID( fpid );
2299  module->CalculateBoundingBox();
2300 
2301  return module.release();
2302 }
const wxPoint & GetPos0() const
Definition: class_pad.h:278
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:158
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:224
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:76
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:229
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:241
PCB_LAYER_ID
A quick note on layer IDs:
void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:225
TEXT_TYPE GetType() const
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
#define THROW_IO_ERROR(msg)
#define _(s)
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:77
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:101
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:71
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:126
void SetTextAngle(double aAngle)
TEXTE_MODULE * parseTEXTE_MODULE()
D_PAD * parseD_PAD(MODULE *aParent=NULL)
long parseHex()
Definition: pcb_parser.h:290
int parseInt()
Definition: pcb_parser.h:279
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:352

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 1552 of file pcb_parser.cpp.

1553 {
1554  wxCHECK_RET( CurTok() == T_net_class,
1555  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as net class." ) );
1556 
1557  T token;
1558 
1559  NETCLASSPTR nc = std::make_shared<NETCLASS>( wxEmptyString );
1560 
1561  // Read netclass name (can be a name or just a number like track width)
1562  NeedSYMBOLorNUMBER();
1563  nc->SetName( FromUTF8() );
1564  NeedSYMBOL();
1565  nc->SetDescription( FromUTF8() );
1566 
1567  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1568  {
1569  if( token != T_LEFT )
1570  Expecting( T_LEFT );
1571 
1572  token = NextTok();
1573 
1574  switch( token )
1575  {
1576  case T_clearance:
1577  nc->SetClearance( parseBoardUnits( T_clearance ) );
1578  break;
1579 
1580  case T_trace_width:
1581  nc->SetTrackWidth( parseBoardUnits( T_trace_width ) );
1582  break;
1583 
1584  case T_via_dia:
1585  nc->SetViaDiameter( parseBoardUnits( T_via_dia ) );
1586  break;
1587 
1588  case T_via_drill:
1589  nc->SetViaDrill( parseBoardUnits( T_via_drill ) );
1590  break;
1591 
1592  case T_uvia_dia:
1593  nc->SetuViaDiameter( parseBoardUnits( T_uvia_dia ) );
1594  break;
1595 
1596  case T_uvia_drill:
1597  nc->SetuViaDrill( parseBoardUnits( T_uvia_drill ) );
1598  break;
1599 
1600  case T_diff_pair_width:
1601  nc->SetDiffPairWidth( parseBoardUnits( T_diff_pair_width ) );
1602  break;
1603 
1604  case T_diff_pair_gap:
1605  nc->SetDiffPairGap( parseBoardUnits( T_diff_pair_gap ) );
1606  break;
1607 
1608  case T_add_net:
1609  NeedSYMBOLorNUMBER();
1610  nc->Add( FromUTF8() );
1611  break;
1612 
1613  default:
1614  Expecting( "clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, diff_pair_width, diff_pair_gap or add_net" );
1615  }
1616 
1617  NeedRIGHT();
1618  }
1619 
1620  if( !m_board->GetDesignSettings().m_NetClasses.Add( nc ) )
1621  {
1622  // Must have been a name conflict, this is a bad board file.
1623  // User may have done a hand edit to the file.
1624 
1625  // unique_ptr will delete nc on this code path
1626 
1627  wxString error;
1628  error.Printf( _( "Duplicate NETCLASS name \"%s\" in file \"%s\" at line %d, offset %d" ),
1629  nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(), CurOffset() );
1630  THROW_IO_ERROR( error );
1631  }
1632 }
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:540
int parseBoardUnits()
Definition: pcb_parser.h:241
#define THROW_IO_ERROR(msg)
#define _(s)
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:71

References _, and THROW_IO_ERROR.

◆ parseNETINFO_ITEM()

void PCB_PARSER::parseNETINFO_ITEM ( )
private

Definition at line 1526 of file pcb_parser.cpp.

1527 {
1528  wxCHECK_RET( CurTok() == T_net,
1529  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as net." ) );
1530 
1531  int netCode = parseInt( "net number" );
1532 
1533  NeedSYMBOLorNUMBER();
1534  wxString name = FromUTF8();
1535 
1536  NeedRIGHT();
1537 
1538  // net 0 should be already in list, so store this net
1539  // if it is not the net 0, or if the net 0 does not exists.
1540  // (TODO: a better test.)
1542  {
1543  NETINFO_ITEM* net = new NETINFO_ITEM( m_board, name, netCode );
1544  m_board->Add( net );
1545 
1546  // Store the new code mapping
1547  pushValueIntoMap( netCode, net->GetNet() );
1548  }
1549 }
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:65
const char * name
Definition: DXF_plotter.cpp:61
int GetNet() const
Function GetNet.
Definition: netinfo.h:225
BOARD * m_board
Definition: pcb_parser.h:71
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:115
int parseInt()
Definition: pcb_parser.h:279
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:463

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

◆ parsePAGE_INFO()

void PCB_PARSER::parsePAGE_INFO ( )
private

Definition at line 750 of file pcb_parser.cpp.

751 {
752  wxCHECK_RET( CurTok() == T_page,
753  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a PAGE_INFO." ) );
754 
755  T token;
756  PAGE_INFO pageInfo;
757 
758  NeedSYMBOL();
759 
760  wxString pageType = FromUTF8();
761 
762  if( !pageInfo.SetType( pageType ) )
763  {
764  wxString err;
765  err.Printf( _( "Page type \"%s\" is not valid " ), GetChars( FromUTF8() ) );
766  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
767  }
768 
769  if( pageType == PAGE_INFO::Custom )
770  {
771  double width = parseDouble( "width" ); // width in mm
772 
773  // Perform some controls to avoid crashes if the size is edited by hands
774  if( width < 100.0 )
775  width = 100.0;
776  else if( width > 1200.0 )
777  width = 1200.0;
778 
779  double height = parseDouble( "height" ); // height in mm
780 
781  if( height < 100.0 )
782  height = 100.0;
783  else if( height > 1200.0 )
784  height = 1200.0;
785 
786  pageInfo.SetWidthMils( Mm2mils( width ) );
787  pageInfo.SetHeightMils( Mm2mils( height ) );
788  }
789 
790  token = NextTok();
791 
792  if( token == T_portrait )
793  {
794  pageInfo.SetPortrait( true );
795  NeedRIGHT();
796  }
797  else if( token != T_RIGHT )
798  {
799  Expecting( "portrait|)" );
800  }
801 
802  m_board->SetPageSettings( pageInfo );
803 }
int Mm2mils(double x)
Convert mm to mils.
Definition: base_units.h:51
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: class_board.h:556
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)
#define _(s)
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:101
BOARD * m_board
Definition: pcb_parser.h:71
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:126
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 3603 of file pcb_parser.cpp.

3604 {
3605  wxCHECK_MSG( CurTok() == T_target, NULL,
3606  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as PCB_TARGET." ) );
3607 
3608  wxPoint pt;
3609  T token;
3610 
3611  std::unique_ptr< PCB_TARGET > target( new PCB_TARGET( NULL ) );
3612 
3613  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3614  {
3615  if( token == T_LEFT )
3616  token = NextTok();
3617 
3618  switch( token )
3619  {
3620  case T_x:
3621  target->SetShape( 1 );
3622  break;
3623 
3624  case T_plus:
3625  target->SetShape( 0 );
3626  break;
3627 
3628  case T_at:
3629  pt.x = parseBoardUnits( "target x position" );
3630  pt.y = parseBoardUnits( "target y position" );
3631  target->SetPosition( pt );
3632  NeedRIGHT();
3633  break;
3634 
3635  case T_size:
3636  target->SetSize( parseBoardUnits( "target size" ) );
3637  NeedRIGHT();
3638  break;
3639 
3640  case T_width:
3641  target->SetWidth( parseBoardUnits( "target thickness" ) );
3642  NeedRIGHT();
3643  break;
3644 
3645  case T_layer:
3646  target->SetLayer( parseBoardItemLayer() );
3647  NeedRIGHT();
3648  break;
3649 
3650  case T_tstamp:
3651  target->SetTimeStamp( parseHex() );
3652  NeedRIGHT();
3653  break;
3654 
3655  default:
3656  Expecting( "x, plus, at, size, width, layer or tstamp" );
3657  }
3658  }
3659 
3660  return target.release();
3661 }
int parseBoardUnits()
Definition: pcb_parser.h:241
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
long parseHex()
Definition: pcb_parser.h:290

References parseHex().

◆ parseSetup()

void PCB_PARSER::parseSetup ( )
private

Definition at line 1164 of file pcb_parser.cpp.

1165 {
1166  wxCHECK_RET( CurTok() == T_setup,
1167  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as setup." ) );
1168 
1169  T token;
1170  NETCLASSPTR defaultNetClass = m_board->GetDesignSettings().GetDefault();
1171  // TODO Orson: is it really necessary to first operate on a copy and then apply it?
1172  // would not it be better to use reference here and apply all the changes instantly?
1173  BOARD_DESIGN_SETTINGS designSettings = m_board->GetDesignSettings();
1174  ZONE_SETTINGS zoneSettings = m_board->GetZoneSettings();
1175 
1176  // Missing soldermask min width value means that the user has set the value to 0 and
1177  // not the default value (0.25mm)
1178  designSettings.m_SolderMaskMinWidth = 0;
1179 
1180  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1181  {
1182  if( token != T_LEFT )
1183  Expecting( T_LEFT );
1184 
1185  token = NextTok();
1186 
1187  switch( token )
1188  {
1189  case T_last_trace_width: // not used now
1190  /* lastTraceWidth =*/ parseBoardUnits( T_last_trace_width );
1191  NeedRIGHT();
1192  break;
1193 
1194  case T_user_trace_width:
1195  designSettings.m_TrackWidthList.push_back( parseBoardUnits( T_user_trace_width ) );
1196  NeedRIGHT();
1197  break;
1198 
1199  case T_trace_clearance:
1200  defaultNetClass->SetClearance( parseBoardUnits( T_trace_clearance ) );
1201  NeedRIGHT();
1202  break;
1203 
1204  case T_zone_clearance:
1205  zoneSettings.m_ZoneClearance = parseBoardUnits( T_zone_clearance );
1206  NeedRIGHT();
1207  break;
1208 
1209  case T_zone_45_only:
1210  zoneSettings.m_Zone_45_Only = parseBool();
1211  NeedRIGHT();
1212  break;
1213 
1214  case T_trace_min:
1215  designSettings.m_TrackMinWidth = parseBoardUnits( T_trace_min );
1216  NeedRIGHT();
1217  break;
1218 
1219  case T_via_size:
1220  defaultNetClass->SetViaDiameter( parseBoardUnits( T_via_size ) );
1221  NeedRIGHT();
1222  break;
1223 
1224  case T_via_drill:
1225  defaultNetClass->SetViaDrill( parseBoardUnits( T_via_drill ) );
1226  NeedRIGHT();
1227  break;
1228 
1229  case T_via_min_size:
1230  designSettings.m_ViasMinSize = parseBoardUnits( T_via_min_size );
1231  NeedRIGHT();
1232  break;
1233 
1234  case T_via_min_drill:
1235  designSettings.m_ViasMinDrill = parseBoardUnits( T_via_min_drill );
1236  NeedRIGHT();
1237  break;
1238 
1239  case T_user_via:
1240  {
1241  int viaSize = parseBoardUnits( "user via size" );
1242  int viaDrill = parseBoardUnits( "user via drill" );
1243  designSettings.m_ViasDimensionsList.emplace_back( VIA_DIMENSION( viaSize, viaDrill ) );
1244  NeedRIGHT();
1245  }
1246  break;
1247 
1248  case T_uvia_size:
1249  defaultNetClass->SetuViaDiameter( parseBoardUnits( T_uvia_size ) );
1250  NeedRIGHT();
1251  break;
1252 
1253  case T_uvia_drill:
1254  defaultNetClass->SetuViaDrill( parseBoardUnits( T_uvia_drill ) );
1255  NeedRIGHT();
1256  break;
1257 
1258  case T_uvias_allowed:
1259  designSettings.m_MicroViasAllowed = parseBool();
1260  NeedRIGHT();
1261  break;
1262 
1263  case T_blind_buried_vias_allowed:
1264  designSettings.m_BlindBuriedViaAllowed = parseBool();
1265  NeedRIGHT();
1266  break;
1267 
1268  case T_uvia_min_size:
1269  designSettings.m_MicroViasMinSize = parseBoardUnits( T_uvia_min_size );
1270  NeedRIGHT();
1271  break;
1272 
1273  case T_uvia_min_drill:
1274  designSettings.m_MicroViasMinDrill = parseBoardUnits( T_uvia_min_drill );
1275  NeedRIGHT();
1276  break;
1277 
1278  case T_user_diff_pair:
1279  {
1280  int width = parseBoardUnits( "user diff-pair width" );
1281  int gap = parseBoardUnits( "user diff-pair gap" );
1282  int viaGap = parseBoardUnits( "user diff-pair via gap" );
1283  designSettings.m_DiffPairDimensionsList.emplace_back( DIFF_PAIR_DIMENSION( width, gap, viaGap ) );
1284  NeedRIGHT();
1285  }
1286  break;
1287 
1288  case T_segment_width: // note: legacy (pre-6.0) token
1289  designSettings.m_LineThickness[ LAYER_CLASS_COPPER ] = parseBoardUnits( T_segment_width );
1290  NeedRIGHT();
1291  break;
1292 
1293  case T_edge_width: // note: legacy (pre-6.0) token
1294  designSettings.m_LineThickness[ LAYER_CLASS_EDGES ] = parseBoardUnits( T_edge_width );
1295  NeedRIGHT();
1296  break;
1297 
1298  case T_mod_edge_width: // note: legacy (pre-6.0) token
1299  designSettings.m_LineThickness[ LAYER_CLASS_SILK ] = parseBoardUnits( T_mod_edge_width );
1300  NeedRIGHT();
1301  break;
1302 
1303  case T_pcb_text_width: // note: legacy (pre-6.0) token
1304  designSettings.m_TextThickness[ LAYER_CLASS_COPPER ] = parseBoardUnits( T_pcb_text_width );
1305  NeedRIGHT();
1306  break;
1307 
1308  case T_mod_text_width: // note: legacy (pre-6.0) token
1309  designSettings.m_TextThickness[ LAYER_CLASS_SILK ] = parseBoardUnits( T_mod_text_width );
1310  NeedRIGHT();
1311  break;
1312 
1313  case T_pcb_text_size: // note: legacy (pre-6.0) token
1314  designSettings.m_TextSize[ LAYER_CLASS_COPPER ].x = parseBoardUnits( "pcb text width" );
1315  designSettings.m_TextSize[ LAYER_CLASS_COPPER ].y = parseBoardUnits( "pcb text height" );
1316  NeedRIGHT();
1317  break;
1318 
1319  case T_mod_text_size: // note: legacy (pre-6.0) token
1320  designSettings.m_TextSize[ LAYER_CLASS_SILK ].x = parseBoardUnits( "module text width" );
1321  designSettings.m_TextSize[ LAYER_CLASS_SILK ].y = parseBoardUnits( "module text height" );
1322  NeedRIGHT();
1323  break;
1324 
1325  case T_defaults:
1326  parseDefaults( designSettings );
1327  break;
1328 
1329  case T_pad_size:
1330  {
1331  wxSize sz;
1332  sz.SetWidth( parseBoardUnits( "master pad width" ) );
1333  sz.SetHeight( parseBoardUnits( "master pad height" ) );
1334  designSettings.m_Pad_Master.SetSize( sz );
1335  NeedRIGHT();
1336  }
1337  break;
1338 
1339  case T_pad_drill:
1340  {
1341  int drillSize = parseBoardUnits( T_pad_drill );
1342  designSettings.m_Pad_Master.SetDrillSize( wxSize( drillSize, drillSize ) );
1343  NeedRIGHT();
1344  }
1345  break;
1346 
1347  case T_pad_to_mask_clearance:
1348  designSettings.m_SolderMaskMargin = parseBoardUnits( T_pad_to_mask_clearance );
1349  NeedRIGHT();
1350  break;
1351 
1352  case T_solder_mask_min_width:
1353  designSettings.m_SolderMaskMinWidth = parseBoardUnits( T_solder_mask_min_width );
1354  NeedRIGHT();
1355  break;
1356 
1357  case T_pad_to_paste_clearance:
1358  designSettings.m_SolderPasteMargin = parseBoardUnits( T_pad_to_paste_clearance );
1359  NeedRIGHT();
1360  break;
1361 
1362  case T_pad_to_paste_clearance_ratio:
1363  designSettings.m_SolderPasteMarginRatio = parseDouble( T_pad_to_paste_clearance_ratio );
1364  NeedRIGHT();
1365  break;
1366 
1367  case T_aux_axis_origin:
1368  {
1369  int x = parseBoardUnits( "auxiliary origin X" );
1370  int y = parseBoardUnits( "auxiliary origin Y" );
1371  // m_board->SetAuxOrigin( wxPoint( x, y ) ); gets overwritten via SetDesignSettings below
1372  designSettings.m_AuxOrigin = wxPoint( x, y );
1373  NeedRIGHT();
1374  }
1375  break;
1376 
1377  case T_grid_origin:
1378  {
1379  int x = parseBoardUnits( "grid origin X" );
1380  int y = parseBoardUnits( "grid origin Y" );
1381  // m_board->SetGridOrigin( wxPoint( x, y ) ); gets overwritten SetDesignSettings below
1382  designSettings.m_GridOrigin = wxPoint( x, y );
1383  NeedRIGHT();
1384  }
1385  break;
1386 
1387  case T_visible_elements:
1388  designSettings.SetVisibleElements( parseHex() | MIN_VISIBILITY_MASK );
1389  NeedRIGHT();
1390  break;
1391 
1392  case T_max_error:
1393  designSettings.m_MaxError = parseBoardUnits( T_max_error );
1394  NeedRIGHT();
1395  break;
1396 
1397  case T_filled_areas_thickness:
1398  designSettings.m_ZoneUseNoOutlineInFill = not parseBool();
1399  NeedRIGHT();
1400  break;
1401 
1402  case T_pcbplotparams:
1403  {
1404  PCB_PLOT_PARAMS plotParams;
1405  PCB_PLOT_PARAMS_PARSER parser( reader );
1406  // parser must share the same current line as our current PCB parser
1407  // synchronize it.
1408  parser.SyncLineReaderWith( *this );
1409 
1410  plotParams.Parse( &parser );
1411  SyncLineReaderWith( parser );
1412 
1413  m_board->SetPlotOptions( plotParams );
1414  }
1415  break;
1416 
1417  default:
1418  Unexpected( CurText() );
1419  }
1420  }
1421 
1422  m_board->SetDesignSettings( designSettings );
1423  m_board->SetZoneSettings( zoneSettings );
1424 }
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:565
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
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:540
void SetDrillSize(const wxSize &aSize)
Definition: class_pad.h:289
Struct DIFF_PAIR_DIMENSION is a small helper container to handle a stock of specific differential pai...
int parseBoardUnits()
Definition: pcb_parser.h:241
wxSize m_TextSize[LAYER_CLASS_COUNT]
bool parseBool()
Definition: pcb_parser.cpp:156
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:283
int m_ZoneClearance
Clearance value.
Definition: zone_settings.h:64
void SetDesignSettings(const BOARD_DESIGN_SETTINGS &aDesignSettings)
Function SetDesignSettings.
Definition: class_board.h:550
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
void SetPlotOptions(const PCB_PLOT_PARAMS &aOptions)
Definition: class_board.h:559
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]
void parseDefaults(BOARD_DESIGN_SETTINGS &aSettings)
Class ZONE_SETTINGS handles zones parameters.
Definition: zone_settings.h:49
NETCLASSPTR GetDefault() const
Function GetDefault.
bool m_ZoneUseNoOutlineInFill
Option to handle filled polygons in zones: the "legacy" option is using thick outlines around filled ...
BOARD * m_board
Definition: pcb_parser.h:71
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:564
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:126
bool m_MicroViasAllowed
true to allow micro vias
int m_MicroViasMinDrill
micro vias (not vias) min drill diameter
long parseHex()
Definition: pcb_parser.h:290
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_DiffPairDimensionsList, BOARD_DESIGN_SETTINGS::m_GridOrigin, BOARD_DESIGN_SETTINGS::m_LineThickness, BOARD_DESIGN_SETTINGS::m_MaxError, 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, BOARD_DESIGN_SETTINGS::m_ZoneUseNoOutlineInFill, 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 2305 of file pcb_parser.cpp.

2306 {
2307  wxCHECK_MSG( CurTok() == T_fp_text, NULL,
2308  wxString::Format( wxT( "Cannot parse %s as TEXTE_MODULE at line %d, offset %d." ),
2309  GetChars( GetTokenString( CurTok() ) ),
2310  CurLineNumber(), CurOffset() ) );
2311 
2312  T token = NextTok();
2313 
2314  std::unique_ptr<TEXTE_MODULE> text( new TEXTE_MODULE( NULL ) );
2315 
2316  switch( token )
2317  {
2318  case T_reference:
2319  text->SetType( TEXTE_MODULE::TEXT_is_REFERENCE );
2320  break;
2321 
2322  case T_value:
2323  text->SetType( TEXTE_MODULE::TEXT_is_VALUE );
2324  break;
2325 
2326  case T_user:
2327  break; // Default type is user text.
2328 
2329  default:
2330  THROW_IO_ERROR( wxString::Format( _( "Cannot handle footprint text type %s" ),
2331  GetChars( FromUTF8() ) ) );
2332  }
2333 
2334  NeedSYMBOLorNUMBER();
2335 
2336  text->SetText( FromUTF8() );
2337  NeedLEFT();
2338  token = NextTok();
2339 
2340  if( token != T_at )
2341  Expecting( T_at );
2342 
2343  wxPoint pt;
2344 
2345  pt.x = parseBoardUnits( "X coordinate" );
2346  pt.y = parseBoardUnits( "Y coordinate" );
2347  text->SetPos0( pt );
2348 
2349  NextTok();
2350 
2351  if( CurTok() == T_NUMBER )
2352  {
2353  text->SetTextAngle( parseDouble() * 10.0 );
2354  NextTok();
2355  }
2356 
2357  if( CurTok() == T_unlocked )
2358  {
2359  text->SetKeepUpright( false );
2360  NextTok();
2361  }
2362 
2363  if( CurTok() != T_RIGHT )
2364  {
2365  Unexpected( CurText() );
2366  }
2367 
2368  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2369  {
2370  if( token == T_LEFT )
2371  token = NextTok();
2372 
2373  switch( token )
2374  {
2375  case T_layer:
2376  text->SetLayer( parseBoardItemLayer() );
2377  NeedRIGHT();
2378  break;
2379 
2380  case T_hide:
2381  text->SetVisible( false );
2382  break;
2383 
2384  case T_effects:
2385  parseEDA_TEXT( (EDA_TEXT*) text.get() );
2386  break;
2387 
2388  default:
2389  Expecting( "hide or effects" );
2390  }
2391  }
2392 
2393  return text.release();
2394 }
void parseEDA_TEXT(EDA_TEXT *aText)
Function parseEDA_TEXT parses the common settings for any object derived from EDA_TEXT.
Definition: pcb_parser.cpp:240
int parseBoardUnits()
Definition: pcb_parser.h:241
Class EDA_TEXT is a mix-in class (via multiple inheritance) that handles texts such as labels,...
Definition: eda_text.h:109
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
#define THROW_IO_ERROR(msg)
#define _(s)
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:101
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:126

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 1808 of file pcb_parser.cpp.

1809 {
1810  wxCHECK_MSG( CurTok() == T_gr_text, NULL,
1811  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as TEXTE_PCB." ) );
1812 
1813  T token;
1814 
1815  std::unique_ptr<TEXTE_PCB> text( new TEXTE_PCB( m_board ) );
1816  NeedSYMBOLorNUMBER();
1817 
1818  text->SetText( FromUTF8() );
1819  NeedLEFT();
1820  token = NextTok();
1821 
1822  if( token != T_at )
1823  Expecting( T_at );
1824 
1825  wxPoint pt;
1826 
1827  pt.x = parseBoardUnits( "X coordinate" );
1828  pt.y = parseBoardUnits( "Y coordinate" );
1829  text->SetTextPos( pt );
1830 
1831  // If there is no orientation defined, then it is the default value of 0 degrees.
1832  token = NextTok();
1833 
1834  if( token == T_NUMBER )
1835  {
1836  text->SetTextAngle( parseDouble() * 10.0 );
1837  NeedRIGHT();
1838  }
1839  else if( token != T_RIGHT )
1840  {
1841  Unexpected( CurText() );
1842  }
1843 
1844  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1845  {
1846  if( token != T_LEFT )
1847  Expecting( T_LEFT );
1848 
1849  token = NextTok();
1850 
1851  switch( token )
1852  {
1853  case T_layer:
1854  text->SetLayer( parseBoardItemLayer() );
1855  NeedRIGHT();
1856  break;
1857 
1858  case T_tstamp:
1859  text->SetTimeStamp( parseHex() );
1860  NeedRIGHT();
1861  break;
1862 
1863  case T_effects:
1864  parseEDA_TEXT( (EDA_TEXT*) text.get() );
1865  break;
1866 
1867  default:
1868  Expecting( "layer, tstamp or effects" );
1869  }
1870  }
1871 
1872  return text.release();
1873 }
void parseEDA_TEXT(EDA_TEXT *aText)
Function parseEDA_TEXT parses the common settings for any object derived from EDA_TEXT.
Definition: pcb_parser.cpp:240
int parseBoardUnits()
Definition: pcb_parser.h:241
Class EDA_TEXT is a mix-in class (via multiple inheritance) that handles texts such as labels,...
Definition: eda_text.h:109
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
BOARD * m_board
Definition: pcb_parser.h:71
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:126
long parseHex()
Definition: pcb_parser.h:290

References parseDouble(), and parseHex().

◆ parseTITLE_BLOCK()

void PCB_PARSER::parseTITLE_BLOCK ( )
private

Definition at line 806 of file pcb_parser.cpp.

807 {
808  wxCHECK_RET( CurTok() == T_title_block,
809  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
810  wxT( " as TITLE_BLOCK." ) );
811 
812  T token;
813  TITLE_BLOCK titleBlock;
814 
815  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
816  {
817  if( token != T_LEFT )
818  Expecting( T_LEFT );
819 
820  token = NextTok();
821 
822  switch( token )
823  {
824  case T_title:
825  NextTok();
826  titleBlock.SetTitle( FromUTF8() );
827  break;
828 
829  case T_date:
830  NextTok();
831  titleBlock.SetDate( FromUTF8() );
832  break;
833 
834  case T_rev:
835  NextTok();
836  titleBlock.SetRevision( FromUTF8() );
837  break;
838 
839  case T_company:
840  NextTok();
841  titleBlock.SetCompany( FromUTF8() );
842  break;
843 
844  case T_comment:
845  {
846  int commentNumber = parseInt( "comment" );
847 
848  switch( commentNumber )
849  {
850  case 1:
851  NextTok();
852  titleBlock.SetComment1( FromUTF8() );
853  break;
854 
855  case 2:
856  NextTok();
857  titleBlock.SetComment2( FromUTF8() );
858  break;
859 
860  case 3:
861  NextTok();
862  titleBlock.SetComment3( FromUTF8() );
863  break;
864 
865  case 4:
866  NextTok();
867  titleBlock.SetComment4( FromUTF8() );
868  break;
869 
870  default:
871  wxString err;
872  err.Printf( wxT( "%d is not a valid title block comment number" ), commentNumber );
873  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
874  }
875  }
876  break;
877 
878  default:
879  Expecting( "title, date, rev, company, or comment" );
880  }
881 
882  NeedRIGHT();
883  }
884 
885  m_board->SetTitleBlock( titleBlock );
886 }
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:562
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:71
void SetComment3(const wxString &aComment)
Definition: title_block.h:119
int parseInt()
Definition: pcb_parser.h:279

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 3019 of file pcb_parser.cpp.

3020 {
3021  wxCHECK_MSG( CurTok() == T_segment, NULL,
3022  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as TRACK." ) );
3023 
3024  wxPoint pt;
3025  T token;
3026 
3027  std::unique_ptr< TRACK > track( new TRACK( m_board ) );
3028 
3029  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3030  {
3031  if( token != T_LEFT )
3032  Expecting( T_LEFT );
3033 
3034  token = NextTok();
3035 
3036  switch( token )
3037  {
3038  case T_start:
3039  pt.x = parseBoardUnits( "start x" );
3040  pt.y = parseBoardUnits( "start y" );
3041  track->SetStart( pt );
3042  break;
3043 
3044  case T_end:
3045  pt.x = parseBoardUnits( "end x" );
3046  pt.y = parseBoardUnits( "end y" );
3047  track->SetEnd( pt );
3048  break;
3049 
3050  case T_width:
3051  track->SetWidth( parseBoardUnits( "width" ) );
3052  break;
3053 
3054  case T_layer:
3055  track->SetLayer( parseBoardItemLayer() );
3056  break;
3057 
3058  case T_net:
3059  if( ! track->SetNetCode( getNetCode( parseInt( "net number" ) ), /* aNoAssert */ true ) )
3061  wxString::Format( _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
3062  GetChars( CurSource() ), CurLineNumber(), CurOffset() )
3063  );
3064  break;
3065 
3066  case T_tstamp:
3067  track->SetTimeStamp( parseHex() );
3068  break;
3069 
3070  case T_status:
3071  track->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
3072  break;
3073 
3074  default:
3075  Expecting( "start, end, width, layer, net, tstamp, or status" );
3076  }
3077 
3078  NeedRIGHT();
3079  }
3080 
3081  return track.release();
3082 }
int parseBoardUnits()
Definition: pcb_parser.h:241
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
#define THROW_IO_ERROR(msg)
#define _(s)
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:101
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:83
BOARD * m_board
Definition: pcb_parser.h:71
long parseHex()
Definition: pcb_parser.h:290
int parseInt()
Definition: pcb_parser.h:279

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 171 of file pcb_parser.cpp.

172 {
173  if( NextTok() != T_version )
174  Expecting( GetTokenText( T_version ) );
175 
176  int pcb_version = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
177 
178  NeedRIGHT();
179 
180  return pcb_version;
181 }
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:279

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

◆ parseVIA()

VIA * PCB_PARSER::parseVIA ( )
private

Definition at line 3085 of file pcb_parser.cpp.

3086 {
3087  wxCHECK_MSG( CurTok() == T_via, NULL,
3088  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as VIA." ) );
3089 
3090  wxPoint pt;
3091  T token;
3092 
3093  std::unique_ptr< VIA > via( new VIA( m_board ) );
3094 
3095  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3096  {
3097  if( token == T_LEFT )
3098  token = NextTok();
3099 
3100  switch( token )
3101  {
3102  case T_blind:
3103  via->SetViaType( VIA_BLIND_BURIED );
3104  break;
3105 
3106  case T_micro:
3107  via->SetViaType( VIA_MICROVIA );
3108  break;
3109 
3110  case T_at:
3111  pt.x = parseBoardUnits( "start x" );
3112  pt.y = parseBoardUnits( "start y" );
3113  via->SetStart( pt );
3114  via->SetEnd( pt );
3115  NeedRIGHT();
3116  break;
3117 
3118  case T_size:
3119  via->SetWidth( parseBoardUnits( "via width" ) );
3120  NeedRIGHT();
3121  break;
3122 
3123  case T_drill:
3124  via->SetDrill( parseBoardUnits( "drill diameter" ) );
3125  NeedRIGHT();
3126  break;
3127 
3128  case T_layers:
3129  {
3130  PCB_LAYER_ID layer1, layer2;
3131  NextTok();
3132  layer1 = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
3133  NextTok();
3134  layer2 = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
3135  via->SetLayerPair( layer1, layer2 );
3136  NeedRIGHT();
3137  }
3138  break;
3139 
3140  case T_net:
3141  if(! via->SetNetCode( getNetCode( parseInt( "net number" ) ), /* aNoAssert */ true))
3143  wxString::Format( _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
3144  GetChars( CurSource() ), CurLineNumber(), CurOffset() )
3145  );
3146  NeedRIGHT();
3147  break;
3148 
3149  case T_tstamp:
3150  via->SetTimeStamp( parseHex() );
3151  NeedRIGHT();
3152  break;
3153 
3154  case T_status:
3155  via->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
3156  NeedRIGHT();
3157  break;
3158 
3159  default:
3160  Expecting( "blind, micro, at, size, drill, layers, net, tstamp, or status" );
3161  }
3162  }
3163 
3164  return via.release();
3165 }
int parseBoardUnits()
Definition: pcb_parser.h:241
PCB_LAYER_ID
A quick note on layer IDs:
#define THROW_IO_ERROR(msg)
#define _(s)
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:101
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:83
BOARD * m_board
Definition: pcb_parser.h:71
LAYER_ID_MAP m_layerIndices
map layer name to it's index
Definition: pcb_parser.h:72
long parseHex()
Definition: pcb_parser.h:290
int parseInt()
Definition: pcb_parser.h:279

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 208 of file pcb_parser.cpp.

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

◆ parseXY() [2/2]

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

Definition at line 228 of file pcb_parser.cpp.

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

◆ parseZONE_CONTAINER()

ZONE_CONTAINER * PCB_PARSER::parseZONE_CONTAINER ( )
private

Definition at line 3168 of file pcb_parser.cpp.

3169 {
3170  wxCHECK_MSG( CurTok() == T_zone, NULL,
3171  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
3172  wxT( " as ZONE_CONTAINER." ) );
3173 
3175 
3176  int hatchPitch = ZONE_CONTAINER::GetDefaultHatchPitch();
3177  wxPoint pt;
3178  T token;
3179  int tmp;
3180  wxString netnameFromfile; // the zone net name find in file
3181 
3182  // bigger scope since each filled_polygon is concatenated in here
3183  SHAPE_POLY_SET pts;
3184 
3185  std::unique_ptr< ZONE_CONTAINER > zone( new ZONE_CONTAINER( m_board ) );
3186 
3187  zone->SetPriority( 0 );
3188 
3189  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3190  {
3191  if( token == T_LEFT )
3192  token = NextTok();
3193 
3194  switch( token )
3195  {
3196  case T_net:
3197  // Init the net code only, not the netname, to be sure
3198  // the zone net name is the name read in file.
3199  // (When mismatch, the user will be prompted in DRC, to fix the actual name)
3200  tmp = getNetCode( parseInt( "net number" ) );
3201 
3202  if( tmp < 0 )
3203  tmp = 0;
3204 
3205  if( ! zone->SetNetCode( tmp, /* aNoAssert */ true ) )
3207  wxString::Format( _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
3208  GetChars( CurSource() ), CurLineNumber(), CurOffset() )
3209  );
3210 
3211  NeedRIGHT();
3212  break;
3213 
3214  case T_net_name:
3215  NeedSYMBOLorNUMBER();
3216  netnameFromfile = FromUTF8();
3217  NeedRIGHT();
3218  break;
3219 
3220  case T_layer: // keyword for zones that are on only one layer
3221  zone->SetLayer( parseBoardItemLayer() );
3222  NeedRIGHT();
3223  break;
3224 
3225  case T_layers: // keyword for zones that can live on a set of layer
3226  // currently: keepout zones
3227  zone->SetLayerSet( parseBoardItemLayersAsMask() );
3228  break;
3229 
3230  case T_tstamp:
3231  zone->SetTimeStamp( parseHex() );
3232  NeedRIGHT();
3233  break;
3234 
3235  case T_hatch:
3236  token = NextTok();
3237 
3238  if( token != T_none && token != T_edge && token != T_full )
3239  Expecting( "none, edge, or full" );
3240 
3241  switch( token )
3242  {
3243  default:
3244  case T_none: hatchStyle = ZONE_CONTAINER::NO_HATCH; break;
3245  case T_edge: hatchStyle = ZONE_CONTAINER::DIAGONAL_EDGE; break;
3246  case T_full: hatchStyle = ZONE_CONTAINER::DIAGONAL_FULL;
3247  }
3248 
3249  hatchPitch = parseBoardUnits( "hatch pitch" );
3250  NeedRIGHT();
3251  break;
3252 
3253  case T_priority:
3254  zone->SetPriority( parseInt( "zone priority" ) );
3255  NeedRIGHT();
3256  break;
3257 
3258  case T_connect_pads:
3259  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3260  {
3261  if( token == T_LEFT )
3262  token = NextTok();
3263 
3264  switch( token )
3265  {
3266  case T_yes:
3267  zone->SetPadConnection( PAD_ZONE_CONN_FULL );
3268  break;
3269 
3270  case T_no:
3271  zone->SetPadConnection( PAD_ZONE_CONN_NONE );
3272  break;
3273 
3274  case T_thru_hole_only:
3275  zone->SetPadConnection( PAD_ZONE_CONN_THT_THERMAL );
3276  break;
3277 
3278  case T_clearance:
3279  zone->SetZoneClearance( parseBoardUnits( "zone clearance" ) );
3280  NeedRIGHT();
3281  break;
3282 
3283  default:
3284  Expecting( "yes, no, or clearance" );
3285  }
3286  }
3287 
3288  break;
3289 
3290  case T_min_thickness:
3291  zone->SetMinThickness( parseBoardUnits( T_min_thickness ) );
3292  NeedRIGHT();
3293  break;
3294 
3295  case T_filled_areas_thickness:
3296  zone->SetFilledPolysUseThickness( parseBool() );
3297  NeedRIGHT();
3298  break;
3299 
3300  case T_fill:
3301  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3302  {
3303  if( token == T_LEFT )
3304  token = NextTok();
3305 
3306  switch( token )
3307  {
3308  case T_yes:
3309  zone->SetIsFilled( true );
3310  break;
3311 
3312  case T_mode:
3313  token = NextTok();
3314 
3315  if( token != T_segment && token != T_hatch && token != T_polygon )
3316  Expecting( "segment, hatch or polygon" );
3317 
3318  if( token == T_segment ) // deprecated
3319  {
3320  // SEGMENT fill mode no longer supported. Make sure user is OK with converting them.
3322  {
3323  KIDIALOG dlg( nullptr,
3324  _( "The legacy segment fill mode is no longer supported.\n"
3325  "Convert zones to polygon fills?"),
3326  _( "Legacy Zone Warning" ),
3327  wxYES_NO | wxICON_WARNING );
3328 
3329  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
3330 
3331  if( dlg.ShowModal() == wxID_NO )
3332  THROW_IO_ERROR( wxT( "CANCEL" ) );
3333 
3334  m_showLegacyZoneWarning = false;
3335  }
3336 
3337  zone->SetFillMode( ZFM_POLYGONS );
3338  m_board->SetModified();
3339  }
3340  else if( token == T_hatch )
3341  zone->SetFillMode( ZFM_HATCH_PATTERN );
3342  else
3343  zone->SetFillMode( ZFM_POLYGONS );
3344  NeedRIGHT();
3345  break;
3346 
3347  case T_hatch_thickness:
3348  zone->SetHatchFillTypeThickness( parseBoardUnits( T_hatch_thickness ) );
3349  NeedRIGHT();
3350  break;
3351 
3352  case T_hatch_gap:
3353  zone->SetHatchFillTypeGap( parseBoardUnits( T_hatch_gap ) );
3354  NeedRIGHT();
3355  break;
3356 
3357  case T_hatch_orientation:
3358  zone->SetHatchFillTypeOrientation( parseDouble( T_hatch_orientation ) );
3359  NeedRIGHT();
3360  break;
3361 
3362  case T_hatch_smoothing_level:
3363  zone->SetHatchFillTypeSmoothingLevel( parseDouble( T_hatch_smoothing_level ) );
3364  NeedRIGHT();
3365  break;
3366 
3367  case T_hatch_smoothing_value:
3368  zone->SetHatchFillTypeSmoothingValue( parseDouble( T_hatch_smoothing_value ) );
3369  NeedRIGHT();
3370  break;
3371 
3372  case T_arc_segments:
3373  static_cast<void>( parseInt( "arc segment count" ) );
3374  NeedRIGHT();
3375  break;
3376 
3377  case T_thermal_gap:
3378  zone->SetThermalReliefGap( parseBoardUnits( T_thermal_gap ) );
3379  NeedRIGHT();
3380  break;
3381 
3382  case T_thermal_bridge_width:
3383  zone->SetThermalReliefCopperBridge( parseBoardUnits( T_thermal_bridge_width ) );
3384  NeedRIGHT();
3385  break;
3386 
3387  case T_smoothing:
3388  switch( NextTok() )
3389  {
3390  case T_none:
3391  zone->SetCornerSmoothingType( ZONE_SETTINGS::SMOOTHING_NONE );
3392  break;
3393 
3394  case T_chamfer:
3395  if( !zone->GetIsKeepout() ) // smoothing has meaning only for filled zones
3396  zone->SetCornerSmoothingType( ZONE_SETTINGS::SMOOTHING_CHAMFER );
3397  break;
3398 
3399  case T_fillet:
3400  if( !zone->GetIsKeepout() ) // smoothing has meaning only for filled zones
3401  zone->SetCornerSmoothingType( ZONE_SETTINGS::SMOOTHING_FILLET );
3402  break;
3403 
3404  default:
3405  Expecting( "none, chamfer, or fillet" );
3406  }
3407  NeedRIGHT();
3408  break;
3409 
3410  case T_radius:
3411  tmp = parseBoardUnits( "corner radius" );
3412  if( !zone->GetIsKeepout() ) // smoothing has meaning only for filled zones
3413  zone->SetCornerRadius( tmp );
3414  NeedRIGHT();
3415  break;
3416 
3417  default:
3418  Expecting( "mode, arc_segments, thermal_gap, thermal_bridge_width, "
3419  "hatch_thickness, hatch_gap, hatch_orientation, "
3420  "hatch_smoothing_level, hatch_smoothing_value, smoothing, or radius" );
3421  }
3422  }
3423  break;
3424 
3425  case T_keepout:
3426  zone->SetIsKeepout( true );
3427 
3428  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3429  {
3430  if( token == T_LEFT )
3431  token = NextTok();
3432 
3433  switch( token )
3434  {
3435  case T_tracks:
3436  token = NextTok();
3437 
3438  if( token != T_allowed && token != T_not_allowed )
3439  Expecting( "allowed or not_allowed" );
3440  zone->SetDoNotAllowTracks( token == T_not_allowed );
3441  break;
3442 
3443  case T_vias:
3444  token = NextTok();
3445 
3446  if( token != T_allowed && token != T_not_allowed )
3447  Expecting( "allowed or not_allowed" );
3448  zone->SetDoNotAllowVias( token == T_not_allowed );
3449  break;
3450 
3451  case T_copperpour:
3452  token = NextTok();
3453 
3454  if( token != T_allowed && token != T_not_allowed )
3455  Expecting( "allowed or not_allowed" );
3456  zone->SetDoNotAllowCopperPour( token == T_not_allowed );
3457  break;
3458 
3459  default:
3460  Expecting( "tracks, vias or copperpour" );
3461  }
3462 
3463  NeedRIGHT();
3464  }
3465 
3466  break;
3467 
3468  case T_polygon:
3469  {
3470  std::vector< wxPoint > corners;
3471 
3472  NeedLEFT();
3473  token = NextTok();
3474 
3475  if( token != T_pts )
3476  Expecting( T_pts );
3477 
3478  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3479  {
3480  corners.push_back( parseXY() );
3481  }
3482 
3483  NeedRIGHT();
3484 
3485  // Remark: The first polygon is the main outline.
3486  // Others are holes inside the main outline.
3487  zone->AddPolygon( corners );
3488  }
3489  break;
3490 
3491  case T_filled_polygon:
3492  {
3493  // "(filled_polygon (pts"
3494  NeedLEFT();
3495  token = NextTok();
3496 
3497  if( token != T_pts )
3498  Expecting( T_pts );
3499 
3500  pts.NewOutline();
3501 
3502  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3503  {
3504  pts.Append( parseXY() );
3505  }
3506 
3507  NeedRIGHT();
3508  }
3509  break;
3510 
3511  case T_fill_segments:
3512  {
3513  ZONE_SEGMENT_FILL segs;
3514 
3515  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3516  {
3517  if( token != T_LEFT )
3518  Expecting( T_LEFT );
3519 
3520  token = NextTok();
3521 
3522  if( token != T_pts )
3523  Expecting( T_pts );
3524 
3525  SEG segment( parseXY(), parseXY() );
3526  NeedRIGHT();
3527  segs.push_back( segment );
3528  }
3529 
3530  zone->SetFillSegments( segs );
3531  }
3532  break;
3533 
3534  default:
3535  Expecting( "net, layer/layers, tstamp, hatch, priority, connect_pads, min_thickness, "
3536  "fill, polygon, filled_polygon, or fill_segments" );
3537  }
3538  }
3539 
3540  if( zone->GetNumCorners() > 2 )
3541  {
3542  if( !zone->IsOnCopperLayer() )
3543  {
3544  //zone->SetFillMode( ZFM_POLYGONS );
3545  zone->SetNetCode( NETINFO_LIST::UNCONNECTED );
3546  }
3547 
3548  // Set hatch here, after outlines corners are read
3549  zone->SetHatch( hatchStyle, hatchPitch, true );
3550  }
3551 
3552  if( !pts.IsEmpty() )
3553  zone->SetFilledPolysList( pts );
3554 
3555  // Ensure keepout and non copper zones do not have a net
3556  // (which have no sense for these zones)
3557  // the netcode 0 is used for these zones
3558  bool zone_has_net = zone->IsOnCopperLayer() && !zone->GetIsKeepout();
3559 
3560  if( !zone_has_net )
3561  zone->SetNetCode( NETINFO_LIST::UNCONNECTED );
3562 
3563  // Ensure the zone net name is valid, and matches the net code, for copper zones
3564  if( zone_has_net && ( zone->GetNet()->GetNetname() != netnameFromfile ) )
3565  {
3566  // Can happens which old boards, with nonexistent nets ...
3567  // or after being edited by hand
3568  // We try to fix the mismatch.
3569  NETINFO_ITEM* net = m_board->FindNet( netnameFromfile );
3570 
3571  if( net ) // An existing net has the same net name. use it for the zone
3572  zone->SetNetCode( net->GetNet() );
3573  else // Not existing net: add a new net to keep trace of the zone netname
3574  {
3575  int newnetcode = m_board->GetNetCount();
3576  net = new NETINFO_ITEM( m_board, netnameFromfile, newnetcode );
3577  m_board->Add( net );
3578 
3579  // Store the new code mapping
3580  pushValueIntoMap( newnetcode, net->GetNet() );
3581  // and update the zone netcode
3582  zone->SetNetCode( net->GetNet() );
3583 
3584  // FIXME: a call to any GUI item is not allowed in io plugins:
3585  // Change this code to generate a warning message outside this plugin
3586  // Prompt the user
3587  wxString msg;
3588  msg.Printf( _( "There is a zone that belongs to a not existing net\n"
3589  "\"%s\"\n"
3590  "you should verify and edit it (run DRC test)." ),
3591  GetChars( netnameFromfile ) );
3592  DisplayError( NULL, msg );
3593  }
3594  }
3595 
3596  // Clear flags used in zone edition:
3597  zone->SetNeedRefill( false );
3598 
3599  return zone.release();
3600 }
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
void SetModified()
Definition: base_struct.cpp:98
Class ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:57
std::vector< SEG > ZONE_SEGMENT_FILL
Definition: class_zone.h:47
LSET parseBoardItemLayersAsMask()
Function parseBoardItemLayersAsMask parses the layers definition of a BOARD_ITEM object.
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:44
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:208
static int GetDefaultHatchPitch()
Function GetDefaultHatchPitchMils.
int parseBoardUnits()
Definition: pcb_parser.h:241
Pads are not covered.
Definition: zones.h:52
bool parseBool()
Definition: pcb_parser.cpp:156
unsigned GetNetCount() const
Function GetNetCount.
Definition: class_board.h:779
Class SHAPE_POLY_SET.
void SetNetCode(int aNetCode)
Definition: netinfo.h:227
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:64
bool m_showLegacyZoneWarning
Definition: pcb_parser.h:79
int NewOutline()
Creates a new empty polygon in the set and returns its index
#define _(s)
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:65
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:101
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:225
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:83
BOARD * m_board
Definition: pcb_parser.h:71
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:115
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:126
long parseHex()
Definition: pcb_parser.h:290
int parseInt()
Definition: pcb_parser.h:279
void DisplayError(wxWindow *parent, const wxString &text, int displaytime)
Display 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:463
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(), KIDIALOG::DoNotShowCheckbox(), 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, parseDouble(), parseHex(), parseInt(), NETINFO_ITEM::SetNetCode(), KIDIALOG::ShowModal(), ZONE_SETTINGS::SMOOTHING_CHAMFER, ZONE_SETTINGS::SMOOTHING_FILLET, ZONE_SETTINGS::SMOOTHING_NONE, THROW_IO_ERROR, NETINFO_LIST::UNCONNECTED, ZFM_HATCH_PATTERN, and ZFM_POLYGONS.

◆ 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 115 of file pcb_parser.cpp.

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

◆ SetBoard()

void PCB_PARSER::SetBoard ( BOARD aBoard)
inline

Definition at line 328 of file pcb_parser.h.

329  {
330  init();
331  m_board = aBoard;
332  }
BOARD * m_board
Definition: pcb_parser.h:71
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 321 of file pcb_parser.h.

322  {
323  LINE_READER* ret = PopReader();
324  PushReader( aReader );
325  return ret;
326  }
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 71 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 72 of file pcb_parser.h.

◆ m_layerMasks

LSET_MAP PCB_PARSER::m_layerMasks
private

map layer names to their masks

Definition at line 73 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 75 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 77 of file pcb_parser.h.

◆ m_showLegacyZoneWarning

bool PCB_PARSER::m_showLegacyZoneWarning
private

Definition at line 79 of file pcb_parser.h.

◆ m_tooRecent

bool PCB_PARSER::m_tooRecent
private

true if version parses as later than supported

Definition at line 76 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 74 of file pcb_parser.h.


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