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 );
560 const wxString& aAsyFileContent,
566 lt_symbol.
Name = aAscFileName;
570 for( wxString line : wxSplit( aAsyFileContent,
'\n' ) )
574 wxArrayString tokens = wxSplit( line,
' ' );
576 if( tokens.IsEmpty() )
579 wxString element = tokens[0].Upper();
581 if( element ==
"LINE" )
585 wxString lineWidth = tokens[1];
586 wxString startPointX = tokens[2];
587 wxString startPointY = tokens[3];
588 wxString endPointX = tokens[4];
589 wxString endPointY = tokens[5];
593 lt_line.
Start =
pointCheck( startPointX, startPointY, lineNumber, aAscFileName );
594 lt_line.
End =
pointCheck( endPointX, endPointY, lineNumber, aAscFileName );
596 int lineStyleNumber = 0;
598 if( tokens.size() == 7 )
600 wxString lineStyle = tokens[6];
601 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
606 lt_symbol.
Lines.push_back( lt_line );
608 else if( element ==
"RECTANGLE" )
612 wxString lineWidth = tokens[1];
613 wxString botRightX = tokens[2];
614 wxString botRightY = tokens[3];
615 wxString topLeftX = tokens[4];
616 wxString topRightY = tokens[5];
623 int lineStyleNumber = 0;
625 if( tokens.size() == 7 )
627 wxString lineStyle = tokens[6];
628 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
635 else if( element ==
"CIRCLE" )
643 wxString lineWidth = tokens[1];
644 wxString botRightX = tokens[2];
645 wxString botRightY = tokens[3];
646 wxString topLeftX = tokens[4];
647 wxString topRightY = tokens[5];
651 circle.BotRight =
pointCheck( botRightX, botRightY, lineNumber, aAscFileName );
652 circle.TopLeft =
pointCheck( topLeftX, topRightY, lineNumber, aAscFileName );
654 int lineStyleNumber = 0;
656 if( tokens.size() == 7 )
658 wxString lineStyle = tokens[6];
659 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
666 else if( element ==
"ARC" )
675 wxString lineWidth = tokens[1];
676 wxString botRightX = tokens[2];
677 wxString botRightY = tokens[3];
678 wxString topLeftX = tokens[4];
679 wxString topRightY = tokens[5];
680 wxString arcStartPointX = tokens[6];
681 wxString arcStartPointY = tokens[7];
682 wxString arcEndPointX = tokens[8];
683 wxString arcEndPointY = tokens[9];
689 arc.
ArcStart =
pointCheck( arcStartPointX, arcStartPointY, lineNumber, aAscFileName );
690 arc.
ArcEnd =
pointCheck( arcEndPointX, arcEndPointY, lineNumber, aAscFileName );
692 int lineStyleNumber = 0;
694 if( tokens.size() == 11 )
696 wxString lineStyle = tokens[10];
697 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
702 lt_symbol.
Arcs.push_back( arc );
704 else if( element ==
"WINDOW" )
708 wxString number = tokens[1];
709 wxString windowPosX = tokens[2];
710 wxString windowPosY = tokens[3];
711 wxString justification = tokens[4];
712 wxString fontSize = tokens[5];
724 lt_symbol.
Windows.push_back( window );
726 else if( element ==
"SYMATTR" )
732 wxString key = tokens[1];
733 wxString value = tokens[2];
735 if( value == wxS(
"\"\"" ) )
736 value = wxEmptyString;
740 else if( element ==
"PIN" )
744 wxString pinLocationX = tokens[1];
745 wxString pinLocationY = tokens[2];
746 wxString Justification = tokens[3];
747 wxString nameOffSet = tokens[4];
750 pin.PinLocation =
pointCheck( pinLocationX, pinLocationY, lineNumber,aAscFileName );
754 lt_symbol.
Pins.push_back(
pin );
756 else if( element ==
"PINATTR" )
762 wxString
name = tokens[1];
763 wxString Value = tokens[2];
765 lt_symbol.
Pins.back().PinAttribute.insert( {
name, Value } );
767 else if( element ==
"SYMBOLTYPE" )
771 wxString symbolType = tokens[1];
807 std::vector<LT_ASC> ascFiles;
809 for(
const auto& [ fileName, contents ] :
m_fileCache[ wxS(
"ascFiles" ) ] )
812 std::vector<LT_SYMBOL> symbolArray;
822 for( wxString line : wxSplit( contents,
'\n' ) )
826 wxArrayString tokens = wxSplit( line,
' ' );
828 if( tokens.IsEmpty() )
831 wxString element = tokens[0].Upper();
833 if( element ==
"SHEET" )
837 wxString sheetNumber = tokens[1];
838 wxString sheetWidth = tokens[2];
839 wxString sheetHeight = tokens[3];
844 else if( element ==
"SYMBOL" )
848 wxString symbolName = tokens[1];
849 wxString posX = tokens[2];
850 wxString posY = tokens[3];
851 wxString rotate_mirror_option = tokens[4];
853 symbolName.Replace(
'\\',
'/' );
861 ascFile.
Symbols.push_back( lt_symbol );
874 ascFile.
Symbols.push_back( lt_symbol );
878 else if( element ==
"WIRE" )
882 wxString startPointX = tokens[1];
883 wxString startPointY = tokens[2];
884 wxString endPointX = tokens[3];
885 wxString endPointY = tokens[4];
888 wire.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
889 wire.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
891 ascFile.
Wires.push_back( wire );
895 else if( element ==
"FLAG" )
899 wxString posX = tokens[1];
900 wxString posY = tokens[2];
901 wxString
name = tokens[3];
911 else if( element ==
"DATAFLAG" )
915 wxString posX = tokens[1];
916 wxString posY = tokens[2];
917 wxString expression = tokens[3];
921 flag.Expression = expression;
927 else if( element ==
"WINDOW" )
931 wxString number = tokens[1];
932 wxString windowPosX = tokens[2];
933 wxString windowPosY = tokens[3];
934 wxString justification = tokens[4];
935 wxString fontSize = tokens[5];
937 int windowNumber =
integerCheck( number, lineNumber, fileName );
943 if( candidate.WindowNumber == windowNumber )
953 window = &ascFile.
Symbols.back().Windows.back();
963 else if( element ==
"SYMATTR" )
969 wxString
name = tokens[1];
970 wxString value = tokens[2];
972 if( value == wxS(
"\"\"" ) )
973 value = wxEmptyString;
975 ascFile.
Symbols.back().SymAttributes[
name.Upper() ] = value;
977 else if( element ==
"LINE" )
981 wxString lineWidth = tokens[1];
982 wxString startPointX = tokens[2];
983 wxString startPointY = tokens[3];
984 wxString endPointX = tokens[4];
985 wxString endPointY = tokens[5];
989 lt_line.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
990 lt_line.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
992 int lineStyleNumber = 0;
994 if( tokens.size() == 7 )
996 wxString lineStyle = tokens[6];
997 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1002 ascFile.
Lines.push_back( lt_line );
1006 else if( element ==
"RECTANGLE" )
1011 wxString botRightX = tokens[2];
1012 wxString botRightY = tokens[3];
1013 wxString topLeftX = tokens[4];
1014 wxString topRightY = tokens[5];
1021 int lineStyleNumber = 0;
1023 if( tokens.size() == 7 )
1025 wxString lineStyle = tokens[6];
1026 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1035 else if( element ==
"CIRCLE" )
1039 wxString lineWidth = tokens[1];
1040 wxString botRightX = tokens[2];
1041 wxString botRightY = tokens[3];
1042 wxString topLeftX = tokens[4];
1043 wxString topRightY = tokens[5];
1047 circle.BotRight =
pointCheck( botRightX, botRightY, lineNumber, fileName );
1050 int lineStyleNumber = 0;
1052 if( tokens.size() == 7 )
1054 wxString lineStyle = tokens[6];
1055 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1064 else if( element ==
"ARC" )
1073 wxString lineWidth = tokens[1];
1074 wxString botRightX = tokens[2];
1075 wxString botRightY = tokens[3];
1076 wxString topLeftX = tokens[4];
1077 wxString topRightY = tokens[5];
1078 wxString arcStartPointX = tokens[6];
1079 wxString arcStartPointY = tokens[7];
1080 wxString arcEndPointX = tokens[8];
1081 wxString arcEndPointY = tokens[9];
1087 arc.
ArcEnd =
pointCheck( arcStartPointX, arcStartPointY, lineNumber, fileName );
1090 int lineStyleNumber = 0;
1092 if( tokens.size() == 11 )
1094 wxString lineStyle = tokens[10];
1095 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1100 ascFile.
Arcs.push_back( arc );
1104 else if( element ==
"IOPIN" )
1108 wxString pinLocationX = tokens[1];
1109 wxString pinLocationY = tokens[2];
1110 wxString pinPolarity = tokens[3];
1116 ascFile.
Iopins.push_back( iopin );
1119 else if( element ==
"TEXT" )
1125 wxString positionX = tokens[1];
1126 wxString positionY = tokens[2];
1127 wxString justification = tokens[3];
1128 wxString fontSize = tokens[4];
1129 wxString value = tokens[5];
1132 text.Offset =
pointCheck( positionX, positionY, lineNumber, fileName );
1136 if( value.StartsWith( wxS(
"!" ), &
text.Value ) )
1137 text.Value.Replace( wxS(
"! " ), wxS(
"\n" ) );
1138 else if( value.StartsWith( wxS(
";" ), &
text.Value ) )
1139 text.Value.Replace( wxS(
"; " ), wxS(
"\n" ) );
1143 text.Value.Replace( wxS(
"\\n" ), wxS(
"\n" ) );
1148 else if( element ==
"BUSTAP" )
1152 wxString startPointX = tokens[1];
1153 wxString startPointY = tokens[2];
1154 wxString endPointX = tokens[3];
1155 wxString endPointY = tokens[4];
1158 bustap.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
1159 bustap.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
1161 ascFile.
Bustap.push_back( bustap );
1165 else if( element ==
"VERSION" )
1167 wxString versionNumber = tokens[1];
1168 if( versionNumber.Contains(
'.' ) )
1170 wxString majorStr = versionNumber.BeforeFirst(
'.' );
1171 wxString minorStr = versionNumber.AfterFirst(
'.' );
1184 ascFiles.push_back( std::move( ascFile ) );