KiCad PCB EDA Suite
PCB_PARSER Class Reference

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 skipCurrent ()
 Function skipCurrent Skip the current token level, i.e search for the RIGHT parenthesis which closes the current description. More...
 
void parseHeader ()
 
void parseGeneralSection ()
 
void parsePAGE_INFO ()
 
void parseTITLE_BLOCK ()
 
void parseLayers ()
 
void parseLayer (LAYER *aLayer)
 
void parseBoardStackup ()
 
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)
 
ARCparseARC ()
 
TRACKparseTRACK ()
 
VIAparseVIA ()
 
ZONE_CONTAINERparseZONE_CONTAINER (BOARD_ITEM_CONTAINER *aParent)
 
PCB_TARGETparsePCB_TARGET ()
 
MARKER_PCBparseMARKER (BOARD_ITEM_CONTAINER *aParent)
 
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

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

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

◆ LSET_MAP

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

Definition at line 72 of file pcb_parser.h.

Constructor & Destructor Documentation

◆ PCB_PARSER()

PCB_PARSER::PCB_PARSER ( LINE_READER aReader = NULL)
inline

Definition at line 320 of file pcb_parser.h.

320  :
321  PCB_LEXER( aReader ),
322  m_board( 0 )
323  {
324  init();
325  }
BOARD * m_board
Definition: pcb_parser.h:74
void init()
Function init clears and re-establishes m_layerMap with the default layer names.
Definition: pcb_parser.cpp:58

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

1198 {
1199  // N.B. This mapping only includes Italian, Polish and French as they were the only languages that
1200  // mapped the layer names as of cc2022b1ac739aa673d2a0b7a2047638aa7a47b3 (kicad-i18n) when the
1201  // bug was fixed in KiCad source.
1202 
1203  // Italian
1204  aMap["Adesivo.Retro"] = "B.Adhes";
1205  aMap["Adesivo.Fronte"] = "F.Adhes";
1206  aMap["Pasta.Retro"] = "B.Paste";
1207  aMap["Pasta.Fronte"] = "F.Paste";
1208  aMap["Serigrafia.Retro"] = "B.SilkS";
1209  aMap["Serigrafia.Fronte"] = "F.SilkS";
1210  aMap["Maschera.Retro"] = "B.Mask";
1211  aMap["Maschera.Fronte"] = "F.Mask";
1212  aMap["Grafica"] = "Dwgs.User";
1213  aMap["Commenti"] = "Cmts.User";
1214  aMap["Eco1"] = "Eco1.User";
1215  aMap["Eco2"] = "Eco2.User";
1216  aMap["Contorno.scheda"] = "Edge.Cuts";
1217 
1218  // Polish
1219  aMap["Kleju_Dolna"] = "B.Adhes";
1220  aMap["Kleju_Gorna"] = "F.Adhes";
1221  aMap["Pasty_Dolna"] = "B.Paste";
1222  aMap["Pasty_Gorna"] = "F.Paste";
1223  aMap["Opisowa_Dolna"] = "B.SilkS";
1224  aMap["Opisowa_Gorna"] = "F.SilkS";
1225  aMap["Maski_Dolna"] = "B.Mask";
1226  aMap["Maski_Gorna"] = "F.Mask";
1227  aMap["Rysunkowa"] = "Dwgs.User";
1228  aMap["Komentarzy"] = "Cmts.User";
1229  aMap["ECO1"] = "Eco1.User";
1230  aMap["ECO2"] = "Eco2.User";
1231  aMap["Krawedziowa"] = "Edge.Cuts";
1232 
1233  // French
1234  aMap["Dessous.Adhes"] = "B.Adhes";
1235  aMap["Dessus.Adhes"] = "F.Adhes";
1236  aMap["Dessous.Pate"] = "B.Paste";
1237  aMap["Dessus.Pate"] = "F.Paste";
1238  aMap["Dessous.SilkS"] = "B.SilkS";
1239  aMap["Dessus.SilkS"] = "F.SilkS";
1240  aMap["Dessous.Masque"] = "B.Mask";
1241  aMap["Dessus.Masque"] = "F.Mask";
1242  aMap["Dessin.User"] = "Dwgs.User";
1243  aMap["Contours.Ci"] = "Edge.Cuts";
1244 }

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

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

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

209 {
210  int year, month, day;
211 
212  year = m_requiredVersion / 10000;
213  month = ( m_requiredVersion / 100 ) - ( year * 100 );
214  day = m_requiredVersion - ( year * 10000 ) - ( month * 100 );
215 
216  // wx throws an assertion, not a catchable exception, when the date is invalid.
217  // User input shouldn't give wx asserts, so check manually and throw a proper
218  // error instead
219  if( day <= 0 || month <= 0 || month > 12 ||
220  day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
221  {
222  wxString err;
223  err.Printf( _( "Cannot interpret date code %d" ), m_requiredVersion );
224  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
225  }
226 
227  wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
228  return date.FormatDate();
229 }
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:80
#define _(s)
Definition: 3d_actions.cpp:33

References _, 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 58 of file pcb_parser.cpp.

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

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, In15_Cu, LSET::InternalCuMask(), 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 360 of file pcb_parser.h.

361  {
362  return m_tooRecent;
363  }
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:79

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

1382 {
1383  // avoid constructing another std::string, use lexer's directly
1384  typename M::const_iterator it = aMap.find( curText );
1385 
1386  if( it == aMap.end() )
1387  {
1388 #if 0 && defined(DEBUG)
1389  // dump the whole darn table, there's something wrong with it.
1390  for( it = aMap.begin(); it != aMap.end(); ++it )
1391  {
1392  wxLogDebug( &aMap == (void*)&m_layerIndices ? wxT( "lm[%s] = %d" ) :
1393  wxT( "lm[%s] = %08X" ), it->first.c_str(), it->second );
1394  }
1395 #endif
1396 
1397  m_undefinedLayers.insert( curText );
1398  return Rescue;
1399  }
1400 
1401  return it->second;
1402 }
LAYER_ID_MAP m_layerIndices
map layer name to it's index
Definition: pcb_parser.h:75
std::set< wxString > m_undefinedLayers
set of layers not defined in layers section
Definition: pcb_parser.h:77

References Rescue.

◆ Parse()

BOARD_ITEM * PCB_PARSER::Parse ( )

Definition at line 481 of file pcb_parser.cpp.

482 {
483  T token;
484  BOARD_ITEM* item;
485  LOCALE_IO toggle;
486 
487  // MODULEs can be prefixed with an initial block of single line comments and these
488  // are kept for Format() so they round trip in s-expression form. BOARDs might
489  // eventually do the same, but currently do not.
490  std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
491 
492  token = CurTok();
493 
494  if( token != T_LEFT )
495  Expecting( T_LEFT );
496 
497  switch( NextTok() )
498  {
499  case T_kicad_pcb:
500  if( m_board == NULL )
501  m_board = new BOARD();
502 
503  item = (BOARD_ITEM*) parseBOARD();
504  break;
505 
506  case T_module:
507  item = (BOARD_ITEM*) parseMODULE( initial_comments.release() );
508  break;
509 
510  default:
511  wxString err;
512  err.Printf( _( "Unknown token \"%s\"" ), GetChars( FromUTF8() ) );
513  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
514  }
515 
516  return item;
517 }
Instantiate the current locale within a scope in which you are expecting exceptions to be thrown.
Definition: common.h:216
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
BOARD * parseBOARD()
Definition: pcb_parser.cpp:520
T
enum T contains all this lexer's tokens.
#define NULL
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
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:153
BOARD holds information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:180
#define _(s)
Definition: 3d_actions.cpp:33
BOARD * m_board
Definition: pcb_parser.h:74
MODULE * parseMODULE(wxArrayString *aInitialComments=0)
Function parseMODULE.

References _, GetChars(), NULL, DRCRULE_T::T_LEFT, and THROW_PARSE_ERROR.

Referenced by GITHUB_PLUGIN::FootprintLoad(), CLIPBOARD_IO::Load(), PCB_IO::Load(), FP_CACHE::Load(), parse(), PCB_IO::Parse(), KI_TEST::ReadBoardItemFromFile(), and KI_TEST::ReadBoardItemFromStream().

◆ parse3DModel()

MODULE_3D_SETTINGS * PCB_PARSER::parse3DModel ( )
private

Definition at line 375 of file pcb_parser.cpp.

376 {
377  wxCHECK_MSG( CurTok() == T_model, NULL,
378  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as MODULE_3D_SETTINGS." ) );
379 
380  T token;
381 
383  NeedSYMBOLorNUMBER();
384  n3D->m_Filename = FromUTF8();
385 
386  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
387  {
388  if( token == T_LEFT )
389  token = NextTok();
390 
391  switch( token )
392  {
393  case T_at:
394  NeedLEFT();
395  token = NextTok();
396 
397  if( token != T_xyz )
398  Expecting( T_xyz );
399 
400  /* Note:
401  * Prior to KiCad v5, model offset was designated by "at",
402  * and the units were in inches.
403  * Now we use mm, but support reading of legacy files
404  */
405 
406  n3D->m_Offset.x = parseDouble( "x value" ) * 25.4f;
407  n3D->m_Offset.y = parseDouble( "y value" ) * 25.4f;
408  n3D->m_Offset.z = parseDouble( "z value" ) * 25.4f;
409 
410  NeedRIGHT(); // xyz
411  NeedRIGHT(); // at
412  break;
413 
414  case T_hide:
415  n3D->m_Show = false;
416  break;
417 
418  case T_opacity:
419  n3D->m_Opacity = parseDouble( "opacity value" );
420  NeedRIGHT();
421  break;
422 
423  case T_offset:
424  NeedLEFT();
425  token = NextTok();
426 
427  if( token != T_xyz )
428  Expecting( T_xyz );
429 
430  /*
431  * 3D model offset is in mm
432  */
433  n3D->m_Offset.x = parseDouble( "x value" );
434  n3D->m_Offset.y = parseDouble( "y value" );
435  n3D->m_Offset.z = parseDouble( "z value" );
436 
437  NeedRIGHT(); // xyz
438  NeedRIGHT(); // offset
439  break;
440 
441  case T_scale:
442  NeedLEFT();
443  token = NextTok();
444 
445  if( token != T_xyz )
446  Expecting( T_xyz );
447 
448  n3D->m_Scale.x = parseDouble( "x value" );
449  n3D->m_Scale.y = parseDouble( "y value" );
450  n3D->m_Scale.z = parseDouble( "z value" );
451 
452  NeedRIGHT(); // xyz
453  NeedRIGHT(); // scale
454  break;
455 
456  case T_rotate:
457  NeedLEFT();
458  token = NextTok();
459 
460  if( token != T_xyz )
461  Expecting( T_xyz );
462 
463  n3D->m_Rotation.x = parseDouble( "x value" );
464  n3D->m_Rotation.y = parseDouble( "y value" );
465  n3D->m_Rotation.z = parseDouble( "z value" );
466 
467  NeedRIGHT(); // xyz
468  NeedRIGHT(); // rotate
469  break;
470 
471  default:
472  Expecting( "at, hide, opacity, offset, scale, or rotate" );
473  }
474 
475  }
476 
477  return n3D;
478 }
bool m_Show
Include module in rendering.
Definition: class_module.h:97
T
enum T contains all this lexer's tokens.
VECTOR3D m_Offset
3D model offset (mm)
Definition: class_module.h:94
#define NULL
wxString m_Filename
The 3D shape filename in 3D library.
Definition: class_module.h:96
VECTOR3D m_Rotation
3D model rotation (degrees)
Definition: class_module.h:93
VECTOR3D m_Scale
3D model scaling factor (dimensionless)
Definition: class_module.h:92
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:150

References MODULE_3D_SETTINGS::m_Filename, MODULE_3D_SETTINGS::m_Offset, MODULE_3D_SETTINGS::m_Opacity, MODULE_3D_SETTINGS::m_Rotation, MODULE_3D_SETTINGS::m_Scale, MODULE_3D_SETTINGS::m_Show, NULL, parseDouble(), DRCRULE_T::T_LEFT, DRCRULE_T::T_RIGHT, MODULE_3D_SETTINGS::VECTOR3D::x, MODULE_3D_SETTINGS::VECTOR3D::y, and MODULE_3D_SETTINGS::VECTOR3D::z.

◆ parseARC()

ARC * PCB_PARSER::parseARC ( )
private

Definition at line 3541 of file pcb_parser.cpp.

3542 {
3543  wxCHECK_MSG( CurTok() == T_arc, NULL,
3544  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as ARC." ) );
3545 
3546  wxPoint pt;
3547  T token;
3548 
3549  std::unique_ptr<ARC> arc( new ARC( m_board ) );
3550 
3551  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3552  {
3553  if( token != T_LEFT )
3554  Expecting( T_LEFT );
3555 
3556  token = NextTok();
3557 
3558  switch( token )
3559  {
3560  case T_start:
3561  pt.x = parseBoardUnits( "start x" );
3562  pt.y = parseBoardUnits( "start y" );
3563  arc->SetStart( pt );
3564  break;
3565 
3566  case T_mid:
3567  pt.x = parseBoardUnits( "mid x" );
3568  pt.y = parseBoardUnits( "mid y" );
3569  arc->SetMid( pt );
3570  break;
3571 
3572  case T_end:
3573  pt.x = parseBoardUnits( "end x" );
3574  pt.y = parseBoardUnits( "end y" );
3575  arc->SetEnd( pt );
3576  break;
3577 
3578  case T_width:
3579  arc->SetWidth( parseBoardUnits( "width" ) );
3580  break;
3581 
3582  case T_layer:
3583  arc->SetLayer( parseBoardItemLayer() );
3584  break;
3585 
3586  case T_net:
3587  if( !arc->SetNetCode( getNetCode( parseInt( "net number" ) ), /* aNoAssert */ true ) )
3589  _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
3590  GetChars( CurSource() ), CurLineNumber(), CurOffset() ) );
3591  break;
3592 
3593  case T_tstamp:
3594  NextTok();
3595  const_cast<KIID&>( arc->m_Uuid ) = KIID( CurStr() );
3596  break;
3597 
3598  case T_status:
3599  arc->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
3600  break;
3601 
3602  default:
3603  Expecting( "start, mid, end, width, layer, net, tstamp, or status" );
3604  }
3605 
3606  NeedRIGHT();
3607  }
3608 
3609  return arc.release();
3610 }
T
enum T contains all this lexer's tokens.
int parseBoardUnits()
Definition: pcb_parser.h:255
Definition: common.h:68
#define NULL
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
#define THROW_IO_ERROR(msg)
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:153
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
#define _(s)
Definition: 3d_actions.cpp:33
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:86
BOARD * m_board
Definition: pcb_parser.h:74
long parseHex()
Definition: pcb_parser.h:304
int parseInt()
Definition: pcb_parser.h:293

References _, ARC, Format(), GetChars(), NULL, parseHex(), parseInt(), DRCRULE_T::T_LEFT, DRCRULE_T::T_RIGHT, THROW_IO_ERROR, wxPoint::x, and wxPoint::y.

◆ parseBOARD()

BOARD * PCB_PARSER::parseBOARD ( )
private

Definition at line 520 of file pcb_parser.cpp.

521 {
522  try
523  {
524  return parseBOARD_unchecked();
525  }
526  catch( const PARSE_ERROR& parse_error )
527  {
528  if( m_tooRecent )
529  throw FUTURE_FORMAT_ERROR( parse_error, GetRequiredVersion() );
530  else
531  throw;
532  }
533 }
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:79
wxString GetRequiredVersion()
Return a string representing the version of kicad required to open this file.
Definition: pcb_parser.cpp:208
BOARD * parseBOARD_unchecked()
Function parseBOARD_unchecked Parse a module, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR...
Definition: pcb_parser.cpp:536
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 536 of file pcb_parser.cpp.

537 {
538  T token;
539 
540  parseHeader();
541 
542  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
543  {
544  if( token != T_LEFT )
545  Expecting( T_LEFT );
546 
547  token = NextTok();
548 
549  if( token == T_page && m_requiredVersion <= 20200119 )
550  token = T_paper;
551 
552  switch( token )
553  {
554  case T_general:
556  break;
557 
558  case T_paper:
559  parsePAGE_INFO();
560  break;
561 
562  case T_title_block:
564  break;
565 
566  case T_layers:
567  parseLayers();
568  break;
569 
570  case T_setup:
571  parseSetup();
572  break;
573 
574  case T_net:
576  break;
577 
578  case T_net_class:
579  parseNETCLASS();
581  break;
582 
583  case T_gr_arc:
584  case T_gr_circle:
585  case T_gr_curve:
586  case T_gr_rect:
587  case T_gr_line:
588  case T_gr_poly:
590  break;
591 
592  case T_gr_text:
594  break;
595 
596  case T_dimension:
598  break;
599 
600  case T_module:
602  break;
603 
604  case T_segment:
606  break;
607 
608  case T_arc:
610  break;
611 
612  case T_via:
614  break;
615 
616  case T_zone:
618  break;
619 
620  case T_target:
622  break;
623 
624  default:
625  wxString err;
626  err.Printf( _( "Unknown token \"%s\"" ), GetChars( FromUTF8() ) );
627  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
628  }
629  }
630 
631  if( m_undefinedLayers.size() > 0 )
632  {
633  bool deleteItems;
634  std::vector<BOARD_ITEM*> deleteList;
635  wxString msg = wxString::Format( _( "Items found on undefined layers. Do you wish to\n"
636  "rescue them to the Cmts.User layer?" ) );
637  wxString details = wxString::Format( _( "Undefined layers:" ) );
638 
639  for( const wxString& undefinedLayer : m_undefinedLayers )
640  details += wxT( "\n " ) + undefinedLayer;
641 
642  wxRichMessageDialog dlg( nullptr, msg, _( "Warning" ),
643  wxYES_NO | wxCANCEL | wxCENTRE | wxICON_WARNING | wxSTAY_ON_TOP );
644  dlg.ShowDetailedText( details );
645  dlg.SetYesNoCancelLabels( _( "Rescue" ), _( "Delete" ), _( "Cancel" ) );
646 
647  switch( dlg.ShowModal() )
648  {
649  case wxID_YES: deleteItems = false; break;
650  case wxID_NO: deleteItems = true; break;
651  case wxID_CANCEL:
652  default: THROW_IO_ERROR( wxT( "CANCEL" ) );
653  }
654 
655  auto visitItem = [&]( BOARD_ITEM* item )
656  {
657  if( item->GetLayer() == Rescue )
658  {
659  if( deleteItems )
660  deleteList.push_back( item );
661  else
662  item->SetLayer( Cmts_User );
663  }
664  };
665 
666  for( auto segm : m_board->Tracks() )
667  {
668  if( segm->Type() == PCB_VIA_T )
669  {
670  VIA* via = (VIA*) segm;
671  PCB_LAYER_ID top_layer, bottom_layer;
672 
673  if( via->GetViaType() == VIATYPE::THROUGH )
674  continue;
675 
676  via->LayerPair( &top_layer, &bottom_layer );
677 
678  if( top_layer == Rescue || bottom_layer == Rescue )
679  {
680  if( deleteItems )
681  deleteList.push_back( via );
682  else
683  {
684  if( top_layer == Rescue )
685  top_layer = F_Cu;
686 
687  if( bottom_layer == Rescue )
688  bottom_layer = B_Cu;
689 
690  via->SetLayerPair( top_layer, bottom_layer );
691  }
692  }
693  }
694  else
695  visitItem( segm );
696  }
697 
698  for( BOARD_ITEM* zone : m_board->Zones() )
699  visitItem( zone );
700 
701  for( BOARD_ITEM* drawing : m_board->Drawings() )
702  visitItem( drawing );
703 
704  for( BOARD_ITEM* item : deleteList )
705  m_board->Delete( item );
706 
707  m_undefinedLayers.clear();
708  }
709 
710  return m_board;
711 }
void parseHeader()
Definition: pcb_parser.cpp:714
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.
bool m_LegacyNetclassesLoaded
True if netclasses were loaded from the file.
Definition: class_board.h:303
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()
ARC * parseARC()
DIMENSION * parseDIMENSION()
T
enum T contains all this lexer's tokens.
void parseTITLE_BLOCK()
Definition: pcb_parser.cpp:852
void parseLayers()
void parsePAGE_INFO()
Definition: pcb_parser.cpp:796
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
PCB_LAYER_ID
A quick note on layer IDs:
PCB_TARGET * parsePCB_TARGET()
ZONE_CONTAINER * parseZONE_CONTAINER(BOARD_ITEM_CONTAINER *aParent)
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()
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:80
ZONE_CONTAINERS & Zones()
Definition: class_board.h:280
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:153
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
#define _(s)
Definition: 3d_actions.cpp:33
BOARD * m_board
Definition: pcb_parser.h:74
void parseGeneralSection()
Definition: pcb_parser.cpp:750
VIATYPE GetViaType() const
Definition: class_track.h:373
virtual void Delete(BOARD_ITEM *aItem)
Removes an item from the container and deletes it.
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
MODULE * parseMODULE(wxArrayString *aInitialComments=0)
Function parseMODULE.
DRAWINGS & Drawings()
Definition: class_board.h:275
TRACKS & Tracks()
Definition: class_board.h:257
void parseSetup()
std::set< wxString > m_undefinedLayers
set of layers not defined in layers section
Definition: pcb_parser.h:77

References _, APPEND, B_Cu, Cmts_User, F_Cu, Format(), GetChars(), VIA::GetViaType(), VIA::LayerPair(), PCB_VIA_T, Rescue, VIA::SetLayerPair(), DRCRULE_T::T_LEFT, DRCRULE_T::T_RIGHT, THROUGH, THROW_IO_ERROR, and THROW_PARSE_ERROR.

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

1406 {
1407  wxCHECK_MSG( CurTok() == T_layer, UNDEFINED_LAYER,
1408  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as layer." ) );
1409 
1410  NextTok();
1411 
1412  PCB_LAYER_ID layerIndex = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
1413 
1414  // Handle closing ) in object parser.
1415 
1416  return layerIndex;
1417 }
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:75

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

1421 {
1422  wxCHECK_MSG( CurTok() == T_layers, LSET(),
1423  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1424  wxT( " as item layer mask." ) );
1425 
1426  LSET layerMask;
1427 
1428  for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
1429  {
1430  LSET mask = lookUpLayer<LSET>( m_layerMasks );
1431  layerMask |= mask;
1432  }
1433 
1434  return layerMask;
1435 }
T
enum T contains all this lexer's tokens.
LSET is a set of PCB_LAYER_IDs.
LSET_MAP m_layerMasks
map layer names to their masks
Definition: pcb_parser.h:76

References DRCRULE_T::T_RIGHT.

◆ parseBoardStackup()

void PCB_PARSER::parseBoardStackup ( )
private

Definition at line 1001 of file pcb_parser.cpp.

1002 {
1003  T token;
1004  wxString name;
1005  int dielectric_idx = 1; // the index of dielectric layers
1007 
1008  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1009  {
1010  if( CurTok() != T_LEFT )
1011  Expecting( T_LEFT );
1012 
1013  token = NextTok();
1014 
1015  if( token != T_layer )
1016  {
1017  switch( token )
1018  {
1019  case T_copper_finish:
1020  NeedSYMBOL();
1021  stackup.m_FinishType = FromUTF8();
1022  NeedRIGHT();
1023  break;
1024 
1025  case T_edge_plating:
1026  token = NextTok();
1027  stackup.m_EdgePlating = token == T_yes;
1028  NeedRIGHT();
1029  break;
1030 
1031  case T_dielectric_constraints:
1032  token = NextTok();
1033  stackup.m_HasDielectricConstrains = token == T_yes;
1034  NeedRIGHT();
1035  break;
1036 
1037  case T_edge_connector:
1038  token = NextTok();
1040 
1041  if( token == T_yes )
1043  else if( token == T_bevelled )
1045 
1046  NeedRIGHT();
1047  break;
1048 
1049  case T_castellated_pads:
1050  token = NextTok();
1051  stackup.m_CastellatedPads = token == T_yes;
1052  NeedRIGHT();
1053  break;
1054 
1055  default:
1056  // Currently, skip this item if not defined, because the stackup def
1057  // is a moving target
1058  //Expecting( "copper_finish, edge_plating, dielectric_constrains, edge_connector, castellated_pads" );
1059  skipCurrent();
1060  break;
1061  }
1062 
1063  continue;
1064  }
1065 
1066  NeedSYMBOL();
1067  name = FromUTF8();
1068 
1069  // init the layer id. For dielectric, layer id = UNDEFINED_LAYER
1070  PCB_LAYER_ID layerId = m_board->GetLayerID( name );
1071 
1072  // Init the type
1074 
1075  if( layerId == F_SilkS || layerId == B_SilkS )
1076  type = BS_ITEM_TYPE_SILKSCREEN;
1077  else if( layerId == F_Mask || layerId == B_Mask )
1078  type = BS_ITEM_TYPE_SOLDERMASK;
1079  else if( layerId == F_Paste || layerId == B_Paste )
1080  type = BS_ITEM_TYPE_SOLDERPASTE;
1081  else if( layerId == UNDEFINED_LAYER )
1082  type = BS_ITEM_TYPE_DIELECTRIC;
1083  else if( layerId >= F_Cu && layerId <= B_Cu )
1084  type = BS_ITEM_TYPE_COPPER;
1085 
1086  BOARD_STACKUP_ITEM* item = nullptr;
1087 
1088  if( type != BS_ITEM_TYPE_UNDEFINED )
1089  {
1090  item = new BOARD_STACKUP_ITEM( type );
1091  item->SetBrdLayerId( layerId );
1092 
1093  if( type == BS_ITEM_TYPE_DIELECTRIC )
1094  item->SetDielectricLayerId( dielectric_idx++ );
1095 
1096  stackup.Add( item );
1097  }
1098  else
1099  Expecting( "layer_name" );
1100 
1101  bool has_next_sublayer = true;
1102  int sublayer_idx = 0; // the index of dielectric sub layers
1103  // sublayer 0 is always existing (main sublayer)
1104 
1105  while( has_next_sublayer )
1106  {
1107  has_next_sublayer = false;
1108 
1109  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1110  {
1111  if( token == T_addsublayer )
1112  {
1113  has_next_sublayer = true;
1114  break;
1115  }
1116 
1117  if( token == T_LEFT )
1118  {
1119  token = NextTok();
1120 
1121  switch( token )
1122  {
1123  case T_type:
1124  NeedSYMBOL();
1125  item->SetTypeName( FromUTF8() );
1126  NeedRIGHT();
1127  break;
1128 
1129  case T_thickness:
1130  item->SetThickness( parseBoardUnits( T_thickness ), sublayer_idx );
1131  token = NextTok();
1132 
1133  if( token == T_LEFT )
1134  break;
1135 
1136  if( token == T_locked )
1137  {
1138  // Dielectric thickness can be locked (for impedance controled layers)
1139  if( type == BS_ITEM_TYPE_DIELECTRIC )
1140  item->SetThicknessLocked( true, sublayer_idx );
1141 
1142  NeedRIGHT();
1143  }
1144  break;
1145 
1146  case T_material:
1147  NeedSYMBOL();
1148  item->SetMaterial( FromUTF8(), sublayer_idx );
1149  NeedRIGHT();
1150  break;
1151 
1152  case T_epsilon_r:
1153  NextTok();
1154  item->SetEpsilonR( parseDouble(), sublayer_idx );
1155  NeedRIGHT();
1156  break;
1157 
1158  case T_loss_tangent:
1159  NextTok();
1160  item->SetLossTangent( parseDouble(), sublayer_idx );
1161  NeedRIGHT();
1162  break;
1163 
1164  case T_color:
1165  NeedSYMBOL();
1166  item->SetColor( FromUTF8() );
1167  NeedRIGHT();
1168  break;
1169 
1170  default:
1171  // Currently, skip this item if not defined, because the stackup def
1172  // is a moving target
1173  //Expecting( "type, thickness, material, epsilon_r, loss_tangent, color" );
1174  skipCurrent();
1175  }
1176  }
1177  }
1178 
1179  if( has_next_sublayer ) // Prepare reading the next sublayer description
1180  {
1181  sublayer_idx++;
1182  item->AddDielectricPrms( sublayer_idx );
1183  }
1184  }
1185  }
1186 
1187  if( token != T_RIGHT )
1188  {
1189  Expecting( ")" );
1190  }
1191 
1192  // Success:
1194 }
const PCB_LAYER_ID GetLayerID(const wxString &aLayerName) const
Function GetLayerID returns the ID of a layer.
void SetBrdLayerId(PCB_LAYER_ID aBrdLayerId)
void SetTypeName(const wxString &aName)
this class manage the layers needed to make a physical board they are solder mask,...
wxString m_FinishType
The name of external copper finish.
bool m_EdgePlating
True if the edge board is plated.
BS_EDGE_CONNECTOR_CONSTRAINTS m_EdgeConnectorConstraints
If the board has edge connector cards, some constrains can be specifed in job file: BS_EDGE_CONNECTOR...
bool m_CastellatedPads
True if castellated pads exist.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:551
T
enum T contains all this lexer's tokens.
int parseBoardUnits()
Definition: pcb_parser.h:255
void skipCurrent()
Function skipCurrent Skip the current token level, i.e search for the RIGHT parenthesis which closes ...
Definition: pcb_parser.cpp:117
bool m_HasDielectricConstrains
True if some layers have impedance controlled tracks or have specific constrains for micro-wave appli...
BOARD_STACKUP & GetStackupDescriptor()
PCB_LAYER_ID
A quick note on layer IDs:
void SetDielectricLayerId(int aLayerId)
void SetMaterial(const wxString &aName, int aDielectricSubLayer=0)
this class manage one layer needed to make a physical board it can be a solder mask,...
void SetEpsilonR(double aEpsilon, int aDielectricSubLayer=0)
void AddDielectricPrms(int aDielectricPrmsIdx)
true if this stackup item must be taken in account, false to ignore it.
void SetThickness(int aThickness, int aDielectricSubLayer=0)
void SetThicknessLocked(bool aLocked, int aDielectricSubLayer=0)
const char * name
Definition: DXF_plotter.cpp:60
BOARD * m_board
Definition: pcb_parser.h:74
BOARD_STACKUP_ITEM_TYPE
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:150
void SetColor(const wxString &aColorName)
bool m_HasStackup
Set to true if the board has a stackup management.
void Add(BOARD_STACKUP_ITEM *aItem)
Add a new item in stackup layer.
void SetLossTangent(double aTg, int aDielectricSubLayer=0)

References BOARD_STACKUP::Add(), BOARD_STACKUP_ITEM::AddDielectricPrms(), B_Cu, B_Mask, B_Paste, B_SilkS, BS_EDGE_CONNECTOR_BEVELLED, BS_EDGE_CONNECTOR_IN_USE, BS_EDGE_CONNECTOR_NONE, BS_ITEM_TYPE_COPPER, BS_ITEM_TYPE_DIELECTRIC, BS_ITEM_TYPE_SILKSCREEN, BS_ITEM_TYPE_SOLDERMASK, BS_ITEM_TYPE_SOLDERPASTE, BS_ITEM_TYPE_UNDEFINED, F_Cu, F_Mask, F_Paste, F_SilkS, BOARD_STACKUP::m_CastellatedPads, BOARD_STACKUP::m_EdgeConnectorConstraints, BOARD_STACKUP::m_EdgePlating, BOARD_STACKUP::m_FinishType, BOARD_STACKUP::m_HasDielectricConstrains, name, parseDouble(), BOARD_STACKUP_ITEM::SetBrdLayerId(), BOARD_STACKUP_ITEM::SetColor(), BOARD_STACKUP_ITEM::SetDielectricLayerId(), BOARD_STACKUP_ITEM::SetEpsilonR(), BOARD_STACKUP_ITEM::SetLossTangent(), BOARD_STACKUP_ITEM::SetMaterial(), BOARD_STACKUP_ITEM::SetThickness(), BOARD_STACKUP_ITEM::SetThicknessLocked(), BOARD_STACKUP_ITEM::SetTypeName(), DRCRULE_T::T_LEFT, DRCRULE_T::T_RIGHT, DRCRULE_T::T_type, and UNDEFINED_LAYER.

◆ parseBoardUnits() [1/3]

int PCB_PARSER::parseBoardUnits ( )
inlineprivate

Definition at line 255 of file pcb_parser.h.

256  {
257  // There should be no major rounding issues here, since the values in
258  // the file are in mm and get converted to nano-meters.
259  // See test program tools/test-nm-biu-to-ascii-mm-round-tripping.cpp
260  // to confirm or experiment. Use a similar strategy in both places, here
261  // and in the test program. Make that program with:
262  // $ make test-nm-biu-to-ascii-mm-round-tripping
263  auto retval = parseDouble() * IU_PER_MM;
264 
265  // N.B. we currently represent board units as integers. Any values that are
266  // larger or smaller than those board units represent undefined behavior for
267  // the system. We limit values to the largest that is visible on the screen
268  // This is the diagonal distance of the full screen ~1.5m
269  double int_limit = std::numeric_limits<int>::max() * 0.7071; // 0.7071 = roughly 1/sqrt(2)
270  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
271  }
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:150

References KiROUND(), and parseDouble().

Referenced by parseBoardUnits().

◆ parseBoardUnits() [2/3]

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

Definition at line 273 of file pcb_parser.h.

274  {
275  auto retval = parseDouble( aExpected ) * IU_PER_MM;
276 
277  // N.B. we currently represent board units as integers. Any values that are
278  // larger or smaller than those board units represent undefined behavior for
279  // the system. We limit values to the largest that is visible on the screen
280  double int_limit = std::numeric_limits<int>::max() * 0.7071;
281 
282  // Use here KiROUND, not KIROUND (see comments about them)
283  // when having a function as argument, because it will be called twice
284  // with KIROUND
285  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
286  }
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:150

References KiROUND(), and parseDouble().

◆ parseBoardUnits() [3/3]

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

Definition at line 288 of file pcb_parser.h.

289  {
290  return parseBoardUnits( GetTokenText( aToken ) );
291  }
int parseBoardUnits()
Definition: pcb_parser.h:255
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 180 of file pcb_parser.cpp.

181 {
182  T token = NextTok();
183 
184  if( token == T_yes )
185  return true;
186  else if( token == T_no )
187  return false;
188  else
189  Expecting( "yes or no" );
190 
191  return false;
192 }
T
enum T contains all this lexer's tokens.

◆ parseD_PAD()

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

Definition at line 3020 of file pcb_parser.cpp.

3021 {
3022  wxCHECK_MSG( CurTok() == T_pad, NULL,
3023  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as D_PAD." ) );
3024 
3025  wxSize sz;
3026  wxPoint pt;
3027 
3028  std::unique_ptr< D_PAD > pad( new D_PAD( aParent ) );
3029 
3030  NeedSYMBOLorNUMBER();
3031  pad->SetName( FromUTF8() );
3032 
3033  T token = NextTok();
3034 
3035  switch( token )
3036  {
3037  case T_thru_hole:
3038  pad->SetAttribute( PAD_ATTRIB_STANDARD );
3039  break;
3040 
3041  case T_smd:
3042  pad->SetAttribute( PAD_ATTRIB_SMD );
3043 
3044  // Default D_PAD object is thru hole with drill.
3045  // SMD pads have no hole
3046  pad->SetDrillSize( wxSize( 0, 0 ) );
3047  break;
3048 
3049  case T_connect:
3050  pad->SetAttribute( PAD_ATTRIB_CONN );
3051 
3052  // Default D_PAD object is thru hole with drill.
3053  // CONN pads have no hole
3054  pad->SetDrillSize( wxSize( 0, 0 ) );
3055  break;
3056 
3057  case T_np_thru_hole:
3058  pad->SetAttribute( PAD_ATTRIB_HOLE_NOT_PLATED );
3059  break;
3060 
3061  default:
3062  Expecting( "thru_hole, smd, connect, or np_thru_hole" );
3063  }
3064 
3065  token = NextTok();
3066 
3067  switch( token )
3068  {
3069  case T_circle:
3070  pad->SetShape( PAD_SHAPE_CIRCLE );
3071  break;
3072 
3073  case T_rect:
3074  pad->SetShape( PAD_SHAPE_RECT );
3075  break;
3076 
3077  case T_oval:
3078  pad->SetShape( PAD_SHAPE_OVAL );
3079  break;
3080 
3081  case T_trapezoid:
3082  pad->SetShape( PAD_SHAPE_TRAPEZOID );
3083  break;
3084 
3085  case T_roundrect:
3086  // Note: the shape can be PAD_SHAPE_ROUNDRECT or PAD_SHAPE_CHAMFERED_RECT
3087  // (if champfer parameters are found later in pad descr.)
3088  pad->SetShape( PAD_SHAPE_ROUNDRECT );
3089  break;
3090 
3091  case T_custom:
3092  pad->SetShape( PAD_SHAPE_CUSTOM );
3093  break;
3094 
3095  default:
3096  Expecting( "circle, rectangle, roundrect, oval, trapezoid or custom" );
3097  }
3098 
3099  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3100  {
3101  if( token != T_LEFT )
3102  Expecting( T_LEFT );
3103 
3104  token = NextTok();
3105 
3106  switch( token )
3107  {
3108  case T_size:
3109  sz.SetWidth( parseBoardUnits( "width value" ) );
3110  sz.SetHeight( parseBoardUnits( "height value" ) );
3111  pad->SetSize( sz );
3112  NeedRIGHT();
3113  break;
3114 
3115  case T_at:
3116  pt.x = parseBoardUnits( "X coordinate" );
3117  pt.y = parseBoardUnits( "Y coordinate" );
3118  pad->SetPos0( pt );
3119  token = NextTok();
3120 
3121  if( token == T_NUMBER )
3122  {
3123  pad->SetOrientation( parseDouble() * 10.0 );
3124  NeedRIGHT();
3125  }
3126  else if( token != T_RIGHT )
3127  {
3128  Expecting( ") or angle value" );
3129  }
3130 
3131  break;
3132 
3133  case T_rect_delta:
3134  {
3135  wxSize delta;
3136  delta.SetWidth( parseBoardUnits( "rectangle delta width" ) );
3137  delta.SetHeight( parseBoardUnits( "rectangle delta height" ) );
3138  pad->SetDelta( delta );
3139  NeedRIGHT();
3140  }
3141  break;
3142 
3143  case T_drill:
3144  {
3145  bool haveWidth = false;
3146  wxSize drillSize = pad->GetDrillSize();
3147 
3148  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3149  {
3150  if( token == T_LEFT )
3151  token = NextTok();
3152 
3153  switch( token )
3154  {
3155  case T_oval:
3156  pad->SetDrillShape( PAD_DRILL_SHAPE_OBLONG );
3157  break;
3158 
3159  case T_NUMBER:
3160  {
3161  if( !haveWidth )
3162  {
3163  drillSize.SetWidth( parseBoardUnits() );
3164 
3165  // If height is not defined the width and height are the same.
3166  drillSize.SetHeight( drillSize.GetWidth() );
3167  haveWidth = true;
3168  }
3169  else
3170  {
3171  drillSize.SetHeight( parseBoardUnits() );
3172  }
3173 
3174  }
3175  break;
3176 
3177  case T_offset:
3178  pt.x = parseBoardUnits( "drill offset x" );
3179  pt.y = parseBoardUnits( "drill offset y" );
3180  pad->SetOffset( pt );
3181  NeedRIGHT();
3182  break;
3183 
3184  default:
3185  Expecting( "oval, size, or offset" );
3186  }
3187  }
3188 
3189  // This fixes a bug caused by setting the default D_PAD drill size to a value
3190  // other than 0 used to fix a bunch of debug assertions even though it is defined
3191  // as a through hole pad. Wouldn't a though hole pad with no drill be a surface
3192  // mount pad (or a conn pad which is a smd pad with no solder paste)?
3193  if( ( pad->GetAttribute() != PAD_ATTRIB_SMD ) && ( pad->GetAttribute() != PAD_ATTRIB_CONN ) )
3194  pad->SetDrillSize( drillSize );
3195  else
3196  pad->SetDrillSize( wxSize( 0, 0 ) );
3197 
3198  }
3199  break;
3200 
3201  case T_layers:
3202  {
3203  LSET layerMask = parseBoardItemLayersAsMask();
3204  pad->SetLayerSet( layerMask );
3205  }
3206  break;
3207 
3208  case T_net:
3209  if( ! pad->SetNetCode( getNetCode( parseInt( "net number" ) ), /* aNoAssert */ true ) )
3210  {
3211  wxLogError( wxString::Format( _( "Invalid net ID in\n"
3212  "file: '%s'\n"
3213  "line: %d\n"
3214  "offset: %d" ),
3215  CurSource(),
3216  CurLineNumber(),
3217  CurOffset() ) );
3218  }
3219 
3220  NeedSYMBOLorNUMBER();
3221 
3222  // Test validity of the netname in file for netcodes expected having a net name
3223  if( m_board && pad->GetNetCode() > 0 &&
3224  FromUTF8() != m_board->FindNet( pad->GetNetCode() )->GetNetname() )
3225  {
3226  pad->SetNetCode( NETINFO_LIST::ORPHANED, /* aNoAssert */ true );
3227  wxLogError( wxString::Format( _( "Net name doesn't match net ID in\n"
3228  "file: '%s'\n"
3229  "line: %d\n"
3230  "offset: %d" ),
3231  CurSource(),
3232  CurLineNumber(),
3233  CurOffset() ) );
3234  }
3235 
3236  NeedRIGHT();
3237  break;
3238 
3239  case T_pinfunction:
3240  NeedSYMBOLorNUMBER();
3241  pad->SetPinFunction( FromUTF8() );
3242  NeedRIGHT();
3243  break;
3244 
3245  case T_die_length:
3246  pad->SetPadToDieLength( parseBoardUnits( T_die_length ) );
3247  NeedRIGHT();
3248  break;
3249 
3250  case T_solder_mask_margin:
3251  pad->SetLocalSolderMaskMargin( parseBoardUnits( T_solder_mask_margin ) );
3252  NeedRIGHT();
3253  break;
3254 
3255  case T_solder_paste_margin:
3256  pad->SetLocalSolderPasteMargin( parseBoardUnits( T_solder_paste_margin ) );
3257  NeedRIGHT();
3258  break;
3259 
3260  case T_solder_paste_margin_ratio:
3261  pad->SetLocalSolderPasteMarginRatio(
3262  parseDouble( "pad local solder paste margin ratio value" ) );
3263  NeedRIGHT();
3264  break;
3265 
3266  case T_clearance:
3267  pad->SetLocalClearance( parseBoardUnits( "local clearance value" ) );
3268  NeedRIGHT();
3269  break;
3270 
3271  case T_zone_connect:
3272  pad->SetZoneConnection( (ZONE_CONNECTION) parseInt( "zone connection value" ) );
3273  NeedRIGHT();
3274  break;
3275 
3276  case T_thermal_width:
3277  pad->SetThermalWidth( parseBoardUnits( T_thermal_width ) );
3278  NeedRIGHT();
3279  break;
3280 
3281  case T_thermal_gap:
3282  pad->SetThermalGap( parseBoardUnits( T_thermal_gap ) );
3283  NeedRIGHT();
3284  break;
3285 
3286  case T_roundrect_rratio:
3287  pad->SetRoundRectRadiusRatio( parseDouble( "roundrect radius ratio" ) );
3288  NeedRIGHT();
3289  break;
3290 
3291  case T_chamfer_ratio:
3292  pad->SetChamferRectRatio( parseDouble( "chamfer ratio" ) );
3293 
3294  if( pad->GetChamferRectRatio() > 0 )
3295  pad->SetShape( PAD_SHAPE_CHAMFERED_RECT );
3296 
3297  NeedRIGHT();
3298  break;
3299 
3300  case T_chamfer:
3301  {
3302  int chamfers = 0;
3303  bool end_list = false;
3304 
3305  while( !end_list )
3306  {
3307  token = NextTok();
3308  switch( token )
3309  {
3310  case T_top_left:
3311  chamfers |= RECT_CHAMFER_TOP_LEFT;
3312  break;
3313 
3314  case T_top_right:
3315  chamfers |= RECT_CHAMFER_TOP_RIGHT;
3316  break;
3317 
3318  case T_bottom_left:
3319  chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
3320  break;
3321 
3322  case T_bottom_right:
3323  chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
3324  break;
3325 
3326  case T_RIGHT:
3327  pad->SetChamferPositions( chamfers );
3328  end_list = true;
3329  break;
3330 
3331  default:
3332  Expecting( "chamfer_top_left chamfer_top_right chamfer_bottom_left or chamfer_bottom_right" );
3333  }
3334  }
3335 
3336  if( pad->GetChamferPositions() != RECT_NO_CHAMFER )
3337  pad->SetShape( PAD_SHAPE_CHAMFERED_RECT );
3338  }
3339  break;
3340 
3341  case T_property:
3342  {
3343  while( token != T_RIGHT )
3344  {
3345  token = NextTok();
3346 
3347  switch( token )
3348  {
3349  case T_pad_prop_bga:
3350  pad->SetProperty( PAD_PROP_BGA );
3351  break;
3352 
3353  case T_pad_prop_fiducial_glob:
3354  pad->SetProperty( PAD_PROP_FIDUCIAL_GLBL );
3355  break;
3356 
3357  case T_pad_prop_fiducial_loc:
3358  pad->SetProperty( PAD_PROP_FIDUCIAL_LOCAL );
3359  break;
3360 
3361  case T_pad_prop_testpoint:
3362  pad->SetProperty( PAD_PROP_TESTPOINT );
3363  break;
3364 
3365  case T_pad_prop_castellated:
3366  pad->SetProperty( PAD_PROP_CASTELLATED );
3367  break;
3368 
3369  case T_pad_prop_heatsink:
3370  pad->SetProperty( PAD_PROP_HEATSINK );
3371  break;
3372 
3373  case T_RIGHT:
3374  break;
3375 
3376  default:
3377 #if 0 // Currently: skip unknown property
3378  Expecting( "pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
3379  " pad_prop_heatsink or pad_prop_castellated" );
3380 #endif
3381  break;
3382  }
3383  }
3384  }
3385  break;
3386 
3387  case T_options:
3388  parseD_PAD_option( pad.get() );
3389  break;
3390 
3391  case T_primitives:
3392  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3393  {
3394  if( token == T_LEFT )
3395  token = NextTok();
3396 
3397  // Currently, I am using parseDRAWSEGMENT() to read basic shapes parameters,
3398  // because they are the same as a DRAWSEGMENT.
3399  // However it could be better to write a specific parser, to avoid possible issues
3400  // if the DRAWSEGMENT parser is modified.
3401  DRAWSEGMENT* dummysegm = NULL;
3402 
3403  switch( token )
3404  {
3405  case T_gr_arc:
3406  dummysegm = parseDRAWSEGMENT();
3407  pad->AddPrimitiveArc( dummysegm->GetCenter(), dummysegm->GetArcStart(),
3408  dummysegm->GetAngle(), dummysegm->GetWidth() );
3409  break;
3410 
3411  case T_gr_line:
3412  dummysegm = parseDRAWSEGMENT();
3413  pad->AddPrimitiveSegment( dummysegm->GetStart(), dummysegm->GetEnd(),
3414  dummysegm->GetWidth() );
3415  break;
3416 
3417  case T_gr_circle:
3418  dummysegm = parseDRAWSEGMENT( true ); // Circles with 0 thickness are allowed
3419  // ( filled circles )
3420  pad->AddPrimitiveCircle( dummysegm->GetCenter(), dummysegm->GetRadius(),
3421  dummysegm->GetWidth() );
3422  break;
3423 
3424  case T_gr_rect:
3425  dummysegm = parseDRAWSEGMENT( true );
3426  pad->AddPrimitiveRect( dummysegm->GetStart(), dummysegm->GetEnd(),
3427  dummysegm->GetWidth() );
3428  break;
3429 
3430 
3431  case T_gr_poly:
3432  dummysegm = parseDRAWSEGMENT();
3433  pad->AddPrimitivePoly( dummysegm->BuildPolyPointsList(),
3434  dummysegm->GetWidth() );
3435  break;
3436 
3437  case T_gr_curve:
3438  dummysegm = parseDRAWSEGMENT();
3439  pad->AddPrimitiveCurve( dummysegm->GetStart(), dummysegm->GetEnd(),
3440  dummysegm->GetBezControl1(),
3441  dummysegm->GetBezControl2(),
3442  dummysegm->GetWidth() );
3443  break;
3444 
3445  default:
3446  Expecting( "gr_line, gr_arc, gr_circle, gr_curve, gr_rect or gr_poly" );
3447  break;
3448  }
3449 
3450  delete dummysegm;
3451  }
3452  break;
3453 
3454  case T_tstamp:
3455  NextTok();
3456  const_cast<KIID&>( pad->m_Uuid ) = KIID( CurStr() );
3457  NeedRIGHT();
3458  break;
3459 
3460  default:
3461  Expecting( "at, drill, layers, net, die_length, solder_mask_margin, roundrect_rratio,\n"
3462  "solder_paste_margin, solder_paste_margin_ratio, clearance, tstamp,\n"
3463  "zone_connect, fp_poly, primitives, thermal_width, or thermal_gap" );
3464  }
3465  }
3466 
3467  return pad.release();
3468 }
NETINFO_ITEM * FindNet(int aNetcode) const
Function FindNet searches for a net with the given netcode.
ZONE_CONNECTION
How pads are covered by copper in zone.
Definition: zones.h:41
wxPoint GetArcStart() const
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:85
a fiducial (usually a smd) for the full board
Definition: pad_shapes.h:99
Smd pad, appears on the solder paste layer (default)
Definition: pad_shapes.h:81
Smd pad, used in BGA footprints.
Definition: pad_shapes.h:98
bool parseD_PAD_option(D_PAD *aPad)
T
enum T contains all this lexer's tokens.
a pad used as heat sink, usually in SMD footprints
Definition: pad_shapes.h:102
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:255
a pad with a castellated through hole
Definition: pad_shapes.h:103
Definition: common.h:68
LSET is a set of PCB_LAYER_IDs.
#define NULL
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:82
int GetWidth() const
static const int ORPHANED
Constant that forces initialization of a netinfo item to the NETINFO_ITEM ORPHANED (typically -1) whe...
Definition: netinfo.h:480
double GetAngle() const
a fiducial (usually a smd) local to the parent footprint
Definition: pad_shapes.h:100
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
#define _(s)
Definition: 3d_actions.cpp:33
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:86
BOARD * m_board
Definition: pcb_parser.h:74
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:150
const wxPoint & GetBezControl1() const
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
int parseInt()
Definition: pcb_parser.h:293
a test point pad
Definition: pad_shapes.h:101
wxPoint GetCenter() const override
Function GetCenter()

References _, DRAWSEGMENT::BuildPolyPointsList(), Format(), DRAWSEGMENT::GetAngle(), DRAWSEGMENT::GetArcStart(), DRAWSEGMENT::GetBezControl1(), DRAWSEGMENT::GetBezControl2(), DRAWSEGMENT::GetCenter(), DRAWSEGMENT::GetEnd(), DRAWSEGMENT::GetRadius(), DRAWSEGMENT::GetStart(), DRAWSEGMENT::GetWidth(), NULL, NETINFO_LIST::ORPHANED, PAD_ATTRIB_CONN, PAD_ATTRIB_HOLE_NOT_PLATED, PAD_ATTRIB_SMD, PAD_ATTRIB_STANDARD, PAD_DRILL_SHAPE_OBLONG, PAD_PROP_BGA, PAD_PROP_CASTELLATED, PAD_PROP_FIDUCIAL_GLBL, PAD_PROP_FIDUCIAL_LOCAL, PAD_PROP_HEATSINK, PAD_PROP_TESTPOINT, 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, DRCRULE_T::T_LEFT, DRCRULE_T::T_NUMBER, DRCRULE_T::T_RIGHT, wxPoint::x, and wxPoint::y.

◆ parseD_PAD_option()

bool PCB_PARSER::parseD_PAD_option ( D_PAD aPad)
private

Definition at line 3471 of file pcb_parser.cpp.

3472 {
3473  // Parse only the (option ...) inside a pad description
3474  for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
3475  {
3476  if( token != T_LEFT )
3477  Expecting( T_LEFT );
3478 
3479  token = NextTok();
3480 
3481  switch( token )
3482  {
3483  case T_anchor:
3484  token = NextTok();
3485  // Custom shaped pads have a "anchor pad", which is the reference
3486  // for connection calculations.
3487  // Because this is an anchor, only the 2 very basic shapes are managed:
3488  // circle and rect. The default is circle
3489  switch( token )
3490  {
3491  case T_circle: // default
3492  break;
3493 
3494  case T_rect:
3496  break;
3497 
3498  default:
3499  // Currently, because pad options is a moving target
3500  // just skip unknown keywords
3501  break;
3502  }
3503  NeedRIGHT();
3504  break;
3505 
3506  case T_clearance:
3507  token = NextTok();
3508  // Custom shaped pads have a clearance area that is the pad shape
3509  // (like usual pads) or the convew hull of the pad shape.
3510  switch( token )
3511  {
3512  case T_outline:
3514  break;
3515 
3516  case T_convexhull:
3518  break;
3519 
3520  default:
3521  // Currently, because pad options is a moving target
3522  // just skip unknown keywords
3523  break;
3524  }
3525  NeedRIGHT();
3526  break;
3527 
3528  default:
3529  // Currently, because pad options is a moving target
3530  // just skip unknown keywords
3531  while( (token = NextTok() ) != T_RIGHT )
3532  {}
3533  break;
3534  }
3535  }
3536 
3537  return true;
3538 }
T
enum T contains all this lexer's tokens.
void SetAnchorPadShape(PAD_SHAPE_T aShape)
Function SetAnchorPadShape Set the shape of the anchor pad for custm shped pads.
Definition: class_pad.h:195
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:184

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

◆ parseDefaults()

void PCB_PARSER::parseDefaults ( BOARD_DESIGN_SETTINGS aSettings)
private

Definition at line 1769 of file pcb_parser.cpp.

1770 {
1771  T token;
1772 
1773  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1774  {
1775  if( token != T_LEFT )
1776  Expecting( T_LEFT );
1777 
1778  token = NextTok();
1779 
1780  switch( token )
1781  {
1782  case T_edge_clearance:
1783  designSettings.m_CopperEdgeClearance = parseBoardUnits( T_edge_clearance );
1784  NeedRIGHT();
1785  break;
1786 
1787  case T_copper_line_width:
1788  designSettings.m_LineThickness[ LAYER_CLASS_COPPER ] = parseBoardUnits( token );
1789  NeedRIGHT();
1790  break;
1791 
1792  case T_copper_text_dims:
1793  parseDefaultTextDims( designSettings, LAYER_CLASS_COPPER );
1794  break;
1795 
1796  case T_courtyard_line_width:
1797  designSettings.m_LineThickness[ LAYER_CLASS_COURTYARD ] = parseBoardUnits( token );
1798  NeedRIGHT();
1799  break;
1800 
1801  case T_edge_cuts_line_width:
1802  designSettings.m_LineThickness[ LAYER_CLASS_EDGES ] = parseBoardUnits( token );
1803  NeedRIGHT();
1804  break;
1805 
1806  case T_silk_line_width:
1807  designSettings.m_LineThickness[ LAYER_CLASS_SILK ] = parseBoardUnits( token );
1808  NeedRIGHT();
1809  break;
1810 
1811  case T_silk_text_dims:
1812  parseDefaultTextDims( designSettings, LAYER_CLASS_SILK );
1813  break;
1814 
1815  case T_fab_layers_line_width:
1816  designSettings.m_LineThickness[ LAYER_CLASS_FAB ] = parseBoardUnits( token );
1817  NeedRIGHT();
1818  break;
1819 
1820  case T_fab_layers_text_dims:
1821  parseDefaultTextDims( designSettings, LAYER_CLASS_FAB );
1822  break;
1823 
1824  case T_other_layers_line_width:
1825  designSettings.m_LineThickness[ LAYER_CLASS_OTHERS ] = parseBoardUnits( token );
1826  NeedRIGHT();
1827  break;
1828 
1829  case T_other_layers_text_dims:
1830  parseDefaultTextDims( designSettings, LAYER_CLASS_OTHERS );
1831  break;
1832 
1833  case T_dimension_units:
1834  designSettings.m_DimensionUnits = parseInt( "dimension units" );
1835  NeedRIGHT();
1836  break;
1837 
1838  case T_dimension_precision:
1839  designSettings.m_DimensionPrecision = parseInt( "dimension precision" );
1840  NeedRIGHT();
1841  break;
1842 
1843  default:
1844  Unexpected( CurText() );
1845  }
1846  }
1847 }
T
enum T contains all this lexer's tokens.
int parseBoardUnits()
Definition: pcb_parser.h:255
void parseDefaultTextDims(BOARD_DESIGN_SETTINGS &aSettings, int aLayer)
int parseInt()
Definition: pcb_parser.h:293

References LAYER_CLASS_COPPER, LAYER_CLASS_COURTYARD, LAYER_CLASS_EDGES, LAYER_CLASS_FAB, LAYER_CLASS_OTHERS, LAYER_CLASS_SILK, BOARD_DESIGN_SETTINGS::m_CopperEdgeClearance, BOARD_DESIGN_SETTINGS::m_DimensionPrecision, BOARD_DESIGN_SETTINGS::m_DimensionUnits, BOARD_DESIGN_SETTINGS::m_LineThickness, parseInt(), DRCRULE_T::T_LEFT, and DRCRULE_T::T_RIGHT.

◆ parseDefaultTextDims()

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

Definition at line 1850 of file pcb_parser.cpp.

1851 {
1852  T token;
1853 
1854  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1855  {
1856  if( token == T_LEFT )
1857  token = NextTok();
1858 
1859  switch( token )
1860  {
1861  case T_size:
1862  aSettings.m_TextSize[ aLayer ].x = parseBoardUnits( "default text size X" );
1863  aSettings.m_TextSize[ aLayer ].y = parseBoardUnits( "default text size Y" );
1864  NeedRIGHT();
1865  break;
1866 
1867  case T_thickness:
1868  aSettings.m_TextThickness[ aLayer ] = parseBoardUnits( "default text width" );
1869  NeedRIGHT();
1870  break;
1871 
1872  case T_italic:
1873  aSettings.m_TextItalic[ aLayer ] = true;
1874  break;
1875 
1876  case T_keep_upright:
1877  aSettings.m_TextUpright[ aLayer ] = true;
1878  break;
1879 
1880  default:
1881  Expecting( "size, thickness, italic or keep_upright" );
1882  }
1883  }
1884 }
T
enum T contains all this lexer's tokens.
int parseBoardUnits()
Definition: pcb_parser.h:255
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, BOARD_DESIGN_SETTINGS::m_TextUpright, DRCRULE_T::T_LEFT, and DRCRULE_T::T_RIGHT.

◆ parseDIMENSION()

DIMENSION * PCB_PARSER::parseDIMENSION ( )
private

Definition at line 2265 of file pcb_parser.cpp.

2266 {
2267  wxCHECK_MSG( CurTok() == T_dimension, NULL,
2268  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as DIMENSION." ) );
2269 
2270  T token;
2271 
2272  std::unique_ptr<DIMENSION> dimension( new DIMENSION( NULL ) );
2273 
2274  dimension->SetValue( parseBoardUnits( "dimension value" ) );
2275  NeedLEFT();
2276  token = NextTok();
2277 
2278  if( token != T_width )
2279  Expecting( T_width );
2280 
2281  dimension->SetWidth( parseBoardUnits( "dimension width value" ) );
2282  NeedRIGHT();
2283 
2284  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2285  {
2286  if( token != T_LEFT )
2287  Expecting( T_LEFT );
2288 
2289  token = NextTok();
2290 
2291  switch( token )
2292  {
2293  case T_layer:
2294  dimension->SetLayer( parseBoardItemLayer() );
2295  NeedRIGHT();
2296  break;
2297 
2298  case T_tstamp:
2299  NextTok();
2300  const_cast<KIID&>( dimension->m_Uuid ) = KIID( CurStr() );
2301  NeedRIGHT();
2302  break;
2303 
2304  case T_gr_text:
2305  {
2306  TEXTE_PCB* text = parseTEXTE_PCB();
2307  dimension->Text() = *text;
2308 
2309  // The text is part of the dimension and shares its uuid
2310  const_cast<KIID&>( dimension->Text().m_Uuid ) = dimension->m_Uuid;
2311 
2312  // Fetch other dimension properties out of the text item
2313  dimension->SetPosition( text->GetTextPos() );
2314 
2315  EDA_UNITS units = EDA_UNITS::INCHES;
2316  bool useMils = false;
2317  FetchUnitsFromString( text->GetText(), units, useMils );
2318  dimension->SetUnits( units, useMils );
2319 
2320  delete text;
2321  break;
2322  }
2323 
2324  case T_feature1:
2325  NeedLEFT();
2326  token = NextTok();
2327 
2328  if( token != T_pts )
2329  Expecting( T_pts );
2330 
2331  parseXY( &dimension->m_featureLineDO.x, &dimension->m_featureLineDO.y );
2332  parseXY( &dimension->m_featureLineDF.x, &dimension->m_featureLineDF.y );
2333  dimension->UpdateHeight();
2334  NeedRIGHT();
2335  NeedRIGHT();
2336  break;
2337 
2338  case T_feature2:
2339  NeedLEFT();
2340  token = NextTok();
2341 
2342  if( token != T_pts )
2343  Expecting( T_pts );
2344 
2345  parseXY( &dimension->m_featureLineGO.x, &dimension->m_featureLineGO.y );
2346  parseXY( &dimension->m_featureLineGF.x, &dimension->m_featureLineGF.y );
2347  dimension->UpdateHeight();
2348  NeedRIGHT();
2349  NeedRIGHT();
2350  break;
2351 
2352 
2353  case T_crossbar:
2354  NeedLEFT();
2355  token = NextTok();
2356 
2357  if( token != T_pts )
2358  Expecting( T_pts );
2359 
2360  parseXY( &dimension->m_crossBarO.x, &dimension->m_crossBarO.y );
2361  parseXY( &dimension->m_crossBarF.x, &dimension->m_crossBarF.y );
2362  dimension->UpdateHeight();
2363  NeedRIGHT();
2364  NeedRIGHT();
2365  break;
2366 
2367  case T_arrow1a:
2368  NeedLEFT();
2369  token = NextTok();
2370 
2371  if( token != T_pts )
2372  Expecting( T_pts );
2373 
2374  parseXY( &dimension->m_crossBarF.x, &dimension->m_crossBarF.y );
2375  parseXY( &dimension->m_arrowD1F.x, &dimension->m_arrowD1F.y );
2376  NeedRIGHT();
2377  NeedRIGHT();
2378  break;
2379 
2380  case T_arrow1b:
2381  NeedLEFT();
2382  token = NextTok();
2383 
2384  if( token != T_pts )
2385  Expecting( T_pts );
2386 
2387  parseXY( &dimension->m_crossBarF.x, &dimension->m_crossBarF.y );
2388  parseXY( &dimension->m_arrowD2F.x, &dimension->m_arrowD2F.y );
2389  NeedRIGHT();
2390  NeedRIGHT();
2391  break;
2392 
2393  case T_arrow2a:
2394  NeedLEFT();
2395  token = NextTok();
2396 
2397  if( token != T_pts )
2398  Expecting( T_pts );
2399 
2400  parseXY( &dimension->m_crossBarO.x, &dimension->m_crossBarO.y );
2401  parseXY( &dimension->m_arrowG1F.x, &dimension->m_arrowG1F.y );
2402  NeedRIGHT();
2403  NeedRIGHT();
2404  break;
2405 
2406  case T_arrow2b:
2407  NeedLEFT();
2408  token = NextTok();
2409 
2410  if( token != T_pts )
2411  Expecting( T_pts );
2412 
2413  parseXY( &dimension->m_crossBarO.x, &dimension->m_crossBarO.y );
2414  parseXY( &dimension->m_arrowG2F.x, &dimension->m_arrowG2F.y );
2415  NeedRIGHT();
2416  NeedRIGHT();
2417  break;
2418 
2419  default:
2420  Expecting( "layer, tstamp, gr_text, feature1, feature2 crossbar, arrow1a, "
2421  "arrow1b, arrow2a, or arrow2b" );
2422  }
2423  }
2424 
2425  return dimension.release();
2426 }
EDA_UNITS
Definition: common.h:198
wxPoint parseXY()
Function parseXY parses a coordinate pair (xy X Y) in board units (mm).
Definition: pcb_parser.cpp:232
T
enum T contains all this lexer's tokens.
int parseBoardUnits()
Definition: pcb_parser.h:255
Definition: common.h:68
#define NULL
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
TEXTE_PCB * parseTEXTE_PCB()
const KIID m_Uuid
Definition: base_struct.h:162
void FetchUnitsFromString(const wxString &aTextValue, EDA_UNITS &aUnits, bool &aUseMils)
Function FetchUnitsFromString writes any unit info found in the string to aUnits and aUseMils.
Definition: base_units.cpp:432
const wxPoint & GetTextPos() const
Definition: eda_text.h:247
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:126
DIMENSION.

References FetchUnitsFromString(), EDA_TEXT::GetText(), EDA_TEXT::GetTextPos(), INCHES, EDA_ITEM::m_Uuid, NULL, DRCRULE_T::T_LEFT, and DRCRULE_T::T_RIGHT.

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

151 {
152  char* tmp;
153 
154  errno = 0;
155 
156  double fval = strtod( CurText(), &tmp );
157 
158  if( errno )
159  {
160  wxString error;
161  error.Printf( _( "Invalid floating point number in\nfile: \"%s\"\nline: %d\noffset: %d" ),
162  GetChars( CurSource() ), CurLineNumber(), CurOffset() );
163 
164  THROW_IO_ERROR( error );
165  }
166 
167  if( CurText() == tmp )
168  {
169  wxString error;
170  error.Printf( _( "Missing floating point number in\nfile: \"%s\"\nline: %d\noffset: %d" ),
171  GetChars( CurSource() ), CurLineNumber(), CurOffset() );
172 
173  THROW_IO_ERROR( error );
174  }
175 
176  return fval;
177 }
#define THROW_IO_ERROR(msg)
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:153
#define _(s)
Definition: 3d_actions.cpp:33

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

245  {
246  NeedNUMBER( aExpected );
247  return parseDouble();
248  }
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:150

References parseDouble().

◆ parseDouble() [3/3]

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

Definition at line 250 of file pcb_parser.h.

251  {
252  return parseDouble( GetTokenText( aToken ) );
253  }
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:150
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 1996 of file pcb_parser.cpp.

1997 {
1998  wxCHECK_MSG( CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
1999  CurTok() == T_gr_rect || CurTok() == T_gr_line || CurTok() == T_gr_poly, NULL,
2000  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as DRAWSEGMENT." ) );
2001 
2002  T token;
2003  wxPoint pt;
2004  std::unique_ptr< DRAWSEGMENT > segment( new DRAWSEGMENT( NULL ) );
2005 
2006  switch( CurTok() )
2007  {
2008  case T_gr_arc:
2009  segment->SetShape( S_ARC );
2010  NeedLEFT();
2011  token = NextTok();
2012 
2013  // the start keyword actually gives the arc center
2014  // Allows also T_center for future change
2015  if( token != T_start && token != T_center )
2016  Expecting( T_start );
2017 
2018  pt.x = parseBoardUnits( "X coordinate" );
2019  pt.y = parseBoardUnits( "Y coordinate" );
2020  segment->SetCenter( pt );
2021  NeedRIGHT();
2022  NeedLEFT();
2023  token = NextTok();
2024 
2025  if( token != T_end ) // the end keyword actually gives the starting point of the arc
2026  Expecting( T_end );
2027 
2028  pt.x = parseBoardUnits( "X coordinate" );
2029  pt.y = parseBoardUnits( "Y coordinate" );
2030  segment->SetArcStart( pt );
2031  NeedRIGHT();
2032  break;
2033 
2034  case T_gr_circle:
2035  segment->SetShape( S_CIRCLE );
2036  NeedLEFT();
2037  token = NextTok();
2038 
2039  if( token != T_center )
2040  Expecting( T_center );
2041 
2042  pt.x = parseBoardUnits( "X coordinate" );
2043  pt.y = parseBoardUnits( "Y coordinate" );
2044  segment->SetCenter( pt );
2045  NeedRIGHT();
2046  NeedLEFT();
2047 
2048  token = NextTok();
2049 
2050  if( token != T_end )
2051  Expecting( T_end );
2052 
2053  pt.x = parseBoardUnits( "X coordinate" );
2054  pt.y = parseBoardUnits( "Y coordinate" );
2055  segment->SetEnd( pt );
2056  NeedRIGHT();
2057  break;
2058 
2059  case T_gr_curve:
2060  segment->SetShape( S_CURVE );
2061  NeedLEFT();
2062  token = NextTok();
2063 
2064  if( token != T_pts )
2065  Expecting( T_pts );
2066 
2067  segment->SetStart( parseXY() );
2068  segment->SetBezControl1( parseXY() );
2069  segment->SetBezControl2( parseXY() );
2070  segment->SetEnd( parseXY() );
2071  NeedRIGHT();
2072  break;
2073 
2074  case T_gr_rect:
2075  segment->SetShape( S_RECT );
2076  NeedLEFT();
2077  token = NextTok();
2078 
2079  if( token != T_start )
2080  Expecting( T_start );
2081 
2082  pt.x = parseBoardUnits( "X coordinate" );
2083  pt.y = parseBoardUnits( "Y coordinate" );
2084  segment->SetStart( pt );
2085  NeedRIGHT();
2086  NeedLEFT();
2087  token = NextTok();
2088 
2089  if( token != T_end )
2090  Expecting( T_end );
2091 
2092  pt.x = parseBoardUnits( "X coordinate" );
2093  pt.y = parseBoardUnits( "Y coordinate" );
2094  segment->SetEnd( pt );
2095  NeedRIGHT();
2096  break;
2097 
2098  case T_gr_line:
2099  // Default DRAWSEGMENT type is S_SEGMENT.
2100  NeedLEFT();
2101  token = NextTok();
2102 
2103  if( token != T_start )
2104  Expecting( T_start );
2105 
2106  pt.x = parseBoardUnits( "X coordinate" );
2107  pt.y = parseBoardUnits( "Y coordinate" );
2108  segment->SetStart( pt );
2109  NeedRIGHT();
2110  NeedLEFT();
2111  token = NextTok();
2112 
2113  if( token != T_end )
2114  Expecting( T_end );
2115 
2116  pt.x = parseBoardUnits( "X coordinate" );
2117  pt.y = parseBoardUnits( "Y coordinate" );
2118  segment->SetEnd( pt );
2119  NeedRIGHT();
2120  break;
2121 
2122  case T_gr_poly:
2123  {
2124  segment->SetShape( S_POLYGON );
2125  segment->SetWidth( 0 ); // this is the default value. will be (perhaps) modified later
2126  NeedLEFT();
2127  token = NextTok();
2128 
2129  if( token != T_pts )
2130  Expecting( T_pts );
2131 
2132  std::vector< wxPoint > pts;
2133 
2134  while( (token = NextTok()) != T_RIGHT )
2135  pts.push_back( parseXY() );
2136 
2137  segment->SetPolyPoints( pts );
2138  }
2139  break;
2140 
2141  default:
2142  Expecting( "gr_arc, gr_circle, gr_curve, gr_line, gr_poly, or gp_rect" );
2143  }
2144 
2145  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2146  {
2147  if( token != T_LEFT )
2148  Expecting( T_LEFT );
2149 
2150  token = NextTok();
2151 
2152  switch( token )
2153  {
2154  case T_angle:
2155  segment->SetAngle( parseDouble( "segment angle" ) * 10.0 );
2156  break;
2157 
2158  case T_layer:
2159  segment->SetLayer( parseBoardItemLayer() );
2160  break;
2161 
2162  case T_width:
2163  segment->SetWidth( parseBoardUnits( T_width ) );
2164  break;
2165 
2166  case T_tstamp:
2167  NextTok();
2168  const_cast<KIID&>( segment->m_Uuid ) = KIID( CurStr() );
2169  break;
2170 
2171  case T_status:
2172  segment->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
2173  break;
2174 
2175  default:
2176  Expecting( "layer, width, tstamp, or status" );
2177  }
2178 
2179  NeedRIGHT();
2180  }
2181 
2182  // Only filled polygons may have a zero-line width
2183  // This is not permitted in KiCad but some external tools generate invalid
2184  // files.
2185  // However in custom pad shapes, zero-line width is allowed for filled circles
2186  if( segment->GetShape() != S_POLYGON && segment->GetWidth() == 0 &&
2187  !( segment->GetShape() == S_CIRCLE && aAllowCirclesZeroWidth ) )
2188  {
2189  segment->SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) );
2190  }
2191 
2192  return segment.release();
2193 }
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:232
#define DEFAULT_LINE_WIDTH
T
enum T contains all this lexer's tokens.
int parseBoardUnits()
Definition: pcb_parser.h:255
Definition: common.h:68
segment with non rounded ends
#define NULL
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:150
long parseHex()
Definition: pcb_parser.h:304

References DEFAULT_LINE_WIDTH, NULL, parseDouble(), parseHex(), S_ARC, S_CIRCLE, S_CURVE, S_POLYGON, S_RECT, DRCRULE_T::T_LEFT, DRCRULE_T::T_RIGHT, wxPoint::x, and wxPoint::y.

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

265 {
266  wxCHECK_RET( CurTok() == T_effects,
267  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as EDA_TEXT." ) );
268 
269  T token;
270 
271  // Prior to v5.0 text size was omitted from file format if equal to 60mils
272  // Now, it is always explicitly written to file
273  bool foundTextSize = false;
274 
275  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
276  {
277  if( token == T_LEFT )
278  token = NextTok();
279 
280  switch( token )
281  {
282  case T_font:
283  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
284  {
285  if( token == T_LEFT )
286  continue;
287 
288  switch( token )
289  {
290  case T_size:
291  {
292  wxSize sz;
293  sz.SetHeight( parseBoardUnits( "text height" ) );
294  sz.SetWidth( parseBoardUnits( "text width" ) );
295  aText->SetTextSize( sz );
296  NeedRIGHT();
297 
298  foundTextSize = true;
299  }
300  break;
301 
302  case T_thickness:aText->SetTextThickness( parseBoardUnits( "text thickness" ));
303  NeedRIGHT();
304  break;
305 
306  case T_bold:
307  aText->SetBold( true );
308  break;
309 
310  case T_italic:
311  aText->SetItalic( true );
312  break;
313 
314  default:
315  Expecting( "size, bold, or italic" );
316  }
317  }
318  break;
319 
320  case T_justify:
321  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
322  {
323  if( token == T_LEFT )
324  continue;
325 
326  switch( token )
327  {
328  case T_left:
330  break;
331 
332  case T_right:
334  break;
335 
336  case T_top:
338  break;
339 
340  case T_bottom:
342  break;
343 
344  case T_mirror:
345  aText->SetMirrored( true );
346  break;
347 
348  default:
349  Expecting( "left, right, top, bottom, or mirror" );
350  }
351 
352  }
353  break;
354 
355  case T_hide:
356  aText->SetVisible( false );
357  break;
358 
359  default:
360  Expecting( "font, justify, or hide" );
361  }
362  }
363 
364  // Text size was not specified in file, force legacy default units
365  // 60mils is 1.524mm
366  if( !foundTextSize )
367  {
368  const double defaultTextSize = 1.524 * IU_PER_MM;
369 
370  aText->SetTextSize( wxSize( defaultTextSize, defaultTextSize ) );
371  }
372 }
void SetMirrored(bool isMirrored)
Definition: eda_text.h:187
void SetItalic(bool isItalic)
Definition: eda_text.h:178
void SetVisible(bool aVisible)
Definition: eda_text.h:184
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:237
T
enum T contains all this lexer's tokens.
int parseBoardUnits()
Definition: pcb_parser.h:255
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:202
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:201
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:157
void SetBold(bool aBold)
Definition: eda_text.h:181

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::SetTextThickness(), EDA_TEXT::SetVertJustify(), EDA_TEXT::SetVisible(), DRCRULE_T::T_LEFT, and DRCRULE_T::T_RIGHT.

◆ parseEDGE_MODULE()

EDGE_MODULE * PCB_PARSER::parseEDGE_MODULE ( )
private

Definition at line 2819 of file pcb_parser.cpp.

2820 {
2821  wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
2822  CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly, NULL,
2823  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as EDGE_MODULE." ) );
2824 
2825  wxPoint pt;
2826  T token;
2827 
2828  std::unique_ptr< EDGE_MODULE > segment( new EDGE_MODULE( NULL ) );
2829 
2830  switch( CurTok() )
2831  {
2832  case T_fp_arc:
2833  segment->SetShape( S_ARC );
2834  NeedLEFT();
2835  token = NextTok();
2836 
2837  // the start keyword actually gives the arc center
2838  // Allows also T_center for future change
2839  if( token != T_start && token != T_center )
2840  Expecting( T_start );
2841 
2842  pt.x = parseBoardUnits( "X coordinate" );
2843  pt.y = parseBoardUnits( "Y coordinate" );
2844  segment->SetStart0( pt );
2845  NeedRIGHT();
2846  NeedLEFT();
2847  token = NextTok();
2848 
2849  if( token != T_end ) // end keyword actually gives the starting point of the arc
2850  Expecting( T_end );
2851 
2852  pt.x = parseBoardUnits( "X coordinate" );
2853  pt.y = parseBoardUnits( "Y coordinate" );
2854  segment->SetEnd0( pt );
2855  NeedRIGHT();
2856  NeedLEFT();
2857  token = NextTok();
2858 
2859  if( token != T_angle )
2860  Expecting( T_angle );
2861 
2862  segment->SetAngle( parseDouble( "segment angle" ) * 10.0 );
2863  NeedRIGHT();
2864  break;
2865 
2866  case T_fp_circle:
2867  segment->SetShape( S_CIRCLE );
2868  NeedLEFT();
2869  token = NextTok();
2870 
2871  if( token != T_center )
2872  Expecting( T_center );
2873 
2874  pt.x = parseBoardUnits( "X coordinate" );
2875  pt.y = parseBoardUnits( "Y coordinate" );
2876  segment->SetStart0( pt );
2877  NeedRIGHT();
2878  NeedLEFT();
2879  token = NextTok();
2880 
2881  if( token != T_end )
2882  Expecting( T_end );
2883 
2884  pt.x = parseBoardUnits( "X coordinate" );
2885  pt.y = parseBoardUnits( "Y coordinate" );
2886  segment->SetEnd0( pt );
2887  NeedRIGHT();
2888  break;
2889 
2890  case T_fp_curve:
2891  segment->SetShape( S_CURVE );
2892  NeedLEFT();
2893  token = NextTok();
2894 
2895  if( token != T_pts )
2896  Expecting( T_pts );
2897 
2898  segment->SetStart0( parseXY() );
2899  segment->SetBezier0_C1( parseXY() );
2900  segment->SetBezier0_C2( parseXY() );
2901  segment->SetEnd0( parseXY() );
2902  NeedRIGHT();
2903  break;
2904 
2905  case T_fp_rect:
2906  segment->SetShape( S_RECT );
2907  NeedLEFT();
2908  token = NextTok();
2909 
2910  if( token != T_start )
2911  Expecting( T_start );
2912 
2913  pt.x = parseBoardUnits( "X coordinate" );
2914  pt.y = parseBoardUnits( "Y coordinate" );
2915  segment->SetStart0( pt );
2916 
2917  NeedRIGHT();
2918  NeedLEFT();
2919  token = NextTok();
2920 
2921  if( token != T_end )
2922  Expecting( T_end );
2923 
2924  pt.x = parseBoardUnits( "X coordinate" );
2925  pt.y = parseBoardUnits( "Y coordinate" );
2926  segment->SetEnd0( pt );
2927  NeedRIGHT();
2928  break;
2929 
2930  case T_fp_line:
2931  // Default DRAWSEGMENT type is S_SEGMENT.
2932  NeedLEFT();
2933  token = NextTok();
2934 
2935  if( token != T_start )
2936  Expecting( T_start );
2937 
2938  pt.x = parseBoardUnits( "X coordinate" );
2939  pt.y = parseBoardUnits( "Y coordinate" );
2940  segment->SetStart0( pt );
2941 
2942  NeedRIGHT();
2943  NeedLEFT();
2944  token = NextTok();
2945 
2946  if( token != T_end )
2947  Expecting( T_end );
2948 
2949  pt.x = parseBoardUnits( "X coordinate" );
2950  pt.y = parseBoardUnits( "Y coordinate" );
2951  segment->SetEnd0( pt );
2952  NeedRIGHT();
2953  break;
2954 
2955  case T_fp_poly:
2956  {
2957  segment->SetShape( S_POLYGON );
2958  NeedLEFT();
2959  token = NextTok();
2960 
2961  if( token != T_pts )
2962  Expecting( T_pts );
2963 
2964  std::vector< wxPoint > pts;
2965 
2966  while( (token = NextTok()) != T_RIGHT )
2967  pts.push_back( parseXY() );
2968 
2969  segment->SetPolyPoints( pts );
2970  }
2971  break;
2972 
2973  default:
2974  Expecting( "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, or fp_rect" );
2975  }
2976 
2977  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2978  {
2979  if( token != T_LEFT )
2980  Expecting( T_LEFT );
2981 
2982  token = NextTok();
2983 
2984  switch( token )
2985  {
2986  case T_layer:
2987  segment->SetLayer( parseBoardItemLayer() );
2988  break;
2989 
2990  case T_width:
2991  segment->SetWidth( parseBoardUnits( T_width ) );
2992  break;
2993 
2994  case T_tstamp:
2995  NextTok();
2996  const_cast<KIID&>( segment->m_Uuid ) = KIID( CurStr() );
2997  break;
2998 
2999  case T_status:
3000  segment->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
3001  break;
3002 
3003  default:
3004  Expecting( "layer or width" );
3005  }
3006 
3007  NeedRIGHT();
3008  }
3009 
3010  // Only filled polygons may have a zero-line width
3011  // This is not permitted in KiCad but some external tools generate invalid
3012  // files.
3013  if( segment->GetShape() != S_POLYGON && segment->GetWidth() == 0 )
3014  segment->SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) );
3015 
3016  return segment.release();
3017 }
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:232
#define DEFAULT_LINE_WIDTH
T
enum T contains all this lexer's tokens.
int parseBoardUnits()
Definition: pcb_parser.h:255
Definition: common.h:68
segment with non rounded ends
#define NULL
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:150
long parseHex()
Definition: pcb_parser.h:304

References DEFAULT_LINE_WIDTH, NULL, parseDouble(), parseHex(), S_ARC, S_CIRCLE, S_CURVE, S_POLYGON, S_RECT, DRCRULE_T::T_LEFT, DRCRULE_T::T_RIGHT, wxPoint::x, and wxPoint::y.

◆ parseGeneralSection()

void PCB_PARSER::parseGeneralSection ( )
private

Definition at line 750 of file pcb_parser.cpp.

751 {
752  wxCHECK_RET( CurTok() == T_general,
753  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
754  wxT( " as a general section." ) );
755 
756  T token;
757 
758  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
759  {
760  if( token != T_LEFT )
761  Expecting( T_LEFT );
762 
763  token = NextTok();
764 
765  switch( token )
766  {
767  case T_thickness:
769  NeedRIGHT();
770  break;
771 
772  case T_nets:
773  m_netCodes.resize( parseInt( "nets number" ) );
774  NeedRIGHT();
775  break;
776 
777  case T_no_connects:
778  // ignore
779  parseInt( "no connect count" );
780  NeedRIGHT();
781  break;
782 
783  default: // Skip everything but the board thickness.
784  //wxLogDebug( wxT( "Skipping general section token %s " ), GetChars( GetTokenString( token ) ) );
785 
786  while( ( token = NextTok() ) != T_RIGHT )
787  {
788  if( !IsSymbol( token ) && token != T_NUMBER )
789  Expecting( "symbol or number" );
790  }
791  }
792  }
793 }
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:551
T
enum T contains all this lexer's tokens.
void SetBoardThickness(int aThickness)
int parseBoardUnits()
Definition: pcb_parser.h:255
std::vector< int > m_netCodes
net codes mapping for boards being loaded
Definition: pcb_parser.h:78
BOARD * m_board
Definition: pcb_parser.h:74
int parseInt()
Definition: pcb_parser.h:293

References parseInt(), DRCRULE_T::T_LEFT, DRCRULE_T::T_NUMBER, and DRCRULE_T::T_RIGHT.

◆ parseHeader()

void PCB_PARSER::parseHeader ( )
private

Definition at line 714 of file pcb_parser.cpp.

715 {
716  wxCHECK_RET( CurTok() == T_kicad_pcb,
717  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a header." ) );
718 
719  NeedLEFT();
720 
721  T tok = NextTok();
722  if( tok == T_version )
723  {
724  m_requiredVersion = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
726  NeedRIGHT();
727 
728  // Skip the host name and host build version information.
729  NeedLEFT();
730  NeedSYMBOL();
731  NeedSYMBOL();
732  NeedSYMBOL();
733  NeedRIGHT();
734  }
735  else
736  {
739 
740  // Skip the host name and host build version information.
741  NeedSYMBOL();
742  NeedSYMBOL();
743  NeedRIGHT();
744  }
745 
747 }
void SetFileFormatVersionAtLoad(int aVersion)
Definition: class_board.h:319
#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:79
T
enum T contains all this lexer's tokens.
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:80
BOARD * m_board
Definition: pcb_parser.h:74
int parseInt()
Definition: pcb_parser.h:293

References parseInt(), SEXPR_BOARD_FILE_VERSION, and DRCRULE_T::T_version.

◆ parseHex()

long PCB_PARSER::parseHex ( )
inlineprivate

Definition at line 304 of file pcb_parser.h.

305  {
306  NextTok();
307  return strtol( CurText(), NULL, 16 );
308  }
#define NULL

References NULL.

◆ parseInt() [1/2]

int PCB_PARSER::parseInt ( )
inlineprivate

Definition at line 293 of file pcb_parser.h.

294  {
295  return (int)strtol( CurText(), NULL, 10 );
296  }
#define NULL

References NULL.

Referenced by parseInt().

◆ parseInt() [2/2]

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

Definition at line 298 of file pcb_parser.h.

299  {
300  NeedNUMBER( aExpected );
301  return parseInt();
302  }
int parseInt()
Definition: pcb_parser.h:293

References parseInt().

◆ parseLayer()

void PCB_PARSER::parseLayer ( LAYER aLayer)
private

Definition at line 960 of file pcb_parser.cpp.

961 {
962  T token;
963 
964  std::string name;
965  std::string type;
966  bool isVisible = true;
967 
968  aLayer->clear();
969 
970  if( CurTok() != T_LEFT )
971  Expecting( T_LEFT );
972 
973  // this layer_num is not used, we DO depend on LAYER_T however.
974  LAYER_NUM layer_num = parseInt( "layer index" );
975 
976  NeedSYMBOLorNUMBER();
977  name = CurText();
978 
979  NeedSYMBOL();
980  type = CurText();
981 
982  token = NextTok();
983 
984  if( token == T_hide )
985  {
986  isVisible = false;
987  NeedRIGHT();
988  }
989  else if( token != T_RIGHT )
990  {
991  Expecting( "hide or )" );
992  }
993 
994  aLayer->m_name = FROM_UTF8( name.c_str() );
995  aLayer->m_type = LAYER::ParseType( type.c_str() );
996  aLayer->m_number = layer_num;
997  aLayer->m_visible = isVisible;
998 }
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:114
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
T
enum T contains all this lexer's tokens.
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:60
int m_number
Definition: class_board.h:109
int parseInt()
Definition: pcb_parser.h:293

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

◆ parseLayers()

void PCB_PARSER::parseLayers ( )
private

Definition at line 1247 of file pcb_parser.cpp.

1248 {
1249  wxCHECK_RET( CurTok() == T_layers,
1250  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as layers." ) );
1251 
1252  T token;
1253  LSET visibleLayers;
1254  LSET enabledLayers;
1255  int copperLayerCount = 0;
1256  LAYER layer;
1257  bool anyHidden = false;
1258 
1259  std::unordered_map< std::string, std::string > v3_layer_names;
1260  std::vector<LAYER> cu;
1261 
1262  createOldLayerMapping( v3_layer_names );
1263 
1264  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1265  {
1266  parseLayer( &layer );
1267 
1268  if( layer.m_type == LT_UNDEFINED ) // it's a non-copper layer
1269  break;
1270 
1271  cu.push_back( layer ); // it's copper
1272  }
1273 
1274  // All Cu layers are parsed, but not the non-cu layers here.
1275 
1276  // The original *.kicad_pcb file format and the inverted
1277  // Cu stack format both have all the Cu layers first, so use this
1278  // trick to handle either. The layer number in the (layers ..)
1279  // s-expression element are ignored.
1280  if( cu.size() )
1281  {
1282  // Rework the layer numbers, which changed when the Cu stack
1283  // was flipped. So we instead use position in the list.
1284  cu[cu.size()-1].m_number = B_Cu;
1285 
1286  for( unsigned i=0; i < cu.size()-1; ++i )
1287  {
1288  cu[i].m_number = i;
1289  }
1290 
1291  for( std::vector<LAYER>::const_iterator it = cu.begin(); it<cu.end(); ++it )
1292  {
1293  enabledLayers.set( it->m_number );
1294 
1295  if( it->m_visible )
1296  visibleLayers.set( it->m_number );
1297  else
1298  anyHidden = true;
1299 
1300  m_board->SetLayerDescr( PCB_LAYER_ID( it->m_number ), *it );
1301 
1302  UTF8 name = it->m_name;
1303 
1304  m_layerIndices[ name ] = PCB_LAYER_ID( it->m_number );
1305  m_layerMasks[ name ] = LSET( PCB_LAYER_ID( it->m_number ) );
1306  }
1307 
1308  copperLayerCount = cu.size();
1309  }
1310 
1311  // process non-copper layers
1312  while( token != T_RIGHT )
1313  {
1314  LAYER_ID_MAP::const_iterator it = m_layerIndices.find( UTF8( layer.m_name ) );
1315 
1316  if( it == m_layerIndices.end() )
1317  {
1318  auto new_layer_it = v3_layer_names.find( layer.m_name.ToStdString() );
1319 
1320  if( new_layer_it != v3_layer_names.end() )
1321  it = m_layerIndices.find( new_layer_it->second );
1322 
1323  if( it == m_layerIndices.end() )
1324  {
1325  wxString error = wxString::Format(
1326  _( "Layer \"%s\" in file \"%s\" at line %d, is not in fixed layer hash" ),
1327  GetChars( layer.m_name ),
1328  GetChars( CurSource() ),
1329  CurLineNumber(),
1330  CurOffset()
1331  );
1332 
1333  THROW_IO_ERROR( error );
1334  }
1335 
1336  // If we are here, then we have found a translated layer name. Put it in the maps so that
1337  // items on this layer get the appropriate layer ID number
1338  m_layerIndices[ UTF8( layer.m_name ) ] = it->second;
1339  m_layerMasks[ UTF8( layer.m_name ) ] = it->second;
1340  layer.m_name = it->first;
1341  }
1342 
1343  layer.m_number = it->second;
1344  enabledLayers.set( layer.m_number );
1345 
1346  if( layer.m_visible )
1347  visibleLayers.set( layer.m_number );
1348  else
1349  anyHidden = true;
1350 
1351  m_board->SetLayerDescr( it->second, layer );
1352 
1353  token = NextTok();
1354 
1355  if( token != T_LEFT )
1356  break;
1357 
1358  parseLayer( &layer );
1359  }
1360 
1361  // We need at least 2 copper layers and there must be an even number of them.
1362  if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
1363  {
1364  wxString err = wxString::Format(
1365  _( "%d is not a valid layer count" ), copperLayerCount );
1366 
1367  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
1368  }
1369 
1370  m_board->SetCopperLayerCount( copperLayerCount );
1371  m_board->SetEnabledLayers( enabledLayers );
1372 
1373  // Only set this if any layers were explicitly marked as hidden. Otherwise, we want to leave
1374  // this alone; default visibility will show everything
1375  if( anyHidden )
1376  m_board->m_LegacyVisibleLayers = visibleLayers;
1377 }
UTF8 is an 8 bit string that is assuredly encoded in UTF8, and supplies special conversion support to...
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...
void SetCopperLayerCount(int aCount)
T
enum T contains all this lexer's tokens.
PCB_LAYER_ID
A quick note on layer IDs:
LSET is a set of PCB_LAYER_IDs.
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)
void parseLayer(LAYER *aLayer)
Definition: pcb_parser.cpp:960
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:153
const char * name
Definition: DXF_plotter.cpp:60
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
LAYER holds information pertinent to a layer of a BOARD.
Definition: class_board.h:80
#define _(s)
Definition: 3d_actions.cpp:33
BOARD * m_board
Definition: pcb_parser.h:74
LAYER_ID_MAP m_layerIndices
map layer name to it's index
Definition: pcb_parser.h:75
int m_number
Definition: class_board.h:109
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition: class_board.h:296
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:76

References _, B_Cu, Format(), GetChars(), LT_UNDEFINED, LAYER::m_name, LAYER::m_number, LAYER::m_type, LAYER::m_visible, name, DRCRULE_T::T_LEFT, DRCRULE_T::T_RIGHT, THROW_IO_ERROR, and THROW_PARSE_ERROR.

◆ parseMARKER()

MARKER_PCB* PCB_PARSER::parseMARKER ( BOARD_ITEM_CONTAINER aParent)
private

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

2430 {
2431  try
2432  {
2433  return parseMODULE_unchecked( aInitialComments );
2434  }
2435  catch( const PARSE_ERROR& parse_error )
2436  {
2437  if( m_tooRecent )
2438  throw FUTURE_FORMAT_ERROR( parse_error, GetRequiredVersion() );
2439  else
2440  throw;
2441  }
2442 }
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:79
wxString GetRequiredVersion()
Return a string representing the version of kicad required to open this file.
Definition: pcb_parser.cpp:208
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 2445 of file pcb_parser.cpp.

2446 {
2447  wxCHECK_MSG( CurTok() == T_module, NULL,
2448  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as MODULE." ) );
2449 
2450  wxString name;
2451  wxPoint pt;
2452  T token;
2453  LIB_ID fpid;
2454 
2455  std::unique_ptr<MODULE> module( new MODULE( m_board ) );
2456 
2457  module->SetInitialComments( aInitialComments );
2458 
2459  token = NextTok();
2460 
2461  if( !IsSymbol( token ) && token != T_NUMBER )
2462  Expecting( "symbol|number" );
2463 
2464  name = FromUTF8();
2465 
2466  if( !name.IsEmpty() && fpid.Parse( name, LIB_ID::ID_PCB, true ) >= 0 )
2467  {
2468  wxString error;
2469  error.Printf( _( "Invalid footprint ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
2470  GetChars( CurSource() ), CurLineNumber(), CurOffset() );
2471  THROW_IO_ERROR( error );
2472  }
2473 
2474  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2475  {
2476  if( token == T_LEFT )
2477  token = NextTok();
2478 
2479  switch( token )
2480  {
2481  case T_version:
2482  {
2483  // Theoretically a module nested in a PCB could declare its own version, though
2484  // as of writing this comment we don't do that. Just in case, take the greater
2485  // version.
2486  int this_version = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
2487  NeedRIGHT();
2488  m_requiredVersion = std::max( m_requiredVersion, this_version );
2490  break;
2491  }
2492 
2493  case T_locked:
2494  module->SetLocked( true );
2495  break;
2496 
2497  case T_placed:
2498  module->SetIsPlaced( true );
2499  break;
2500 
2501  case T_layer:
2502  {
2503  // Footprints can be only on the front side or the back side.
2504  // but because we can find some stupid layer in file, ensure a
2505  // acceptable layer is set for the footprint
2507  module->SetLayer( layer == B_Cu ? B_Cu : F_Cu );
2508  }
2509  NeedRIGHT();
2510  break;
2511 
2512  case T_tedit:
2513  module->SetLastEditTime( parseHex() );
2514  NeedRIGHT();
2515  break;
2516 
2517  case T_tstamp:
2518  NextTok();
2519  const_cast<KIID&>( module->m_Uuid ) = KIID( CurStr() );
2520  NeedRIGHT();
2521  break;
2522 
2523  case T_at:
2524  pt.x = parseBoardUnits( "X coordinate" );
2525  pt.y = parseBoardUnits( "Y coordinate" );
2526  module->SetPosition( pt );
2527  token = NextTok();
2528 
2529  if( token == T_NUMBER )
2530  {
2531  module->SetOrientation( parseDouble() * 10.0 );
2532  NeedRIGHT();
2533  }
2534  else if( token != T_RIGHT )
2535  {
2536  Expecting( T_RIGHT );
2537  }
2538 
2539  break;
2540 
2541  case T_descr:
2542  NeedSYMBOLorNUMBER(); // some symbols can be 0508, so a number is also a symbol here
2543  module->SetDescription( FromUTF8() );
2544  NeedRIGHT();
2545  break;
2546 
2547  case T_tags:
2548  NeedSYMBOLorNUMBER(); // some symbols can be 0508, so a number is also a symbol here
2549  module->SetKeywords( FromUTF8() );
2550  NeedRIGHT();
2551  break;
2552 
2553  case T_path:
2554  NeedSYMBOLorNUMBER(); // Paths can be numerical so a number is also a symbol here
2555  module->SetPath( KIID_PATH( FromUTF8() ) );
2556  NeedRIGHT();
2557  break;
2558 
2559  case T_autoplace_cost90:
2560  module->SetPlacementCost90( parseInt( "auto place cost at 90 degrees" ) );
2561  NeedRIGHT();
2562  break;
2563 
2564  case T_autoplace_cost180:
2565  module->SetPlacementCost180( parseInt( "auto place cost at 180 degrees" ) );
2566  NeedRIGHT();
2567  break;
2568 
2569  case T_solder_mask_margin:
2570  module->SetLocalSolderMaskMargin( parseBoardUnits( "local solder mask margin value" ) );
2571  NeedRIGHT();
2572  break;
2573 
2574  case T_solder_paste_margin:
2575  module->SetLocalSolderPasteMargin(
2576  parseBoardUnits( "local solder paste margin value" ) );
2577  NeedRIGHT();
2578  break;
2579 
2580  case T_solder_paste_ratio:
2581  module->SetLocalSolderPasteMarginRatio(
2582  parseDouble( "local solder paste margin ratio value" ) );
2583  NeedRIGHT();
2584  break;
2585 
2586  case T_clearance:
2587  module->SetLocalClearance( parseBoardUnits( "local clearance value" ) );
2588  NeedRIGHT();
2589  break;
2590 
2591  case T_zone_connect:
2592  module->SetZoneConnection( (ZONE_CONNECTION) parseInt( "zone connection value" ) );
2593  NeedRIGHT();
2594  break;
2595 
2596  case T_thermal_width:
2597  module->SetThermalWidth( parseBoardUnits( "thermal width value" ) );
2598  NeedRIGHT();
2599  break;
2600 
2601  case T_thermal_gap:
2602  module->SetThermalGap( parseBoardUnits( "thermal gap value" ) );
2603  NeedRIGHT();
2604  break;
2605 
2606  case T_attr:
2607  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2608  {
2609  switch( token )
2610  {
2611  case T_smd:
2612  module->SetAttributes( module->GetAttributes() | MOD_CMS );
2613  break;
2614 
2615  case T_virtual:
2616  module->SetAttributes( module->GetAttributes() | MOD_VIRTUAL );
2617  break;
2618 
2619  default:
2620  Expecting( "smd and/or virtual" );
2621  }
2622  }
2623  break;
2624 
2625  case T_fp_text:
2626  {
2627  TEXTE_MODULE* text = parseTEXTE_MODULE();
2628  text->SetParent( module.get() );
2629  double orientation = text->GetTextAngle();
2630  orientation -= module->GetOrientation();
2631  text->SetTextAngle( orientation );
2632  text->SetDrawCoord();
2633 
2634  switch( text->GetType() )
2635  {
2637  module->Reference() = *text;
2638  delete text;
2639  break;
2640 
2642  module->Value() = *text;
2643  delete text;
2644  break;
2645 
2646  default:
2647  module->Add( text, ADD_MODE::APPEND );
2648  }
2649  }
2650  break;
2651 
2652  case T_fp_arc:
2653  {
2654  EDGE_MODULE* em = parseEDGE_MODULE();
2655 
2656  // Drop 0 and NaN angles as these can corrupt/crash the schematic
2657  if( std::isnormal( em->GetAngle() ) )
2658  {
2659  em->SetParent( module.get() );
2660  em->SetDrawCoord();
2661  module->Add( em, ADD_MODE::APPEND );
2662  }
2663  else
2664  delete em;
2665  }
2666 
2667  break;
2668 
2669  case T_fp_circle:
2670  case T_fp_curve:
2671  case T_fp_rect:
2672  case T_fp_line:
2673  case T_fp_poly:
2674  {
2675  EDGE_MODULE* em = parseEDGE_MODULE();
2676  em->SetParent( module.get() );
2677  em->SetDrawCoord();
2678  module->Add( em, ADD_MODE::APPEND );
2679  }
2680 
2681  break;
2682 
2683  case T_pad:
2684  {
2685  D_PAD* pad = parseD_PAD( module.get() );
2686  pt = pad->GetPos0();
2687 
2688  RotatePoint( &pt, module->GetOrientation() );
2689  pad->SetPosition( pt + module->GetPosition() );
2690  module->Add( pad, ADD_MODE::APPEND );
2691  }
2692 
2693  break;
2694 
2695  case T_model:
2696  module->Add3DModel( parse3DModel() );
2697  break;
2698 
2699  case T_zone:
2700  {
2701  ZONE_CONTAINER* zone = parseZONE_CONTAINER( module.get() );
2702  module->Add( zone, ADD_MODE::APPEND );
2703  }
2704  break;
2705 
2706  default:
2707  Expecting(
2708  "locked, placed, tedit, tstamp, at, descr, tags, path, "
2709  "autoplace_cost90, autoplace_cost180, solder_mask_margin, "
2710  "solder_paste_margin, solder_paste_ratio, clearance, "
2711  "zone_connect, thermal_width, thermal_gap, attr, fp_text, "
2712  "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, fp_rect, pad, "
2713  "zone, or model" );
2714  }
2715  }
2716 
2717  module->SetFPID( fpid );
2718  module->CalculateBoundingBox();
2719 
2720  return module.release();
2721 }
ZONE_CONNECTION
How pads are covered by copper in zone.
Definition: zones.h:41
ZONE_CONTAINER handles a list of polygons defining a copper zone.
Definition: class_zone.h:61
const wxPoint & GetPos0() const
Definition: class_pad.h:215
Set for modules listed in the automatic insertion list (usually SMD footprints)
Definition: class_module.h:68
#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:173
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:156
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:79
T
enum T contains all this lexer's tokens.
void RotatePoint(int *pX, int *pY, double angle)
Definition: trigo.cpp:208
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
virtual void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:196
int parseBoardUnits()
Definition: pcb_parser.h:255
Definition: common.h:68
PCB_LAYER_ID
A quick note on layer IDs:
#define NULL
TEXT_TYPE GetType() const
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
ZONE_CONTAINER * parseZONE_CONTAINER(BOARD_ITEM_CONTAINER *aParent)
#define THROW_IO_ERROR(msg)
void SetTextAngle(double aAngle) override
double GetAngle() const
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:80
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:153
EDGE_MODULE * parseEDGE_MODULE()
const char * name
Definition: DXF_plotter.cpp:60
#define _(s)
Definition: 3d_actions.cpp:33
BOARD * m_board
Definition: pcb_parser.h:74
Virtual component: when created by copper shapes on board (Like edge card connectors,...
Definition: class_module.h:70
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:150
TEXTE_MODULE * parseTEXTE_MODULE()
D_PAD * parseD_PAD(MODULE *aParent=NULL)
long parseHex()
Definition: pcb_parser.h:304
int parseInt()
Definition: pcb_parser.h:293
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:375

References _, APPEND, B_Cu, F_Cu, DRAWSEGMENT::GetAngle(), GetChars(), D_PAD::GetPos0(), EDA_TEXT::GetTextAngle(), TEXTE_MODULE::GetType(), LIB_ID::ID_PCB, MOD_CMS, MOD_VIRTUAL, name, NULL, 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, DRCRULE_T::T_LEFT, DRCRULE_T::T_NUMBER, DRCRULE_T::T_RIGHT, DRCRULE_T::T_version, TEXTE_MODULE::TEXT_is_REFERENCE, TEXTE_MODULE::TEXT_is_VALUE, THROW_IO_ERROR, wxPoint::x, and wxPoint::y.

◆ parseNETCLASS()

void PCB_PARSER::parseNETCLASS ( )
private

Definition at line 1913 of file pcb_parser.cpp.

1914 {
1915  wxCHECK_RET( CurTok() == T_net_class,
1916  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as net class." ) );
1917 
1918  T token;
1919 
1920  NETCLASSPTR nc = std::make_shared<NETCLASS>( wxEmptyString );
1921 
1922  // Read netclass name (can be a name or just a number like track width)
1923  NeedSYMBOLorNUMBER();
1924  nc->SetName( FromUTF8() );
1925  NeedSYMBOL();
1926  nc->SetDescription( FromUTF8() );
1927 
1928  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1929  {
1930  if( token != T_LEFT )
1931  Expecting( T_LEFT );
1932 
1933  token = NextTok();
1934 
1935  switch( token )
1936  {
1937  case T_clearance:
1938  nc->SetClearance( parseBoardUnits( T_clearance ) );
1939  break;
1940 
1941  case T_trace_width:
1942  nc->SetTrackWidth( parseBoardUnits( T_trace_width ) );
1943  break;
1944 
1945  case T_via_dia:
1946  nc->SetViaDiameter( parseBoardUnits( T_via_dia ) );
1947  break;
1948 
1949  case T_via_drill:
1950  nc->SetViaDrill( parseBoardUnits( T_via_drill ) );
1951  break;
1952 
1953  case T_uvia_dia:
1954  nc->SetuViaDiameter( parseBoardUnits( T_uvia_dia ) );
1955  break;
1956 
1957  case T_uvia_drill:
1958  nc->SetuViaDrill( parseBoardUnits( T_uvia_drill ) );
1959  break;
1960 
1961  case T_diff_pair_width:
1962  nc->SetDiffPairWidth( parseBoardUnits( T_diff_pair_width ) );
1963  break;
1964 
1965  case T_diff_pair_gap:
1966  nc->SetDiffPairGap( parseBoardUnits( T_diff_pair_gap ) );
1967  break;
1968 
1969  case T_add_net:
1970  NeedSYMBOLorNUMBER();
1971  nc->Add( FromUTF8() );
1972  break;
1973 
1974  default:
1975  Expecting( "clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, diff_pair_width, diff_pair_gap or add_net" );
1976  }
1977 
1978  NeedRIGHT();
1979  }
1980 
1981  if( !m_board->GetDesignSettings().GetNetClasses().Add( nc ) )
1982  {
1983  // Must have been a name conflict, this is a bad board file.
1984  // User may have done a hand edit to the file.
1985 
1986  // unique_ptr will delete nc on this code path
1987 
1988  wxString error;
1989  error.Printf( _( "Duplicate NETCLASS name \"%s\" in file \"%s\" at line %d, offset %d" ),
1990  nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(), CurOffset() );
1991  THROW_IO_ERROR( error );
1992  }
1993 }
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:551
T
enum T contains all this lexer's tokens.
int parseBoardUnits()
Definition: pcb_parser.h:255
NETCLASSES & GetNetClasses() const
#define THROW_IO_ERROR(msg)
bool Add(const NETCLASSPTR &aNetclass)
Function Add takes aNetclass and puts it into this NETCLASSES container.
Definition: netclass.cpp:90
#define _(s)
Definition: 3d_actions.cpp:33
BOARD * m_board
Definition: pcb_parser.h:74

References _, DRCRULE_T::T_LEFT, DRCRULE_T::T_RIGHT, and THROW_IO_ERROR.

◆ parseNETINFO_ITEM()

void PCB_PARSER::parseNETINFO_ITEM ( )
private

Definition at line 1887 of file pcb_parser.cpp.

1888 {
1889  wxCHECK_RET( CurTok() == T_net,
1890  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as net." ) );
1891 
1892  int netCode = parseInt( "net number" );
1893 
1894  NeedSYMBOLorNUMBER();
1895  wxString name = FromUTF8();
1896 
1897  NeedRIGHT();
1898 
1899  // net 0 should be already in list, so store this net
1900  // if it is not the net 0, or if the net 0 does not exists.
1901  // (TODO: a better test.)
1903  {
1904  NETINFO_ITEM* net = new NETINFO_ITEM( m_board, name, netCode );
1905  m_board->Add( net );
1906 
1907  // Store the new code mapping
1908  pushValueIntoMap( netCode, net->GetNet() );
1909  }
1910 }
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_MODE::INSERT) override
Adds an item to the container.
NETINFO_ITEM handles the data for a net.
Definition: netinfo.h:65
const char * name
Definition: DXF_plotter.cpp:60
int GetNet() const
Function GetNet.
Definition: netinfo.h:223
BOARD * m_board
Definition: pcb_parser.h:74
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:138
int parseInt()
Definition: pcb_parser.h:293
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:476

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

◆ parsePAGE_INFO()

void PCB_PARSER::parsePAGE_INFO ( )
private

Definition at line 796 of file pcb_parser.cpp.

797 {
798  wxCHECK_RET( ( CurTok() == T_page && m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
799  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a PAGE_INFO." ) );
800 
801  T token;
802  PAGE_INFO pageInfo;
803 
804  NeedSYMBOL();
805 
806  wxString pageType = FromUTF8();
807 
808  if( !pageInfo.SetType( pageType ) )
809  {
810  wxString err;
811  err.Printf( _( "Page type \"%s\" is not valid " ), GetChars( FromUTF8() ) );
812  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
813  }
814 
815  if( pageType == PAGE_INFO::Custom )
816  {
817  double width = parseDouble( "width" ); // width in mm
818 
819  // Perform some controls to avoid crashes if the size is edited by hands
820  if( width < 100.0 )
821  width = 100.0;
822  else if( width > 1200.0 )
823  width = 1200.0;
824 
825  double height = parseDouble( "height" ); // height in mm
826 
827  if( height < 100.0 )
828  height = 100.0;
829  else if( height > 1200.0 )
830  height = 1200.0;
831 
832  pageInfo.SetWidthMils( Mm2mils( width ) );
833  pageInfo.SetHeightMils( Mm2mils( height ) );
834  }
835 
836  token = NextTok();
837 
838  if( token == T_portrait )
839  {
840  pageInfo.SetPortrait( true );
841  NeedRIGHT();
842  }
843  else if( token != T_RIGHT )
844  {
845  Expecting( "portrait|)" );
846  }
847 
848  m_board->SetPageSettings( pageInfo );
849 }
int Mm2mils(double x)
Convert mm to mils.
Definition: base_units.h:62
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: class_board.h:573
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
T
enum T contains all this lexer's tokens.
PAGE_INFO describes the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:54
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
void SetHeightMils(int aHeightInMils)
Definition: page_info.cpp:253
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:80
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:153
#define _(s)
Definition: 3d_actions.cpp:33
BOARD * m_board
Definition: pcb_parser.h:74
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:150
void SetPortrait(bool aIsPortrait)
Function SetPortrait will rotate the paper page 90 degrees.
Definition: page_info.cpp:182

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

◆ parsePCB_TARGET()

PCB_TARGET * PCB_PARSER::parsePCB_TARGET ( )
private

Definition at line 4316 of file pcb_parser.cpp.

4317 {
4318  wxCHECK_MSG( CurTok() == T_target, NULL,
4319  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as PCB_TARGET." ) );
4320 
4321  wxPoint pt;
4322  T token;
4323 
4324  std::unique_ptr< PCB_TARGET > target( new PCB_TARGET( NULL ) );
4325 
4326  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4327  {
4328  if( token == T_LEFT )
4329  token = NextTok();
4330 
4331  switch( token )
4332  {
4333  case T_x:
4334  target->SetShape( 1 );
4335  break;
4336 
4337  case T_plus:
4338  target->SetShape( 0 );
4339  break;
4340 
4341  case T_at:
4342  pt.x = parseBoardUnits( "target x position" );
4343  pt.y = parseBoardUnits( "target y position" );
4344  target->SetPosition( pt );
4345  NeedRIGHT();
4346  break;
4347 
4348  case T_size:
4349  target->SetSize( parseBoardUnits( "target size" ) );
4350  NeedRIGHT();
4351  break;
4352 
4353  case T_width:
4354  target->SetWidth( parseBoardUnits( "target thickness" ) );
4355  NeedRIGHT();
4356  break;
4357 
4358  case T_layer:
4359  target->SetLayer( parseBoardItemLayer() );
4360  NeedRIGHT();
4361  break;
4362 
4363  case T_tstamp:
4364  NextTok();
4365  const_cast<KIID&>( target->m_Uuid ) = KIID( CurStr() );
4366  NeedRIGHT();
4367  break;
4368 
4369  default:
4370  Expecting( "x, plus, at, size, width, layer or tstamp" );
4371  }
4372  }
4373 
4374  return target.release();
4375 }
T
enum T contains all this lexer's tokens.
int parseBoardUnits()
Definition: pcb_parser.h:255
Definition: common.h:68
#define NULL
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.

References NULL, DRCRULE_T::T_LEFT, DRCRULE_T::T_RIGHT, wxPoint::x, and wxPoint::y.

◆ parseSetup()

void PCB_PARSER::parseSetup ( )
private

Definition at line 1438 of file pcb_parser.cpp.

1439 {
1440  wxCHECK_RET( CurTok() == T_setup,
1441  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as setup." ) );
1442 
1443  T token;
1444  NETCLASS* defaultNetClass = m_board->GetDesignSettings().GetDefault();
1445  BOARD_DESIGN_SETTINGS& designSettings = m_board->GetDesignSettings();
1446  ZONE_SETTINGS& zoneSettings = designSettings.GetDefaultZoneSettings();
1447 
1448  // Missing soldermask min width value means that the user has set the value to 0 and
1449  // not the default value (0.25mm)
1450  designSettings.m_SolderMaskMinWidth = 0;
1451 
1452  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1453  {
1454  if( token != T_LEFT )
1455  Expecting( T_LEFT );
1456 
1457  token = NextTok();
1458 
1459  switch( token )
1460  {
1461  case T_stackup:
1463  break;
1464 
1465  case T_last_trace_width: // not used now
1466  /* lastTraceWidth =*/ parseBoardUnits( T_last_trace_width );
1467  NeedRIGHT();
1468  break;
1469 
1470  case T_user_trace_width:
1471  designSettings.m_TrackWidthList.push_back( parseBoardUnits( T_user_trace_width ) );
1473  NeedRIGHT();
1474  break;
1475 
1476  case T_trace_clearance:
1477  defaultNetClass->SetClearance( parseBoardUnits( T_trace_clearance ) );
1479  NeedRIGHT();
1480  break;
1481 
1482  case T_zone_clearance:
1483  zoneSettings.m_ZoneClearance = parseBoardUnits( T_zone_clearance );
1485  NeedRIGHT();
1486  break;
1487 
1488  case T_zone_45_only:
1489  zoneSettings.m_Zone_45_Only = parseBool();
1491  NeedRIGHT();
1492  break;
1493 
1494  case T_clearance_min:
1495  designSettings.m_MinClearance = parseBoardUnits( T_clearance_min );
1497  NeedRIGHT();
1498  break;
1499 
1500  case T_trace_min:
1501  designSettings.m_TrackMinWidth = parseBoardUnits( T_trace_min );
1503  NeedRIGHT();
1504  break;
1505 
1506  case T_via_size:
1507  defaultNetClass->SetViaDiameter( parseBoardUnits( T_via_size ) );
1509  NeedRIGHT();
1510  break;
1511 
1512  case T_via_drill:
1513  defaultNetClass->SetViaDrill( parseBoardUnits( T_via_drill ) );
1515  NeedRIGHT();
1516  break;
1517 
1518  case T_via_min_annulus:
1519  designSettings.m_ViasMinAnnulus = parseBoardUnits( T_via_min_annulus );
1521  NeedRIGHT();
1522  break;
1523 
1524  case T_via_min_size:
1525  designSettings.m_ViasMinSize = parseBoardUnits( T_via_min_size );
1527  NeedRIGHT();
1528  break;
1529 
1530  case T_through_hole_min:
1531  designSettings.m_MinThroughDrill = parseBoardUnits( T_through_hole_min );
1533  NeedRIGHT();
1534  break;
1535 
1536  // Legacy token for T_through_hole_min
1537  case T_via_min_drill:
1538  designSettings.m_MinThroughDrill = parseBoardUnits( T_via_min_drill );
1540  NeedRIGHT();
1541  break;
1542 
1543  case T_hole_to_hole_min:
1544  designSettings.m_HoleToHoleMin = parseBoardUnits( T_hole_to_hole_min );
1546  NeedRIGHT();
1547  break;
1548 
1549  case T_user_via:
1550  {
1551  int viaSize = parseBoardUnits( "user via size" );
1552  int viaDrill = parseBoardUnits( "user via drill" );
1553  designSettings.m_ViasDimensionsList.emplace_back( VIA_DIMENSION( viaSize, viaDrill ) );
1555  NeedRIGHT();
1556  }
1557  break;
1558 
1559  case T_uvia_size:
1560  defaultNetClass->SetuViaDiameter( parseBoardUnits( T_uvia_size ) );
1562  NeedRIGHT();
1563  break;
1564 
1565  case T_uvia_drill:
1566  defaultNetClass->SetuViaDrill( parseBoardUnits( T_uvia_drill ) );
1568  NeedRIGHT();
1569  break;
1570 
1571  case T_uvias_allowed:
1572  designSettings.m_MicroViasAllowed = parseBool();
1574  NeedRIGHT();
1575  break;
1576 
1577  case T_blind_buried_vias_allowed:
1578  designSettings.m_BlindBuriedViaAllowed = parseBool();
1580  NeedRIGHT();
1581  break;
1582 
1583  case T_uvia_min_size:
1584  designSettings.m_MicroViasMinSize = parseBoardUnits( T_uvia_min_size );
1586  NeedRIGHT();
1587  break;
1588 
1589  case T_uvia_min_drill:
1590  designSettings.m_MicroViasMinDrill = parseBoardUnits( T_uvia_min_drill );
1592  NeedRIGHT();
1593  break;
1594 
1595  case T_user_diff_pair:
1596  {
1597  int width = parseBoardUnits( "user diff-pair width" );
1598  int gap = parseBoardUnits( "user diff-pair gap" );
1599  int viaGap = parseBoardUnits( "user diff-pair via gap" );
1600  designSettings.m_DiffPairDimensionsList.emplace_back( DIFF_PAIR_DIMENSION( width, gap, viaGap ) );
1602  NeedRIGHT();
1603  }
1604  break;
1605 
1606  case T_segment_width: // note: legacy (pre-6.0) token
1607  designSettings.m_LineThickness[ LAYER_CLASS_COPPER ] = parseBoardUnits( T_segment_width );
1609  NeedRIGHT();
1610  break;
1611 
1612  case T_edge_width: // note: legacy (pre-6.0) token
1613  designSettings.m_LineThickness[ LAYER_CLASS_EDGES ] = parseBoardUnits( T_edge_width );
1615  NeedRIGHT();
1616  break;
1617 
1618  case T_mod_edge_width: // note: legacy (pre-6.0) token
1619  designSettings.m_LineThickness[ LAYER_CLASS_SILK ] = parseBoardUnits( T_mod_edge_width );
1621  NeedRIGHT();
1622  break;
1623 
1624  case T_pcb_text_width: // note: legacy (pre-6.0) token
1625  designSettings.m_TextThickness[ LAYER_CLASS_COPPER ] = parseBoardUnits( T_pcb_text_width );
1627  NeedRIGHT();
1628  break;
1629 
1630  case T_mod_text_width: // note: legacy (pre-6.0) token
1631  designSettings.m_TextThickness[ LAYER_CLASS_SILK ] = parseBoardUnits( T_mod_text_width );
1633  NeedRIGHT();
1634  break;
1635 
1636  case T_pcb_text_size: // note: legacy (pre-6.0) token
1637  designSettings.m_TextSize[ LAYER_CLASS_COPPER ].x = parseBoardUnits( "pcb text width" );
1638  designSettings.m_TextSize[ LAYER_CLASS_COPPER ].y = parseBoardUnits( "pcb text height" );
1640  NeedRIGHT();
1641  break;
1642 
1643  case T_mod_text_size: // note: legacy (pre-6.0) token
1644  designSettings.m_TextSize[ LAYER_CLASS_SILK ].x = parseBoardUnits( "module text width" );
1645  designSettings.m_TextSize[ LAYER_CLASS_SILK ].y = parseBoardUnits( "module text height" );
1647  NeedRIGHT();
1648  break;
1649 
1650  case T_defaults:
1651  parseDefaults( designSettings );
1653  break;
1654 
1655  case T_pad_size:
1656  {
1657  wxSize sz;
1658  sz.SetWidth( parseBoardUnits( "master pad width" ) );
1659  sz.SetHeight( parseBoardUnits( "master pad height" ) );
1660  designSettings.m_Pad_Master.SetSize( sz );
1662  NeedRIGHT();
1663  }
1664  break;
1665 
1666  case T_pad_drill:
1667  {
1668  int drillSize = parseBoardUnits( T_pad_drill );
1669  designSettings.m_Pad_Master.SetDrillSize( wxSize( drillSize, drillSize ) );
1671  NeedRIGHT();
1672  }
1673  break;
1674 
1675  case T_pad_to_mask_clearance:
1676  designSettings.m_SolderMaskMargin = parseBoardUnits( T_pad_to_mask_clearance );
1678  NeedRIGHT();
1679  break;
1680 
1681  case T_solder_mask_min_width:
1682  designSettings.m_SolderMaskMinWidth = parseBoardUnits( T_solder_mask_min_width );
1684  NeedRIGHT();
1685  break;
1686 
1687  case T_pad_to_paste_clearance:
1688  designSettings.m_SolderPasteMargin = parseBoardUnits( T_pad_to_paste_clearance );
1690  NeedRIGHT();
1691  break;
1692 
1693  case T_pad_to_paste_clearance_ratio:
1694  designSettings.m_SolderPasteMarginRatio = parseDouble( T_pad_to_paste_clearance_ratio );
1696  NeedRIGHT();
1697  break;
1698 
1699  case T_aux_axis_origin:
1700  {
1701  int x = parseBoardUnits( "auxiliary origin X" );
1702  int y = parseBoardUnits( "auxiliary origin Y" );
1703  designSettings.m_AuxOrigin = wxPoint( x, y );
1704  // Aux origin still stored in board for the moment
1705  //m_board->m_LegacyDesignSettingsLoaded = true;
1706  NeedRIGHT();
1707  }
1708  break;
1709 
1710  case T_grid_origin:
1711  {
1712  int x = parseBoardUnits( "grid origin X" );
1713  int y = parseBoardUnits( "grid origin Y" );
1714  designSettings.m_GridOrigin = wxPoint( x, y );
1715  // Grid origin still stored in board for the moment
1716  //m_board->m_LegacyDesignSettingsLoaded = true;
1717  NeedRIGHT();
1718  }
1719  break;
1720 
1721  // Stored in board prior to 6.0
1722  case T_visible_elements:
1723  {
1724  m_board->m_LegacyVisibleItems.reset();
1725 
1726  int visible = parseHex() | MIN_VISIBILITY_MASK;
1727 
1728  for( size_t i = 0; i < sizeof( int ) * CHAR_BIT; i++ )
1729  m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
1730 
1731  NeedRIGHT();
1732  }
1733  break;
1734 
1735  case T_max_error:
1736  designSettings.m_MaxError = parseBoardUnits( T_max_error );
1738  NeedRIGHT();
1739  break;
1740 
1741  case T_filled_areas_thickness:
1742  designSettings.m_ZoneUseNoOutlineInFill = not parseBool();
1744  NeedRIGHT();
1745  break;
1746 
1747  case T_pcbplotparams:
1748  {
1749  PCB_PLOT_PARAMS plotParams;
1750  PCB_PLOT_PARAMS_PARSER parser( reader );
1751  // parser must share the same current line as our current PCB parser
1752  // synchronize it.
1753  parser.SyncLineReaderWith( *this );
1754 
1755  plotParams.Parse( &parser );
1756  SyncLineReaderWith( parser );
1757 
1758  m_board->SetPlotOptions( plotParams );
1759  }
1760  break;
1761 
1762  default:
1763  Unexpected( CurText() );
1764  }
1765  }
1766 }
int m_SolderMaskMargin
Solder mask margin.
Struct VIA_DIMENSION is a small helper container to handle a stock of specific vias each with unique ...
wxPoint m_GridOrigin
origin for grid offsets
bool m_LegacyDesignSettingsLoaded
True if the legacy board design settings were loaded from a file.
Definition: class_board.h:300
int m_SolderPasteMargin
Solder paste margin absolute value.
PCB_PLOT_PARAMS_PARSER is the parser class for PCB_PLOT_PARAMS.
std::vector< int > m_TrackWidthList
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
void parseBoardStackup()
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Function GetDesignSettings.
Definition: class_board.h:551
void SetDrillSize(const wxSize &aSize)
Definition: class_pad.h:226
T
enum T contains all this lexer's tokens.
Struct DIFF_PAIR_DIMENSION is a small helper container to handle a stock of specific differential pai...
void SetViaDrill(int aSize)
Definition: netclass.h:175
int parseBoardUnits()
Definition: pcb_parser.h:255
wxSize m_TextSize[LAYER_CLASS_COUNT]
bool parseBool()
Definition: pcb_parser.cpp:180
int m_TextThickness[LAYER_CLASS_COUNT]
#define MIN_VISIBILITY_MASK
void SetClearance(int aClearance)
Definition: netclass.h:166
NETCLASS handles a collection of nets and the parameters used to route or test these nets.
Definition: netclass.h:49
void SetSize(const wxSize &aSize)
Definition: class_pad.h:220
int m_ZoneClearance
Minimal clearance value.
Definition: zone_settings.h:83
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
void SetPlotOptions(const PCB_PLOT_PARAMS &aOptions)
Definition: class_board.h:576
void SetuViaDiameter(int aSize)
Definition: netclass.h:178
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)
ZONE_SETTINGS handles zones parameters.
Definition: zone_settings.h:67
void SetuViaDrill(int aSize)
Definition: netclass.h:181
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:74
D_PAD m_Pad_Master
A dummy pad to store all default parameters.
NETCLASS * GetDefault() const
Function GetDefault.
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:150
void SetViaDiameter(int aDia)
Definition: netclass.h:172
ZONE_SETTINGS & GetDefaultZoneSettings()
bool m_MicroViasAllowed
true to allow micro vias
long parseHex()
Definition: pcb_parser.h:304
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.
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
GAL_SET m_LegacyVisibleItems
Definition: class_board.h:297

References BOARD_DESIGN_SETTINGS::GetDefaultZoneSettings(), 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_HoleToHoleMin, 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_MinClearance, BOARD_DESIGN_SETTINGS::m_MinThroughDrill, 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_ViasMinAnnulus, 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(), NETCLASS::SetClearance(), D_PAD::SetDrillSize(), D_PAD::SetSize(), NETCLASS::SetuViaDiameter(), NETCLASS::SetuViaDrill(), NETCLASS::SetViaDiameter(), NETCLASS::SetViaDrill(), DRCRULE_T::T_LEFT, and DRCRULE_T::T_RIGHT.

◆ parseTEXTE_MODULE()

TEXTE_MODULE * PCB_PARSER::parseTEXTE_MODULE ( )
private

Definition at line 2724 of file pcb_parser.cpp.

2725 {
2726  wxCHECK_MSG( CurTok() == T_fp_text, NULL,
2727  wxString::Format( wxT( "Cannot parse %s as TEXTE_MODULE at line %d, offset %d." ),
2728  GetChars( GetTokenString( CurTok() ) ),
2729  CurLineNumber(), CurOffset() ) );
2730 
2731  T token = NextTok();
2732 
2733  std::unique_ptr<TEXTE_MODULE> text( new TEXTE_MODULE( NULL ) );
2734 
2735  switch( token )
2736  {
2737  case T_reference:
2738  text->SetType( TEXTE_MODULE::TEXT_is_REFERENCE );
2739  break;
2740 
2741  case T_value:
2742  text->SetType( TEXTE_MODULE::TEXT_is_VALUE );
2743  break;
2744 
2745  case T_user:
2746  break; // Default type is user text.
2747 
2748  default:
2749  THROW_IO_ERROR( wxString::Format( _( "Cannot handle footprint text type %s" ),
2750  GetChars( FromUTF8() ) ) );
2751  }
2752 
2753  NeedSYMBOLorNUMBER();
2754 
2755  wxString value = FromUTF8();
2756  value.Replace( "%V", "${VALUE}" );
2757  value.Replace( "%R", "${REFERENCE}" );
2758  text->SetText( value );
2759  NeedLEFT();
2760  token = NextTok();
2761 
2762  if( token != T_at )
2763  Expecting( T_at );
2764 
2765  wxPoint pt;
2766 
2767  pt.x = parseBoardUnits( "X coordinate" );
2768  pt.y = parseBoardUnits( "Y coordinate" );
2769  text->SetPos0( pt );
2770 
2771  NextTok();
2772 
2773  if( CurTok() == T_NUMBER )
2774  {
2775  text->SetTextAngle( parseDouble() * 10.0 );
2776  NextTok();
2777  }
2778 
2779  if( CurTok() == T_unlocked )
2780  {
2781  text->SetKeepUpright( false );
2782  NextTok();
2783  }
2784 
2785  if( CurTok() != T_RIGHT )
2786  {
2787  Unexpected( CurText() );
2788  }
2789 
2790  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2791  {
2792  if( token == T_LEFT )
2793  token = NextTok();
2794 
2795  switch( token )
2796  {
2797  case T_layer:
2798  text->SetLayer( parseBoardItemLayer() );
2799  NeedRIGHT();
2800  break;
2801 
2802  case T_hide:
2803  text->SetVisible( false );
2804  break;
2805 
2806  case T_effects:
2807  parseEDA_TEXT( (EDA_TEXT*) text.get() );
2808  break;
2809 
2810  default:
2811  Expecting( "hide or effects" );
2812  }
2813  }
2814 
2815  return text.release();
2816 }
void parseEDA_TEXT(EDA_TEXT *aText)
Function parseEDA_TEXT parses the common settings for any object derived from EDA_TEXT.
Definition: pcb_parser.cpp:264
T
enum T contains all this lexer's tokens.
int parseBoardUnits()
Definition: pcb_parser.h:255
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:112
#define NULL
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
#define THROW_IO_ERROR(msg)
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:153
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
#define _(s)
Definition: 3d_actions.cpp:33
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:150

References _, Format(), GetChars(), NULL, parseDouble(), DRCRULE_T::T_LEFT, DRCRULE_T::T_NUMBER, DRCRULE_T::T_RIGHT, TEXTE_MODULE::TEXT_is_REFERENCE, TEXTE_MODULE::TEXT_is_VALUE, THROW_IO_ERROR, wxPoint::x, and wxPoint::y.

◆ parseTEXTE_PCB()

TEXTE_PCB * PCB_PARSER::parseTEXTE_PCB ( )
private

Definition at line 2196 of file pcb_parser.cpp.

2197 {
2198  wxCHECK_MSG( CurTok() == T_gr_text, NULL,
2199  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as TEXTE_PCB." ) );
2200 
2201  T token;
2202 
2203  std::unique_ptr<TEXTE_PCB> text( new TEXTE_PCB( m_board ) );
2204  NeedSYMBOLorNUMBER();
2205 
2206  text->SetText( FromUTF8() );
2207  NeedLEFT();
2208  token = NextTok();
2209 
2210  if( token != T_at )
2211  Expecting( T_at );
2212 
2213  wxPoint pt;
2214 
2215  pt.x = parseBoardUnits( "X coordinate" );
2216  pt.y = parseBoardUnits( "Y coordinate" );
2217  text->SetTextPos( pt );
2218 
2219  // If there is no orientation defined, then it is the default value of 0 degrees.
2220  token = NextTok();
2221 
2222  if( token == T_NUMBER )
2223  {
2224  text->SetTextAngle( parseDouble() * 10.0 );
2225  NeedRIGHT();
2226  }
2227  else if( token != T_RIGHT )
2228  {
2229  Unexpected( CurText() );
2230  }
2231 
2232  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2233  {
2234  if( token != T_LEFT )
2235  Expecting( T_LEFT );
2236 
2237  token = NextTok();
2238 
2239  switch( token )
2240  {
2241  case T_layer:
2242  text->SetLayer( parseBoardItemLayer() );
2243  NeedRIGHT();
2244  break;
2245 
2246  case T_tstamp:
2247  NextTok();
2248  const_cast<KIID&>( text->m_Uuid ) = KIID( CurStr() );
2249  NeedRIGHT();
2250  break;
2251 
2252  case T_effects:
2253  parseEDA_TEXT( (EDA_TEXT*) text.get() );
2254  break;
2255 
2256  default:
2257  Expecting( "layer, tstamp or effects" );
2258  }
2259  }
2260 
2261  return text.release();
2262 }
void parseEDA_TEXT(EDA_TEXT *aText)
Function parseEDA_TEXT parses the common settings for any object derived from EDA_TEXT.
Definition: pcb_parser.cpp:264
T
enum T contains all this lexer's tokens.
int parseBoardUnits()
Definition: pcb_parser.h:255
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:112
Definition: common.h:68
#define NULL
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
BOARD * m_board
Definition: pcb_parser.h:74
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:150

References NULL, parseDouble(), DRCRULE_T::T_LEFT, DRCRULE_T::T_NUMBER, DRCRULE_T::T_RIGHT, wxPoint::x, and wxPoint::y.

◆ parseTITLE_BLOCK()

void PCB_PARSER::parseTITLE_BLOCK ( )
private

Definition at line 852 of file pcb_parser.cpp.

853 {
854  wxCHECK_RET( CurTok() == T_title_block,
855  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
856  wxT( " as TITLE_BLOCK." ) );
857 
858  T token;
859  TITLE_BLOCK titleBlock;
860 
861  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
862  {
863  if( token != T_LEFT )
864  Expecting( T_LEFT );
865 
866  token = NextTok();
867 
868  switch( token )
869  {
870  case T_title:
871  NextTok();
872  titleBlock.SetTitle( FromUTF8() );
873  break;
874 
875  case T_date:
876  NextTok();
877  titleBlock.SetDate( FromUTF8() );
878  break;
879 
880  case T_rev:
881  NextTok();
882  titleBlock.SetRevision( FromUTF8() );
883  break;
884 
885  case T_company:
886  NextTok();
887  titleBlock.SetCompany( FromUTF8() );
888  break;
889 
890  case T_comment:
891  {
892  int commentNumber = parseInt( "comment" );
893 
894  switch( commentNumber )
895  {
896  case 1:
897  NextTok();
898  titleBlock.SetComment( 0, FromUTF8() );
899  break;
900 
901  case 2:
902  NextTok();
903  titleBlock.SetComment( 1, FromUTF8() );
904  break;
905 
906  case 3:
907  NextTok();
908  titleBlock.SetComment( 2, FromUTF8() );
909  break;
910 
911  case 4:
912  NextTok();
913  titleBlock.SetComment( 3, FromUTF8() );
914  break;
915 
916  case 5:
917  NextTok();
918  titleBlock.SetComment( 4, FromUTF8() );
919  break;
920 
921  case 6:
922  NextTok();
923  titleBlock.SetComment( 5, FromUTF8() );
924  break;
925 
926  case 7:
927  NextTok();
928  titleBlock.SetComment( 6, FromUTF8() );
929  break;
930 
931  case 8:
932  NextTok();
933  titleBlock.SetComment( 7, FromUTF8() );
934  break;
935 
936  case 9:
937  NextTok();
938  titleBlock.SetComment( 8, FromUTF8() );
939  break;
940 
941  default:
942  wxString err;
943  err.Printf( wxT( "%d is not a valid title block comment number" ), commentNumber );
944  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
945  }
946  }
947  break;
948 
949  default:
950  Expecting( "title, date, rev, company, or comment" );
951  }
952 
953  NeedRIGHT();
954  }
955 
956  m_board->SetTitleBlock( titleBlock );
957 }
void SetRevision(const wxString &aRevision)
Definition: title_block.h:84
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition: class_board.h:579
void SetDate(const wxString &aDate)
Function SetDate sets the date field, and defaults to the current time and date.
Definition: title_block.h:74
T
enum T contains all this lexer's tokens.
TITLE_BLOCK holds the information shown in the lower right corner of a plot, printout,...
Definition: title_block.h:40
void SetComment(int aIdx, const wxString &aComment)
Definition: title_block.h:104
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
BOARD * m_board
Definition: pcb_parser.h:74
int parseInt()
Definition: pcb_parser.h:293

References parseInt(), TITLE_BLOCK::SetComment(), TITLE_BLOCK::SetCompany(), TITLE_BLOCK::SetDate(), TITLE_BLOCK::SetRevision(), TITLE_BLOCK::SetTitle(), DRCRULE_T::T_LEFT, DRCRULE_T::T_RIGHT, and THROW_PARSE_ERROR.

◆ parseTRACK()

TRACK * PCB_PARSER::parseTRACK ( )
private

Definition at line 3613 of file pcb_parser.cpp.

3614 {
3615  wxCHECK_MSG( CurTok() == T_segment, NULL,
3616  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as TRACK." ) );
3617 
3618  wxPoint pt;
3619  T token;
3620 
3621  std::unique_ptr< TRACK > track( new TRACK( m_board ) );
3622 
3623  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3624  {
3625  if( token != T_LEFT )
3626  Expecting( T_LEFT );
3627 
3628  token = NextTok();
3629 
3630  switch( token )
3631  {
3632  case T_start:
3633  pt.x = parseBoardUnits( "start x" );
3634  pt.y = parseBoardUnits( "start y" );
3635  track->SetStart( pt );
3636  break;
3637 
3638  case T_end:
3639  pt.x = parseBoardUnits( "end x" );
3640  pt.y = parseBoardUnits( "end y" );
3641  track->SetEnd( pt );
3642  break;
3643 
3644  case T_width:
3645  track->SetWidth( parseBoardUnits( "width" ) );
3646  break;
3647 
3648  case T_layer:
3649  track->SetLayer( parseBoardItemLayer() );
3650  break;
3651 
3652  case T_net:
3653  if( ! track->SetNetCode( getNetCode( parseInt( "net number" ) ), /* aNoAssert */ true ) )
3655  wxString::Format( _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
3656  GetChars( CurSource() ), CurLineNumber(), CurOffset() )
3657  );
3658  break;
3659 
3660  case T_tstamp:
3661  NextTok();
3662  const_cast<KIID&>( track->m_Uuid ) = KIID( CurStr() );
3663  break;
3664 
3665  case T_status:
3666  track->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
3667  break;
3668 
3669  default:
3670  Expecting( "start, end, width, layer, net, tstamp, or status" );
3671  }
3672 
3673  NeedRIGHT();
3674  }
3675 
3676  return track.release();
3677 }
T
enum T contains all this lexer's tokens.
int parseBoardUnits()
Definition: pcb_parser.h:255
Definition: common.h:68
#define NULL
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
#define THROW_IO_ERROR(msg)
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:153
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
#define _(s)
Definition: 3d_actions.cpp:33
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:86
BOARD * m_board
Definition: pcb_parser.h:74
long parseHex()
Definition: pcb_parser.h:304
int parseInt()
Definition: pcb_parser.h:293

References _, Format(), GetChars(), NULL, parseHex(), parseInt(), DRCRULE_T::T_LEFT, DRCRULE_T::T_RIGHT, THROW_IO_ERROR, TRACK, wxPoint::x, and wxPoint::y.

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

196 {
197  if( NextTok() != T_version )
198  Expecting( GetTokenText( T_version ) );
199 
200  int pcb_version = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
201 
202  NeedRIGHT();
203 
204  return pcb_version;
205 }
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:293

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

◆ parseVIA()

VIA * PCB_PARSER::parseVIA ( )
private

Definition at line 3680 of file pcb_parser.cpp.

3681 {
3682  wxCHECK_MSG( CurTok() == T_via, NULL,
3683  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as VIA." ) );
3684 
3685  wxPoint pt;
3686  T token;
3687 
3688  std::unique_ptr< VIA > via( new VIA( m_board ) );
3689 
3690  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3691  {
3692  if( token == T_LEFT )
3693  token = NextTok();
3694 
3695  switch( token )
3696  {
3697  case T_blind:
3698  via->SetViaType( VIATYPE::BLIND_BURIED );
3699  break;
3700 
3701  case T_micro:
3702  via->SetViaType( VIATYPE::MICROVIA );
3703  break;
3704 
3705  case T_at:
3706  pt.x = parseBoardUnits( "start x" );
3707  pt.y = parseBoardUnits( "start y" );
3708  via->SetStart( pt );
3709  via->SetEnd( pt );
3710  NeedRIGHT();
3711  break;
3712 
3713  case T_size:
3714  via->SetWidth( parseBoardUnits( "via width" ) );
3715  NeedRIGHT();
3716  break;
3717 
3718  case T_drill:
3719  via->SetDrill( parseBoardUnits( "drill diameter" ) );
3720  NeedRIGHT();
3721  break;
3722 
3723  case T_layers:
3724  {
3725  PCB_LAYER_ID layer1, layer2;
3726  NextTok();
3727  layer1 = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
3728  NextTok();
3729  layer2 = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
3730  via->SetLayerPair( layer1, layer2 );
3731  NeedRIGHT();
3732  }
3733  break;
3734 
3735  case T_net:
3736  if(! via->SetNetCode( getNetCode( parseInt( "net number" ) ), /* aNoAssert */ true))
3738  wxString::Format( _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
3739  GetChars( CurSource() ), CurLineNumber(), CurOffset() )
3740  );
3741  NeedRIGHT();
3742  break;
3743 
3744  case T_tstamp:
3745  NextTok();
3746  const_cast<KIID&>( via->m_Uuid ) = KIID( CurStr() );
3747  NeedRIGHT();
3748  break;
3749 
3750  case T_status:
3751  via->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
3752  NeedRIGHT();
3753  break;
3754 
3755  default:
3756  Expecting( "blind, micro, at, size, drill, layers, net, tstamp, or status" );
3757  }
3758  }
3759 
3760  return via.release();
3761 }
T
enum T contains all this lexer's tokens.
int parseBoardUnits()
Definition: pcb_parser.h:255
Definition: common.h:68
PCB_LAYER_ID
A quick note on layer IDs:
#define NULL
#define THROW_IO_ERROR(msg)
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:153
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
#define _(s)
Definition: 3d_actions.cpp:33
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:86
BOARD * m_board
Definition: pcb_parser.h:74
LAYER_ID_MAP m_layerIndices
map layer name to it's index
Definition: pcb_parser.h:75
long parseHex()
Definition: pcb_parser.h:304
int parseInt()
Definition: pcb_parser.h:293

References _, BLIND_BURIED, Format(), GetChars(), MICROVIA, NULL, parseHex(), parseInt(), DRCRULE_T::T_LEFT, DRCRULE_T::T_RIGHT, THROW_IO_ERROR, VIA, wxPoint::x, and wxPoint::y.

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

233 {
234  if( CurTok() != T_LEFT )
235  NeedLEFT();
236 
237  wxPoint pt;
238  T token = NextTok();
239 
240  if( token != T_xy )
241  Expecting( T_xy );
242 
243  pt.x = parseBoardUnits( "X coordinate" );
244  pt.y = parseBoardUnits( "Y coordinate" );
245 
246  NeedRIGHT();
247 
248  return pt;
249 }
T
enum T contains all this lexer's tokens.
int parseBoardUnits()
Definition: pcb_parser.h:255

References DRCRULE_T::T_LEFT, wxPoint::x, and wxPoint::y.

◆ parseXY() [2/2]

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

Definition at line 252 of file pcb_parser.cpp.

253 {
254  wxPoint pt = parseXY();
255 
256  if( aX )
257  *aX = pt.x;
258 
259  if( aY )
260  *aY = pt.y;
261 }
wxPoint parseXY()
Function parseXY parses a coordinate pair (xy X Y) in board units (mm).
Definition: pcb_parser.cpp:232

References wxPoint::x, and wxPoint::y.

◆ parseZONE_CONTAINER()

ZONE_CONTAINER * PCB_PARSER::parseZONE_CONTAINER ( BOARD_ITEM_CONTAINER aParent)
private

Definition at line 3764 of file pcb_parser.cpp.

3765 {
3766  wxCHECK_MSG( CurTok() == T_zone, NULL,
3767  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
3768  wxT( " as ZONE_CONTAINER." ) );
3769 
3771 
3772  int hatchPitch = ZONE_CONTAINER::GetDefaultHatchPitch();
3773  wxPoint pt;
3774  T token;
3775  int tmp;
3776  wxString netnameFromfile; // the zone net name find in file
3777 
3778  // bigger scope since each filled_polygon is concatenated in here
3779  std::map<PCB_LAYER_ID, SHAPE_POLY_SET> pts;
3780  bool inModule = false;
3781  PCB_LAYER_ID filledLayer;
3782  bool addedFilledPolygons = false;
3783 
3784  if( dynamic_cast<MODULE*>( aParent ) ) // The zone belongs a footprint
3785  inModule = true;
3786 
3787  std::unique_ptr<ZONE_CONTAINER> zone( inModule ?
3788  new MODULE_ZONE_CONTAINER( aParent ) :
3789  new ZONE_CONTAINER( aParent ) );
3790 
3791  zone->SetPriority( 0 );
3792 
3793  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3794  {
3795  if( token == T_LEFT )
3796  token = NextTok();
3797 
3798  switch( token )
3799  {
3800  case T_net:
3801  // Init the net code only, not the netname, to be sure
3802  // the zone net name is the name read in file.
3803  // (When mismatch, the user will be prompted in DRC, to fix the actual name)
3804  tmp = getNetCode( parseInt( "net number" ) );
3805 
3806  if( tmp < 0 )
3807  tmp = 0;
3808 
3809  if( ! zone->SetNetCode( tmp, /* aNoAssert */ true ) )
3811  wxString::Format( _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
3812  GetChars( CurSource() ), CurLineNumber(), CurOffset() )
3813  );
3814 
3815  NeedRIGHT();
3816  break;
3817 
3818  case T_net_name:
3819  NeedSYMBOLorNUMBER();
3820  netnameFromfile = FromUTF8();
3821  NeedRIGHT();
3822  break;
3823 
3824  case T_layer: // keyword for zones that are on only one layer
3825  zone->SetLayer( parseBoardItemLayer() );
3826  NeedRIGHT();
3827  break;
3828 
3829  case T_layers: // keyword for zones that can live on a set of layers
3830  zone->SetLayerSet( parseBoardItemLayersAsMask() );
3831  break;
3832 
3833  case T_tstamp:
3834  NextTok();
3835  const_cast<KIID&>( zone->m_Uuid ) = KIID( CurStr() );
3836  NeedRIGHT();
3837  break;
3838 
3839  case T_hatch:
3840  token = NextTok();
3841 
3842  if( token != T_none && token != T_edge && token != T_full )
3843  Expecting( "none, edge, or full" );
3844 
3845  switch( token )
3846  {
3847  default:
3848  case T_none:
3849  hatchStyle = ZONE_HATCH_STYLE::NO_HATCH;
3850  break;
3851  case T_edge:
3852  hatchStyle = ZONE_HATCH_STYLE::DIAGONAL_EDGE;
3853  break;
3854  case T_full:
3855  hatchStyle = ZONE_HATCH_STYLE::DIAGONAL_FULL;
3856  }
3857 
3858  hatchPitch = parseBoardUnits( "hatch pitch" );
3859  NeedRIGHT();
3860  break;
3861 
3862  case T_priority:
3863  zone->SetPriority( parseInt( "zone priority" ) );
3864  NeedRIGHT();
3865  break;
3866 
3867  case T_connect_pads:
3868  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3869  {
3870  if( token == T_LEFT )
3871  token = NextTok();
3872 
3873  switch( token )
3874  {
3875  case T_yes:
3876  zone->SetPadConnection( ZONE_CONNECTION::FULL );
3877  break;
3878 
3879  case T_no:
3880  zone->SetPadConnection( ZONE_CONNECTION::NONE );
3881  break;
3882 
3883  case T_thru_hole_only:
3884  zone->SetPadConnection( ZONE_CONNECTION::THT_THERMAL );
3885  break;
3886 
3887  case T_clearance:
3888  zone->SetZoneClearance( parseBoardUnits( "zone clearance" ) );
3889  NeedRIGHT();
3890  break;
3891 
3892  default:
3893  Expecting( "yes, no, or clearance" );
3894  }
3895  }
3896 
3897  break;
3898 
3899  case T_min_thickness:
3900  zone->SetMinThickness( parseBoardUnits( T_min_thickness ) );
3901  NeedRIGHT();
3902  break;
3903 
3904  case T_filled_areas_thickness:
3905  zone->SetFilledPolysUseThickness( parseBool() );
3906  NeedRIGHT();
3907  break;
3908 
3909  case T_fill:
3910  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3911  {
3912  if( token == T_LEFT )
3913  token = NextTok();
3914 
3915  switch( token )
3916  {
3917  case T_yes:
3918  zone->SetIsFilled( true );
3919  break;
3920 
3921  case T_mode:
3922  token = NextTok();
3923 
3924  if( token != T_segment && token != T_hatch && token != T_polygon )
3925  Expecting( "segment, hatch or polygon" );
3926 
3927  if( token == T_segment ) // deprecated
3928  {
3929  // SEGMENT fill mode no longer supported. Make sure user is OK with converting them.
3931  {
3932  KIDIALOG dlg( nullptr,
3933  _( "The legacy segment fill mode is no longer supported.\n"
3934  "Convert zones to polygon fills?"),
3935  _( "Legacy Zone Warning" ),
3936  wxYES_NO | wxICON_WARNING );
3937 
3938  dlg.DoNotShowCheckbox( __FILE__, __LINE__ );
3939 
3940  if( dlg.ShowModal() == wxID_NO )
3941  THROW_IO_ERROR( wxT( "CANCEL" ) );
3942 
3943  m_showLegacyZoneWarning = false;
3944  }
3945 
3946  zone->SetFillMode( ZONE_FILL_MODE::POLYGONS );
3947  m_board->SetModified();
3948  }
3949  else if( token == T_hatch )
3950  zone->SetFillMode( ZONE_FILL_MODE::HATCH_PATTERN );
3951  else
3952  zone->SetFillMode( ZONE_FILL_MODE::POLYGONS );
3953  NeedRIGHT();
3954  break;
3955 
3956  case T_hatch_thickness:
3957  zone->SetHatchFillTypeThickness( parseBoardUnits( T_hatch_thickness ) );
3958  NeedRIGHT();
3959  break;
3960 
3961  case T_hatch_gap:
3962  zone->SetHatchFillTypeGap( parseBoardUnits( T_hatch_gap ) );
3963  NeedRIGHT();
3964  break;
3965 
3966  case T_hatch_orientation:
3967  zone->SetHatchFillTypeOrientation( parseDouble( T_hatch_orientation ) );
3968  NeedRIGHT();