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.

260 lines
8.2 KiB

  1. /*
  2. * This program source code file is part of KiCad, a free EDA CAD application.
  3. *
  4. * Copyright (C) 1992-2011 Jean-Pierre Charras.
  5. * Copyright (C) 2013 Wayne Stambaugh <stambaughw@gmail.com>.
  6. * Copyright The KiCad Developers, see AUTHORS.txt for contributors.
  7. *
  8. * This program is free software; you can redistribute it and/or
  9. * modify it under the terms of the GNU General Public License
  10. * as published by the Free Software Foundation; either version 2
  11. * of the License, or (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program; if not, you may find one here:
  20. * http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
  21. * or you may search the http://www.gnu.org website for the version 2 license,
  22. * or you may write to the Free Software Foundation, Inc.,
  23. * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
  24. */
  25. #include <richio.h>
  26. #include <string_utils.h>
  27. #include "pcb_netlist.h"
  28. #include "netlist_reader.h"
  29. void LEGACY_NETLIST_READER::LoadNetlist()
  30. {
  31. int state = 0;
  32. bool is_comment = false;
  33. COMPONENT* component = nullptr;
  34. while( m_lineReader->ReadLine() )
  35. {
  36. char* line = StrPurge( m_lineReader->Line() );
  37. if( is_comment ) // Comments in progress
  38. {
  39. // Test for end of the current comment
  40. if( ( line = strchr( line, '}' ) ) == nullptr )
  41. continue;
  42. is_comment = false;
  43. }
  44. if( *line == '{' ) // Start Comment or Pcbnew info section
  45. {
  46. is_comment = true;
  47. if( m_loadFootprintFilters && state == 0
  48. && (strncasecmp( line, "{ Allowed footprints", 20 ) == 0) )
  49. {
  50. loadFootprintFilters();
  51. continue;
  52. }
  53. if( ( line = strchr( line, '}' ) ) == nullptr )
  54. continue;
  55. }
  56. if( *line == '(' )
  57. state++;
  58. if( *line == ')' )
  59. state--;
  60. if( state == 2 )
  61. {
  62. component = loadComponent( line );
  63. continue;
  64. }
  65. if( state >= 3 ) // Pad descriptions are read here.
  66. {
  67. wxASSERT( component != nullptr );
  68. loadNet( line, component );
  69. state--;
  70. }
  71. }
  72. if( m_footprintReader )
  73. {
  74. m_footprintReader->Load( m_netlist );
  75. }
  76. }
  77. COMPONENT* LEGACY_NETLIST_READER::loadComponent( char* aText )
  78. {
  79. char* text;
  80. wxString msg;
  81. wxString footprintName; // the footprint name read from netlist
  82. wxString value; // the component value read from netlist
  83. wxString reference; // the component schematic reference designator read from netlist
  84. wxString name; // the name of component that was placed in the schematic
  85. char line[1024];
  86. strncpy( line, aText, sizeof(line)-1 );
  87. line[sizeof(line)-1] = '\0';
  88. value = wxT( "~" );
  89. // Sample component line: /68183921-93a5-49ac-91b0-49d05a0e1647 $noname R20 4.7K {Lib=R}
  90. // Read time stamp (first word)
  91. if( ( text = strtok( line, " ()\t\n" ) ) == nullptr )
  92. {
  93. msg = _( "Cannot parse time stamp in symbol section of netlist." );
  94. THROW_PARSE_ERROR( msg, m_lineReader->GetSource(), line, m_lineReader->LineNumber(),
  95. m_lineReader->Length() );
  96. }
  97. KIID_PATH path( From_UTF8( text ) );
  98. // Read footprint name (second word)
  99. if( ( text = strtok( nullptr, " ()\t\n" ) ) == nullptr )
  100. {
  101. msg = _( "Cannot parse footprint name in symbol section of netlist." );
  102. THROW_PARSE_ERROR( msg, m_lineReader->GetSource(), aText, m_lineReader->LineNumber(),
  103. m_lineReader->Length() );
  104. }
  105. footprintName = From_UTF8( text );
  106. // The footprint name will have to be looked up in the *.cmp file.
  107. if( footprintName == wxT( "$noname" ) )
  108. footprintName = wxEmptyString;
  109. // Read schematic reference designator (third word)
  110. if( ( text = strtok( nullptr, " ()\t\n" ) ) == nullptr )
  111. {
  112. msg = _( "Cannot parse reference designator in symbol section of netlist." );
  113. THROW_PARSE_ERROR( msg, m_lineReader->GetSource(), aText, m_lineReader->LineNumber(),
  114. m_lineReader->Length() );
  115. }
  116. reference = From_UTF8( text );
  117. // Read schematic value (forth word)
  118. if( ( text = strtok( nullptr, " ()\t\n" ) ) == nullptr )
  119. {
  120. msg = _( "Cannot parse value in symbol section of netlist." );
  121. THROW_PARSE_ERROR( msg, m_lineReader->GetSource(), aText, m_lineReader->LineNumber(),
  122. m_lineReader->Length() );
  123. }
  124. value = From_UTF8( text );
  125. // Read component name (fifth word) {Lib=C}
  126. // This is an optional field (a comment), which does not always exists
  127. if( ( text = strtok( nullptr, " ()\t\n" ) ) != nullptr )
  128. {
  129. name = From_UTF8( text ).AfterFirst( wxChar( '=' ) ).BeforeLast( wxChar( '}' ) );
  130. }
  131. LIB_ID fpid;
  132. if( !footprintName.IsEmpty() )
  133. fpid.SetLibItemName( footprintName );
  134. COMPONENT* component = new COMPONENT( fpid, reference, value, path, {} );
  135. component->SetName( name );
  136. m_netlist->AddComponent( component );
  137. return component;
  138. }
  139. void LEGACY_NETLIST_READER::loadNet( char* aText, COMPONENT* aComponent )
  140. {
  141. wxString msg;
  142. char* p;
  143. char line[256];
  144. strncpy( line, aText, sizeof( line ) );
  145. line[ sizeof(line) - 1 ] = '\0';
  146. if( ( p = strtok( line, " ()\t\n" ) ) == nullptr )
  147. {
  148. msg = _( "Cannot parse pin name in symbol net section of netlist." );
  149. THROW_PARSE_ERROR( msg, m_lineReader->GetSource(), line, m_lineReader->LineNumber(),
  150. m_lineReader->Length() );
  151. }
  152. wxString pinName = From_UTF8( p );
  153. if( ( p = strtok( nullptr, " ()\t\n" ) ) == nullptr )
  154. {
  155. msg = _( "Cannot parse net name in symbol net section of netlist." );
  156. THROW_PARSE_ERROR( msg, m_lineReader->GetSource(), line, m_lineReader->LineNumber(),
  157. m_lineReader->Length() );
  158. }
  159. wxString netName = From_UTF8( p );
  160. if( (char) netName[0] == '?' ) // ? indicates no net connected to pin.
  161. netName = wxEmptyString;
  162. aComponent->AddNet( pinName, netName, wxEmptyString, wxEmptyString );
  163. }
  164. void LEGACY_NETLIST_READER::loadFootprintFilters()
  165. {
  166. wxArrayString filters;
  167. wxString cmpRef;
  168. char* line;
  169. COMPONENT* component = nullptr; // Suppress compile warning
  170. while( ( line = m_lineReader->ReadLine() ) != nullptr )
  171. {
  172. if( strncasecmp( line, "$endlist", 8 ) == 0 ) // end of list for the current component
  173. {
  174. wxASSERT( component != nullptr );
  175. component->SetFootprintFilters( filters );
  176. component = nullptr;
  177. filters.Clear();
  178. continue;
  179. }
  180. if( strncasecmp( line, "$endfootprintlist", 4 ) == 0 )
  181. // End of this section
  182. return;
  183. if( strncasecmp( line, "$component", 10 ) == 0 ) // New component reference found
  184. {
  185. cmpRef = From_UTF8( line + 11 );
  186. cmpRef.Trim( true );
  187. cmpRef.Trim( false );
  188. component = m_netlist->GetComponentByReference( cmpRef );
  189. // Cannot happen if the netlist is valid.
  190. if( component == nullptr )
  191. {
  192. wxString msg;
  193. msg.Printf( _( "Cannot find symbol %s in footprint filter section of netlist." ),
  194. cmpRef );
  195. THROW_PARSE_ERROR( msg, m_lineReader->GetSource(), line, m_lineReader->LineNumber(),
  196. m_lineReader->Length() );
  197. }
  198. }
  199. else
  200. {
  201. // Add new filter to list
  202. wxString fp = From_UTF8( line + 1 );
  203. fp.Trim( false );
  204. fp.Trim( true );
  205. filters.Add( fp );
  206. }
  207. }
  208. }
  209. // LocalWords: EDA Charras pcb netlist noname cmp endlist
  210. // LocalWords: endfootprintlist