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.

263 lines
8.2 KiB

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