You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

403 lines
13 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 2012 CERN
  5. * Copyright (C) 2012-2019 KiCad Developers, see AUTHORS.txt for contributors.
  6. *
  7. * This program is free software; you can redistribute it and/or
  8. * modify it under the terms of the GNU General Public License
  9. * as published by the Free Software Foundation; either version 2
  10. * of the License, or (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program; if not, you may find one here:
  19. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  20. * or you may search the http://www.gnu.org website for the version 2 license,
  21. * or you may write to the Free Software Foundation, Inc.,
  22. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  23. */
  24. /**
  25. * @file pcb_parser.h
  26. * @brief Pcbnew s-expression file format parser definition.
  27. */
  28. #ifndef _PCBNEW_PARSER_H_
  29. #define _PCBNEW_PARSER_H_
  30. #include <convert_to_biu.h> // IU_PER_MM
  31. #include <hashtables.h>
  32. #include <layers_id_colors_and_visibility.h> // PCB_LAYER_ID
  33. #include <math/util.h> // KiROUND, Clamp
  34. #include <pcb_lexer.h>
  35. #include <unordered_map>
  36. class ARC;
  37. class BOARD;
  38. class BOARD_ITEM;
  39. class BOARD_ITEM_CONTAINER;
  40. class D_PAD;
  41. class BOARD_DESIGN_SETTINGS;
  42. class DIMENSION;
  43. class DRAWSEGMENT;
  44. class EDA_TEXT;
  45. class EDGE_MODULE;
  46. class TEXTE_MODULE;
  47. class TEXTE_PCB;
  48. class TRACK;
  49. class MODULE;
  50. class PCB_GROUP;
  51. class PCB_TARGET;
  52. class VIA;
  53. class ZONE_CONTAINER;
  54. class MARKER_PCB;
  55. class MODULE_3D_SETTINGS;
  56. struct LAYER;
  57. /**
  58. * PCB_PARSER
  59. * reads a Pcbnew s-expression formatted #LINE_READER object and returns the appropriate
  60. * #BOARD_ITEM object.
  61. */
  62. class PCB_PARSER : public PCB_LEXER
  63. {
  64. typedef std::unordered_map< std::string, PCB_LAYER_ID > LAYER_ID_MAP;
  65. typedef std::unordered_map< std::string, LSET > LSET_MAP;
  66. typedef std::unordered_map< wxString, KIID > KIID_MAP;
  67. BOARD* m_board;
  68. LAYER_ID_MAP m_layerIndices; ///< map layer name to it's index
  69. LSET_MAP m_layerMasks; ///< map layer names to their masks
  70. std::set<wxString> m_undefinedLayers; ///< set of layers not defined in layers section
  71. std::vector<int> m_netCodes; ///< net codes mapping for boards being loaded
  72. bool m_tooRecent; ///< true if version parses as later than supported
  73. int m_requiredVersion; ///< set to the KiCad format version this board requires
  74. bool m_resetKIIDs; ///< reading into an existing board; reset UUIDs
  75. KIID_MAP m_resetKIIDMap; ///< if resetting UUIDs, record new ones to update groups with
  76. bool m_showLegacyZoneWarning;
  77. // Group membership info refers to other Uuids in the file.
  78. // We don't want to rely on group declarations being last in the file, so
  79. // we store info about the group declarations here during parsing and then resolve
  80. // them into BOARD_ITEM* after we've parsed the rest of the file.
  81. typedef struct
  82. {
  83. wxString name;
  84. KIID uuid;
  85. std::vector<KIID> memberUuids;
  86. } GroupInfo;
  87. std::vector<GroupInfo> m_groupInfos;
  88. ///> Converts net code using the mapping table if available,
  89. ///> otherwise returns unchanged net code if < 0 or if is is out of range
  90. inline int getNetCode( int aNetCode )
  91. {
  92. if( ( aNetCode >= 0 ) && ( aNetCode < (int) m_netCodes.size() ) )
  93. return m_netCodes[aNetCode];
  94. return aNetCode;
  95. }
  96. /**
  97. * function pushValueIntoMap
  98. * Add aValue value in netcode mapping (m_netCodes) at index aIndex
  99. * ensure there is room in m_netCodes for that, and add room if needed.
  100. * @param aIndex = the index ( expected >=0 )of the location to use in m_netCodes
  101. * @param aValue = the netcode value to map
  102. */
  103. void pushValueIntoMap( int aIndex, int aValue );
  104. /**
  105. * Function init
  106. * clears and re-establishes m_layerMap with the default layer names.
  107. * m_layerMap will have some of its entries overwritten whenever a (new) board
  108. * is encountered.
  109. */
  110. void init();
  111. /**
  112. * Creates a mapping from the (short-lived) bug where layer names were translated
  113. * TODO: Remove this once we support custom layer names
  114. *
  115. * @param aMap string mapping from translated to English layer names
  116. */
  117. void createOldLayerMapping( std::unordered_map< std::string, std::string >& aMap );
  118. /**
  119. * Function skipCurrent
  120. * Skip the current token level, i.e
  121. * search for the RIGHT parenthesis which closes the current description
  122. */
  123. void skipCurrent();
  124. void parseHeader();
  125. void parseGeneralSection();
  126. void parsePAGE_INFO();
  127. void parseTITLE_BLOCK();
  128. void parseLayers();
  129. void parseLayer( LAYER* aLayer );
  130. void parseBoardStackup();
  131. void parseSetup();
  132. void parseDefaults( BOARD_DESIGN_SETTINGS& aSettings );
  133. void parseDefaultTextDims( BOARD_DESIGN_SETTINGS& aSettings, int aLayer );
  134. void parseNETINFO_ITEM();
  135. void parseNETCLASS();
  136. /** Read a DRAWSEGMENT description.
  137. * @param aAllowCirclesZeroWidth = true to allow items with 0 width
  138. * Only used in custom pad shapes for filled circles.
  139. */
  140. DRAWSEGMENT* parseDRAWSEGMENT( bool aAllowCirclesZeroWidth = false );
  141. TEXTE_PCB* parseTEXTE_PCB();
  142. DIMENSION* parseDIMENSION();
  143. /**
  144. * Function parseMODULE_unchecked
  145. * Parse a module, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR automatically.
  146. */
  147. MODULE* parseMODULE_unchecked( wxArrayString* aInitialComments = 0 );
  148. TEXTE_MODULE* parseTEXTE_MODULE();
  149. EDGE_MODULE* parseEDGE_MODULE();
  150. D_PAD* parseD_PAD( MODULE* aParent = NULL );
  151. // Parse only the (option ...) inside a pad description
  152. bool parseD_PAD_option( D_PAD* aPad );
  153. ARC* parseARC();
  154. TRACK* parseTRACK();
  155. VIA* parseVIA();
  156. ZONE_CONTAINER* parseZONE_CONTAINER( BOARD_ITEM_CONTAINER* aParent );
  157. PCB_TARGET* parsePCB_TARGET();
  158. MARKER_PCB* parseMARKER( BOARD_ITEM_CONTAINER* aParent );
  159. BOARD* parseBOARD();
  160. void parseGROUP();
  161. /**
  162. * Function parseBOARD_unchecked
  163. * Parse a module, but do not replace PARSE_ERROR with FUTURE_FORMAT_ERROR automatically.
  164. */
  165. BOARD* parseBOARD_unchecked();
  166. /**
  167. * Function lookUpLayer
  168. * parses the current token for the layer definition of a #BOARD_ITEM object.
  169. *
  170. * @param aMap is the LAYER_{NUM|MSK}_MAP to use for the lookup.
  171. *
  172. * @throw IO_ERROR if the layer is not valid.
  173. * @throw PARSE_ERROR if the layer syntax is incorrect.
  174. * @return int - The result of the parsed #BOARD_ITEM layer or set designator.
  175. */
  176. template<class T, class M>
  177. T lookUpLayer( const M& aMap );
  178. /**
  179. * Function parseBoardItemLayer
  180. * parses the layer definition of a #BOARD_ITEM object.
  181. *
  182. * @throw IO_ERROR if the layer is not valid.
  183. * @throw PARSE_ERROR if the layer syntax is incorrect.
  184. * @return The index the parsed #BOARD_ITEM layer.
  185. */
  186. PCB_LAYER_ID parseBoardItemLayer();
  187. /**
  188. * Function parseBoardItemLayersAsMask
  189. * parses the layers definition of a #BOARD_ITEM object.
  190. *
  191. * @throw IO_ERROR if any of the layers is not valid.
  192. * @throw PARSE_ERROR if the layers syntax is incorrect.
  193. * @return The mask of layers the parsed #BOARD_ITEM is on.
  194. */
  195. LSET parseBoardItemLayersAsMask();
  196. /**
  197. * Function parseXY
  198. * parses a coordinate pair (xy X Y) in board units (mm).
  199. *
  200. * The parser checks if the previous token was T_LEFT and parses the remainder of
  201. * the token syntax. This is used when parsing a list of coordinate points. This
  202. * way the parser can be used in either case.
  203. *
  204. * @throw PARSE_ERROR if the coordinate pair syntax is incorrect.
  205. * @return A wxPoint object containing the coordinate pair.
  206. */
  207. wxPoint parseXY();
  208. void parseXY( int* aX, int* aY );
  209. std::pair<wxString, wxString> parseProperty();
  210. /**
  211. * Function parseEDA_TEXT
  212. * parses the common settings for any object derived from #EDA_TEXT.
  213. *
  214. * @throw PARSE_ERROR if the text syntax is not valid.
  215. * @param aText A point to the #EDA_TEXT object to save the parsed settings into.
  216. */
  217. void parseEDA_TEXT( EDA_TEXT* aText );
  218. MODULE_3D_SETTINGS* parse3DModel();
  219. /**
  220. * Function parseDouble
  221. * parses the current token as an ASCII numeric string with possible leading
  222. * whitespace into a double precision floating point number.
  223. *
  224. * @throw IO_ERROR if an error occurs attempting to convert the current token.
  225. * @return The result of the parsed token.
  226. */
  227. double parseDouble();
  228. inline double parseDouble( const char* aExpected )
  229. {
  230. NeedNUMBER( aExpected );
  231. return parseDouble();
  232. }
  233. inline double parseDouble( PCB_KEYS_T::T aToken )
  234. {
  235. return parseDouble( GetTokenText( aToken ) );
  236. }
  237. inline int parseBoardUnits()
  238. {
  239. // There should be no major rounding issues here, since the values in
  240. // the file are in mm and get converted to nano-meters.
  241. // See test program tools/test-nm-biu-to-ascii-mm-round-tripping.cpp
  242. // to confirm or experiment. Use a similar strategy in both places, here
  243. // and in the test program. Make that program with:
  244. // $ make test-nm-biu-to-ascii-mm-round-tripping
  245. auto retval = parseDouble() * IU_PER_MM;
  246. // N.B. we currently represent board units as integers. Any values that are
  247. // larger or smaller than those board units represent undefined behavior for
  248. // the system. We limit values to the largest that is visible on the screen
  249. // This is the diagonal distance of the full screen ~1.5m
  250. double int_limit = std::numeric_limits<int>::max() * 0.7071; // 0.7071 = roughly 1/sqrt(2)
  251. return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
  252. }
  253. inline int parseBoardUnits( const char* aExpected )
  254. {
  255. auto retval = parseDouble( aExpected ) * IU_PER_MM;
  256. // N.B. we currently represent board units as integers. Any values that are
  257. // larger or smaller than those board units represent undefined behavior for
  258. // the system. We limit values to the largest that is visible on the screen
  259. double int_limit = std::numeric_limits<int>::max() * 0.7071;
  260. // Use here KiROUND, not KIROUND (see comments about them)
  261. // when having a function as argument, because it will be called twice
  262. // with KIROUND
  263. return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
  264. }
  265. inline int parseBoardUnits( PCB_KEYS_T::T aToken )
  266. {
  267. return parseBoardUnits( GetTokenText( aToken ) );
  268. }
  269. inline int parseInt()
  270. {
  271. return (int)strtol( CurText(), NULL, 10 );
  272. }
  273. inline int parseInt( const char* aExpected )
  274. {
  275. NeedNUMBER( aExpected );
  276. return parseInt();
  277. }
  278. inline long parseHex()
  279. {
  280. NextTok();
  281. return strtol( CurText(), NULL, 16 );
  282. }
  283. bool parseBool();
  284. /**
  285. * Parse a format version tag like (version 20160417) return the version.
  286. * Expects to start on 'version', and eats the closing paren.
  287. */
  288. int parseVersion();
  289. /*
  290. * @return if m_resetKIIDs, returns new KIID(), otehrwise returns CurStr() as KIID.
  291. */
  292. KIID CurStrToKIID();
  293. public:
  294. PCB_PARSER( LINE_READER* aReader = NULL ) :
  295. PCB_LEXER( aReader ),
  296. m_board( 0 ),
  297. m_resetKIIDs( false )
  298. {
  299. init();
  300. }
  301. // ~PCB_PARSER() {}
  302. /**
  303. * Function SetLineReader
  304. * sets @a aLineReader into the parser, and returns the previous one, if any.
  305. * @param aReader is what to read from for tokens, no ownership is received.
  306. * @return LINE_READER* - previous LINE_READER or NULL if none.
  307. */
  308. LINE_READER* SetLineReader( LINE_READER* aReader )
  309. {
  310. LINE_READER* ret = PopReader();
  311. PushReader( aReader );
  312. return ret;
  313. }
  314. void SetBoard( BOARD* aBoard )
  315. {
  316. init();
  317. m_board = aBoard;
  318. if( aBoard != nullptr )
  319. m_resetKIIDs = true;
  320. }
  321. BOARD_ITEM* Parse();
  322. /**
  323. * Function parseMODULE
  324. * @param aInitialComments may be a pointer to a heap allocated initial comment block
  325. * or NULL. If not NULL, then caller has given ownership of a wxArrayString to
  326. * this function and care must be taken to delete it even on exception.
  327. */
  328. MODULE* parseMODULE( wxArrayString* aInitialComments = 0 );
  329. /**
  330. * Return whether a version number, if any was parsed, was too recent
  331. */
  332. bool IsTooRecent()
  333. {
  334. return m_tooRecent;
  335. }
  336. /**
  337. * Return a string representing the version of kicad required to open this
  338. * file. Not particularly meaningful if IsTooRecent() returns false.
  339. */
  340. wxString GetRequiredVersion();
  341. };
  342. #endif // _PCBNEW_PARSER_H_