42 const wxFileName& aLibraryFileName,
REPORTER* aReporter )
44 std::map<wxString, wxString> mapOfAscFiles;
45 std::map<wxString, wxString> mapOfAsyFiles;
61 std::queue<wxString> ascFileQueue;
62 ascFileQueue.push( aLibraryFileName.GetName().Lower() );
64 LTSPICE_FILE rootAscFile( ascFileQueue.front(), { 0, 0 } );
66 rootAscFile.
Sheet = aRootSheet;
69 int parentSheetIndex = 0;
72 std::vector<LTSPICE_FILE> ascFiles;
74 ascFiles.push_back( rootAscFile );
76 while( !ascFileQueue.empty() )
81 wxString ascFilePath = mapOfAscFiles[ ascFileQueue.front() ];
86 std::erase_if( newSubSchematicElements,
92 for(
LTSPICE_FILE& newSubSchematicElement : newSubSchematicElements )
94 wxString asyName = newSubSchematicElement.ElementName;
95 auto it = mapOfAsyFiles.find( asyName );
97 if( it == mapOfAsyFiles.end() )
107 newSubSchematicElement.ParentIndex = parentSheetIndex;
108 newSubSchematicElement.Screen = screen;
109 newSubSchematicElement.Sheet =
new SCH_SHEET();
111 ascFileQueue.push( newSubSchematicElement.ElementName );
112 ascFiles.push_back( newSubSchematicElement );
121 for(
unsigned int i = 0; i < ascFiles.size(); i++ )
124 wxString buffer =
SafeReadFile( mapOfAscFiles[ascFiles[i].ElementName], wxS(
"r" ) );
131 m_fileCache[ wxS(
"ascFiles" ) ][ wxS(
"parentFile" ) ] = buffer;
134 wxASSERT( file.Sheet ==
nullptr && file.Screen ==
nullptr );
143 std::map tempAsyMap =
ReadAsyFile( ascFiles[i], mapOfAsyFiles );
144 wxString ascFileName = ascFiles[i].ElementName;
147 LIB_SYMBOL tempLibSymbol( ascFiles[i].ElementName );
155 curSheet->
SetParent( ascFiles[ascFiles[i].ParentIndex].Sheet );
159 wxString sheetName = wxString::Format( wxS(
"%s-subsheet-%d" ),
160 ascFiles[i].ElementName,
163 sheetNameField->
SetText( sheetName );
164 fileNameSheet->
SetText( sheetName +
".kicad_sch" );
166 curSheet->
SetScreen( ascFiles[i].Screen );
168 curSheetPath = ascFiles[ascFiles[i].ParentIndex].SheetPath;
171 ascFiles[i].SheetPath = curSheetPath;
173 ascFiles[ascFiles[i].ParentIndex].Sheet->GetScreen()->Append( curSheet );
181 ascFiles[i].SheetPath.push_back( curSheet );
182 curSheetPath = ascFiles[i].SheetPath;
185 std::vector<wxString> subSchematicAsyFiles;
188 subSchematicAsyFiles.push_back( ascFile.ElementName );
193 parser.
Parse( &curSheetPath, lt_ascs, subSchematicAsyFiles );
204 std::map<wxString, wxString>& aMapOfAscFiles,
205 std::map<wxString, wxString>& aMapOfAsyFiles,
206 const std::vector<wxString>& aBaseDirs )
210 if( !aDir.IsOpened() )
213 bool cont = aDir.GetFirst( &filename, wxEmptyString, wxDIR_FILES | wxDIR_HIDDEN );
217 wxFileName
path( aDir.GetName(), filename );
220 [&]( std::map<wxString, wxString>& aMapToLogTo,
const wxString& aKey )
222 if( aMapToLogTo.count( aKey ) )
226 m_reporter->Report( wxString::Format(
_(
"File at '%s' was ignored. Using previously "
227 "found file at '%s' instead." ),
229 aMapToLogTo.at( aKey ) ) );
234 aMapToLogTo.emplace( aKey,
path.GetFullPath() );
239 wxString extension =
path.GetExt().Lower();
241 for(
size_t i = 0; i < aBaseDirs.size() + 1; i++ )
245 for(
size_t j = i; j < aBaseDirs.size(); j++ )
246 alias << aBaseDirs[j].Lower() <<
'/';
248 alias <<
path.GetName().Lower();
250 if( extension == wxS(
"asc" ) )
251 logToMap( aMapOfAscFiles, alias );
252 else if( extension == wxS(
"asy" ) )
253 logToMap( aMapOfAsyFiles, alias );
256 cont = aDir.GetNext( &filename );
261 cont = aDir.GetFirst( &filename, wxEmptyString, wxDIR_DIRS | wxDIR_HIDDEN );
265 wxFileName
path( aDir.GetName(), filename );
266 wxDir subDir(
path.GetFullPath() );
268 std::vector<wxString> newBase = aBaseDirs;
269 newBase.push_back( filename );
273 cont = aDir.GetNext( &filename );
546 const wxString& aAsyFileContent,
552 lt_symbol.
Name = aAscFileName;
556 for( wxString line : wxSplit( aAsyFileContent,
'\n' ) )
560 wxArrayString tokens = wxSplit( line,
' ' );
562 if( tokens.IsEmpty() )
565 wxString element = tokens[0].Upper();
567 if( element ==
"LINE" )
571 wxString lineWidth = tokens[1];
572 wxString startPointX = tokens[2];
573 wxString startPointY = tokens[3];
574 wxString endPointX = tokens[4];
575 wxString endPointY = tokens[5];
579 lt_line.
Start =
pointCheck( startPointX, startPointY, lineNumber, aAscFileName );
580 lt_line.
End =
pointCheck( endPointX, endPointY, lineNumber, aAscFileName );
582 int lineStyleNumber = 0;
584 if( tokens.size() == 7 )
586 wxString lineStyle = tokens[6];
587 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
592 lt_symbol.
Lines.push_back( lt_line );
594 else if( element ==
"RECTANGLE" )
598 wxString lineWidth = tokens[1];
599 wxString botRightX = tokens[2];
600 wxString botRightY = tokens[3];
601 wxString topLeftX = tokens[4];
602 wxString topRightY = tokens[5];
609 int lineStyleNumber = 0;
611 if( tokens.size() == 7 )
613 wxString lineStyle = tokens[6];
614 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
621 else if( element ==
"CIRCLE" )
629 wxString lineWidth = tokens[1];
630 wxString botRightX = tokens[2];
631 wxString botRightY = tokens[3];
632 wxString topLeftX = tokens[4];
633 wxString topRightY = tokens[5];
637 circle.BotRight =
pointCheck( botRightX, botRightY, lineNumber, aAscFileName );
638 circle.TopLeft =
pointCheck( topLeftX, topRightY, lineNumber, aAscFileName );
640 int lineStyleNumber = 0;
642 if( tokens.size() == 7 )
644 wxString lineStyle = tokens[6];
645 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
652 else if( element ==
"ARC" )
661 wxString lineWidth = tokens[1];
662 wxString botRightX = tokens[2];
663 wxString botRightY = tokens[3];
664 wxString topLeftX = tokens[4];
665 wxString topRightY = tokens[5];
666 wxString arcStartPointX = tokens[6];
667 wxString arcStartPointY = tokens[7];
668 wxString arcEndPointX = tokens[8];
669 wxString arcEndPointY = tokens[9];
675 arc.
ArcStart =
pointCheck( arcStartPointX, arcStartPointY, lineNumber, aAscFileName );
676 arc.
ArcEnd =
pointCheck( arcEndPointX, arcEndPointY, lineNumber, aAscFileName );
678 int lineStyleNumber = 0;
680 if( tokens.size() == 11 )
682 wxString lineStyle = tokens[10];
683 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
688 lt_symbol.
Arcs.push_back( arc );
690 else if( element ==
"WINDOW" )
694 wxString number = tokens[1];
695 wxString windowPosX = tokens[2];
696 wxString windowPosY = tokens[3];
697 wxString justification = tokens[4];
698 wxString fontSize = tokens[5];
710 lt_symbol.
Windows.push_back( window );
712 else if( element ==
"SYMATTR" )
718 wxString key = tokens[1];
719 wxString value = tokens[2];
721 if( value == wxS(
"\"\"" ) )
722 value = wxEmptyString;
726 else if( element ==
"PIN" )
730 wxString pinLocationX = tokens[1];
731 wxString pinLocationY = tokens[2];
732 wxString Justification = tokens[3];
733 wxString nameOffSet = tokens[4];
736 pin.PinLocation =
pointCheck( pinLocationX, pinLocationY, lineNumber,aAscFileName );
740 lt_symbol.
Pins.push_back(
pin );
742 else if( element ==
"PINATTR" )
748 wxString
name = tokens[1];
749 wxString Value = tokens[2];
751 lt_symbol.
Pins.back().PinAttribute.insert( {
name, Value } );
753 else if( element ==
"SYMBOLTYPE" )
757 wxString symbolType = tokens[1];
793 std::vector<LT_ASC> ascFiles;
795 for(
const auto& [ fileName, contents ] :
m_fileCache[ wxS(
"ascFiles" ) ] )
798 std::vector<LT_SYMBOL> symbolArray;
808 for( wxString line : wxSplit( contents,
'\n' ) )
812 wxArrayString tokens = wxSplit( line,
' ' );
814 if( tokens.IsEmpty() )
817 wxString element = tokens[0].Upper();
819 if( element ==
"SHEET" )
823 wxString sheetNumber = tokens[1];
824 wxString sheetWidth = tokens[2];
825 wxString sheetHeight = tokens[3];
830 else if( element ==
"SYMBOL" )
834 wxString symbolName = tokens[1];
835 wxString posX = tokens[2];
836 wxString posY = tokens[3];
837 wxString rotate_mirror_option = tokens[4];
839 symbolName.Replace(
'\\',
'/' );
847 ascFile.
Symbols.push_back( lt_symbol );
860 ascFile.
Symbols.push_back( lt_symbol );
864 else if( element ==
"WIRE" )
868 wxString startPointX = tokens[1];
869 wxString startPointY = tokens[2];
870 wxString endPointX = tokens[3];
871 wxString endPointY = tokens[4];
874 wire.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
875 wire.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
877 ascFile.
Wires.push_back( wire );
881 else if( element ==
"FLAG" )
885 wxString posX = tokens[1];
886 wxString posY = tokens[2];
887 wxString
name = tokens[3];
897 else if( element ==
"DATAFLAG" )
901 wxString posX = tokens[1];
902 wxString posY = tokens[2];
903 wxString expression = tokens[3];
907 flag.Expression = expression;
913 else if( element ==
"WINDOW" )
917 wxString number = tokens[1];
918 wxString windowPosX = tokens[2];
919 wxString windowPosY = tokens[3];
920 wxString justification = tokens[4];
921 wxString fontSize = tokens[5];
923 int windowNumber =
integerCheck( number, lineNumber, fileName );
929 if( candidate.WindowNumber == windowNumber )
939 window = &ascFile.
Symbols.back().Windows.back();
949 else if( element ==
"SYMATTR" )
955 wxString
name = tokens[1];
956 wxString value = tokens[2];
958 if( value == wxS(
"\"\"" ) )
959 value = wxEmptyString;
961 ascFile.
Symbols.back().SymAttributes[
name.Upper() ] = value;
963 else if( element ==
"LINE" )
967 wxString lineWidth = tokens[1];
968 wxString startPointX = tokens[2];
969 wxString startPointY = tokens[3];
970 wxString endPointX = tokens[4];
971 wxString endPointY = tokens[5];
975 lt_line.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
976 lt_line.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
978 int lineStyleNumber = 0;
980 if( tokens.size() == 7 )
982 wxString lineStyle = tokens[6];
983 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
988 ascFile.
Lines.push_back( lt_line );
992 else if( element ==
"RECTANGLE" )
997 wxString botRightX = tokens[2];
998 wxString botRightY = tokens[3];
999 wxString topLeftX = tokens[4];
1000 wxString topRightY = tokens[5];
1007 int lineStyleNumber = 0;
1009 if( tokens.size() == 7 )
1011 wxString lineStyle = tokens[6];
1012 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1021 else if( element ==
"CIRCLE" )
1025 wxString lineWidth = tokens[1];
1026 wxString botRightX = tokens[2];
1027 wxString botRightY = tokens[3];
1028 wxString topLeftX = tokens[4];
1029 wxString topRightY = tokens[5];
1033 circle.BotRight =
pointCheck( botRightX, botRightY, lineNumber, fileName );
1036 int lineStyleNumber = 0;
1038 if( tokens.size() == 7 )
1040 wxString lineStyle = tokens[6];
1041 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1050 else if( element ==
"ARC" )
1059 wxString lineWidth = tokens[1];
1060 wxString botRightX = tokens[2];
1061 wxString botRightY = tokens[3];
1062 wxString topLeftX = tokens[4];
1063 wxString topRightY = tokens[5];
1064 wxString arcStartPointX = tokens[6];
1065 wxString arcStartPointY = tokens[7];
1066 wxString arcEndPointX = tokens[8];
1067 wxString arcEndPointY = tokens[9];
1073 arc.
ArcEnd =
pointCheck( arcStartPointX, arcStartPointY, lineNumber, fileName );
1076 int lineStyleNumber = 0;
1078 if( tokens.size() == 11 )
1080 wxString lineStyle = tokens[10];
1081 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1086 ascFile.
Arcs.push_back( arc );
1090 else if( element ==
"IOPIN" )
1094 wxString pinLocationX = tokens[1];
1095 wxString pinLocationY = tokens[2];
1096 wxString pinPolarity = tokens[3];
1102 ascFile.
Iopins.push_back( iopin );
1105 else if( element ==
"TEXT" )
1111 wxString positionX = tokens[1];
1112 wxString positionY = tokens[2];
1113 wxString justification = tokens[3];
1114 wxString fontSize = tokens[4];
1115 wxString value = tokens[5];
1118 text.Offset =
pointCheck( positionX, positionY, lineNumber, fileName );
1122 if( value.StartsWith( wxS(
"!" ), &
text.Value ) )
1123 text.Value.Replace( wxS(
"! " ), wxS(
"\n" ) );
1124 else if( value.StartsWith( wxS(
";" ), &
text.Value ) )
1125 text.Value.Replace( wxS(
"; " ), wxS(
"\n" ) );
1129 text.Value.Replace( wxS(
"\\n" ), wxS(
"\n" ) );
1134 else if( element ==
"BUSTAP" )
1138 wxString startPointX = tokens[1];
1139 wxString startPointY = tokens[2];
1140 wxString endPointX = tokens[3];
1141 wxString endPointY = tokens[4];
1144 bustap.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
1145 bustap.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
1147 ascFile.
Bustap.push_back( bustap );
1151 else if( element ==
"VERSION" )
1153 wxString versionNumber = tokens[1];
1154 if( versionNumber.Contains(
'.' ) )
1156 wxString majorStr = versionNumber.BeforeFirst(
'.' );
1157 wxString minorStr = versionNumber.AfterFirst(
'.' );
1170 ascFiles.push_back( std::move( ascFile ) );