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 )
211 bool cont = aDir.GetFirst( &filename, wxEmptyString, wxDIR_FILES | wxDIR_HIDDEN );
215 wxFileName
path( aDir.GetName(), filename );
217 auto logToMap = [&]( std::map<wxString, wxString>& aMapToLogTo,
const wxString& aKey )
219 if( aMapToLogTo.count( aKey ) )
223 m_reporter->Report( wxString::Format(
_(
"File at '%s' was ignored. Using previously "
224 "found file at '%s' instead." ),
226 aMapToLogTo.at( aKey ) ) );
231 aMapToLogTo.emplace( aKey,
path.GetFullPath() );
236 wxString extension =
path.GetExt().Lower();
238 for(
size_t i = 0; i < aBaseDirs.size() + 1; i++ )
242 for(
size_t j = i; j < aBaseDirs.size(); j++ )
243 alias << aBaseDirs[j].Lower() <<
'/';
245 alias <<
path.GetName().Lower();
247 if( extension == wxS(
"asc" ) )
248 logToMap( aMapOfAscFiles, alias );
249 else if( extension == wxS(
"asy" ) )
250 logToMap( aMapOfAsyFiles, alias );
253 cont = aDir.GetNext( &filename );
259 bool cont = aDir.GetFirst( &filename, wxEmptyString, wxDIR_DIRS | wxDIR_HIDDEN );
263 wxFileName
path( aDir.GetName(), filename );
264 wxDir subDir(
path.GetFullPath() );
266 std::vector<wxString> newBase = aBaseDirs;
267 newBase.push_back( filename );
271 cont = aDir.GetNext( &filename );
558 const wxString& aAsyFileContent,
564 lt_symbol.
Name = aAscFileName;
568 for( wxString line : wxSplit( aAsyFileContent,
'\n' ) )
572 wxArrayString tokens = wxSplit( line,
' ' );
574 if( tokens.IsEmpty() )
577 wxString element = tokens[0].Upper();
579 if( element ==
"LINE" )
583 wxString lineWidth = tokens[1];
584 wxString startPointX = tokens[2];
585 wxString startPointY = tokens[3];
586 wxString endPointX = tokens[4];
587 wxString endPointY = tokens[5];
591 lt_line.
Start =
pointCheck( startPointX, startPointY, lineNumber, aAscFileName );
592 lt_line.
End =
pointCheck( endPointX, endPointY, lineNumber, aAscFileName );
594 int lineStyleNumber = 0;
596 if( tokens.size() == 7 )
598 wxString lineStyle = tokens[6];
599 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
604 lt_symbol.
Lines.push_back( lt_line );
606 else if( element ==
"RECTANGLE" )
610 wxString lineWidth = tokens[1];
611 wxString botRightX = tokens[2];
612 wxString botRightY = tokens[3];
613 wxString topLeftX = tokens[4];
614 wxString topRightY = tokens[5];
621 int lineStyleNumber = 0;
623 if( tokens.size() == 7 )
625 wxString lineStyle = tokens[6];
626 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
633 else if( element ==
"CIRCLE" )
641 wxString lineWidth = tokens[1];
642 wxString botRightX = tokens[2];
643 wxString botRightY = tokens[3];
644 wxString topLeftX = tokens[4];
645 wxString topRightY = tokens[5];
649 circle.BotRight =
pointCheck( botRightX, botRightY, lineNumber, aAscFileName );
650 circle.TopLeft =
pointCheck( topLeftX, topRightY, lineNumber, aAscFileName );
652 int lineStyleNumber = 0;
654 if( tokens.size() == 7 )
656 wxString lineStyle = tokens[6];
657 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
664 else if( element ==
"ARC" )
673 wxString lineWidth = tokens[1];
674 wxString botRightX = tokens[2];
675 wxString botRightY = tokens[3];
676 wxString topLeftX = tokens[4];
677 wxString topRightY = tokens[5];
678 wxString arcStartPointX = tokens[6];
679 wxString arcStartPointY = tokens[7];
680 wxString arcEndPointX = tokens[8];
681 wxString arcEndPointY = tokens[9];
687 arc.
ArcStart =
pointCheck( arcStartPointX, arcStartPointY, lineNumber, aAscFileName );
688 arc.
ArcEnd =
pointCheck( arcEndPointX, arcEndPointY, lineNumber, aAscFileName );
690 int lineStyleNumber = 0;
692 if( tokens.size() == 11 )
694 wxString lineStyle = tokens[10];
695 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
700 lt_symbol.
Arcs.push_back( arc );
702 else if( element ==
"WINDOW" )
706 wxString number = tokens[1];
707 wxString windowPosX = tokens[2];
708 wxString windowPosY = tokens[3];
709 wxString justification = tokens[4];
710 wxString fontSize = tokens[5];
722 lt_symbol.
Windows.push_back( window );
724 else if( element ==
"SYMATTR" )
730 wxString key = tokens[1];
731 wxString value = tokens[2];
733 if( value == wxS(
"\"\"" ) )
734 value = wxEmptyString;
738 else if( element ==
"PIN" )
742 wxString pinLocationX = tokens[1];
743 wxString pinLocationY = tokens[2];
744 wxString Justification = tokens[3];
745 wxString nameOffSet = tokens[4];
748 pin.PinLocation =
pointCheck( pinLocationX, pinLocationY, lineNumber,aAscFileName );
752 lt_symbol.
Pins.push_back(
pin );
754 else if( element ==
"PINATTR" )
760 wxString
name = tokens[1];
761 wxString Value = tokens[2];
763 lt_symbol.
Pins.back().PinAttribute.insert( {
name, Value } );
765 else if( element ==
"SYMBOLTYPE" )
769 wxString symbolType = tokens[1];
805 std::vector<LT_ASC> ascFiles;
807 for(
const auto& [ fileName, contents ] :
m_fileCache[ wxS(
"ascFiles" ) ] )
810 std::vector<LT_SYMBOL> symbolArray;
820 for( wxString line : wxSplit( contents,
'\n' ) )
824 wxArrayString tokens = wxSplit( line,
' ' );
826 if( tokens.IsEmpty() )
829 wxString element = tokens[0].Upper();
831 if( element ==
"SHEET" )
835 wxString sheetNumber = tokens[1];
836 wxString sheetWidth = tokens[2];
837 wxString sheetHeight = tokens[3];
842 else if( element ==
"SYMBOL" )
846 wxString symbolName = tokens[1];
847 wxString posX = tokens[2];
848 wxString posY = tokens[3];
849 wxString rotate_mirror_option = tokens[4];
851 symbolName.Replace(
'\\',
'/' );
859 ascFile.
Symbols.push_back( lt_symbol );
872 ascFile.
Symbols.push_back( lt_symbol );
876 else if( element ==
"WIRE" )
880 wxString startPointX = tokens[1];
881 wxString startPointY = tokens[2];
882 wxString endPointX = tokens[3];
883 wxString endPointY = tokens[4];
886 wire.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
887 wire.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
889 ascFile.
Wires.push_back( wire );
893 else if( element ==
"FLAG" )
897 wxString posX = tokens[1];
898 wxString posY = tokens[2];
899 wxString
name = tokens[3];
909 else if( element ==
"DATAFLAG" )
913 wxString posX = tokens[1];
914 wxString posY = tokens[2];
915 wxString expression = tokens[3];
919 flag.Expression = expression;
925 else if( element ==
"WINDOW" )
929 wxString number = tokens[1];
930 wxString windowPosX = tokens[2];
931 wxString windowPosY = tokens[3];
932 wxString justification = tokens[4];
933 wxString fontSize = tokens[5];
935 int windowNumber =
integerCheck( number, lineNumber, fileName );
941 if( candidate.WindowNumber == windowNumber )
951 window = &ascFile.
Symbols.back().Windows.back();
961 else if( element ==
"SYMATTR" )
967 wxString
name = tokens[1];
968 wxString value = tokens[2];
970 if( value == wxS(
"\"\"" ) )
971 value = wxEmptyString;
973 ascFile.
Symbols.back().SymAttributes[
name.Upper() ] = value;
975 else if( element ==
"LINE" )
979 wxString lineWidth = tokens[1];
980 wxString startPointX = tokens[2];
981 wxString startPointY = tokens[3];
982 wxString endPointX = tokens[4];
983 wxString endPointY = tokens[5];
987 lt_line.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
988 lt_line.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
990 int lineStyleNumber = 0;
992 if( tokens.size() == 7 )
994 wxString lineStyle = tokens[6];
995 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1000 ascFile.
Lines.push_back( lt_line );
1004 else if( element ==
"RECTANGLE" )
1009 wxString botRightX = tokens[2];
1010 wxString botRightY = tokens[3];
1011 wxString topLeftX = tokens[4];
1012 wxString topRightY = tokens[5];
1019 int lineStyleNumber = 0;
1021 if( tokens.size() == 7 )
1023 wxString lineStyle = tokens[6];
1024 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1033 else if( element ==
"CIRCLE" )
1037 wxString lineWidth = tokens[1];
1038 wxString botRightX = tokens[2];
1039 wxString botRightY = tokens[3];
1040 wxString topLeftX = tokens[4];
1041 wxString topRightY = tokens[5];
1045 circle.BotRight =
pointCheck( botRightX, botRightY, lineNumber, fileName );
1048 int lineStyleNumber = 0;
1050 if( tokens.size() == 7 )
1052 wxString lineStyle = tokens[6];
1053 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1062 else if( element ==
"ARC" )
1071 wxString lineWidth = tokens[1];
1072 wxString botRightX = tokens[2];
1073 wxString botRightY = tokens[3];
1074 wxString topLeftX = tokens[4];
1075 wxString topRightY = tokens[5];
1076 wxString arcStartPointX = tokens[6];
1077 wxString arcStartPointY = tokens[7];
1078 wxString arcEndPointX = tokens[8];
1079 wxString arcEndPointY = tokens[9];
1085 arc.
ArcEnd =
pointCheck( arcStartPointX, arcStartPointY, lineNumber, fileName );
1088 int lineStyleNumber = 0;
1090 if( tokens.size() == 11 )
1092 wxString lineStyle = tokens[10];
1093 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1098 ascFile.
Arcs.push_back( arc );
1102 else if( element ==
"IOPIN" )
1106 wxString pinLocationX = tokens[1];
1107 wxString pinLocationY = tokens[2];
1108 wxString pinPolarity = tokens[3];
1114 ascFile.
Iopins.push_back( iopin );
1117 else if( element ==
"TEXT" )
1123 wxString positionX = tokens[1];
1124 wxString positionY = tokens[2];
1125 wxString justification = tokens[3];
1126 wxString fontSize = tokens[4];
1127 wxString value = tokens[5];
1130 text.Offset =
pointCheck( positionX, positionY, lineNumber, fileName );
1134 if( value.StartsWith( wxS(
"!" ), &
text.Value ) )
1135 text.Value.Replace( wxS(
"! " ), wxS(
"\n" ) );
1136 else if( value.StartsWith( wxS(
";" ), &
text.Value ) )
1137 text.Value.Replace( wxS(
"; " ), wxS(
"\n" ) );
1141 text.Value.Replace( wxS(
"\\n" ), wxS(
"\n" ) );
1146 else if( element ==
"BUSTAP" )
1150 wxString startPointX = tokens[1];
1151 wxString startPointY = tokens[2];
1152 wxString endPointX = tokens[3];
1153 wxString endPointY = tokens[4];
1156 bustap.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
1157 bustap.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
1159 ascFile.
Bustap.push_back( bustap );
1163 else if( element ==
"VERSION" )
1165 wxString versionNumber = tokens[1];
1166 if( versionNumber.Contains(
'.' ) )
1168 wxString majorStr = versionNumber.BeforeFirst(
'.' );
1169 wxString minorStr = versionNumber.AfterFirst(
'.' );
1182 ascFiles.push_back( std::move( ascFile ) );