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

Classes

struct  GroupInfo
 

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
 
typedef std::unordered_map< wxString, KIIDKIID_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 ()
 
void parseGROUP ()
 
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)
 
std::pair< wxString, wxString > parseProperty ()
 
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...
 
KIID CurStrToKIID ()
 

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_resetKIIDs
 reading into an existing board; reset UUIDs More...
 
KIID_MAP m_resetKIIDMap
 if resetting UUIDs, record new ones to update groups with More...
 
bool m_showLegacyZoneWarning
 
std::vector< GroupInfom_groupInfos
 

Detailed Description

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

Definition at line 70 of file pcb_parser.h.

Member Typedef Documentation

◆ KIID_MAP

typedef std::unordered_map< wxString, KIID > PCB_PARSER::KIID_MAP
private

Definition at line 74 of file pcb_parser.h.

◆ LAYER_ID_MAP

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

Definition at line 72 of file pcb_parser.h.

◆ LSET_MAP

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

Definition at line 73 of file pcb_parser.h.

Constructor & Destructor Documentation

◆ PCB_PARSER()

PCB_PARSER::PCB_PARSER ( LINE_READER aReader = NULL)
inline

Definition at line 345 of file pcb_parser.h.

345  :
346  PCB_LEXER( aReader ),
347  m_board( 0 ),
348  m_resetKIIDs( false )
349  {
350  init();
351  }
BOARD * m_board
Definition: pcb_parser.h:76
void init()
Function init clears and re-establishes m_layerMap with the default layer names.
Definition: pcb_parser.cpp:59
bool m_resetKIIDs
reading into an existing board; reset UUIDs
Definition: pcb_parser.h:83

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

1302 {
1303  // N.B. This mapping only includes Italian, Polish and French as they were the only languages that
1304  // mapped the layer names as of cc2022b1ac739aa673d2a0b7a2047638aa7a47b3 (kicad-i18n) when the
1305  // bug was fixed in KiCad source.
1306 
1307  // Italian
1308  aMap["Adesivo.Retro"] = "B.Adhes";
1309  aMap["Adesivo.Fronte"] = "F.Adhes";
1310  aMap["Pasta.Retro"] = "B.Paste";
1311  aMap["Pasta.Fronte"] = "F.Paste";
1312  aMap["Serigrafia.Retro"] = "B.SilkS";
1313  aMap["Serigrafia.Fronte"] = "F.SilkS";
1314  aMap["Maschera.Retro"] = "B.Mask";
1315  aMap["Maschera.Fronte"] = "F.Mask";
1316  aMap["Grafica"] = "Dwgs.User";
1317  aMap["Commenti"] = "Cmts.User";
1318  aMap["Eco1"] = "Eco1.User";
1319  aMap["Eco2"] = "Eco2.User";
1320  aMap["Contorno.scheda"] = "Edge.Cuts";
1321 
1322  // Polish
1323  aMap["Kleju_Dolna"] = "B.Adhes";
1324  aMap["Kleju_Gorna"] = "F.Adhes";
1325  aMap["Pasty_Dolna"] = "B.Paste";
1326  aMap["Pasty_Gorna"] = "F.Paste";
1327  aMap["Opisowa_Dolna"] = "B.SilkS";
1328  aMap["Opisowa_Gorna"] = "F.SilkS";
1329  aMap["Maski_Dolna"] = "B.Mask";
1330  aMap["Maski_Gorna"] = "F.Mask";
1331  aMap["Rysunkowa"] = "Dwgs.User";
1332  aMap["Komentarzy"] = "Cmts.User";
1333  aMap["ECO1"] = "Eco1.User";
1334  aMap["ECO2"] = "Eco2.User";
1335  aMap["Krawedziowa"] = "Edge.Cuts";
1336 
1337  // French
1338  aMap["Dessous.Adhes"] = "B.Adhes";
1339  aMap["Dessus.Adhes"] = "F.Adhes";
1340  aMap["Dessous.Pate"] = "B.Paste";
1341  aMap["Dessus.Pate"] = "F.Paste";
1342  aMap["Dessous.SilkS"] = "B.SilkS";
1343  aMap["Dessus.SilkS"] = "F.SilkS";
1344  aMap["Dessous.Masque"] = "B.Mask";
1345  aMap["Dessus.Masque"] = "F.Mask";
1346  aMap["Dessin.User"] = "Dwgs.User";
1347  aMap["Contours.Ci"] = "Edge.Cuts";
1348 }

◆ CurStrToKIID()

KIID PCB_PARSER::CurStrToKIID ( )
private

Definition at line 4868 of file pcb_parser.cpp.

4868  {
4869  KIID aid;
4870  if( m_resetKIIDs )
4871  {
4872  aid = KIID();
4873  m_resetKIIDMap.insert( std::make_pair( CurStr(), aid ) );
4874  }
4875  else
4876  {
4877  aid = KIID( CurStr() );
4878  }
4879  return aid;
4880 }
KIID_MAP m_resetKIIDMap
if resetting UUIDs, record new ones to update groups with
Definition: pcb_parser.h:84
Definition: common.h:68
bool m_resetKIIDs
reading into an existing board; reset UUIDs
Definition: pcb_parser.h:83

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

104  {
105  if( ( aNetCode >= 0 ) && ( aNetCode < (int) m_netCodes.size() ) )
106  return m_netCodes[aNetCode];
107 
108  return aNetCode;
109  }
std::vector< int > m_netCodes
net codes mapping for boards being loaded
Definition: pcb_parser.h:80

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

197 {
198  int year, month, day;
199 
200  year = m_requiredVersion / 10000;
201  month = ( m_requiredVersion / 100 ) - ( year * 100 );
202  day = m_requiredVersion - ( year * 10000 ) - ( month * 100 );
203 
204  // wx throws an assertion, not a catchable exception, when the date is invalid.
205  // User input shouldn't give wx asserts, so check manually and throw a proper
206  // error instead
207  if( day <= 0 || month <= 0 || month > 12 ||
208  day > wxDateTime::GetNumberOfDays( (wxDateTime::Month)( month - 1 ), year ) )
209  {
210  wxString err;
211  err.Printf( _( "Cannot interpret date code %d" ), m_requiredVersion );
212  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
213  }
214 
215  wxDateTime date( day, (wxDateTime::Month)( month - 1 ), year, 0, 0, 0, 0 );
216  return date.FormatDate();
217 }
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:162
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:82
#define _(s)
Definition: 3d_actions.cpp:33

References _, and THROW_PARSE_ERROR.

Referenced by PCB_IO::DoLoad(), CLIPBOARD_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 59 of file pcb_parser.cpp.

60 {
62  m_tooRecent = false;
64  m_layerIndices.clear();
65  m_layerMasks.clear();
66  m_groupInfos.clear();
67  m_resetKIIDMap.clear();
68 
69  // Add untranslated default (i.e. English) layernames.
70  // Some may be overridden later if parsing a board rather than a footprint.
71  // The English name will survive if parsing only a footprint.
72  for( LAYER_NUM layer = 0; layer < PCB_LAYER_ID_COUNT; ++layer )
73  {
74  std::string untranslated = TO_UTF8( wxString( LSET::Name( PCB_LAYER_ID( layer ) ) ) );
75 
76  m_layerIndices[ untranslated ] = PCB_LAYER_ID( layer );
77  m_layerMasks[ untranslated ] = LSET( PCB_LAYER_ID( layer ) );
78  }
79 
80  m_layerMasks[ "*.Cu" ] = LSET::AllCuMask();
81  m_layerMasks[ "*In.Cu" ] = LSET::InternalCuMask();
82  m_layerMasks[ "F&B.Cu" ] = LSET( 2, F_Cu, B_Cu );
83  m_layerMasks[ "*.Adhes" ] = LSET( 2, B_Adhes, F_Adhes );
84  m_layerMasks[ "*.Paste" ] = LSET( 2, B_Paste, F_Paste );
85  m_layerMasks[ "*.Mask" ] = LSET( 2, B_Mask, F_Mask );
86  m_layerMasks[ "*.SilkS" ] = LSET( 2, B_SilkS, F_SilkS );
87  m_layerMasks[ "*.Fab" ] = LSET( 2, B_Fab, F_Fab );
88  m_layerMasks[ "*.CrtYd" ] = LSET( 2, B_CrtYd, F_CrtYd );
89 
90  // This is for the first pretty & *.kicad_pcb formats, which had
91  // Inner1_Cu - Inner14_Cu with the numbering sequence
92  // reversed from the subsequent format's In1_Cu - In30_Cu numbering scheme.
93  // The newer format brought in an additional 16 Cu layers and flipped the cu stack but
94  // kept the gap between one of the outside layers and the last cu internal.
95 
96  for( int i=1; i<=14; ++i )
97  {
98  std::string key = StrPrintf( "Inner%d.Cu", i );
99 
100  m_layerMasks[ key ] = LSET( PCB_LAYER_ID( In15_Cu - i ) );
101  }
102 }
static LSET AllCuMask(int aCuLayerCount=MAX_CU_LAYERS)
Return a mask holding the requested number of Cu PCB_LAYER_IDs.
Definition: lset.cpp:749
std::vector< GroupInfo > m_groupInfos
Definition: pcb_parser.h:99
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:81
KIID_MAP m_resetKIIDMap
if resetting UUIDs, record new ones to update groups with
Definition: pcb_parser.h:84
int StrPrintf(std::string *result, const char *format,...)
Function StrPrintf is like sprintf() but the output is appended to a std::string instead of to a char...
Definition: richio.cpp:74
#define TO_UTF8(wxstring)
Macro TO_UTF8 converts a wxString to a UTF8 encoded C string for all wxWidgets build modes.
Definition: macros.h:100
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)
Return the fixed name association with aLayerId.
Definition: lset.cpp:81
static LSET InternalCuMask()
Return a complete set of internal copper layers which is all Cu layers except F_Cu and B_Cu.
Definition: lset.cpp:709
bool m_showLegacyZoneWarning
Definition: pcb_parser.h:86
int LAYER_NUM
This can be replaced with int and removed.
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:82
LAYER_ID_MAP m_layerIndices
map layer name to it's index
Definition: pcb_parser.h:77
LSET_MAP m_layerMasks
map layer names to their masks
Definition: pcb_parser.h:78

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

390  {
391  return m_tooRecent;
392  }
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:81

References m_tooRecent.

Referenced by PCB_IO::DoLoad(), CLIPBOARD_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 1485 of file pcb_parser.cpp.

1486 {
1487  // avoid constructing another std::string, use lexer's directly
1488  typename M::const_iterator it = aMap.find( curText );
1489 
1490  if( it == aMap.end() )
1491  {
1492  m_undefinedLayers.insert( curText );
1493  return Rescue;
1494  }
1495 
1496  return it->second;
1497 }
std::set< wxString > m_undefinedLayers
set of layers not defined in layers section
Definition: pcb_parser.h:79

References Rescue.

◆ Parse()

BOARD_ITEM * PCB_PARSER::Parse ( )

Definition at line 484 of file pcb_parser.cpp.

485 {
486  T token;
487  BOARD_ITEM* item;
488  LOCALE_IO toggle;
489 
490  // MODULEs can be prefixed with an initial block of single line comments and these
491  // are kept for Format() so they round trip in s-expression form. BOARDs might
492  // eventually do the same, but currently do not.
493  std::unique_ptr<wxArrayString> initial_comments( ReadCommentLines() );
494 
495  token = CurTok();
496 
497  if( token != T_LEFT )
498  Expecting( T_LEFT );
499 
500  switch( NextTok() )
501  {
502  case T_kicad_pcb:
503  if( m_board == NULL )
504  m_board = new BOARD();
505 
506  item = (BOARD_ITEM*) parseBOARD();
507  break;
508 
509  case T_module:
510  item = (BOARD_ITEM*) parseMODULE( initial_comments.release() );
511  break;
512 
513  default:
514  wxString err;
515  err.Printf( _( "Unknown token \"%s\"" ), GetChars( FromUTF8() ) );
516  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
517  }
518 
519  return item;
520 }
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:523
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:162
#define NULL
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
Information pertinent to a Pcbnew printed circuit board.
Definition: class_board.h:176
#define _(s)
Definition: 3d_actions.cpp:33
BOARD * m_board
Definition: pcb_parser.h:76
MODULE * parseMODULE(wxArrayString *aInitialComments=0)
Function parseMODULE.

References _, GetChars(), NULL, and THROW_PARSE_ERROR.

Referenced by PCB_IO::DoLoad(), GITHUB_PLUGIN::FootprintLoad(), CLIPBOARD_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 378 of file pcb_parser.cpp.

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

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(), MODULE_3D_SETTINGS::VECTOR3D::x, MODULE_3D_SETTINGS::VECTOR3D::y, and MODULE_3D_SETTINGS::VECTOR3D::z.

◆ parseARC()

ARC * PCB_PARSER::parseARC ( )
private

We continue to parse the status field but it is no longer written

Definition at line 4004 of file pcb_parser.cpp.

4005 {
4006  wxCHECK_MSG( CurTok() == T_arc, NULL,
4007  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as ARC." ) );
4008 
4009  wxPoint pt;
4010  T token;
4011 
4012  std::unique_ptr<ARC> arc( new ARC( m_board ) );
4013 
4014  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4015  {
4016  if( token != T_LEFT )
4017  Expecting( T_LEFT );
4018 
4019  token = NextTok();
4020 
4021  switch( token )
4022  {
4023  case T_start:
4024  pt.x = parseBoardUnits( "start x" );
4025  pt.y = parseBoardUnits( "start y" );
4026  arc->SetStart( pt );
4027  break;
4028 
4029  case T_mid:
4030  pt.x = parseBoardUnits( "mid x" );
4031  pt.y = parseBoardUnits( "mid y" );
4032  arc->SetMid( pt );
4033  break;
4034 
4035  case T_end:
4036  pt.x = parseBoardUnits( "end x" );
4037  pt.y = parseBoardUnits( "end y" );
4038  arc->SetEnd( pt );
4039  break;
4040 
4041  case T_width:
4042  arc->SetWidth( parseBoardUnits( "width" ) );
4043  break;
4044 
4045  case T_layer:
4046  arc->SetLayer( parseBoardItemLayer() );
4047  break;
4048 
4049  case T_net:
4050  if( !arc->SetNetCode( getNetCode( parseInt( "net number" ) ), /* aNoAssert */ true ) )
4052  _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
4053  GetChars( CurSource() ), CurLineNumber(), CurOffset() ) );
4054  break;
4055 
4056  case T_tstamp:
4057  NextTok();
4058  const_cast<KIID&>( arc->m_Uuid ) = CurStrToKIID();
4059  break;
4060 
4062  case T_status:
4063  arc->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
4064  break;
4065 
4066  case T_locked:
4067  arc->SetState( TRACK_LOCKED, 1 );
4068  break;
4069 
4070  default:
4071  Expecting( "start, mid, end, width, layer, net, tstamp, or status" );
4072  }
4073 
4074  NeedRIGHT();
4075  }
4076 
4077  return arc.release();
4078 }
KIID CurStrToKIID()
int parseBoardUnits()
Definition: pcb_parser.h:275
#define NULL
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
#define TRACK_LOCKED
Pcbnew: track locked: protected from global deletion.
Definition: base_struct.h:131
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:201
#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:103
BOARD * m_board
Definition: pcb_parser.h:76
long parseHex()
Definition: pcb_parser.h:324
int parseInt()
Definition: pcb_parser.h:313
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

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

◆ parseBOARD()

BOARD * PCB_PARSER::parseBOARD ( )
private

Definition at line 523 of file pcb_parser.cpp.

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

540 {
541  T token;
542  std::map<wxString, wxString> properties;
543 
544  parseHeader();
545 
546  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
547  {
548  if( token != T_LEFT )
549  Expecting( T_LEFT );
550 
551  token = NextTok();
552 
553  if( token == T_page && m_requiredVersion <= 20200119 )
554  token = T_paper;
555 
556  switch( token )
557  {
558  case T_general:
560  break;
561 
562  case T_paper:
563  parsePAGE_INFO();
564  break;
565 
566  case T_title_block:
568  break;
569 
570  case T_layers:
571  parseLayers();
572  break;
573 
574  case T_setup:
575  parseSetup();
576  break;
577 
578  case T_property:
579  properties.insert( parseProperty() );
580  break;
581 
582  case T_net:
584  break;
585 
586  case T_net_class:
587  parseNETCLASS();
589  break;
590 
591  case T_gr_arc:
592  case T_gr_circle:
593  case T_gr_curve:
594  case T_gr_rect:
595  case T_gr_line:
596  case T_gr_poly:
598  break;
599 
600  case T_gr_text:
602  break;
603 
604  case T_dimension:
606  break;
607 
608  case T_module:
610  break;
611 
612  case T_segment:
614  break;
615 
616  case T_arc:
618  break;
619 
620  case T_group:
621  parseGROUP();
622  break;
623 
624  case T_via:
626  break;
627 
628  case T_zone:
630  break;
631 
632  case T_target:
634  break;
635 
636  default:
637  wxString err;
638  err.Printf( _( "Unknown token \"%s\"" ), GetChars( FromUTF8() ) );
639  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
640  }
641  }
642 
643  m_board->SetProperties( properties );
644 
645  if( m_undefinedLayers.size() > 0 )
646  {
647  bool deleteItems;
648  std::vector<BOARD_ITEM*> deleteList;
649  wxString msg = wxString::Format( _( "Items found on undefined layers. Do you wish to\n"
650  "rescue them to the Cmts.User layer?" ) );
651  wxString details = wxString::Format( _( "Undefined layers:" ) );
652 
653  for( const wxString& undefinedLayer : m_undefinedLayers )
654  details += wxT( "\n " ) + undefinedLayer;
655 
656  wxRichMessageDialog dlg( nullptr, msg, _( "Warning" ),
657  wxYES_NO | wxCANCEL | wxCENTRE | wxICON_WARNING | wxSTAY_ON_TOP );
658  dlg.ShowDetailedText( details );
659  dlg.SetYesNoCancelLabels( _( "Rescue" ), _( "Delete" ), _( "Cancel" ) );
660 
661  switch( dlg.ShowModal() )
662  {
663  case wxID_YES: deleteItems = false; break;
664  case wxID_NO: deleteItems = true; break;
665  case wxID_CANCEL:
666  default: THROW_IO_ERROR( wxT( "CANCEL" ) );
667  }
668 
669  auto visitItem = [&]( BOARD_ITEM* item )
670  {
671  if( item->GetLayer() == Rescue )
672  {
673  if( deleteItems )
674  deleteList.push_back( item );
675  else
676  item->SetLayer( Cmts_User );
677  }
678  };
679 
680  for( auto segm : m_board->Tracks() )
681  {
682  if( segm->Type() == PCB_VIA_T )
683  {
684  VIA* via = (VIA*) segm;
685  PCB_LAYER_ID top_layer, bottom_layer;
686 
687  if( via->GetViaType() == VIATYPE::THROUGH )
688  continue;
689 
690  via->LayerPair( &top_layer, &bottom_layer );
691 
692  if( top_layer == Rescue || bottom_layer == Rescue )
693  {
694  if( deleteItems )
695  deleteList.push_back( via );
696  else
697  {
698  if( top_layer == Rescue )
699  top_layer = F_Cu;
700 
701  if( bottom_layer == Rescue )
702  bottom_layer = B_Cu;
703 
704  via->SetLayerPair( top_layer, bottom_layer );
705  }
706  }
707  }
708  else
709  visitItem( segm );
710  }
711 
712  for( BOARD_ITEM* zone : m_board->Zones() )
713  visitItem( zone );
714 
715  for( BOARD_ITEM* drawing : m_board->Drawings() )
716  visitItem( drawing );
717 
718  for( BOARD_ITEM* item : deleteList )
719  m_board->Delete( item );
720 
721  m_undefinedLayers.clear();
722  }
723 
724  // Now that we've parsed the other Uuids in the file we can resolve
725  // the uuids referred to in the group declarations we saw.
726  //
727  // First add all group objects so subsequent GetItem() calls for nested
728  // groups work.
729 
730  for( size_t idx = 0; idx < m_groupInfos.size(); idx++ )
731  {
732  auto& aGrp = m_groupInfos[idx];
733  PCB_GROUP* group = new PCB_GROUP( m_board );
734  group->SetName( aGrp.name );
735  const_cast<KIID&>( group->m_Uuid ) = aGrp.uuid;
736  m_board->Add( group );
737  }
738 
739  wxString error;
740 
741  for( size_t idx = 0; idx < m_groupInfos.size(); idx++ )
742  {
743  auto& aGrp = m_groupInfos[idx];
744  BOARD_ITEM* bItem = m_board->GetItem( aGrp.uuid );
745 
746  if( bItem == nullptr || bItem->Type() != PCB_GROUP_T )
747  {
748  error = wxString::Format( _( "Group %s not found in board" ),
749  aGrp.uuid.AsString() );
750  continue;
751  }
752 
753  PCB_GROUP* group = static_cast<PCB_GROUP*>( bItem );
754 
755  for( const auto& aUuid : aGrp.memberUuids )
756  {
757  KIID tUuid = aUuid;
758 
759  if( m_resetKIIDs )
760  {
761  if( m_resetKIIDMap.find( aUuid.AsString() ) == m_resetKIIDMap.end() )
762  {
763  if( error == wxEmptyString )
764  {
765  error = wxString::Format( _( "Group %s references missing item %s" ),
766  aGrp.uuid.AsString(), aUuid.AsString() );
767  }
768  }
769  else
770  {
771  tUuid = m_resetKIIDMap[ aUuid.AsString() ];
772  }
773  }
774 
775  BOARD_ITEM* item = m_board->GetItem( tUuid );
776 
777  if( ( item == nullptr ) || ( item->Type() == NOT_USED ) )
778  {
779  if( error == wxEmptyString )
780  {
781  error = wxString::Format( _( "Group %s references missing item %s" ),
782  aGrp.uuid.AsString(), tUuid.AsString() );
783  }
784  }
785  else
786  {
787  group->AddItem( item );
788  }
789  }
790  }
791 
792  wxString sanityResult = m_board->GroupsSanityCheck();
793 
794  if( error != wxEmptyString || sanityResult != wxEmptyString )
795  {
796  wxString errMsg = ( error != wxEmptyString ) ? error : sanityResult;
797  KIDIALOG dlg( nullptr, wxString::Format(
798  _( "Error in group structure in file: %s\n\nAttempt repair?" ), errMsg ),
799  _( "File data error" ), wxOK | wxCANCEL | wxICON_ERROR );
800  dlg.SetOKLabel( _( "Attempt repair" ) );
801 
802  if( dlg.ShowModal() == wxID_CANCEL )
803  THROW_IO_ERROR( _( "File read canceled" ) );
804 
805  m_board->GroupsSanityCheck( true );
806  }
807 
808  return m_board;
809 }
void parseHeader()
Definition: pcb_parser.cpp:812
bool AddItem(BOARD_ITEM *aItem)
Adds item to group.
std::vector< GroupInfo > m_groupInfos
Definition: pcb_parser.h:99
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:282
Helper class to create more flexible dialogs, including 'do not show again' checkbox handling.
Definition: confirm.h:44
BOARD_ITEM is a base class for any item which can be embedded within the BOARD container class,...
class PCB_GROUP, a set of BOARD_ITEMs
Definition: typeinfo.h:109
void SetProperties(const std::map< wxString, wxString > &aProps)
Definition: class_board.h:270
TRACK * parseTRACK()
VIA * parseVIA()
PCB_GROUP is a set of BOARD_ITEMs (i.e., without duplicates)
the 3d code uses this value
Definition: typeinfo.h:80
void parseNETINFO_ITEM()
wxString AsString() const
Definition: common.cpp:165
ARC * parseARC()
DIMENSION * parseDIMENSION()
void parseTITLE_BLOCK()
Definition: pcb_parser.cpp:940
BOARD_ITEM * GetItem(const KIID &aID)
void parseLayers()
KIID_MAP m_resetKIIDMap
if resetting UUIDs, record new ones to update groups with
Definition: pcb_parser.h:84
void parsePAGE_INFO()
Definition: pcb_parser.cpp:884
void Add(BOARD_ITEM *aItem, ADD_MODE aMode=ADD_MODE::INSERT) override
Adds an item to the container.
Definition: common.h:68
PCB_LAYER_ID
A quick note on layer IDs:
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:162
std::pair< wxString, wxString > parseProperty()
Definition: pcb_parser.cpp:252
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.
void parseNETCLASS()
const KIID m_Uuid
Definition: base_struct.h:162
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:82
ZONE_CONTAINERS & Zones()
Definition: class_board.h:252
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:201
#define _(s)
Definition: 3d_actions.cpp:33
BOARD * m_board
Definition: pcb_parser.h:76
void parseGeneralSection()
Definition: pcb_parser.cpp:851
VIATYPE GetViaType() const
Definition: class_track.h:381
virtual void Delete(BOARD_ITEM *aItem)
Removes an item from the container and deletes it.
wxString GroupsSanityCheck(bool repair=false)
class VIA, a via (like a track segment on a copper layer)
Definition: typeinfo.h:97
MODULE * parseMODULE(wxArrayString *aInitialComments=0)
Function parseMODULE.
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
void parseGROUP()
DRAWINGS & Drawings()
Definition: class_board.h:250
TRACKS & Tracks()
Definition: class_board.h:244
void parseSetup()
std::set< wxString > m_undefinedLayers
set of layers not defined in layers section
Definition: pcb_parser.h:79
void SetName(wxString aName)
bool m_resetKIIDs
reading into an existing board; reset UUIDs
Definition: pcb_parser.h:83
KICAD_T Type() const
Function Type()
Definition: base_struct.h:193

References _, PCB_GROUP::AddItem(), APPEND, KIID::AsString(), B_Cu, Cmts_User, F_Cu, Format(), GetChars(), VIA::GetViaType(), VIA::LayerPair(), EDA_ITEM::m_Uuid, NOT_USED, PCB_GROUP_T, PCB_VIA_T, Rescue, VIA::SetLayerPair(), PCB_GROUP::SetName(), KIDIALOG::ShowModal(), THROUGH, THROW_IO_ERROR, THROW_PARSE_ERROR, and EDA_ITEM::Type().

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

1501 {
1502  wxCHECK_MSG( CurTok() == T_layer, UNDEFINED_LAYER,
1503  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as layer." ) );
1504 
1505  NextTok();
1506 
1507  PCB_LAYER_ID layerIndex = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
1508 
1509  // Handle closing ) in object parser.
1510 
1511  return layerIndex;
1512 }
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:77

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

1516 {
1517  wxCHECK_MSG( CurTok() == T_layers, LSET(),
1518  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1519  wxT( " as item layer mask." ) );
1520 
1521  LSET layerMask;
1522 
1523  for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
1524  {
1525  LSET mask = lookUpLayer<LSET>( m_layerMasks );
1526  layerMask |= mask;
1527  }
1528 
1529  return layerMask;
1530 }
LSET is a set of PCB_LAYER_IDs.
LSET_MAP m_layerMasks
map layer names to their masks
Definition: pcb_parser.h:78

◆ parseBoardStackup()

void PCB_PARSER::parseBoardStackup ( )
private

Definition at line 1105 of file pcb_parser.cpp.

1106 {
1107  T token;
1108  wxString name;
1109  int dielectric_idx = 1; // the index of dielectric layers
1111 
1112  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1113  {
1114  if( CurTok() != T_LEFT )
1115  Expecting( T_LEFT );
1116 
1117  token = NextTok();
1118 
1119  if( token != T_layer )
1120  {
1121  switch( token )
1122  {
1123  case T_copper_finish:
1124  NeedSYMBOL();
1125  stackup.m_FinishType = FromUTF8();
1126  NeedRIGHT();
1127  break;
1128 
1129  case T_edge_plating:
1130  token = NextTok();
1131  stackup.m_EdgePlating = token == T_yes;
1132  NeedRIGHT();
1133  break;
1134 
1135  case T_dielectric_constraints:
1136  token = NextTok();
1137  stackup.m_HasDielectricConstrains = token == T_yes;
1138  NeedRIGHT();
1139  break;
1140 
1141  case T_edge_connector:
1142  token = NextTok();
1144 
1145  if( token == T_yes )
1147  else if( token == T_bevelled )
1149 
1150  NeedRIGHT();
1151  break;
1152 
1153  case T_castellated_pads:
1154  token = NextTok();
1155  stackup.m_CastellatedPads = token == T_yes;
1156  NeedRIGHT();
1157  break;
1158 
1159  default:
1160  // Currently, skip this item if not defined, because the stackup def
1161  // is a moving target
1162  //Expecting( "copper_finish, edge_plating, dielectric_constrains, edge_connector, castellated_pads" );
1163  skipCurrent();
1164  break;
1165  }
1166 
1167  continue;
1168  }
1169 
1170  NeedSYMBOL();
1171  name = FromUTF8();
1172 
1173  // init the layer id. For dielectric, layer id = UNDEFINED_LAYER
1174  PCB_LAYER_ID layerId = m_board->GetLayerID( name );
1175 
1176  // Init the type
1178 
1179  if( layerId == F_SilkS || layerId == B_SilkS )
1180  type = BS_ITEM_TYPE_SILKSCREEN;
1181  else if( layerId == F_Mask || layerId == B_Mask )
1182  type = BS_ITEM_TYPE_SOLDERMASK;
1183  else if( layerId == F_Paste || layerId == B_Paste )
1184  type = BS_ITEM_TYPE_SOLDERPASTE;
1185  else if( layerId == UNDEFINED_LAYER )
1186  type = BS_ITEM_TYPE_DIELECTRIC;
1187  else if( layerId >= F_Cu && layerId <= B_Cu )
1188  type = BS_ITEM_TYPE_COPPER;
1189 
1190  BOARD_STACKUP_ITEM* item = nullptr;
1191 
1192  if( type != BS_ITEM_TYPE_UNDEFINED )
1193  {
1194  item = new BOARD_STACKUP_ITEM( type );
1195  item->SetBrdLayerId( layerId );
1196 
1197  if( type == BS_ITEM_TYPE_DIELECTRIC )
1198  item->SetDielectricLayerId( dielectric_idx++ );
1199 
1200  stackup.Add( item );
1201  }
1202  else
1203  Expecting( "layer_name" );
1204 
1205  bool has_next_sublayer = true;
1206  int sublayer_idx = 0; // the index of dielectric sub layers
1207  // sublayer 0 is always existing (main sublayer)
1208 
1209  while( has_next_sublayer )
1210  {
1211  has_next_sublayer = false;
1212 
1213  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1214  {
1215  if( token == T_addsublayer )
1216  {
1217  has_next_sublayer = true;
1218  break;
1219  }
1220 
1221  if( token == T_LEFT )
1222  {
1223  token = NextTok();
1224 
1225  switch( token )
1226  {
1227  case T_type:
1228  NeedSYMBOL();
1229  item->SetTypeName( FromUTF8() );
1230  NeedRIGHT();
1231  break;
1232 
1233  case T_thickness:
1234  item->SetThickness( parseBoardUnits( T_thickness ), sublayer_idx );
1235  token = NextTok();
1236 
1237  if( token == T_LEFT )
1238  break;
1239 
1240  if( token == T_locked )
1241  {
1242  // Dielectric thickness can be locked (for impedance controlled layers)
1243  if( type == BS_ITEM_TYPE_DIELECTRIC )
1244  item->SetThicknessLocked( true, sublayer_idx );
1245 
1246  NeedRIGHT();
1247  }
1248  break;
1249 
1250  case T_material:
1251  NeedSYMBOL();
1252  item->SetMaterial( FromUTF8(), sublayer_idx );
1253  NeedRIGHT();
1254  break;
1255 
1256  case T_epsilon_r:
1257  NextTok();
1258  item->SetEpsilonR( parseDouble(), sublayer_idx );
1259  NeedRIGHT();
1260  break;
1261 
1262  case T_loss_tangent:
1263  NextTok();
1264  item->SetLossTangent( parseDouble(), sublayer_idx );
1265  NeedRIGHT();
1266  break;
1267 
1268  case T_color:
1269  NeedSYMBOL();
1270  item->SetColor( FromUTF8() );
1271  NeedRIGHT();
1272  break;
1273 
1274  default:
1275  // Currently, skip this item if not defined, because the stackup def
1276  // is a moving target
1277  //Expecting( "type, thickness, material, epsilon_r, loss_tangent, color" );
1278  skipCurrent();
1279  }
1280  }
1281  }
1282 
1283  if( has_next_sublayer ) // Prepare reading the next sublayer description
1284  {
1285  sublayer_idx++;
1286  item->AddDielectricPrms( sublayer_idx );
1287  }
1288  }
1289  }
1290 
1291  if( token != T_RIGHT )
1292  {
1293  Expecting( ")" );
1294  }
1295 
1296  // Success:
1298 }
const PCB_LAYER_ID GetLayerID(const wxString &aLayerName) const
Return 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 specified in job file: BS_EDGE_CONNECTO...
bool m_CastellatedPads
True if castellated pads exist.
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:514
int parseBoardUnits()
Definition: pcb_parser.h:275
void skipCurrent()
Function skipCurrent Skip the current token level, i.e search for the RIGHT parenthesis which closes ...
Definition: pcb_parser.cpp:105
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:76
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:138
void SetColor(const wxString &aColorName)
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(), and UNDEFINED_LAYER.

◆ parseBoardUnits() [1/3]

int PCB_PARSER::parseBoardUnits ( )
inlineprivate

Definition at line 275 of file pcb_parser.h.

276  {
277  // There should be no major rounding issues here, since the values in
278  // the file are in mm and get converted to nano-meters.
279  // See test program tools/test-nm-biu-to-ascii-mm-round-tripping.cpp
280  // to confirm or experiment. Use a similar strategy in both places, here
281  // and in the test program. Make that program with:
282  // $ make test-nm-biu-to-ascii-mm-round-tripping
283  auto retval = parseDouble() * IU_PER_MM;
284 
285  // N.B. we currently represent board units as integers. Any values that are
286  // larger or smaller than those board units represent undefined behavior for
287  // the system. We limit values to the largest that is visible on the screen
288  // This is the diagonal distance of the full screen ~1.5m
289  double int_limit = std::numeric_limits<int>::max() * 0.7071; // 0.7071 = roughly 1/sqrt(2)
290  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
291  }
static constexpr double IU_PER_MM
Mock up a conversion function.
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:138

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

Referenced by parseBoardUnits().

◆ parseBoardUnits() [2/3]

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

Definition at line 293 of file pcb_parser.h.

294  {
295  auto retval = parseDouble( aExpected ) * IU_PER_MM;
296 
297  // N.B. we currently represent board units as integers. Any values that are
298  // larger or smaller than those board units represent undefined behavior for
299  // the system. We limit values to the largest that is visible on the screen
300  double int_limit = std::numeric_limits<int>::max() * 0.7071;
301 
302  // Use here KiROUND, not KIROUND (see comments about them)
303  // when having a function as argument, because it will be called twice
304  // with KIROUND
305  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
306  }
static constexpr double IU_PER_MM
Mock up a conversion function.
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:138

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

◆ parseBoardUnits() [3/3]

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

Definition at line 308 of file pcb_parser.h.

309  {
310  return parseBoardUnits( GetTokenText( aToken ) );
311  }
int parseBoardUnits()
Definition: pcb_parser.h:275
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 168 of file pcb_parser.cpp.

169 {
170  T token = NextTok();
171 
172  if( token == T_yes )
173  return true;
174  else if( token == T_no )
175  return false;
176  else
177  Expecting( "yes or no" );
178 
179  return false;
180 }

◆ parseD_PAD()

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

Definition at line 3409 of file pcb_parser.cpp.

3410 {
3411  wxCHECK_MSG( CurTok() == T_pad, NULL,
3412  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as D_PAD." ) );
3413 
3414  wxSize sz;
3415  wxPoint pt;
3416 
3417  std::unique_ptr< D_PAD > pad( new D_PAD( aParent ) );
3418 
3419  NeedSYMBOLorNUMBER();
3420  pad->SetName( FromUTF8() );
3421 
3422  T token = NextTok();
3423 
3424  switch( token )
3425  {
3426  case T_thru_hole:
3427  pad->SetAttribute( PAD_ATTRIB_STANDARD );
3428  break;
3429 
3430  case T_smd:
3431  pad->SetAttribute( PAD_ATTRIB_SMD );
3432 
3433  // Default D_PAD object is thru hole with drill.
3434  // SMD pads have no hole
3435  pad->SetDrillSize( wxSize( 0, 0 ) );
3436  break;
3437 
3438  case T_connect:
3439  pad->SetAttribute( PAD_ATTRIB_CONN );
3440 
3441  // Default D_PAD object is thru hole with drill.
3442  // CONN pads have no hole
3443  pad->SetDrillSize( wxSize( 0, 0 ) );
3444  break;
3445 
3446  case T_np_thru_hole:
3447  pad->SetAttribute( PAD_ATTRIB_HOLE_NOT_PLATED );
3448  break;
3449 
3450  default:
3451  Expecting( "thru_hole, smd, connect, or np_thru_hole" );
3452  }
3453 
3454  token = NextTok();
3455 
3456  switch( token )
3457  {
3458  case T_circle:
3459  pad->SetShape( PAD_SHAPE_CIRCLE );
3460  break;
3461 
3462  case T_rect:
3463  pad->SetShape( PAD_SHAPE_RECT );
3464  break;
3465 
3466  case T_oval:
3467  pad->SetShape( PAD_SHAPE_OVAL );
3468  break;
3469 
3470  case T_trapezoid:
3471  pad->SetShape( PAD_SHAPE_TRAPEZOID );
3472  break;
3473 
3474  case T_roundrect:
3475  // Note: the shape can be PAD_SHAPE_ROUNDRECT or PAD_SHAPE_CHAMFERED_RECT
3476  // (if chamfer parameters are found later in pad descr.)
3477  pad->SetShape( PAD_SHAPE_ROUNDRECT );
3478  break;
3479 
3480  case T_custom:
3481  pad->SetShape( PAD_SHAPE_CUSTOM );
3482  break;
3483 
3484  default:
3485  Expecting( "circle, rectangle, roundrect, oval, trapezoid or custom" );
3486  }
3487 
3488  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3489  {
3490  if( token != T_LEFT )
3491  Expecting( T_LEFT );
3492 
3493  token = NextTok();
3494 
3495  switch( token )
3496  {
3497  case T_size:
3498  sz.SetWidth( parseBoardUnits( "width value" ) );
3499  sz.SetHeight( parseBoardUnits( "height value" ) );
3500  pad->SetSize( sz );
3501  NeedRIGHT();
3502  break;
3503 
3504  case T_at:
3505  pt.x = parseBoardUnits( "X coordinate" );
3506  pt.y = parseBoardUnits( "Y coordinate" );
3507  pad->SetPos0( pt );
3508  token = NextTok();
3509 
3510  if( token == T_NUMBER )
3511  {
3512  pad->SetOrientation( parseDouble() * 10.0 );
3513  NeedRIGHT();
3514  }
3515  else if( token != T_RIGHT )
3516  {
3517  Expecting( ") or angle value" );
3518  }
3519 
3520  break;
3521 
3522  case T_rect_delta:
3523  {
3524  wxSize delta;
3525  delta.SetWidth( parseBoardUnits( "rectangle delta width" ) );
3526  delta.SetHeight( parseBoardUnits( "rectangle delta height" ) );
3527  pad->SetDelta( delta );
3528  NeedRIGHT();
3529  }
3530  break;
3531 
3532  case T_drill:
3533  {
3534  bool haveWidth = false;
3535  wxSize drillSize = pad->GetDrillSize();
3536 
3537  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3538  {
3539  if( token == T_LEFT )
3540  token = NextTok();
3541 
3542  switch( token )
3543  {
3544  case T_oval:
3545  pad->SetDrillShape( PAD_DRILL_SHAPE_OBLONG );
3546  break;
3547 
3548  case T_NUMBER:
3549  {
3550  if( !haveWidth )
3551  {
3552  drillSize.SetWidth( parseBoardUnits() );
3553 
3554  // If height is not defined the width and height are the same.
3555  drillSize.SetHeight( drillSize.GetWidth() );
3556  haveWidth = true;
3557  }
3558  else
3559  {
3560  drillSize.SetHeight( parseBoardUnits() );
3561  }
3562 
3563  }
3564  break;
3565 
3566  case T_offset:
3567  pt.x = parseBoardUnits( "drill offset x" );
3568  pt.y = parseBoardUnits( "drill offset y" );
3569  pad->SetOffset( pt );
3570  NeedRIGHT();
3571  break;
3572 
3573  default:
3574  Expecting( "oval, size, or offset" );
3575  }
3576  }
3577 
3578  // This fixes a bug caused by setting the default D_PAD drill size to a value
3579  // other than 0 used to fix a bunch of debug assertions even though it is defined
3580  // as a through hole pad. Wouldn't a though hole pad with no drill be a surface
3581  // mount pad (or a conn pad which is a smd pad with no solder paste)?
3582  if( ( pad->GetAttribute() != PAD_ATTRIB_SMD ) && ( pad->GetAttribute() != PAD_ATTRIB_CONN ) )
3583  pad->SetDrillSize( drillSize );
3584  else
3585  pad->SetDrillSize( wxSize( 0, 0 ) );
3586 
3587  }
3588  break;
3589 
3590  case T_layers:
3591  {
3592  LSET layerMask = parseBoardItemLayersAsMask();
3593  pad->SetLayerSet( layerMask );
3594  }
3595  break;
3596 
3597  case T_net:
3598  if( ! pad->SetNetCode( getNetCode( parseInt( "net number" ) ), /* aNoAssert */ true ) )
3599  {
3600  wxLogError( wxString::Format( _( "Invalid net ID in\n"
3601  "file: '%s'\n"
3602  "line: %d\n"
3603  "offset: %d" ),
3604  CurSource(),
3605  CurLineNumber(),
3606  CurOffset() ) );
3607  }
3608 
3609  NeedSYMBOLorNUMBER();
3610 
3611  // Test validity of the netname in file for netcodes expected having a net name
3612  if( m_board && pad->GetNetCode() > 0 &&
3613  FromUTF8() != m_board->FindNet( pad->GetNetCode() )->GetNetname() )
3614  {
3615  pad->SetNetCode( NETINFO_LIST::ORPHANED, /* aNoAssert */ true );
3616  wxLogError( wxString::Format( _( "Net name doesn't match net ID in\n"
3617  "file: '%s'\n"
3618  "line: %d\n"
3619  "offset: %d" ),
3620  CurSource(),
3621  CurLineNumber(),
3622  CurOffset() ) );
3623  }
3624 
3625  NeedRIGHT();
3626  break;
3627 
3628  case T_pinfunction:
3629  NeedSYMBOLorNUMBER();
3630  pad->SetPinFunction( FromUTF8() );
3631  NeedRIGHT();
3632  break;
3633 
3634  case T_die_length:
3635  pad->SetPadToDieLength( parseBoardUnits( T_die_length ) );
3636  NeedRIGHT();
3637  break;
3638 
3639  case T_solder_mask_margin:
3640  pad->SetLocalSolderMaskMargin( parseBoardUnits( T_solder_mask_margin ) );
3641  NeedRIGHT();
3642  break;
3643 
3644  case T_solder_paste_margin:
3645  pad->SetLocalSolderPasteMargin( parseBoardUnits( T_solder_paste_margin ) );
3646  NeedRIGHT();
3647  break;
3648 
3649  case T_solder_paste_margin_ratio:
3650  pad->SetLocalSolderPasteMarginRatio(
3651  parseDouble( "pad local solder paste margin ratio value" ) );
3652  NeedRIGHT();
3653  break;
3654 
3655  case T_clearance:
3656  pad->SetLocalClearance( parseBoardUnits( "local clearance value" ) );
3657  NeedRIGHT();
3658  break;
3659 
3660  case T_zone_connect:
3661  pad->SetZoneConnection( (ZONE_CONNECTION) parseInt( "zone connection value" ) );
3662  NeedRIGHT();
3663  break;
3664 
3665  case T_thermal_width:
3666  pad->SetThermalSpokeWidth( parseBoardUnits( T_thermal_width ) );
3667  NeedRIGHT();
3668  break;
3669 
3670  case T_thermal_gap:
3671  pad->SetThermalGap( parseBoardUnits( T_thermal_gap ) );
3672  NeedRIGHT();
3673  break;
3674 
3675  case T_roundrect_rratio:
3676  pad->SetRoundRectRadiusRatio( parseDouble( "roundrect radius ratio" ) );
3677  NeedRIGHT();
3678  break;
3679 
3680  case T_chamfer_ratio:
3681  pad->SetChamferRectRatio( parseDouble( "chamfer ratio" ) );
3682 
3683  if( pad->GetChamferRectRatio() > 0 )
3684  pad->SetShape( PAD_SHAPE_CHAMFERED_RECT );
3685 
3686  NeedRIGHT();
3687  break;
3688 
3689  case T_chamfer:
3690  {
3691  int chamfers = 0;
3692  bool end_list = false;
3693 
3694  while( !end_list )
3695  {
3696  token = NextTok();
3697  switch( token )
3698  {
3699  case T_top_left:
3700  chamfers |= RECT_CHAMFER_TOP_LEFT;
3701  break;
3702 
3703  case T_top_right:
3704  chamfers |= RECT_CHAMFER_TOP_RIGHT;
3705  break;
3706 
3707  case T_bottom_left:
3708  chamfers |= RECT_CHAMFER_BOTTOM_LEFT;
3709  break;
3710 
3711  case T_bottom_right:
3712  chamfers |= RECT_CHAMFER_BOTTOM_RIGHT;
3713  break;
3714 
3715  case T_RIGHT:
3716  pad->SetChamferPositions( chamfers );
3717  end_list = true;
3718  break;
3719 
3720  default:
3721  Expecting( "chamfer_top_left chamfer_top_right chamfer_bottom_left or chamfer_bottom_right" );
3722  }
3723  }
3724 
3725  if( pad->GetChamferPositions() != RECT_NO_CHAMFER )
3726  pad->SetShape( PAD_SHAPE_CHAMFERED_RECT );
3727  }
3728  break;
3729 
3730  case T_property:
3731  {
3732  while( token != T_RIGHT )
3733  {
3734  token = NextTok();
3735 
3736  switch( token )
3737  {
3738  case T_pad_prop_bga:
3739  pad->SetProperty( PAD_PROP_BGA );
3740  break;
3741 
3742  case T_pad_prop_fiducial_glob:
3743  pad->SetProperty( PAD_PROP_FIDUCIAL_GLBL );
3744  break;
3745 
3746  case T_pad_prop_fiducial_loc:
3747  pad->SetProperty( PAD_PROP_FIDUCIAL_LOCAL );
3748  break;
3749 
3750  case T_pad_prop_testpoint:
3751  pad->SetProperty( PAD_PROP_TESTPOINT );
3752  break;
3753 
3754  case T_pad_prop_castellated:
3755  pad->SetProperty( PAD_PROP_CASTELLATED );
3756  break;
3757 
3758  case T_pad_prop_heatsink:
3759  pad->SetProperty( PAD_PROP_HEATSINK );
3760  break;
3761 
3762  case T_none:
3763  pad->SetProperty( PAD_PROP_NONE );
3764  break;
3765 
3766  case T_RIGHT:
3767  break;
3768 
3769  default:
3770 #if 0 // Currently: skip unknown property
3771  Expecting( "pad_prop_bga pad_prop_fiducial_glob pad_prop_fiducial_loc"
3772  " pad_prop_heatsink or pad_prop_castellated" );
3773 #endif
3774  break;
3775  }
3776  }
3777  }
3778  break;
3779 
3780  case T_options:
3781  parseD_PAD_option( pad.get() );
3782  break;
3783 
3784  case T_primitives:
3785  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3786  {
3787  if( token == T_LEFT )
3788  token = NextTok();
3789 
3790  // Currently, I am using parseDRAWSEGMENT() to read basic shapes parameters,
3791  // because they are the same as a DRAWSEGMENT.
3792  // However it could be better to write a specific parser, to avoid possible issues
3793  // if the DRAWSEGMENT parser is modified.
3794  DRAWSEGMENT* dummysegm = NULL;
3795 
3796  switch( token )
3797  {
3798  case T_gr_arc:
3799  dummysegm = parseDRAWSEGMENT();
3800  pad->AddPrimitiveArc( dummysegm->GetCenter(), dummysegm->GetArcStart(),
3801  dummysegm->GetAngle(), dummysegm->GetWidth() );
3802  break;
3803 
3804  case T_gr_line:
3805  dummysegm = parseDRAWSEGMENT();
3806  pad->AddPrimitiveSegment( dummysegm->GetStart(), dummysegm->GetEnd(),
3807  dummysegm->GetWidth() );
3808  break;
3809 
3810  case T_gr_circle:
3811  dummysegm = parseDRAWSEGMENT( true ); // Circles with 0 thickness are allowed
3812  // ( filled circles )
3813  pad->AddPrimitiveCircle( dummysegm->GetCenter(), dummysegm->GetRadius(),
3814  dummysegm->GetWidth() );
3815  break;
3816 
3817  case T_gr_rect:
3818  dummysegm = parseDRAWSEGMENT( true );
3819  pad->AddPrimitiveRect( dummysegm->GetStart(), dummysegm->GetEnd(),
3820  dummysegm->GetWidth() );
3821  break;
3822 
3823 
3824  case T_gr_poly:
3825  dummysegm = parseDRAWSEGMENT();
3826  pad->AddPrimitivePoly( dummysegm->BuildPolyPointsList(),
3827  dummysegm->GetWidth() );
3828  break;
3829 
3830  case T_gr_curve:
3831  dummysegm = parseDRAWSEGMENT();
3832  pad->AddPrimitiveCurve( dummysegm->GetStart(), dummysegm->GetEnd(),
3833  dummysegm->GetBezControl1(),
3834  dummysegm->GetBezControl2(),
3835  dummysegm->GetWidth() );
3836  break;
3837 
3838  default:
3839  Expecting( "gr_line, gr_arc, gr_circle, gr_curve, gr_rect or gr_poly" );
3840  break;
3841  }
3842 
3843  delete dummysegm;
3844  }
3845  break;
3846 
3847  case T_remove_unused_layers:
3848  pad->SetRemoveUnconnected( true );
3849  NeedRIGHT();
3850  break;
3851 
3852  case T_keep_end_layers:
3853  pad->SetKeepTopBottom( true );
3854  NeedRIGHT();
3855  break;
3856 
3857  case T_tstamp:
3858  NextTok();
3859  const_cast<KIID&>( pad->m_Uuid ) = CurStrToKIID();
3860  NeedRIGHT();
3861  break;
3862 
3863  default:
3864  Expecting( "at, drill, layers, net, die_length, solder_mask_margin, roundrect_rratio,\n"
3865  "solder_paste_margin, solder_paste_margin_ratio, clearance, tstamp,\n"
3866  "zone_connect, fp_poly, primitives, thermal_width, or thermal_gap" );
3867  }
3868  }
3869 
3870  return pad.release();
3871 }
NETINFO_ITEM * FindNet(int aNetcode) const
Search for a net with the given netcode.
ZONE_CONNECTION
How pads are covered by copper in zone.
Definition: zones.h:41
wxPoint GetArcStart() const
KIID CurStrToKIID()
DRAWSEGMENT * parseDRAWSEGMENT(bool aAllowCirclesZeroWidth=false)
Read a DRAWSEGMENT description.
LSET parseBoardItemLayersAsMask()
Function parseBoardItemLayersAsMask parses the layers definition of a BOARD_ITEM object.
no special fabrication property
Definition: pad_shapes.h:97
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)
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:275
a pad with a castellated through hole
Definition: pad_shapes.h:103
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:482
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:201
#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:103
BOARD * m_board
Definition: pcb_parser.h:76
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:138
const wxPoint & GetBezControl1() const
const wxPoint & GetStart() const
Function GetStart returns the starting point of the graphic.
int parseInt()
Definition: pcb_parser.h:313
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_NONE, 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, wxPoint::x, and wxPoint::y.

◆ parseD_PAD_option()

bool PCB_PARSER::parseD_PAD_option ( D_PAD aPad)
private

Definition at line 3874 of file pcb_parser.cpp.

3875 {
3876  // Parse only the (option ...) inside a pad description
3877  for( T token = NextTok(); token != T_RIGHT; token = NextTok() )
3878  {
3879  if( token != T_LEFT )
3880  Expecting( T_LEFT );
3881 
3882  token = NextTok();
3883 
3884  switch( token )
3885  {
3886  case T_anchor:
3887  token = NextTok();
3888  // Custom shaped pads have a "anchor pad", which is the reference
3889  // for connection calculations.
3890  // Because this is an anchor, only the 2 very basic shapes are managed:
3891  // circle and rect. The default is circle
3892  switch( token )
3893  {
3894  case T_circle: // default
3895  break;
3896 
3897  case T_rect:
3899  break;
3900 
3901  default:
3902  // Currently, because pad options is a moving target
3903  // just skip unknown keywords
3904  break;
3905  }
3906  NeedRIGHT();
3907  break;
3908 
3909  case T_clearance:
3910  token = NextTok();
3911  // Custom shaped pads have a clearance area that is the pad shape
3912  // (like usual pads) or the convex hull of the pad shape.
3913  switch( token )
3914  {
3915  case T_outline:
3917  break;
3918 
3919  case T_convexhull:
3921  break;
3922 
3923  default:
3924  // Currently, because pad options is a moving target
3925  // just skip unknown keywords
3926  break;
3927  }
3928  NeedRIGHT();
3929  break;
3930 
3931  default:
3932  // Currently, because pad options is a moving target
3933  // just skip unknown keywords
3934  while( (token = NextTok() ) != T_RIGHT )
3935  {}
3936  break;
3937  }
3938  }
3939 
3940  return true;
3941 }
void SetAnchorPadShape(PAD_SHAPE_T aShape)
Function SetAnchorPadShape Set the shape of the anchor pad for custm shped pads.
Definition: class_pad.h:198
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:187

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

◆ parseDefaults()

void PCB_PARSER::parseDefaults ( BOARD_DESIGN_SETTINGS aSettings)
private

Definition at line 1868 of file pcb_parser.cpp.

1869 {
1870  T token;
1871 
1872  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1873  {
1874  if( token != T_LEFT )
1875  Expecting( T_LEFT );
1876 
1877  token = NextTok();
1878 
1879  switch( token )
1880  {
1881  case T_edge_clearance:
1882  designSettings.m_CopperEdgeClearance = parseBoardUnits( T_edge_clearance );
1883  NeedRIGHT();
1884  break;
1885 
1886  case T_copper_line_width:
1887  designSettings.m_LineThickness[ LAYER_CLASS_COPPER ] = parseBoardUnits( token );
1888  NeedRIGHT();
1889  break;
1890 
1891  case T_copper_text_dims:
1892  parseDefaultTextDims( designSettings, LAYER_CLASS_COPPER );
1893  break;
1894 
1895  case T_courtyard_line_width:
1896  designSettings.m_LineThickness[ LAYER_CLASS_COURTYARD ] = parseBoardUnits( token );
1897  NeedRIGHT();
1898  break;
1899 
1900  case T_edge_cuts_line_width:
1901  designSettings.m_LineThickness[ LAYER_CLASS_EDGES ] = parseBoardUnits( token );
1902  NeedRIGHT();
1903  break;
1904 
1905  case T_silk_line_width:
1906  designSettings.m_LineThickness[ LAYER_CLASS_SILK ] = parseBoardUnits( token );
1907  NeedRIGHT();
1908  break;
1909 
1910  case T_silk_text_dims:
1911  parseDefaultTextDims( designSettings, LAYER_CLASS_SILK );
1912  break;
1913 
1914  case T_fab_layers_line_width:
1915  designSettings.m_LineThickness[ LAYER_CLASS_FAB ] = parseBoardUnits( token );
1916  NeedRIGHT();
1917  break;
1918 
1919  case T_fab_layers_text_dims:
1920  parseDefaultTextDims( designSettings, LAYER_CLASS_FAB );
1921  break;
1922 
1923  case T_other_layers_line_width:
1924  designSettings.m_LineThickness[ LAYER_CLASS_OTHERS ] = parseBoardUnits( token );
1925  NeedRIGHT();
1926  break;
1927 
1928  case T_other_layers_text_dims:
1929  parseDefaultTextDims( designSettings, LAYER_CLASS_OTHERS );
1930  break;
1931 
1932  case T_dimension_units:
1933  designSettings.m_DimensionUnitsMode =
1934  static_cast<DIM_UNITS_MODE>( parseInt( "dimension units" ) );
1935  NeedRIGHT();
1936  break;
1937 
1938  case T_dimension_precision:
1939  designSettings.m_DimensionPrecision = parseInt( "dimension precision" );
1940  NeedRIGHT();
1941  break;
1942 
1943  default:
1944  Unexpected( CurText() );
1945  }
1946  }
1947 }
int parseBoardUnits()
Definition: pcb_parser.h:275
void parseDefaultTextDims(BOARD_DESIGN_SETTINGS &aSettings, int aLayer)
int parseInt()
Definition: pcb_parser.h:313

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_DimensionUnitsMode, BOARD_DESIGN_SETTINGS::m_LineThickness, and parseInt().

◆ parseDefaultTextDims()

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

Definition at line 1950 of file pcb_parser.cpp.

1951 {
1952  T token;
1953 
1954  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1955  {
1956  if( token == T_LEFT )
1957  token = NextTok();
1958 
1959  switch( token )
1960  {
1961  case T_size:
1962  aSettings.m_TextSize[ aLayer ].x = parseBoardUnits( "default text size X" );
1963  aSettings.m_TextSize[ aLayer ].y = parseBoardUnits( "default text size Y" );
1964  NeedRIGHT();
1965  break;
1966 
1967  case T_thickness:
1968  aSettings.m_TextThickness[ aLayer ] = parseBoardUnits( "default text width" );
1969  NeedRIGHT();
1970  break;
1971 
1972  case T_italic:
1973  aSettings.m_TextItalic[ aLayer ] = true;
1974  break;
1975 
1976  case T_keep_upright:
1977  aSettings.m_TextUpright[ aLayer ] = true;
1978  break;
1979 
1980  default:
1981  Expecting( "size, thickness, italic or keep_upright" );
1982  }
1983  }
1984 }
int parseBoardUnits()
Definition: pcb_parser.h:275
wxSize m_TextSize[LAYER_CLASS_COUNT]
int m_TextThickness[LAYER_CLASS_COUNT]
bool m_TextItalic[LAYER_CLASS_COUNT]
bool m_TextUpright[LAYER_CLASS_COUNT]

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

◆ parseDIMENSION()

DIMENSION * PCB_PARSER::parseDIMENSION ( )
private

Definition at line 2366 of file pcb_parser.cpp.

2367 {
2368  wxCHECK_MSG( CurTok() == T_dimension, NULL,
2369  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as DIMENSION." ) );
2370 
2371  T token;
2372 
2373  std::unique_ptr<DIMENSION> dimension;
2374 
2375  // skip value that used to be saved
2376  if( NextTok() != T_LEFT )
2377  NeedLEFT();
2378 
2379  token = NextTok();
2380 
2381  bool isLegacyDimension = false;
2382 
2383  // Old format
2384  if( token == T_width )
2385  {
2386  isLegacyDimension = true;
2387  dimension = std::make_unique<ALIGNED_DIMENSION>( nullptr );
2388  dimension->SetLineThickness( parseBoardUnits( "dimension width value" ) );
2389  NeedRIGHT();
2390  }
2391  else
2392  {
2393  if( token != T_type )
2394  Expecting( T_type );
2395 
2396  switch( NextTok() )
2397  {
2398  case T_aligned:
2399  dimension = std::make_unique<ALIGNED_DIMENSION>( nullptr );
2400  break;
2401 
2402  case T_orthogonal:
2403  dimension = std::make_unique<ORTHOGONAL_DIMENSION>( nullptr );
2404  break;
2405 
2406  case T_leader:
2407  dimension = std::make_unique<LEADER>( nullptr );
2408  break;
2409 
2410  case T_center:
2411  dimension = std::make_unique<CENTER_DIMENSION>( nullptr );
2412  break;
2413 
2414  default:
2415  wxFAIL_MSG( wxT( "Cannot parse unknown dimension type %s" ) +
2416  GetTokenString( CurTok() ) );
2417  }
2418 
2419  NeedRIGHT();
2420  }
2421 
2422  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2423  {
2424  if( token != T_LEFT )
2425  Expecting( T_LEFT );
2426 
2427  token = NextTok();
2428 
2429  switch( token )
2430  {
2431  case T_layer:
2432  dimension->SetLayer( parseBoardItemLayer() );
2433  NeedRIGHT();
2434  break;
2435 
2436  case T_tstamp:
2437  NextTok();
2438  const_cast<KIID&>( dimension->m_Uuid ) = CurStrToKIID();
2439  NeedRIGHT();
2440  break;
2441 
2442  case T_gr_text:
2443  {
2444  TEXTE_PCB* text = parseTEXTE_PCB();
2445  dimension->Text() = *text;
2446 
2447  // The text is part of the dimension and shares its uuid
2448  const_cast<KIID&>( dimension->Text().m_Uuid ) = dimension->m_Uuid;
2449 
2450  // Fetch other dimension properties out of the text item
2451  dimension->SetPosition( text->GetTextPos() );
2452 
2453  if( isLegacyDimension )
2454  {
2455  EDA_UNITS units = EDA_UNITS::INCHES;
2456  bool useMils = false;
2457  FetchUnitsFromString( text->GetText(), units, useMils );
2458  dimension->SetUnits( units, useMils );
2459  }
2460 
2461  delete text;
2462  break;
2463  }
2464 
2465  // New format: feature points
2466  case T_pts:
2467  {
2468  wxPoint point;
2469 
2470  parseXY( &point.x, &point.y );
2471  dimension->SetStart( point );
2472  parseXY( &point.x, &point.y );
2473  dimension->SetEnd( point );
2474 
2475  NeedRIGHT();
2476  break;
2477  }
2478 
2479  case T_height:
2480  {
2481  wxCHECK_MSG( dimension->Type() == PCB_DIM_ALIGNED_T ||
2482  dimension->Type() == PCB_DIM_ORTHOGONAL_T, nullptr,
2483  wxT( "Invalid height token" ) );
2484  ALIGNED_DIMENSION* aligned = static_cast<ALIGNED_DIMENSION*>( dimension.get() );
2485  aligned->SetHeight( parseBoardUnits( "dimension height value" ) );
2486  NeedRIGHT();
2487  break;
2488  }
2489 
2490  case T_orientation:
2491  {
2492  wxCHECK_MSG( dimension->Type() == PCB_DIM_ORTHOGONAL_T, nullptr,
2493  wxT( "Invalid orientation token" ) );
2494  ORTHOGONAL_DIMENSION* ortho = static_cast<ORTHOGONAL_DIMENSION*>( dimension.get() );
2495 
2496  int orientation = parseInt( "orthogonal dimension orientation" );
2497  orientation = std::max( 0, std::min( 1, orientation ) );
2498  ortho->SetOrientation( static_cast<ORTHOGONAL_DIMENSION::DIR>( orientation ) );
2499  NeedRIGHT();
2500  break;
2501  }
2502 
2503  case T_format:
2504  {
2505  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2506  {
2507  switch( token )
2508  {
2509  case T_LEFT:
2510  continue;
2511 
2512  case T_prefix:
2513  NeedSYMBOLorNUMBER();
2514  dimension->SetPrefix( FromUTF8() );
2515  NeedRIGHT();
2516  break;
2517 
2518  case T_suffix:
2519  NeedSYMBOLorNUMBER();
2520  dimension->SetSuffix( FromUTF8() );
2521  NeedRIGHT();
2522  break;
2523 
2524  case T_units:
2525  {
2526  int mode = parseInt( "dimension units mode" );
2527  mode = std::max( 0, std::min( 4, mode ) );
2528  dimension->SetUnitsMode( static_cast<DIM_UNITS_MODE>( mode ) );
2529  NeedRIGHT();
2530  break;
2531  }
2532 
2533  case T_units_format:
2534  {
2535  int format = parseInt( "dimension units format" );
2536  format = std::max( 0, std::min( 3, format ) );
2537  dimension->SetUnitsFormat( static_cast<DIM_UNITS_FORMAT>( format ) );
2538  NeedRIGHT();
2539  break;
2540  }
2541 
2542  case T_precision:
2543  dimension->SetPrecision( parseInt( "dimension precision" ) );
2544  NeedRIGHT();
2545  break;
2546 
2547  case T_override_value:
2548  NeedSYMBOLorNUMBER();
2549  dimension->SetOverrideTextEnabled( true );
2550  dimension->SetOverrideText( FromUTF8() );
2551  NeedRIGHT();
2552  break;
2553 
2554  case T_suppress_zeroes:
2555  dimension->SetSuppressZeroes( true );
2556  break;
2557 
2558  default:
2559  Expecting( "prefix, suffix, units, units_format, precision, override_value, "
2560  "suppress_zeroes" );
2561  }
2562  }
2563  break;
2564  }
2565 
2566  case T_style:
2567  {
2568  // new format: default to keep text aligned off unless token is present
2569  dimension->SetKeepTextAligned( false );
2570 
2571  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2572  {
2573  switch( token )
2574  {
2575  case T_LEFT:
2576  continue;
2577 
2578  case T_thickness:
2579  dimension->SetLineThickness( parseBoardUnits( "extension line thickness" ) );
2580  NeedRIGHT();
2581  break;
2582 
2583  case T_arrow_length:
2584  dimension->SetArrowLength( parseBoardUnits( "arrow length" ) );
2585  NeedRIGHT();
2586  break;
2587 
2588  case T_text_position_mode:
2589  {
2590  int mode = parseInt( "dimension text position mode" );
2591  mode = std::max( 0, std::min( 3, mode ) );
2592  dimension->SetTextPositionMode( static_cast<DIM_TEXT_POSITION>( mode ) );
2593  NeedRIGHT();
2594  break;
2595  }
2596 
2597  case T_extension_height:
2598  {
2599  ALIGNED_DIMENSION* aligned = dynamic_cast<ALIGNED_DIMENSION*>( dimension.get() );
2600  wxCHECK_MSG( aligned, nullptr, wxT( "Invalid extension_height token" ) );
2601  aligned->SetExtensionHeight( parseBoardUnits( "extension height" ) );
2602  NeedRIGHT();
2603  break;
2604  }
2605 
2606  case T_extension_offset:
2607  dimension->SetExtensionOffset( parseBoardUnits( "extension offset" ) );
2608  NeedRIGHT();
2609  break;
2610 
2611  case T_keep_text_aligned:
2612  dimension->SetKeepTextAligned( true );
2613  break;
2614 
2615  case T_text_frame:
2616  {
2617  wxCHECK_MSG( dimension->Type() == PCB_DIM_LEADER_T, nullptr,
2618  wxT( "Invalid text_frame token" ) );
2619  LEADER* leader = static_cast<LEADER*>( dimension.get() );
2620 
2621  int textFrame = parseInt( "dimension text frame mode" );
2622  textFrame = std::max( 0, std::min( 3, textFrame ) );
2623  leader->SetTextFrame( static_cast<DIM_TEXT_FRAME>( textFrame ) );
2624  NeedRIGHT();
2625  break;
2626  }
2627 
2628  default:
2629  Expecting( "thickness, arrow_length, text_position_mode, extension_height, "
2630  "extension_offset" );
2631  }
2632  }
2633 
2634  break;
2635  }
2636 
2637  // Old format: feature1 stores a feature line. We only care about the origin.
2638  case T_feature1:
2639  {
2640  NeedLEFT();
2641  token = NextTok();
2642 
2643  if( token != T_pts )
2644  Expecting( T_pts );
2645 
2646  wxPoint point;
2647 
2648  parseXY( &point.x, &point.y );
2649  dimension->SetStart( point );
2650 
2651  parseXY( nullptr, nullptr ); // Ignore second point
2652  NeedRIGHT();
2653  NeedRIGHT();
2654  break;
2655  }
2656 
2657  // Old format: feature2 stores a feature line. We only care about the end point.
2658  case T_feature2:
2659  {
2660  NeedLEFT();
2661  token = NextTok();
2662 
2663  if( token != T_pts )
2664  Expecting( T_pts );
2665 
2666  wxPoint point;
2667 
2668  parseXY( &point.x, &point.y );
2669  dimension->SetEnd( point );
2670 
2671  parseXY( nullptr, nullptr ); // Ignore second point
2672 
2673  NeedRIGHT();
2674  NeedRIGHT();
2675  break;
2676  }
2677 
2678  case T_crossbar:
2679  {
2680  NeedLEFT();
2681  token = NextTok();
2682 
2683  if( token == T_pts )
2684  {
2685  // If we have a crossbar, we know we're an old aligned dimension
2686  ALIGNED_DIMENSION* aligned = static_cast<ALIGNED_DIMENSION*>( dimension.get() );
2687 
2688  // Old style: calculate height from crossbar
2689  wxPoint point1, point2;
2690  parseXY( &point1.x, &point1.y );
2691  parseXY( &point2.x, &point2.y );
2692  aligned->UpdateHeight( point2, point1 ); // Yes, backwards intentionally
2693  NeedRIGHT();
2694  }
2695 
2696  NeedRIGHT();
2697  break;
2698  }
2699 
2700  // Arrow: no longer saved; no-op
2701  case T_arrow1a:
2702  NeedLEFT();
2703  token = NextTok();
2704 
2705  if( token != T_pts )
2706  Expecting( T_pts );
2707 
2708  parseXY( nullptr, nullptr );
2709  parseXY( nullptr, nullptr );
2710  NeedRIGHT();
2711  NeedRIGHT();
2712  break;
2713 
2714  // Arrow: no longer saved; no-op
2715  case T_arrow1b:
2716  NeedLEFT();
2717  token = NextTok();
2718 
2719  if( token != T_pts )
2720  Expecting( T_pts );
2721 
2722  parseXY( nullptr, nullptr );
2723  parseXY( nullptr, nullptr );
2724  NeedRIGHT();
2725  NeedRIGHT();
2726  break;
2727 
2728  // Arrow: no longer saved; no-op
2729  case T_arrow2a:
2730  NeedLEFT();
2731  token = NextTok();
2732 
2733  if( token != T_pts )
2734  Expecting( T_pts );
2735 
2736  parseXY( nullptr, nullptr );
2737  parseXY( nullptr, nullptr );
2738  NeedRIGHT();
2739  NeedRIGHT();
2740  break;
2741 
2742  // Arrow: no longer saved; no-op
2743  case T_arrow2b:
2744  NeedLEFT();
2745  token = NextTok();
2746 
2747  if( token != T_pts )
2748  Expecting( T_pts );
2749 
2750  parseXY( nullptr, nullptr );
2751  parseXY( nullptr, nullptr );
2752  NeedRIGHT();
2753  NeedRIGHT();
2754  break;
2755 
2756  default:
2757  Expecting( "layer, tstamp, gr_text, feature1, feature2, crossbar, arrow1a, "
2758  "arrow1b, arrow2a, or arrow2b" );
2759  }
2760  }
2761 
2762  dimension->Update();
2763 
2764  return dimension.release();
2765 }
EDA_UNITS
Definition: common.h:198
KIID CurStrToKIID()
class ALIGNED_DIMENSION, a linear dimension (graphic item)
Definition: typeinfo.h:101
class LEADER, a leader dimension (graphic item)
Definition: typeinfo.h:102
wxPoint parseXY()
Function parseXY parses a coordinate pair (xy X Y) in board units (mm).
Definition: pcb_parser.cpp:220
int parseBoardUnits()
Definition: pcb_parser.h:275
void SetExtensionHeight(int aHeight)
void SetHeight(int aHeight)
Sets the distance from the feature points to the crossbar line.
#define NULL
A leader is a dimension-like object pointing to a specific point.
An orthogonal dimension is like an aligned dimension, but the extension lines are locked to the X or ...
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
TEXTE_PCB * parseTEXTE_PCB()
void UpdateHeight(const wxPoint &aCrossbarStart, const wxPoint &aCrossbarEnd)
Updates stored height basing on points coordinates.
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:248
class ORTHOGONAL_DIMENSION, a linear dimension constrained to x/y
Definition: typeinfo.h:104
int parseInt()
Definition: pcb_parser.h:313
For better understanding of the points that make a dimension:
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:127

References FetchUnitsFromString(), EDA_TEXT::GetText(), EDA_TEXT::GetTextPos(), INCHES, EDA_ITEM::m_Uuid, NULL, parseInt(), PCB_DIM_ALIGNED_T, PCB_DIM_LEADER_T, PCB_DIM_ORTHOGONAL_T, ALIGNED_DIMENSION::SetExtensionHeight(), ALIGNED_DIMENSION::SetHeight(), ALIGNED_DIMENSION::UpdateHeight(), wxPoint::x, and wxPoint::y.

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

139 {
140  char* tmp;
141 
142  errno = 0;
143 
144  double fval = strtod( CurText(), &tmp );
145 
146  if( errno )
147  {
148  wxString error;
149  error.Printf( _( "Invalid floating point number in\nfile: \"%s\"\nline: %d\noffset: %d" ),
150  GetChars( CurSource() ), CurLineNumber(), CurOffset() );
151 
152  THROW_IO_ERROR( error );
153  }
154 
155  if( CurText() == tmp )
156  {
157  wxString error;
158  error.Printf( _( "Missing floating point number in\nfile: \"%s\"\nline: %d\noffset: %d" ),
159  GetChars( CurSource() ), CurLineNumber(), CurOffset() );
160 
161  THROW_IO_ERROR( error );
162  }
163 
164  return fval;
165 }
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
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

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

265  {
266  NeedNUMBER( aExpected );
267  return parseDouble();
268  }
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:138

References parseDouble().

◆ parseDouble() [3/3]

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

Definition at line 270 of file pcb_parser.h.

271  {
272  return parseDouble( GetTokenText( aToken ) );
273  }
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:138
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.

We continue to parse the status field but it is no longer written

Definition at line 2096 of file pcb_parser.cpp.

2097 {
2098  wxCHECK_MSG( CurTok() == T_gr_arc || CurTok() == T_gr_circle || CurTok() == T_gr_curve ||
2099  CurTok() == T_gr_rect || CurTok() == T_gr_line || CurTok() == T_gr_poly, NULL,
2100  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as DRAWSEGMENT." ) );
2101 
2102  T token;
2103  wxPoint pt;
2104  std::unique_ptr< DRAWSEGMENT > segment( new DRAWSEGMENT( NULL ) );
2105 
2106  switch( CurTok() )
2107  {
2108  case T_gr_arc:
2109  segment->SetShape( S_ARC );
2110  NeedLEFT();
2111  token = NextTok();
2112 
2113  // the start keyword actually gives the arc center
2114  // Allows also T_center for future change
2115  if( token != T_start && token != T_center )
2116  Expecting( T_start );
2117 
2118  pt.x = parseBoardUnits( "X coordinate" );
2119  pt.y = parseBoardUnits( "Y coordinate" );
2120  segment->SetCenter( pt );
2121  NeedRIGHT();
2122  NeedLEFT();
2123  token = NextTok();
2124 
2125  if( token != T_end ) // the end keyword actually gives the starting point of the arc
2126  Expecting( T_end );
2127 
2128  pt.x = parseBoardUnits( "X coordinate" );
2129  pt.y = parseBoardUnits( "Y coordinate" );
2130  segment->SetArcStart( pt );
2131  NeedRIGHT();
2132  break;
2133 
2134  case T_gr_circle:
2135  segment->SetShape( S_CIRCLE );
2136  NeedLEFT();
2137  token = NextTok();
2138 
2139  if( token != T_center )
2140  Expecting( T_center );
2141 
2142  pt.x = parseBoardUnits( "X coordinate" );
2143  pt.y = parseBoardUnits( "Y coordinate" );
2144  segment->SetCenter( pt );
2145  NeedRIGHT();
2146  NeedLEFT();
2147 
2148  token = NextTok();
2149 
2150  if( token != T_end )
2151  Expecting( T_end );
2152 
2153  pt.x = parseBoardUnits( "X coordinate" );
2154  pt.y = parseBoardUnits( "Y coordinate" );
2155  segment->SetEnd( pt );
2156  NeedRIGHT();
2157  break;
2158 
2159  case T_gr_curve:
2160  segment->SetShape( S_CURVE );
2161  NeedLEFT();
2162  token = NextTok();
2163 
2164  if( token != T_pts )
2165  Expecting( T_pts );
2166 
2167  segment->SetStart( parseXY() );
2168  segment->SetBezControl1( parseXY() );
2169  segment->SetBezControl2( parseXY() );
2170  segment->SetEnd( parseXY() );
2171  NeedRIGHT();
2172  break;
2173 
2174  case T_gr_rect:
2175  segment->SetShape( S_RECT );
2176  NeedLEFT();
2177  token = NextTok();
2178 
2179  if( token != T_start )
2180  Expecting( T_start );
2181 
2182  pt.x = parseBoardUnits( "X coordinate" );
2183  pt.y = parseBoardUnits( "Y coordinate" );
2184  segment->SetStart( pt );
2185  NeedRIGHT();
2186  NeedLEFT();
2187  token = NextTok();
2188 
2189  if( token != T_end )
2190  Expecting( T_end );
2191 
2192  pt.x = parseBoardUnits( "X coordinate" );
2193  pt.y = parseBoardUnits( "Y coordinate" );
2194  segment->SetEnd( pt );
2195  NeedRIGHT();
2196  break;
2197 
2198  case T_gr_line:
2199  // Default DRAWSEGMENT type is S_SEGMENT.
2200  NeedLEFT();
2201  token = NextTok();
2202 
2203  if( token != T_start )
2204  Expecting( T_start );
2205 
2206  pt.x = parseBoardUnits( "X coordinate" );
2207  pt.y = parseBoardUnits( "Y coordinate" );
2208  segment->SetStart( pt );
2209  NeedRIGHT();
2210  NeedLEFT();
2211  token = NextTok();
2212 
2213  if( token != T_end )
2214  Expecting( T_end );
2215 
2216  pt.x = parseBoardUnits( "X coordinate" );
2217  pt.y = parseBoardUnits( "Y coordinate" );
2218  segment->SetEnd( pt );
2219  NeedRIGHT();
2220  break;
2221 
2222  case T_gr_poly:
2223  {
2224  segment->SetShape( S_POLYGON );
2225  segment->SetWidth( 0 ); // this is the default value. will be (perhaps) modified later
2226  NeedLEFT();
2227  token = NextTok();
2228 
2229  if( token != T_pts )
2230  Expecting( T_pts );
2231 
2232  std::vector< wxPoint > pts;
2233 
2234  while( (token = NextTok()) != T_RIGHT )
2235  pts.push_back( parseXY() );
2236 
2237  segment->SetPolyPoints( pts );
2238  }
2239  break;
2240 
2241  default:
2242  Expecting( "gr_arc, gr_circle, gr_curve, gr_line, gr_poly, or gp_rect" );
2243  }
2244 
2245  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2246  {
2247  if( token != T_LEFT )
2248  Expecting( T_LEFT );
2249 
2250  token = NextTok();
2251 
2252  switch( token )
2253  {
2254  case T_angle:
2255  segment->SetAngle( parseDouble( "segment angle" ) * 10.0 );
2256  break;
2257 
2258  case T_layer:
2259  segment->SetLayer( parseBoardItemLayer() );
2260  break;
2261 
2262  case T_width:
2263  segment->SetWidth( parseBoardUnits( T_width ) );
2264  break;
2265 
2266  case T_tstamp:
2267  NextTok();
2268  const_cast<KIID&>( segment->m_Uuid ) = CurStrToKIID();
2269  break;
2270 
2272  case T_status:
2273  segment->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
2274  break;
2275 
2276  default:
2277  Expecting( "layer, width, tstamp, or status" );
2278  }
2279 
2280  NeedRIGHT();
2281  }
2282 
2283  // Only filled polygons may have a zero-line width
2284  // This is not permitted in KiCad but some external tools generate invalid
2285  // files.
2286  // However in custom pad shapes, zero-line width is allowed for filled circles
2287  if( segment->GetShape() != S_POLYGON && segment->GetWidth() == 0 &&
2288  !( segment->GetShape() == S_CIRCLE && aAllowCirclesZeroWidth ) )
2289  {
2290  segment->SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) );
2291  }
2292 
2293  return segment.release();
2294 }
KIID CurStrToKIID()
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:220
#define DEFAULT_LINE_WIDTH
int parseBoardUnits()
Definition: pcb_parser.h:275
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:138
long parseHex()
Definition: pcb_parser.h:324
static constexpr int Millimeter2iu(double mm)

References DEFAULT_LINE_WIDTH, Millimeter2iu(), NULL, parseDouble(), parseHex(), S_ARC, S_CIRCLE, S_CURVE, S_POLYGON, S_RECT, 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 267 of file pcb_parser.cpp.

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

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

◆ parseEDGE_MODULE()

EDGE_MODULE * PCB_PARSER::parseEDGE_MODULE ( )
private

We continue to parse the status field but it is no longer written

Definition at line 3201 of file pcb_parser.cpp.

3202 {
3203  wxCHECK_MSG( CurTok() == T_fp_arc || CurTok() == T_fp_circle || CurTok() == T_fp_curve ||
3204  CurTok() == T_fp_rect || CurTok() == T_fp_line || CurTok() == T_fp_poly, NULL,
3205  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as EDGE_MODULE." ) );
3206 
3207  wxPoint pt;
3208  T token;
3209 
3210  std::unique_ptr< EDGE_MODULE > segment( new EDGE_MODULE( NULL ) );
3211 
3212  switch( CurTok() )
3213  {
3214  case T_fp_arc:
3215  segment->SetShape( S_ARC );
3216  NeedLEFT();
3217  token = NextTok();
3218 
3219  // the start keyword actually gives the arc center
3220  // Allows also T_center for future change
3221  if( token != T_start && token != T_center )
3222  Expecting( T_start );
3223 
3224  pt.x = parseBoardUnits( "X coordinate" );
3225  pt.y = parseBoardUnits( "Y coordinate" );
3226  segment->SetStart0( pt );
3227  NeedRIGHT();
3228  NeedLEFT();
3229  token = NextTok();
3230 
3231  if( token != T_end ) // end keyword actually gives the starting point of the arc
3232  Expecting( T_end );
3233 
3234  pt.x = parseBoardUnits( "X coordinate" );
3235  pt.y = parseBoardUnits( "Y coordinate" );
3236  segment->SetEnd0( pt );
3237  NeedRIGHT();
3238  NeedLEFT();
3239  token = NextTok();
3240 
3241  if( token != T_angle )
3242  Expecting( T_angle );
3243 
3244  // Setting angle will set m_ThirdPoint0, so must be done after setting
3245  // m_Start0 and m_End0
3246  segment->SetAngle( parseDouble( "segment angle" ) * 10.0 );
3247  NeedRIGHT();
3248  break;
3249 
3250  case T_fp_circle:
3251  segment->SetShape( S_CIRCLE );
3252  NeedLEFT();
3253  token = NextTok();
3254 
3255  if( token != T_center )
3256  Expecting( T_center );
3257 
3258  pt.x = parseBoardUnits( "X coordinate" );
3259  pt.y = parseBoardUnits( "Y coordinate" );
3260  segment->SetStart0( pt );
3261  NeedRIGHT();
3262  NeedLEFT();
3263  token = NextTok();
3264 
3265  if( token != T_end )
3266  Expecting( T_end );
3267 
3268  pt.x = parseBoardUnits( "X coordinate" );
3269  pt.y = parseBoardUnits( "Y coordinate" );
3270  segment->SetEnd0( pt );
3271  NeedRIGHT();
3272  break;
3273 
3274  case T_fp_curve:
3275  segment->SetShape( S_CURVE );
3276  NeedLEFT();
3277  token = NextTok();
3278 
3279  if( token != T_pts )
3280  Expecting( T_pts );
3281 
3282  segment->SetStart0( parseXY() );
3283  segment->SetBezier0_C1( parseXY() );
3284  segment->SetBezier0_C2( parseXY() );
3285  segment->SetEnd0( parseXY() );
3286  NeedRIGHT();
3287  break;
3288 
3289  case T_fp_rect:
3290  segment->SetShape( S_RECT );
3291  NeedLEFT();
3292  token = NextTok();
3293 
3294  if( token != T_start )
3295  Expecting( T_start );
3296 
3297  pt.x = parseBoardUnits( "X coordinate" );
3298  pt.y = parseBoardUnits( "Y coordinate" );
3299  segment->SetStart0( pt );
3300 
3301  NeedRIGHT();
3302  NeedLEFT();
3303  token = NextTok();
3304 
3305  if( token != T_end )
3306  Expecting( T_end );
3307 
3308  pt.x = parseBoardUnits( "X coordinate" );
3309  pt.y = parseBoardUnits( "Y coordinate" );
3310  segment->SetEnd0( pt );
3311  NeedRIGHT();
3312  break;
3313 
3314  case T_fp_line:
3315  // Default DRAWSEGMENT type is S_SEGMENT.
3316  NeedLEFT();
3317  token = NextTok();
3318 
3319  if( token != T_start )
3320  Expecting( T_start );
3321 
3322  pt.x = parseBoardUnits( "X coordinate" );
3323  pt.y = parseBoardUnits( "Y coordinate" );
3324  segment->SetStart0( pt );
3325 
3326  NeedRIGHT();
3327  NeedLEFT();
3328  token = NextTok();
3329 
3330  if( token != T_end )
3331  Expecting( T_end );
3332 
3333  pt.x = parseBoardUnits( "X coordinate" );
3334  pt.y = parseBoardUnits( "Y coordinate" );
3335  segment->SetEnd0( pt );
3336  NeedRIGHT();
3337  break;
3338 
3339  case T_fp_poly:
3340  {
3341  segment->SetShape( S_POLYGON );
3342  NeedLEFT();
3343  token = NextTok();
3344 
3345  if( token != T_pts )
3346  Expecting( T_pts );
3347 
3348  std::vector< wxPoint > pts;
3349 
3350  while( (token = NextTok()) != T_RIGHT )
3351  pts.push_back( parseXY() );
3352 
3353  segment->SetPolyPoints( pts );
3354  }
3355  break;
3356 
3357  default:
3358  Expecting( "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, or fp_rect" );
3359  }
3360 
3361  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3362  {
3363  if( token != T_LEFT )
3364  Expecting( T_LEFT );
3365 
3366  token = NextTok();
3367 
3368  switch( token )
3369  {
3370  case T_layer:
3371  segment->SetLayer( parseBoardItemLayer() );
3372  break;
3373 
3374  case T_width:
3375  segment->SetWidth( parseBoardUnits( T_width ) );
3376  break;
3377 
3378  case T_tstamp:
3379  NextTok();
3380  const_cast<KIID&>( segment->m_Uuid ) = CurStrToKIID();
3381  break;
3382 
3384  case T_status:
3385  segment->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
3386  break;
3387 
3388  default:
3389  Expecting( "layer, width or tstamp" );
3390  }
3391 
3392  NeedRIGHT();
3393  }
3394 
3395  // Only filled shapes may have a zero-line width. While not permitted in KiCad, some
3396  // external tools generate invalid files.
3397  if( segment->GetShape() != S_RECT
3398  && segment->GetShape() != S_CIRCLE
3399  && segment->GetShape() != S_POLYGON
3400  && segment->GetWidth() == 0 )
3401  {
3402  segment->SetWidth( Millimeter2iu( DEFAULT_LINE_WIDTH ) );
3403  }
3404 
3405  return segment.release();
3406 }
KIID CurStrToKIID()
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:220
#define DEFAULT_LINE_WIDTH
int parseBoardUnits()
Definition: pcb_parser.h:275
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:138
long parseHex()
Definition: pcb_parser.h:324
static constexpr int Millimeter2iu(double mm)

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

◆ parseGeneralSection()

void PCB_PARSER::parseGeneralSection ( )
private

Definition at line 851 of file pcb_parser.cpp.

852 {
853  wxCHECK_RET( CurTok() == T_general,
854  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
855  wxT( " as a general section." ) );
856 
857  T token;
858 
859  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
860  {
861  if( token != T_LEFT )
862  Expecting( T_LEFT );
863 
864  token = NextTok();
865 
866  switch( token )
867  {
868  case T_thickness:
870  NeedRIGHT();
871  break;
872 
873  default: // Skip everything but the board thickness.
874  while( ( token = NextTok() ) != T_RIGHT )
875  {
876  if( !IsSymbol( token ) && token != T_NUMBER )
877  Expecting( "symbol or number" );
878  }
879  }
880  }
881 }
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:514
void SetBoardThickness(int aThickness)
int parseBoardUnits()
Definition: pcb_parser.h:275
BOARD * m_board
Definition: pcb_parser.h:76

◆ parseGROUP()

void PCB_PARSER::parseGROUP ( )
private

Definition at line 3948 of file pcb_parser.cpp.

3949 {
3950  wxCHECK_RET( CurTok() == T_group,
3951  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as PCB_GROUP." ) );
3952 
3953  wxPoint pt;
3954  T token;
3955 
3956  m_groupInfos.push_back( GroupInfo() );
3957  GroupInfo& groupInfo = m_groupInfos.back();
3958 
3959  token = NextTok();
3960 
3961  if( token != T_LEFT )
3962  {
3963  // Optional group name present.
3964 
3965  if( !IsSymbol( token ) )
3966  Expecting( DSN_SYMBOL );
3967 
3968  groupInfo.name = FromUTF8();
3969  }
3970 
3971  NeedLEFT();
3972  token = NextTok();
3973 
3974  if( token != T_id )
3975  {
3976  Expecting( T_id );
3977  }
3978 
3979  NextTok();
3980  groupInfo.uuid = CurStrToKIID();
3981  NeedRIGHT();
3982 
3983  NeedLEFT();
3984  token = NextTok();
3985 
3986  if( token != T_members )
3987  {
3988  Expecting( T_members );
3989  }
3990 
3991  while( ( token = NextTok() ) != T_RIGHT )
3992  {
3993  // This token is the Uuid of the item in the group.
3994  // Since groups are serialized at the end of the file, the
3995  // Uuid should already have been seen and exist in the board.
3996  KIID uuid( CurStr() );
3997  groupInfo.memberUuids.push_back( uuid );
3998  }
3999 
4000  NeedRIGHT();
4001 }
std::vector< GroupInfo > m_groupInfos
Definition: pcb_parser.h:99
KIID CurStrToKIID()
Definition: common.h:68

References DSN_SYMBOL, PCB_PARSER::GroupInfo::memberUuids, PCB_PARSER::GroupInfo::name, and PCB_PARSER::GroupInfo::uuid.

◆ parseHeader()

void PCB_PARSER::parseHeader ( )
private

Definition at line 812 of file pcb_parser.cpp.

813 {
814  wxCHECK_RET( CurTok() == T_kicad_pcb,
815  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a header." ) );
816 
817  NeedLEFT();
818 
819  T tok = NextTok();
820  if( tok == T_version )
821  {
822  m_requiredVersion = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
824  NeedRIGHT();
825 
826  NeedLEFT();
827  NeedSYMBOL();
828  NeedSYMBOL();
829 
830  // Older formats included build data
832  NeedSYMBOL();
833 
834  NeedRIGHT();
835  }
836  else
837  {
840 
841  // Skip the host name and host build version information.
842  NeedSYMBOL();
843  NeedSYMBOL();
844  NeedRIGHT();
845  }
846 
848 }
void SetFileFormatVersionAtLoad(int aVersion)
Definition: class_board.h:297
#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:81
#define BOARD_FILE_HOST_VERSION
Earlier files than this include the host tag.
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:82
BOARD * m_board
Definition: pcb_parser.h:76
int parseInt()
Definition: pcb_parser.h:313

References BOARD_FILE_HOST_VERSION, parseInt(), and SEXPR_BOARD_FILE_VERSION.

◆ parseHex()

long PCB_PARSER::parseHex ( )
inlineprivate

Definition at line 324 of file pcb_parser.h.

325  {
326  NextTok();
327  return strtol( CurText(), NULL, 16 );
328  }
#define NULL

References NULL.

◆ parseInt() [1/2]

int PCB_PARSER::parseInt ( )
inlineprivate

Definition at line 313 of file pcb_parser.h.

314  {
315  return (int)strtol( CurText(), NULL, 10 );
316  }
#define NULL

References NULL.

Referenced by parseInt().

◆ parseInt() [2/2]

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

Definition at line 318 of file pcb_parser.h.

319  {
320  NeedNUMBER( aExpected );
321  return parseInt();
322  }
int parseInt()
Definition: pcb_parser.h:313

References parseInt().

◆ parseLayer()

void PCB_PARSER::parseLayer ( LAYER aLayer)
private

Definition at line 1048 of file pcb_parser.cpp.

1049 {
1050  T token;
1051 
1052  std::string name;
1053  std::string userName;
1054  std::string type;
1055  bool isVisible = true;
1056 
1057  aLayer->clear();
1058 
1059  if( CurTok() != T_LEFT )
1060  Expecting( T_LEFT );
1061 
1062  // this layer_num is not used, we DO depend on LAYER_T however.
1063  LAYER_NUM layer_num = parseInt( "layer index" );
1064 
1065  NeedSYMBOLorNUMBER();
1066  name = CurText();
1067 
1068  NeedSYMBOL();
1069  type = CurText();
1070 
1071  token = NextTok();
1072 
1073  // @todo Figure out why we are looking for a hide token in the layer definition.
1074  if( token == T_hide )
1075  {
1076  isVisible = false;
1077  NeedRIGHT();
1078  }
1079  else if( token == T_STRING )
1080  {
1081  userName = CurText();
1082  NeedRIGHT();
1083  }
1084  else if( token != T_RIGHT )
1085  {
1086  Expecting( "hide, user defined name, or )" );
1087  }
1088 
1089  aLayer->m_name = FROM_UTF8( name.c_str() );
1090  aLayer->m_type = LAYER::ParseType( type.c_str() );
1091  aLayer->m_number = layer_num;
1092  aLayer->m_visible = isVisible;
1093 
1094  if( !userName.empty() )
1095  aLayer->m_userName = FROM_UTF8( userName.c_str() );
1096 
1097  // The canonical name will get reset back to the default for copper layer on the next
1098  // save. The user defined name is now a separate optional layer token from the canonical
1099  // name.
1100  if( aLayer->m_name != LSET::Name( static_cast<PCB_LAYER_ID>( aLayer->m_number ) ) )
1101  aLayer->m_userName = aLayer->m_name;
1102 }
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 canonical name of the layer.
Definition: class_board.h:102
LAYER_T m_type
The type of the layer.
Definition: class_board.h:104
static const wxChar * Name(PCB_LAYER_ID aLayerId)
Return the fixed name association with aLayerId.
Definition: lset.cpp:81
bool m_visible
Definition: class_board.h:105
wxString m_userName
The user defined name of the layer.
Definition: class_board.h:103
static LAYER_T ParseType(const char *aType)
Convert a string to a LAYER_T.
int LAYER_NUM
This can be replaced with int and removed.
void clear()
Definition: class_board.h:82
const char * name
Definition: DXF_plotter.cpp:60
int m_number
The layer ID.
Definition: class_board.h:106
int parseInt()
Definition: pcb_parser.h:313

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

◆ parseLayers()

void PCB_PARSER::parseLayers ( )
private

Definition at line 1351 of file pcb_parser.cpp.

1352 {
1353  wxCHECK_RET( CurTok() == T_layers,
1354  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as layers." ) );
1355 
1356  T token;
1357  LSET visibleLayers;
1358  LSET enabledLayers;
1359  int copperLayerCount = 0;
1360  LAYER layer;
1361  bool anyHidden = false;
1362 
1363  std::unordered_map< std::string, std::string > v3_layer_names;
1364  std::vector<LAYER> cu;
1365 
1366  createOldLayerMapping( v3_layer_names );
1367 
1368  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1369  {
1370  parseLayer( &layer );
1371 
1372  if( layer.m_type == LT_UNDEFINED ) // it's a non-copper layer
1373  break;
1374 
1375  cu.push_back( layer ); // it's copper
1376  }
1377 
1378  // All Cu layers are parsed, but not the non-cu layers here.
1379 
1380  // The original *.kicad_pcb file format and the inverted
1381  // Cu stack format both have all the Cu layers first, so use this
1382  // trick to handle either. The layer number in the (layers ..)
1383  // s-expression element are ignored.
1384  if( cu.size() )
1385  {
1386  // Rework the layer numbers, which changed when the Cu stack
1387  // was flipped. So we instead use position in the list.
1388  cu[cu.size()-1].m_number = B_Cu;
1389 
1390  for( unsigned i=0; i < cu.size()-1; ++i )
1391  {
1392  cu[i].m_number = i;
1393  }
1394 
1395  for( std::vector<LAYER>::const_iterator it = cu.begin(); it<cu.end(); ++it )
1396  {
1397  enabledLayers.set( it->m_number );
1398 
1399  if( it->m_visible )
1400  visibleLayers.set( it->m_number );
1401  else
1402  anyHidden = true;
1403 
1404  m_board->SetLayerDescr( PCB_LAYER_ID( it->m_number ), *it );
1405 
1406  UTF8 name = it->m_name;
1407 
1408  m_layerIndices[ name ] = PCB_LAYER_ID( it->m_number );
1409  m_layerMasks[ name ] = LSET( PCB_LAYER_ID( it->m_number ) );
1410  }
1411 
1412  copperLayerCount = cu.size();
1413  }
1414 
1415  // process non-copper layers
1416  while( token != T_RIGHT )
1417  {
1418  LAYER_ID_MAP::const_iterator it = m_layerIndices.find( UTF8( layer.m_name ) );
1419 
1420  if( it == m_layerIndices.end() )
1421  {
1422  auto new_layer_it = v3_layer_names.find( layer.m_name.ToStdString() );
1423 
1424  if( new_layer_it != v3_layer_names.end() )
1425  it = m_layerIndices.find( new_layer_it->second );
1426 
1427  if( it == m_layerIndices.end() )
1428  {
1429  wxString error = wxString::Format(
1430  _( "Layer \"%s\" in file \"%s\" at line %d, is not in fixed layer hash" ),
1431  GetChars( layer.m_name ),
1432  GetChars( CurSource() ),
1433  CurLineNumber(),
1434  CurOffset()
1435  );
1436 
1437  THROW_IO_ERROR( error );
1438  }
1439 
1440  // If we are here, then we have found a translated layer name. Put it in the maps so that
1441  // items on this layer get the appropriate layer ID number
1442  m_layerIndices[ UTF8( layer.m_name ) ] = it->second;
1443  m_layerMasks[ UTF8( layer.m_name ) ] = it->second;
1444  layer.m_name = it->first;
1445  }
1446 
1447  layer.m_number = it->second;
1448  enabledLayers.set( layer.m_number );
1449 
1450  if( layer.m_visible )
1451  visibleLayers.set( layer.m_number );
1452  else
1453  anyHidden = true;
1454 
1455  m_board->SetLayerDescr( it->second, layer );
1456 
1457  token = NextTok();
1458 
1459  if( token != T_LEFT )
1460  break;
1461 
1462  parseLayer( &layer );
1463  }
1464 
1465  // We need at least 2 copper layers and there must be an even number of them.
1466  if( copperLayerCount < 2 || (copperLayerCount % 2) != 0 )
1467  {
1468  wxString err = wxString::Format(
1469  _( "%d is not a valid layer count" ), copperLayerCount );
1470 
1471  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
1472  }
1473 
1474  m_board->SetCopperLayerCount( copperLayerCount );
1475  m_board->SetEnabledLayers( enabledLayers );
1476 
1477  // Only set this if any layers were explicitly marked as hidden. Otherwise, we want to leave
1478  // this alone; default visibility will show everything
1479  if( anyHidden )
1480  m_board->m_LegacyVisibleLayers = visibleLayers;
1481 }
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 canonical name of the layer.
Definition: class_board.h:102
LAYER_T m_type
The type of the layer.
Definition: class_board.h:104
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)
PCB_LAYER_ID
A quick note on layer IDs:
LSET is a set of PCB_LAYER_IDs.
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:162
bool SetLayerDescr(PCB_LAYER_ID aIndex, const LAYER &aLayer)
Return the type of the copper layer given by aLayer.
bool m_visible
Definition: class_board.h:105
void parseLayer(LAYER *aLayer)
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:201
Container to hold information pertinent to a layer of a BOARD.
Definition: class_board.h:75
#define _(s)
Definition: 3d_actions.cpp:33
BOARD * m_board
Definition: pcb_parser.h:76
LAYER_ID_MAP m_layerIndices
map layer name to it's index
Definition: pcb_parser.h:77
int m_number
The layer ID.
Definition: class_board.h:106
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
LSET m_LegacyVisibleLayers
Visibility settings stored in board prior to 6.0, only used for loading legacy files.
Definition: class_board.h:275
void SetEnabledLayers(LSET aLayerMask)
A proxy function that calls the correspondent function in m_BoardSettings Changes the bit-mask of ena...
LSET_MAP m_layerMasks
map layer names to their masks
Definition: pcb_parser.h:78

References _, B_Cu, Format(), GetChars(), LT_UNDEFINED, LAYER::m_name, LAYER::m_number, LAYER::m_type, LAYER::m_visible, name, 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 2768 of file pcb_parser.cpp.

2769 {
2770  try
2771  {
2772  return parseMODULE_unchecked( aInitialComments );
2773  }
2774  catch( const PARSE_ERROR& parse_error )
2775  {
2776  if( m_tooRecent )
2777  throw FUTURE_FORMAT_ERROR( parse_error, GetRequiredVersion() );
2778  else
2779  throw;
2780  }
2781 }
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:81
wxString GetRequiredVersion()
Return a string representing the version of kicad required to open this file.
Definition: pcb_parser.cpp:196
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 2784 of file pcb_parser.cpp.

2785 {
2786  wxCHECK_MSG( CurTok() == T_module, NULL,
2787  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as MODULE." ) );
2788 
2789  wxString name;
2790  wxPoint pt;
2791  T token;
2792  LIB_ID fpid;
2793  int attributes = 0;
2794 
2795  std::unique_ptr<MODULE> module( new MODULE( m_board ) );
2796 
2797  std::map<wxString, wxString> properties;
2798 
2799  module->SetInitialComments( aInitialComments );
2800 
2801  token = NextTok();
2802 
2803  if( !IsSymbol( token ) && token != T_NUMBER )
2804  Expecting( "symbol|number" );
2805 
2806  name = FromUTF8();
2807 
2808  if( !name.IsEmpty() && fpid.Parse( name, LIB_ID::ID_PCB, true ) >= 0 )
2809  {
2810  wxString error;
2811  error.Printf( _( "Invalid footprint ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
2812  GetChars( CurSource() ), CurLineNumber(), CurOffset() );
2813  THROW_IO_ERROR( error );
2814  }
2815 
2816  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2817  {
2818  if( token == T_LEFT )
2819  token = NextTok();
2820 
2821  switch( token )
2822  {
2823  case T_version:
2824  {
2825  // Theoretically a module nested in a PCB could declare its own version, though
2826  // as of writing this comment we don't do that. Just in case, take the greater
2827  // version.
2828  int this_version = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
2829  NeedRIGHT();
2830  m_requiredVersion = std::max( m_requiredVersion, this_version );
2832  break;
2833  }
2834 
2835  case T_locked:
2836  module->SetLocked( true );
2837  break;
2838 
2839  case T_placed:
2840  module->SetIsPlaced( true );
2841  break;
2842 
2843  case T_layer:
2844  {
2845  // Footprints can be only on the front side or the back side.
2846  // but because we can find some stupid layer in file, ensure a
2847  // acceptable layer is set for the footprint
2849  module->SetLayer( layer == B_Cu ? B_Cu : F_Cu );
2850  }
2851  NeedRIGHT();
2852  break;
2853 
2854  case T_tedit:
2855  module->SetLastEditTime( parseHex() );
2856  NeedRIGHT();
2857  break;
2858 
2859  case T_tstamp:
2860  NextTok();
2861  const_cast<KIID&>( module->m_Uuid ) = CurStrToKIID();
2862  NeedRIGHT();
2863  break;
2864 
2865  case T_at:
2866  pt.x = parseBoardUnits( "X coordinate" );
2867  pt.y = parseBoardUnits( "Y coordinate" );
2868  module->SetPosition( pt );
2869  token = NextTok();
2870 
2871  if( token == T_NUMBER )
2872  {
2873  module->SetOrientation( parseDouble() * 10.0 );
2874  NeedRIGHT();
2875  }
2876  else if( token != T_RIGHT )
2877  {
2878  Expecting( T_RIGHT );
2879  }
2880 
2881  break;
2882 
2883  case T_descr:
2884  NeedSYMBOLorNUMBER(); // some symbols can be 0508, so a number is also a symbol here
2885  module->SetDescription( FromUTF8() );
2886  NeedRIGHT();
2887  break;
2888 
2889  case T_tags:
2890  NeedSYMBOLorNUMBER(); // some symbols can be 0508, so a number is also a symbol here
2891  module->SetKeywords( FromUTF8() );
2892  NeedRIGHT();
2893  break;
2894 
2895  case T_property:
2896  properties.insert( parseProperty() );
2897  break;
2898 
2899  case T_path:
2900  NeedSYMBOLorNUMBER(); // Paths can be numerical so a number is also a symbol here
2901  module->SetPath( KIID_PATH( FromUTF8() ) );
2902  NeedRIGHT();
2903  break;
2904 
2905  case T_autoplace_cost90:
2906  module->SetPlacementCost90( parseInt( "auto place cost at 90 degrees" ) );
2907  NeedRIGHT();
2908  break;
2909 
2910  case T_autoplace_cost180:
2911  module->SetPlacementCost180( parseInt( "auto place cost at 180 degrees" ) );
2912  NeedRIGHT();
2913  break;
2914 
2915  case T_solder_mask_margin:
2916  module->SetLocalSolderMaskMargin( parseBoardUnits( "local solder mask margin value" ) );
2917  NeedRIGHT();
2918  break;
2919 
2920  case T_solder_paste_margin:
2921  module->SetLocalSolderPasteMargin(
2922  parseBoardUnits( "local solder paste margin value" ) );
2923  NeedRIGHT();
2924  break;
2925 
2926  case T_solder_paste_ratio:
2927  module->SetLocalSolderPasteMarginRatio(
2928  parseDouble( "local solder paste margin ratio value" ) );
2929  NeedRIGHT();
2930  break;
2931 
2932  case T_clearance:
2933  module->SetLocalClearance( parseBoardUnits( "local clearance value" ) );
2934  NeedRIGHT();
2935  break;
2936 
2937  case T_zone_connect:
2938  module->SetZoneConnection( (ZONE_CONNECTION) parseInt( "zone connection value" ) );
2939  NeedRIGHT();
2940  break;
2941 
2942  case T_thermal_width:
2943  module->SetThermalWidth( parseBoardUnits( "thermal width value" ) );
2944  NeedRIGHT();
2945  break;
2946 
2947  case T_thermal_gap:
2948  module->SetThermalGap( parseBoardUnits( "thermal gap value" ) );
2949  NeedRIGHT();
2950  break;
2951 
2952  case T_attr:
2953  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2954  {
2955  switch( token )
2956  {
2957  case T_virtual: // legacy token prior to version 20200826
2959  break;
2960 
2961  case T_through_hole:
2962  attributes |= MOD_THROUGH_HOLE;
2963  break;
2964 
2965  case T_smd:
2966  attributes |= MOD_SMD;
2967  break;
2968 
2969  case T_board_only:
2970  attributes |= MOD_BOARD_ONLY;
2971  break;
2972 
2973  case T_exclude_from_pos_files:
2974  attributes |= MOD_EXCLUDE_FROM_POS_FILES;
2975  break;
2976 
2977  case T_exclude_from_bom:
2978  attributes |= MOD_EXCLUDE_FROM_BOM;
2979  break;
2980 
2981  default:
2982  Expecting( "through_hole, smd, virtual, board_only, exclude_from_pos_files "
2983  "or exclude_from_bom" );
2984  }
2985  }
2986  break;
2987 
2988  case T_fp_text:
2989  {
2990  TEXTE_MODULE* text = parseTEXTE_MODULE();
2991  text->SetParent( module.get() );
2992  double orientation = text->GetTextAngle();
2993  orientation -= module->GetOrientation();
2994  text->SetTextAngle( orientation );
2995  text->SetDrawCoord();
2996 
2997  switch( text->GetType() )
2998  {
3000  module->Reference() = *text;
3001  const_cast<KIID&>( module->Reference().m_Uuid ) = text->m_Uuid;
3002  delete text;
3003  break;
3004 
3006  module->Value() = *text;
3007  const_cast<KIID&>( module->Value().m_Uuid ) = text->m_Uuid;
3008  delete text;
3009  break;
3010 
3011  default:
3012  module->Add( text, ADD_MODE::APPEND );
3013  }
3014  }
3015  break;
3016 
3017  case T_fp_arc:
3018  {
3019  EDGE_MODULE* em = parseEDGE_MODULE();
3020 
3021  // Drop 0 and NaN angles as these can corrupt/crash the schematic
3022  if( std::isnormal( em->GetAngle() ) )
3023  {
3024  em->SetParent( module.get() );
3025  em->SetDrawCoord();
3026  module->Add( em, ADD_MODE::APPEND );
3027  }
3028  else
3029  delete em;
3030  }
3031 
3032  break;
3033 
3034  case T_fp_circle:
3035  case T_fp_curve:
3036  case T_fp_rect:
3037  case T_fp_line:
3038  case T_fp_poly:
3039  {
3040  EDGE_MODULE* em = parseEDGE_MODULE();
3041  em->SetParent( module.get() );
3042  em->SetDrawCoord();
3043  module->Add( em, ADD_MODE::APPEND );
3044  }
3045 
3046  break;
3047 
3048  case T_pad:
3049  {
3050  D_PAD* pad = parseD_PAD( module.get() );
3051  pt = pad->GetPos0();
3052 
3053  RotatePoint( &pt, module->GetOrientation() );
3054  pad->SetPosition( pt + module->GetPosition() );
3055  module->Add( pad, ADD_MODE::APPEND );
3056  }
3057 
3058  break;
3059 
3060  case T_model:
3061  module->Add3DModel( parse3DModel() );
3062  break;
3063 
3064  case T_zone:
3065  {
3066  ZONE_CONTAINER* zone = parseZONE_CONTAINER( module.get() );
3067  module->Add( zone, ADD_MODE::APPEND );
3068  }
3069  break;
3070 
3071  default:
3072  Expecting(
3073  "locked, placed, tedit, tstamp, at, descr, tags, path, "
3074  "autoplace_cost90, autoplace_cost180, solder_mask_margin, "
3075  "solder_paste_margin, solder_paste_ratio, clearance, "
3076  "zone_connect, thermal_width, thermal_gap, attr, fp_text, "
3077  "fp_arc, fp_circle, fp_curve, fp_line, fp_poly, fp_rect, pad, "
3078  "zone, or model" );
3079  }
3080  }
3081 
3082  // In legacy files the lack of attributes indicated a through-hole component which was by
3083  // default excluded from pos files. However there was a hack to look for SMD pads and
3084  // consider those "mislabeled through-hole components" and therefore include them in place
3085  // files. We probably don't want to get into that game so we'll just include them by
3086  // default and let the user change it if required.
3087  if( m_requiredVersion < 20200826 && attributes == 0 )
3088  attributes |= MOD_THROUGH_HOLE;
3089 
3090  module->SetAttributes( attributes );
3091 
3092  module->SetFPID( fpid );
3093  module->SetProperties( properties );
3094  module->CalculateBoundingBox();
3095 
3096  return module.release();
3097 }
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
KIID CurStrToKIID()
const wxPoint & GetPos0() const
Definition: class_pad.h:218
#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:174
void SetPosition(const wxPoint &aPos) override
Definition: class_pad.h:159
bool m_tooRecent
true if version parses as later than supported
Definition: pcb_parser.h:81
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:275
PCB_LAYER_ID
A quick note on layer IDs:
#define NULL
std::pair< wxString, wxString > parseProperty()
Definition: pcb_parser.cpp:252
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)
void SetTextAngle(double aAngle) override
const KIID m_Uuid
Definition: base_struct.h:162
double GetAngle() const
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:82
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:76
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:138
TEXTE_MODULE * parseTEXTE_MODULE()
D_PAD * parseD_PAD(MODULE *aParent=NULL)
long parseHex()
Definition: pcb_parser.h:324
int parseInt()
Definition: pcb_parser.h:313
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
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
MODULE_3D_SETTINGS * parse3DModel()
Definition: pcb_parser.cpp:378

References _, APPEND, B_Cu, F_Cu, DRAWSEGMENT::GetAngle(), GetChars(), D_PAD::GetPos0(), EDA_TEXT::GetTextAngle(), TEXTE_MODULE::GetType(), LIB_ID::ID_PCB, EDA_ITEM::m_Uuid, MOD_BOARD_ONLY, MOD_EXCLUDE_FROM_BOM, MOD_EXCLUDE_FROM_POS_FILES, MOD_SMD, MOD_THROUGH_HOLE, 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, 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 2013 of file pcb_parser.cpp.

2014 {
2015  wxCHECK_RET( CurTok() == T_net_class,
2016  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as net class." ) );
2017 
2018  T token;
2019 
2020  NETCLASSPTR nc = std::make_shared<NETCLASS>( wxEmptyString );
2021 
2022  // Read netclass name (can be a name or just a number like track width)
2023  NeedSYMBOLorNUMBER();
2024  nc->SetName( FromUTF8() );
2025  NeedSYMBOL();
2026  nc->SetDescription( FromUTF8() );
2027 
2028  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2029  {
2030  if( token != T_LEFT )
2031  Expecting( T_LEFT );
2032 
2033  token = NextTok();
2034 
2035  switch( token )
2036  {
2037  case T_clearance:
2038  nc->SetClearance( parseBoardUnits( T_clearance ) );
2039  break;
2040 
2041  case T_trace_width:
2042  nc->SetTrackWidth( parseBoardUnits( T_trace_width ) );
2043  break;
2044 
2045  case T_via_dia:
2046  nc->SetViaDiameter( parseBoardUnits( T_via_dia ) );
2047  break;
2048 
2049  case T_via_drill:
2050  nc->SetViaDrill( parseBoardUnits( T_via_drill ) );
2051  break;
2052 
2053  case T_uvia_dia:
2054  nc->SetuViaDiameter( parseBoardUnits( T_uvia_dia ) );
2055  break;
2056 
2057  case T_uvia_drill:
2058  nc->SetuViaDrill( parseBoardUnits( T_uvia_drill ) );
2059  break;
2060 
2061  case T_diff_pair_width:
2062  nc->SetDiffPairWidth( parseBoardUnits( T_diff_pair_width ) );
2063  break;
2064 
2065  case T_diff_pair_gap:
2066  nc->SetDiffPairGap( parseBoardUnits( T_diff_pair_gap ) );
2067  break;
2068 
2069  case T_add_net:
2070  NeedSYMBOLorNUMBER();
2071  nc->Add( FromUTF8() );
2072  break;
2073 
2074  default:
2075  Expecting( "clearance, trace_width, via_dia, via_drill, uvia_dia, uvia_drill, diff_pair_width, diff_pair_gap or add_net" );
2076  }
2077 
2078  NeedRIGHT();
2079  }
2080 
2081  if( !m_board->GetDesignSettings().GetNetClasses().Add( nc ) )
2082  {
2083  // Must have been a name conflict, this is a bad board file.
2084  // User may have done a hand edit to the file.
2085 
2086  // unique_ptr will delete nc on this code path
2087 
2088  wxString error;
2089  error.Printf( _( "Duplicate NETCLASS name \"%s\" in file \"%s\" at line %d, offset %d" ),
2090  nc->GetName().GetData(), CurSource().GetData(), CurLineNumber(), CurOffset() );
2091  THROW_IO_ERROR( error );
2092  }
2093 }
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:514
int parseBoardUnits()
Definition: pcb_parser.h:275
NETCLASSES & GetNetClasses() const
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:76
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, and THROW_IO_ERROR.

◆ parseNETINFO_ITEM()

void PCB_PARSER::parseNETINFO_ITEM ( )
private

Definition at line 1987 of file pcb_parser.cpp.

1988 {
1989  wxCHECK_RET( CurTok() == T_net,
1990  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as net." ) );
1991 
1992  int netCode = parseInt( "net number" );
1993 
1994  NeedSYMBOLorNUMBER();
1995  wxString name = FromUTF8();
1996 
1997  NeedRIGHT();
1998 
1999  // net 0 should be already in list, so store this net
2000  // if it is not the net 0, or if the net 0 does not exists.
2001  // (TODO: a better test.)
2003  {
2004  NETINFO_ITEM* net = new NETINFO_ITEM( m_board, name, netCode );
2005  m_board->Add( net );
2006 
2007  // Store the new code mapping
2008  pushValueIntoMap( netCode, net->GetNet() );
2009  }
2010 }
NETINFO_ITEM * FindNet(int aNetcode) const
Search 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:76
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:126
int parseInt()
Definition: pcb_parser.h:313
static const int UNCONNECTED
Constant that holds the "unconnected net" number (typically 0) all items "connected" to this net are ...
Definition: netinfo.h:478

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

◆ parsePAGE_INFO()

void PCB_PARSER::parsePAGE_INFO ( )
private

Definition at line 884 of file pcb_parser.cpp.

885 {
886  wxCHECK_RET( ( CurTok() == T_page && m_requiredVersion <= 20200119 ) || CurTok() == T_paper,
887  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a PAGE_INFO." ) );
888 
889  T token;
890  PAGE_INFO pageInfo;
891 
892  NeedSYMBOL();
893 
894  wxString pageType = FromUTF8();
895 
896  if( !pageInfo.SetType( pageType ) )
897  {
898  wxString err;
899  err.Printf( _( "Page type \"%s\" is not valid " ), GetChars( FromUTF8() ) );
900  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
901  }
902 
903  if( pageType == PAGE_INFO::Custom )
904  {
905  double width = parseDouble( "width" ); // width in mm
906 
907  // Perform some controls to avoid crashes if the size is edited by hands
908  if( width < 100.0 )
909  width = 100.0;
910  else if( width > 1200.0 )
911  width = 1200.0;
912 
913  double height = parseDouble( "height" ); // height in mm
914 
915  if( height < 100.0 )
916  height = 100.0;
917  else if( height > 1200.0 )
918  height = 1200.0;
919 
920  pageInfo.SetWidthMils( Mm2mils( width ) );
921  pageInfo.SetHeightMils( Mm2mils( height ) );
922  }
923 
924  token = NextTok();
925 
926  if( token == T_portrait )
927  {
928  pageInfo.SetPortrait( true );
929  NeedRIGHT();
930  }
931  else if( token != T_RIGHT )
932  {
933  Expecting( "portrait|)" );
934  }
935 
936  m_board->SetPageSettings( pageInfo );
937 }
int Mm2mils(double x)
Convert mm to mils.
Definition: base_units.h:62
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: class_board.h:530
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:119
static const wxChar Custom[]
"User" defined page type
Definition: page_info.h:79
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:162
PAGE_INFO describes the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:54
void SetHeightMils(int aHeightInMils)
Definition: page_info.cpp:257
int m_requiredVersion
set to the KiCad format version this board requires
Definition: pcb_parser.h:82
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:76
void SetWidthMils(int aWidthInMils)
Definition: page_info.cpp:243
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:138
void SetPortrait(bool aIsPortrait)
Function SetPortrait will rotate the paper page 90 degrees.
Definition: page_info.cpp:186

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

◆ parsePCB_TARGET()

PCB_TARGET * PCB_PARSER::parsePCB_TARGET ( )
private

Definition at line 4806 of file pcb_parser.cpp.

4807 {
4808  wxCHECK_MSG( CurTok() == T_target, NULL,
4809  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as PCB_TARGET." ) );
4810 
4811  wxPoint pt;
4812  T token;
4813 
4814  std::unique_ptr< PCB_TARGET > target( new PCB_TARGET( NULL ) );
4815 
4816  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4817  {
4818  if( token == T_LEFT )
4819  token = NextTok();
4820 
4821  switch( token )
4822  {
4823  case T_x:
4824  target->SetShape( 1 );
4825  break;
4826 
4827  case T_plus:
4828  target->SetShape( 0 );
4829  break;
4830 
4831  case T_at:
4832  pt.x = parseBoardUnits( "target x position" );
4833  pt.y = parseBoardUnits( "target y position" );
4834  target->SetPosition( pt );
4835  NeedRIGHT();
4836  break;
4837 
4838  case T_size:
4839  target->SetSize( parseBoardUnits( "target size" ) );
4840  NeedRIGHT();
4841  break;
4842 
4843  case T_width:
4844  target->SetWidth( parseBoardUnits( "target thickness" ) );
4845  NeedRIGHT();
4846  break;
4847 
4848  case T_layer:
4849  target->SetLayer( parseBoardItemLayer() );
4850  NeedRIGHT();
4851  break;
4852 
4853  case T_tstamp:
4854  NextTok();
4855  const_cast<KIID&>( target->m_Uuid ) = CurStrToKIID();
4856  NeedRIGHT();
4857  break;
4858 
4859  default:
4860  Expecting( "x, plus, at, size, width, layer or tstamp" );
4861  }
4862  }
4863 
4864  return target.release();
4865 }
KIID CurStrToKIID()
int parseBoardUnits()
Definition: pcb_parser.h:275
#define NULL
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.

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

◆ parseProperty()

std::pair< wxString, wxString > PCB_PARSER::parseProperty ( )
private

Definition at line 252 of file pcb_parser.cpp.

253 {
254  wxString pName;
255  wxString pValue;
256 
257  NeedSYMBOL();
258  pName = FromUTF8();
259  NeedSYMBOL();
260  pValue = FromUTF8();
261  NeedRIGHT();
262 
263  return { pName, pValue };
264 }

◆ parseSetup()

void PCB_PARSER::parseSetup ( )
private

Definition at line 1533 of file pcb_parser.cpp.

1534 {
1535  wxCHECK_RET( CurTok() == T_setup,
1536  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as setup." ) );
1537 
1538  T token;
1539  NETCLASS* defaultNetClass = m_board->GetDesignSettings().GetDefault();
1540  BOARD_DESIGN_SETTINGS& designSettings = m_board->GetDesignSettings();
1541  ZONE_SETTINGS& zoneSettings = designSettings.GetDefaultZoneSettings();
1542 
1543  // Missing soldermask min width value means that the user has set the value to 0 and
1544  // not the default value (0.25mm)
1545  designSettings.m_SolderMaskMinWidth = 0;
1546 
1547  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1548  {
1549  if( token != T_LEFT )
1550  Expecting( T_LEFT );
1551 
1552  token = NextTok();
1553 
1554  switch( token )
1555  {
1556  case T_stackup:
1558  break;
1559 
1560  case T_last_trace_width: // not used now
1561  /* lastTraceWidth =*/ parseBoardUnits( T_last_trace_width );
1562  NeedRIGHT();
1563  break;
1564 
1565  case T_user_trace_width:
1566  designSettings.m_TrackWidthList.push_back( parseBoardUnits( T_user_trace_width ) );
1568  NeedRIGHT();
1569  break;
1570 
1571  case T_trace_clearance:
1572  defaultNetClass->SetClearance( parseBoardUnits( T_trace_clearance ) );
1574  NeedRIGHT();
1575  break;
1576 
1577  case T_zone_clearance:
1578  zoneSettings.m_ZoneClearance = parseBoardUnits( T_zone_clearance );
1580  NeedRIGHT();
1581  break;
1582 
1583  case T_zone_45_only:
1584  zoneSettings.m_Zone_45_Only = parseBool();
1586  NeedRIGHT();
1587  break;
1588 
1589  case T_clearance_min:
1590  designSettings.m_MinClearance = parseBoardUnits( T_clearance_min );
1592  NeedRIGHT();
1593  break;
1594 
1595  case T_trace_min:
1596  designSettings.m_TrackMinWidth = parseBoardUnits( T_trace_min );
1598  NeedRIGHT();
1599  break;
1600 
1601  case T_via_size:
1602  defaultNetClass->SetViaDiameter( parseBoardUnits( T_via_size ) );
1604  NeedRIGHT();
1605  break;
1606 
1607  case T_via_drill:
1608  defaultNetClass->SetViaDrill( parseBoardUnits( T_via_drill ) );
1610  NeedRIGHT();
1611  break;
1612 
1613  case T_via_min_annulus:
1614  designSettings.m_ViasMinAnnulus = parseBoardUnits( T_via_min_annulus );
1616  NeedRIGHT();
1617  break;
1618 
1619  case T_via_min_size:
1620  designSettings.m_ViasMinSize = parseBoardUnits( T_via_min_size );
1622  NeedRIGHT();
1623  break;
1624 
1625  case T_through_hole_min:
1626  designSettings.m_MinThroughDrill = parseBoardUnits( T_through_hole_min );
1628  NeedRIGHT();
1629  break;
1630 
1631  // Legacy token for T_through_hole_min
1632  case T_via_min_drill:
1633  designSettings.m_MinThroughDrill = parseBoardUnits( T_via_min_drill );
1635  NeedRIGHT();
1636  break;
1637 
1638  case T_hole_to_hole_min:
1639  designSettings.m_HoleToHoleMin = parseBoardUnits( T_hole_to_hole_min );
1641  NeedRIGHT();
1642  break;
1643 
1644  case T_user_via:
1645  {
1646  int viaSize = parseBoardUnits( "user via size" );
1647  int viaDrill = parseBoardUnits( "user via drill" );
1648  designSettings.m_ViasDimensionsList.emplace_back( VIA_DIMENSION( viaSize, viaDrill ) );
1650  NeedRIGHT();
1651  }
1652  break;
1653 
1654  case T_uvia_size:
1655  defaultNetClass->SetuViaDiameter( parseBoardUnits( T_uvia_size ) );
1657  NeedRIGHT();
1658  break;
1659 
1660  case T_uvia_drill:
1661  defaultNetClass->SetuViaDrill( parseBoardUnits( T_uvia_drill ) );
1663  NeedRIGHT();
1664  break;
1665 
1666  case T_uvias_allowed:
1667  designSettings.m_MicroViasAllowed = parseBool();
1669  NeedRIGHT();
1670  break;
1671 
1672  case T_blind_buried_vias_allowed:
1673  designSettings.m_BlindBuriedViaAllowed = parseBool();
1675  NeedRIGHT();
1676  break;
1677 
1678  case T_uvia_min_size:
1679  designSettings.m_MicroViasMinSize = parseBoardUnits( T_uvia_min_size );
1681  NeedRIGHT();
1682  break;
1683 
1684  case T_uvia_min_drill:
1685  designSettings.m_MicroViasMinDrill = parseBoardUnits( T_uvia_min_drill );
1687  NeedRIGHT();
1688  break;
1689 
1690  case T_user_diff_pair:
1691  {
1692  int width = parseBoardUnits( "user diff-pair width" );
1693  int gap = parseBoardUnits( "user diff-pair gap" );
1694  int viaGap = parseBoardUnits( "user diff-pair via gap" );
1695  designSettings.m_DiffPairDimensionsList.emplace_back( DIFF_PAIR_DIMENSION( width, gap, viaGap ) );
1697  NeedRIGHT();
1698  }
1699  break;
1700 
1701  case T_segment_width: // note: legacy (pre-6.0) token
1702  designSettings.m_LineThickness[ LAYER_CLASS_COPPER ] = parseBoardUnits( T_segment_width );
1704  NeedRIGHT();
1705  break;
1706 
1707  case T_edge_width: // note: legacy (pre-6.0) token
1708  designSettings.m_LineThickness[ LAYER_CLASS_EDGES ] = parseBoardUnits( T_edge_width );
1710  NeedRIGHT();
1711  break;
1712 
1713  case T_mod_edge_width: // note: legacy (pre-6.0) token
1714  designSettings.m_LineThickness[ LAYER_CLASS_SILK ] = parseBoardUnits( T_mod_edge_width );
1716  NeedRIGHT();
1717  break;
1718 
1719  case T_pcb_text_width: // note: legacy (pre-6.0) token
1720  designSettings.m_TextThickness[ LAYER_CLASS_COPPER ] = parseBoardUnits( T_pcb_text_width );
1722  NeedRIGHT();
1723  break;
1724 
1725  case T_mod_text_width: // note: legacy (pre-6.0) token
1726  designSettings.m_TextThickness[ LAYER_CLASS_SILK ] = parseBoardUnits( T_mod_text_width );
1728  NeedRIGHT();
1729  break;
1730 
1731  case T_pcb_text_size: // note: legacy (pre-6.0) token
1732  designSettings.m_TextSize[ LAYER_CLASS_COPPER ].x = parseBoardUnits( "pcb text width" );
1733  designSettings.m_TextSize[ LAYER_CLASS_COPPER ].y = parseBoardUnits( "pcb text height" );
1735  NeedRIGHT();
1736  break;
1737 
1738  case T_mod_text_size: // note: legacy (pre-6.0) token
1739  designSettings.m_TextSize[ LAYER_CLASS_SILK ].x = parseBoardUnits( "module text width" );
1740  designSettings.m_TextSize[ LAYER_CLASS_SILK ].y = parseBoardUnits( "module text height" );
1742  NeedRIGHT();
1743  break;
1744 
1745  case T_defaults:
1746  parseDefaults( designSettings );
1748  break;
1749 
1750  case T_pad_size:
1751  {
1752  wxSize sz;
1753  sz.SetWidth( parseBoardUnits( "master pad width" ) );
1754  sz.SetHeight( parseBoardUnits( "master pad height" ) );
1755  designSettings.m_Pad_Master.SetSize( sz );
1757  NeedRIGHT();
1758  }
1759  break;
1760 
1761  case T_pad_drill:
1762  {
1763  int drillSize = parseBoardUnits( T_pad_drill );
1764  designSettings.m_Pad_Master.SetDrillSize( wxSize( drillSize, drillSize ) );
1766  NeedRIGHT();
1767  }
1768  break;
1769 
1770  case T_pad_to_mask_clearance:
1771  designSettings.m_SolderMaskMargin = parseBoardUnits( T_pad_to_mask_clearance );
1773  NeedRIGHT();
1774  break;
1775 
1776  case T_solder_mask_min_width:
1777  designSettings.m_SolderMaskMinWidth = parseBoardUnits( T_solder_mask_min_width );
1779  NeedRIGHT();
1780  break;
1781 
1782  case T_pad_to_paste_clearance:
1783  designSettings.m_SolderPasteMargin = parseBoardUnits( T_pad_to_paste_clearance );
1785  NeedRIGHT();
1786  break;
1787 
1788  case T_pad_to_paste_clearance_ratio:
1789  designSettings.m_SolderPasteMarginRatio = parseDouble( T_pad_to_paste_clearance_ratio );
1791  NeedRIGHT();
1792  break;
1793 
1794  case T_aux_axis_origin:
1795  {
1796  int x = parseBoardUnits( "auxiliary origin X" );
1797  int y = parseBoardUnits( "auxiliary origin Y" );
1798  designSettings.m_AuxOrigin = wxPoint( x, y );
1799  // Aux origin still stored in board for the moment
1800  //m_board->m_LegacyDesignSettingsLoaded = true;
1801  NeedRIGHT();
1802  }
1803  break;
1804 
1805  case T_grid_origin:
1806  {
1807  int x = parseBoardUnits( "grid origin X" );
1808  int y = parseBoardUnits( "grid origin Y" );
1809  designSettings.m_GridOrigin = wxPoint( x, y );
1810  // Grid origin still stored in board for the moment
1811  //m_board->m_LegacyDesignSettingsLoaded = true;
1812  NeedRIGHT();
1813  }
1814  break;
1815 
1816  // Stored in board prior to 6.0
1817  case T_visible_elements:
1818  {
1819  m_board->m_LegacyVisibleItems.reset();
1820 
1821  int visible = parseHex() | MIN_VISIBILITY_MASK;
1822 
1823  for( size_t i = 0; i < sizeof( int ) * CHAR_BIT; i++ )
1824  m_board->m_LegacyVisibleItems.set( i, visible & ( 1u << i ) );
1825 
1826  // These didn't exist in legacy files; make sure they are set
1829 
1830  NeedRIGHT();
1831  }
1832  break;
1833 
1834  case T_max_error:
1835  designSettings.m_MaxError = parseBoardUnits( T_max_error );
1837  NeedRIGHT();
1838  break;
1839 
1840  case T_filled_areas_thickness: // Note: legacy (early 5.99) token
1841  designSettings.m_ZoneFillVersion = parseBool() ? 5 : 6;
1843  NeedRIGHT();
1844  break;
1845 
1846  case T_pcbplotparams:
1847  {
1848  PCB_PLOT_PARAMS plotParams;
1849  PCB_PLOT_PARAMS_PARSER parser( reader );
1850  // parser must share the same current line as our current PCB parser
1851  // synchronize it.
1852  parser.SyncLineReaderWith( *this );
1853 
1854  plotParams.Parse( &parser );
1855  SyncLineReaderWith( parser );
1856 
1857  m_board->SetPlotOptions( plotParams );
1858  }
1859  break;
1860 
1861  default:
1862  Unexpected( CurText() );
1863  }
1864  }
1865 }
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:279
PCB_PLOT_PARAMS_PARSER is the parser class for PCB_PLOT_PARAMS.
std::vector< int > m_TrackWidthList
std::vector< DIFF_PAIR_DIMENSION > m_DiffPairDimensionsList
Control for copper zone opacity/visibility (color ignored)
void parseBoardStackup()
BOARD_DESIGN_SETTINGS & GetDesignSettings() const
Definition: class_board.h:514
void SetDrillSize(const wxSize &aSize)
Definition: class_pad.h:229
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:275
wxSize m_TextSize[LAYER_CLASS_COUNT]
bool parseBool()
Definition: pcb_parser.cpp:168
int m_TextThickness[LAYER_CLASS_COUNT]
#define MIN_VISIBILITY_MASK
void SetClearance(int aClearance)
Definition: netclass.h:166
Meta control for all pads opacity/visibility (color ignored)
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:223
bool m_BlindBuriedViaAllowed
true to allow blind/buried vias
void SetPlotOptions(const PCB_PLOT_PARAMS &aOptions)
Definition: class_board.h:533
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
BOARD * m_board
Definition: pcb_parser.h:76
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:138
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:324
void Parse(PCB_PLOT_PARAMS_PARSER *aParser)
wxPoint m_AuxOrigin
origin for plot exports
BOARD_DESIGN_SETTINGS contains design settings for a BOARD object.
GAL_SET m_LegacyVisibleItems
Definition: class_board.h:276

References BOARD_DESIGN_SETTINGS::GetDefaultZoneSettings(), LAYER_CLASS_COPPER, LAYER_CLASS_EDGES, LAYER_CLASS_SILK, LAYER_PADS, LAYER_ZONES, 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_ZoneFillVersion, MIN_VISIBILITY_MASK, PCB_PLOT_PARAMS::Parse(), parseDouble(), parseHex(), NETCLASS::SetClearance(), D_PAD::SetDrillSize(), D_PAD::SetSize(), NETCLASS::SetuViaDiameter(), NETCLASS::SetuViaDrill(), NETCLASS::SetViaDiameter(), and NETCLASS::SetViaDrill().

◆ parseTEXTE_MODULE()

TEXTE_MODULE * PCB_PARSER::parseTEXTE_MODULE ( )
private

Definition at line 3100 of file pcb_parser.cpp.

3101 {
3102  wxCHECK_MSG( CurTok() == T_fp_text, NULL,
3103  wxString::Format( wxT( "Cannot parse %s as TEXTE_MODULE at line %d, offset %d." ),
3104  GetChars( GetTokenString( CurTok() ) ),
3105  CurLineNumber(), CurOffset() ) );
3106 
3107  T token = NextTok();
3108 
3109  std::unique_ptr<TEXTE_MODULE> text( new TEXTE_MODULE( NULL ) );
3110 
3111  switch( token )
3112  {
3113  case T_reference:
3114  text->SetType( TEXTE_MODULE::TEXT_is_REFERENCE );
3115  break;
3116 
3117  case T_value:
3118  text->SetType( TEXTE_MODULE::TEXT_is_VALUE );
3119  break;
3120 
3121  case T_user:
3122  break; // Default type is user text.
3123 
3124  default:
3125  THROW_IO_ERROR( wxString::Format( _( "Cannot handle footprint text type %s" ),
3126  GetChars( FromUTF8() ) ) );
3127  }
3128 
3129  NeedSYMBOLorNUMBER();
3130 
3131  wxString value = FromUTF8();
3132  value.Replace( "%V", "${VALUE}" );
3133  value.Replace( "%R", "${REFERENCE}" );
3134  text->SetText( value );
3135  NeedLEFT();
3136  token = NextTok();
3137 
3138  if( token != T_at )
3139  Expecting( T_at );
3140 
3141  wxPoint pt;
3142 
3143  pt.x = parseBoardUnits( "X coordinate" );
3144  pt.y = parseBoardUnits( "Y coordinate" );
3145  text->SetPos0( pt );
3146 
3147  NextTok();
3148 
3149  if( CurTok() == T_NUMBER )
3150  {
3151  text->SetTextAngle( parseDouble() * 10.0 );
3152  NextTok();
3153  }
3154 
3155  if( CurTok() == T_unlocked )
3156  {
3157  text->SetKeepUpright( false );
3158  NextTok();
3159  }
3160 
3161  if( CurTok() != T_RIGHT )
3162  {
3163  Unexpected( CurText() );
3164  }
3165 
3166  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3167  {
3168  if( token == T_LEFT )
3169  token = NextTok();
3170 
3171  switch( token )
3172  {
3173  case T_layer:
3174  text->SetLayer( parseBoardItemLayer() );
3175  NeedRIGHT();
3176  break;
3177 
3178  case T_hide:
3179  text->SetVisible( false );
3180  break;
3181 
3182  case T_effects:
3183  parseEDA_TEXT( (EDA_TEXT*) text.get() );
3184  break;
3185 
3186  case T_tstamp:
3187  NextTok();
3188  const_cast<KIID&>( text->m_Uuid ) = CurStrToKIID();
3189  NeedRIGHT();
3190  break;
3191 
3192  default:
3193  Expecting( "layer, hide, effects or tstamp" );
3194  }
3195  }
3196 
3197  return text.release();
3198 }
KIID CurStrToKIID()
void parseEDA_TEXT(EDA_TEXT *aText)
Function parseEDA_TEXT parses the common settings for any object derived from EDA_TEXT.
Definition: pcb_parser.cpp:267
int parseBoardUnits()
Definition: pcb_parser.h:275
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:113
#define NULL
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
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:201
#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:138
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, Format(), GetChars(), NULL, parseDouble(), 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 2297 of file pcb_parser.cpp.

2298 {
2299  wxCHECK_MSG( CurTok() == T_gr_text, NULL,
2300  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as TEXTE_PCB." ) );
2301 
2302  T token;
2303 
2304  std::unique_ptr<TEXTE_PCB> text( new TEXTE_PCB( m_board ) );
2305  NeedSYMBOLorNUMBER();
2306 
2307  text->SetText( FromUTF8() );
2308  NeedLEFT();
2309  token = NextTok();
2310 
2311  if( token != T_at )
2312  Expecting( T_at );
2313 
2314  wxPoint pt;
2315 
2316  pt.x = parseBoardUnits( "X coordinate" );
2317  pt.y = parseBoardUnits( "Y coordinate" );
2318  text->SetTextPos( pt );
2319 
2320  // If there is no orientation defined, then it is the default value of 0 degrees.
2321  token = NextTok();
2322 
2323  if( token == T_NUMBER )
2324  {
2325  text->SetTextAngle( parseDouble() * 10.0 );
2326  NeedRIGHT();
2327  }
2328  else if( token != T_RIGHT )
2329  {
2330  Unexpected( CurText() );
2331  }
2332 
2333  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2334  {
2335  if( token != T_LEFT )
2336  Expecting( T_LEFT );
2337 
2338  token = NextTok();
2339 
2340  switch( token )
2341  {
2342  case T_layer:
2343  text->SetLayer( parseBoardItemLayer() );
2344  NeedRIGHT();
2345  break;
2346 
2347  case T_tstamp:
2348  NextTok();
2349  const_cast<KIID&>( text->m_Uuid ) = CurStrToKIID();
2350  NeedRIGHT();
2351  break;
2352 
2353  case T_effects:
2354  parseEDA_TEXT( (EDA_TEXT*) text.get() );
2355  break;
2356 
2357  default:
2358  Expecting( "layer, tstamp or effects" );
2359  }
2360  }
2361 
2362  return text.release();
2363 }
KIID CurStrToKIID()
void parseEDA_TEXT(EDA_TEXT *aText)
Function parseEDA_TEXT parses the common settings for any object derived from EDA_TEXT.
Definition: pcb_parser.cpp:267
int parseBoardUnits()
Definition: pcb_parser.h:275
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:113
#define NULL
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
BOARD * m_board
Definition: pcb_parser.h:76
double parseDouble()
Function parseDouble parses the current token as an ASCII numeric string with possible leading whites...
Definition: pcb_parser.cpp:138

References NULL, parseDouble(), wxPoint::x, and wxPoint::y.

◆ parseTITLE_BLOCK()

void PCB_PARSER::parseTITLE_BLOCK ( )
private

Definition at line 940 of file pcb_parser.cpp.

941 {
942  wxCHECK_RET( CurTok() == T_title_block,
943  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
944  wxT( " as TITLE_BLOCK." ) );
945 
946  T token;
947  TITLE_BLOCK titleBlock;
948 
949  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
950  {
951  if( token != T_LEFT )
952  Expecting( T_LEFT );
953 
954  token = NextTok();
955 
956  switch( token )
957  {
958  case T_title:
959  NextTok();
960  titleBlock.SetTitle( FromUTF8() );
961  break;
962 
963  case T_date:
964  NextTok();
965  titleBlock.SetDate( FromUTF8() );
966  break;
967 
968  case T_rev:
969  NextTok();
970  titleBlock.SetRevision( FromUTF8() );
971  break;
972 
973  case T_company:
974  NextTok();
975  titleBlock.SetCompany( FromUTF8() );
976  break;
977 
978  case T_comment:
979  {
980  int commentNumber = parseInt( "comment" );
981 
982  switch( commentNumber )
983  {
984  case 1:
985  NextTok();
986  titleBlock.SetComment( 0, FromUTF8() );
987  break;
988 
989  case 2:
990  NextTok();
991  titleBlock.SetComment( 1, FromUTF8() );
992  break;
993 
994  case 3:
995  NextTok();
996  titleBlock.SetComment( 2, FromUTF8() );
997  break;
998 
999  case 4:
1000  NextTok();
1001  titleBlock.SetComment( 3, FromUTF8() );
1002  break;
1003 
1004  case 5:
1005  NextTok();
1006  titleBlock.SetComment( 4, FromUTF8() );
1007  break;
1008 
1009  case 6:
1010  NextTok();
1011  titleBlock.SetComment( 5, FromUTF8() );
1012  break;
1013 
1014  case 7:
1015  NextTok();
1016  titleBlock.SetComment( 6, FromUTF8() );
1017  break;
1018 
1019  case 8:
1020  NextTok();
1021  titleBlock.SetComment( 7, FromUTF8() );
1022  break;
1023 
1024  case 9:
1025  NextTok();
1026  titleBlock.SetComment( 8, FromUTF8() );
1027  break;
1028 
1029  default:
1030  wxString err;
1031  err.Printf( wxT( "%d is not a valid title block comment number" ), commentNumber );
1032  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
1033  }
1034  }
1035  break;
1036 
1037  default:
1038  Expecting( "title, date, rev, company, or comment" );
1039  }
1040 
1041  NeedRIGHT();
1042  }
1043 
1044  m_board->SetTitleBlock( titleBlock );
1045 }
void SetRevision(const wxString &aRevision)
Definition: title_block.h:84
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition: class_board.h:536
void SetDate(const wxString &aDate)
Function SetDate sets the date field, and defaults to the current time and date.
Definition: title_block.h:74
TITLE_BLOCK holds the information shown in the lower right corner of a plot, printout,...
Definition: title_block.h:40
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:162
void SetComment(int aIdx, const wxString &aComment)
Definition: title_block.h:104
void SetCompany(const wxString &aCompany)
Definition: title_block.h:94
void SetTitle(const wxString &aTitle)
Definition: title_block.h:60
BOARD * m_board
Definition: pcb_parser.h:76
int parseInt()
Definition: pcb_parser.h:313

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

◆ parseTRACK()

TRACK * PCB_PARSER::parseTRACK ( )
private

We continue to parse the status field but it is no longer written

Definition at line 4081 of file pcb_parser.cpp.

4082 {
4083  wxCHECK_MSG( CurTok() == T_segment, NULL,
4084  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as TRACK." ) );
4085 
4086  wxPoint pt;
4087  T token;
4088 
4089  std::unique_ptr< TRACK > track( new TRACK( m_board ) );
4090 
4091  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4092  {
4093  if( token != T_LEFT )
4094  Expecting( T_LEFT );
4095 
4096  token = NextTok();
4097 
4098  switch( token )
4099  {
4100  case T_start:
4101  pt.x = parseBoardUnits( "start x" );
4102  pt.y = parseBoardUnits( "start y" );
4103  track->SetStart( pt );
4104  break;
4105 
4106  case T_end:
4107  pt.x = parseBoardUnits( "end x" );
4108  pt.y = parseBoardUnits( "end y" );
4109  track->SetEnd( pt );
4110  break;
4111 
4112  case T_width:
4113  track->SetWidth( parseBoardUnits( "width" ) );
4114  break;
4115 
4116  case T_layer:
4117  track->SetLayer( parseBoardItemLayer() );
4118  break;
4119 
4120  case T_net:
4121  if( ! track->SetNetCode( getNetCode( parseInt( "net number" ) ), /* aNoAssert */ true ) )
4123  wxString::Format( _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
4124  GetChars( CurSource() ), CurLineNumber(), CurOffset() )
4125  );
4126  break;
4127 
4128  case T_tstamp:
4129  NextTok();
4130  const_cast<KIID&>( track->m_Uuid ) = CurStrToKIID();
4131  break;
4132 
4134  case T_status:
4135  track->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
4136  break;
4137 
4138  case T_locked:
4139  track->SetState( TRACK_LOCKED, 1 );
4140  break;
4141 
4142  default:
4143  Expecting( "start, end, width, layer, net, tstamp, or locked" );
4144  }
4145 
4146  NeedRIGHT();
4147  }
4148 
4149  return track.release();
4150 }
KIID CurStrToKIID()
int parseBoardUnits()
Definition: pcb_parser.h:275
#define NULL
PCB_LAYER_ID parseBoardItemLayer()
Function parseBoardItemLayer parses the layer definition of a BOARD_ITEM object.
#define TRACK_LOCKED
Pcbnew: track locked: protected from global deletion.
Definition: base_struct.h:131
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:201
#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:103
BOARD * m_board
Definition: pcb_parser.h:76
long parseHex()
Definition: pcb_parser.h:324
int parseInt()
Definition: pcb_parser.h:313
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, Format(), GetChars(), NULL, parseHex(), parseInt(), THROW_IO_ERROR, TRACK, TRACK_LOCKED, 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 183 of file pcb_parser.cpp.

184 {
185  if( NextTok() != T_version )
186  Expecting( GetTokenText( T_version ) );
187 
188  int pcb_version = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
189 
190  NeedRIGHT();
191 
192  return pcb_version;
193 }
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:313

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

◆ parseVIA()

VIA * PCB_PARSER::parseVIA ( )
private

We continue to parse the status field but it is no longer written

Definition at line 4153 of file pcb_parser.cpp.

4154 {
4155  wxCHECK_MSG( CurTok() == T_via, NULL,
4156  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as VIA." ) );
4157 
4158  wxPoint pt;
4159  T token;
4160 
4161  std::unique_ptr< VIA > via( new VIA( m_board ) );
4162 
4163  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4164  {
4165  if( token == T_LEFT )
4166  token = NextTok();
4167 
4168  switch( token )
4169  {
4170  case T_blind:
4171  via->SetViaType( VIATYPE::BLIND_BURIED );
4172  break;
4173 
4174  case T_micro:
4175  via->SetViaType( VIATYPE::MICROVIA );
4176  break;
4177 
4178  case T_at:
4179  pt.x = parseBoardUnits( "start x" );
4180  pt.y = parseBoardUnits( "start y" );
4181  via->SetStart( pt );
4182  via->SetEnd( pt );
4183  NeedRIGHT();
4184  break;
4185 
4186  case T_size:
4187  via->SetWidth( parseBoardUnits( "via width" ) );
4188  NeedRIGHT();
4189  break;
4190 
4191  case T_drill:
4192  via->SetDrill( parseBoardUnits( "drill diameter" ) );
4193  NeedRIGHT();
4194  break;
4195 
4196  case T_layers:
4197  {
4198  PCB_LAYER_ID layer1, layer2;
4199  NextTok();
4200  layer1 = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
4201  NextTok();
4202  layer2 = lookUpLayer<PCB_LAYER_ID>( m_layerIndices );
4203  via->SetLayerPair( layer1, layer2 );
4204  NeedRIGHT();
4205  }
4206  break;
4207 
4208  case T_net:
4209  if(! via->SetNetCode( getNetCode( parseInt( "net number" ) ), /* aNoAssert */ true))
4211  wxString::Format( _( "Invalid net ID in\nfile: \"%s\"\nline: %d\noffset: %d" ),
4212  GetChars( CurSource() ), CurLineNumber(), CurOffset() )
4213  );
4214  NeedRIGHT();
4215  break;
4216 
4217  case T_remove_unused_layers:
4218  via->SetRemoveUnconnected( true );
4219  NeedRIGHT();
4220  break;
4221 
4222  case T_keep_end_layers:
4223  via->SetKeepTopBottom( true );
4224  NeedRIGHT();
4225  break;
4226 
4227  case T_tstamp:
4228  NextTok();
4229  const_cast<KIID&>( via->m_Uuid ) = CurStrToKIID();
4230  NeedRIGHT();
4231  break;
4232 
4234  case T_status:
4235  via->SetStatus( static_cast<STATUS_FLAGS>( parseHex() ) );
4236  NeedRIGHT();
4237  break;
4238 
4239  case T_locked: