65 const wxFileName& aLibraryFileName,
REPORTER* aReporter )
67 std::map<wxString, wxString> mapOfAscFiles;
68 std::map<wxString, wxString> mapOfAsyFiles;
84 std::queue<wxString> ascFileQueue;
85 ascFileQueue.push( aLibraryFileName.GetName().Lower() );
87 LTSPICE_FILE rootAscFile( ascFileQueue.front(), { 0, 0 } );
89 rootAscFile.
Sheet = aRootSheet;
92 int parentSheetIndex = 0;
95 std::vector<LTSPICE_FILE> ascFiles;
97 ascFiles.push_back( rootAscFile );
99 while( !ascFileQueue.empty() )
104 wxString ascFilePath = mapOfAscFiles[ ascFileQueue.front() ];
109 std::erase_if( newSubSchematicElements,
115 for(
LTSPICE_FILE& newSubSchematicElement : newSubSchematicElements )
117 wxString asyName = newSubSchematicElement.ElementName;
120 if( asyKey.IsEmpty() )
123 wxString asyBuffer =
SafeReadFile( mapOfAsyFiles.at( asyKey ),
"r" );
130 newSubSchematicElement.ParentIndex = parentSheetIndex;
131 newSubSchematicElement.Screen = screen;
132 newSubSchematicElement.Sheet =
new SCH_SHEET();
134 ascFileQueue.push( newSubSchematicElement.ElementName );
135 ascFiles.push_back( newSubSchematicElement );
144 for(
unsigned int i = 0; i < ascFiles.size(); i++ )
147 wxString buffer =
SafeReadFile( mapOfAscFiles[ascFiles[i].ElementName], wxS(
"r" ) );
154 m_fileCache[ wxS(
"ascFiles" ) ][ wxS(
"parentFile" ) ] = buffer;
157 wxASSERT( file.Sheet ==
nullptr && file.Screen ==
nullptr );
166 std::map tempAsyMap =
ReadAsyFile( ascFiles[i], mapOfAsyFiles );
167 wxString ascFileName = ascFiles[i].ElementName;
170 LIB_SYMBOL tempLibSymbol( ascFiles[i].ElementName );
178 curSheet->
SetParent( ascFiles[ascFiles[i].ParentIndex].Sheet );
182 wxString sheetName = wxString::Format( wxS(
"%s-subsheet-%d" ),
183 ascFiles[i].ElementName,
186 sheetNameField->
SetText( sheetName );
187 fileNameSheet->
SetText( sheetName +
".kicad_sch" );
189 curSheet->
SetScreen( ascFiles[i].Screen );
191 curSheetPath = ascFiles[ascFiles[i].ParentIndex].SheetPath;
194 ascFiles[i].SheetPath = curSheetPath;
196 ascFiles[ascFiles[i].ParentIndex].Sheet->GetScreen()->Append( curSheet );
204 ascFiles[i].SheetPath.push_back( curSheet );
205 curSheetPath = ascFiles[i].SheetPath;
208 std::vector<wxString> subSchematicAsyFiles;
211 subSchematicAsyFiles.push_back( ascFile.ElementName );
216 parser.
Parse( &curSheetPath, lt_ascs, subSchematicAsyFiles );
227 std::map<wxString, wxString>& aMapOfAscFiles,
228 std::map<wxString, wxString>& aMapOfAsyFiles,
229 const std::vector<wxString>& aBaseDirs )
233 if( !aDir.IsOpened() )
236 bool cont = aDir.GetFirst( &filename, wxEmptyString, wxDIR_FILES | wxDIR_HIDDEN );
240 wxFileName
path( aDir.GetName(), filename );
243 [&]( std::map<wxString, wxString>& aMapToLogTo,
const wxString& aKey )
245 if( aMapToLogTo.count( aKey ) )
249 m_reporter->Report( wxString::Format(
_(
"File at '%s' was ignored. Using previously "
250 "found file at '%s' instead." ),
252 aMapToLogTo.at( aKey ) ) );
257 aMapToLogTo.emplace( aKey,
path.GetFullPath() );
262 wxString extension =
path.GetExt().Lower();
264 for(
size_t i = 0; i < aBaseDirs.size() + 1; i++ )
268 for(
size_t j = i; j < aBaseDirs.size(); j++ )
269 alias << aBaseDirs[j].Lower() <<
'/';
271 alias <<
path.GetName().Lower();
273 if( extension == wxS(
"asc" ) )
274 logToMap( aMapOfAscFiles, alias );
275 else if( extension == wxS(
"asy" ) )
276 logToMap( aMapOfAsyFiles, alias );
279 cont = aDir.GetNext( &filename );
284 cont = aDir.GetFirst( &filename, wxEmptyString, wxDIR_DIRS | wxDIR_HIDDEN );
288 wxFileName
path( aDir.GetName(), filename );
289 wxDir subDir(
path.GetFullPath() );
291 std::vector<wxString> newBase = aBaseDirs;
292 newBase.push_back( filename );
296 cont = aDir.GetNext( &filename );
571 const wxString& aAsyFileContent,
577 lt_symbol.
Name = aAscFileName;
581 for( wxString line : wxSplit( aAsyFileContent,
'\n' ) )
585 wxArrayString tokens = wxSplit( line,
' ' );
587 if( tokens.IsEmpty() )
590 wxString element = tokens[0].Upper();
592 if( element ==
"LINE" )
596 wxString lineWidth = tokens[1];
597 wxString startPointX = tokens[2];
598 wxString startPointY = tokens[3];
599 wxString endPointX = tokens[4];
600 wxString endPointY = tokens[5];
604 lt_line.
Start =
pointCheck( startPointX, startPointY, lineNumber, aAscFileName );
605 lt_line.
End =
pointCheck( endPointX, endPointY, lineNumber, aAscFileName );
607 int lineStyleNumber = 0;
609 if( tokens.size() == 7 )
611 wxString lineStyle = tokens[6];
612 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
617 lt_symbol.
Lines.push_back( lt_line );
619 else if( element ==
"RECTANGLE" )
623 wxString lineWidth = tokens[1];
624 wxString botRightX = tokens[2];
625 wxString botRightY = tokens[3];
626 wxString topLeftX = tokens[4];
627 wxString topRightY = tokens[5];
634 int lineStyleNumber = 0;
636 if( tokens.size() == 7 )
638 wxString lineStyle = tokens[6];
639 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
646 else if( element ==
"CIRCLE" )
654 wxString lineWidth = tokens[1];
655 wxString botRightX = tokens[2];
656 wxString botRightY = tokens[3];
657 wxString topLeftX = tokens[4];
658 wxString topRightY = tokens[5];
662 circle.BotRight =
pointCheck( botRightX, botRightY, lineNumber, aAscFileName );
663 circle.TopLeft =
pointCheck( topLeftX, topRightY, lineNumber, aAscFileName );
665 int lineStyleNumber = 0;
667 if( tokens.size() == 7 )
669 wxString lineStyle = tokens[6];
670 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
677 else if( element ==
"ARC" )
686 wxString lineWidth = tokens[1];
687 wxString botRightX = tokens[2];
688 wxString botRightY = tokens[3];
689 wxString topLeftX = tokens[4];
690 wxString topRightY = tokens[5];
691 wxString arcStartPointX = tokens[6];
692 wxString arcStartPointY = tokens[7];
693 wxString arcEndPointX = tokens[8];
694 wxString arcEndPointY = tokens[9];
700 arc.
ArcStart =
pointCheck( arcStartPointX, arcStartPointY, lineNumber, aAscFileName );
701 arc.
ArcEnd =
pointCheck( arcEndPointX, arcEndPointY, lineNumber, aAscFileName );
703 int lineStyleNumber = 0;
705 if( tokens.size() == 11 )
707 wxString lineStyle = tokens[10];
708 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
713 lt_symbol.
Arcs.push_back( arc );
715 else if( element ==
"WINDOW" )
719 wxString number = tokens[1];
720 wxString windowPosX = tokens[2];
721 wxString windowPosY = tokens[3];
722 wxString justification = tokens[4];
723 wxString fontSize = tokens[5];
735 lt_symbol.
Windows.push_back( window );
737 else if( element ==
"SYMATTR" )
743 wxString key = tokens[1];
744 wxString value = tokens[2];
746 if( value == wxS(
"\"\"" ) )
747 value = wxEmptyString;
751 else if( element ==
"PIN" )
755 wxString pinLocationX = tokens[1];
756 wxString pinLocationY = tokens[2];
757 wxString Justification = tokens[3];
758 wxString nameOffSet = tokens[4];
761 pin.PinLocation =
pointCheck( pinLocationX, pinLocationY, lineNumber,aAscFileName );
765 lt_symbol.
Pins.push_back(
pin );
767 else if( element ==
"PINATTR" )
773 wxString
name = tokens[1];
774 wxString Value = tokens[2];
776 lt_symbol.
Pins.back().PinAttribute.insert( {
name, Value } );
778 else if( element ==
"SYMBOLTYPE" )
782 wxString symbolType = tokens[1];
818 std::vector<LT_ASC> ascFiles;
820 for(
const auto& [ fileName, contents ] :
m_fileCache[ wxS(
"ascFiles" ) ] )
823 std::vector<LT_SYMBOL> symbolArray;
833 for( wxString line : wxSplit( contents,
'\n' ) )
837 wxArrayString tokens = wxSplit( line,
' ' );
839 if( tokens.IsEmpty() )
842 wxString element = tokens[0].Upper();
844 if( element ==
"SHEET" )
848 wxString sheetNumber = tokens[1];
849 wxString sheetWidth = tokens[2];
850 wxString sheetHeight = tokens[3];
855 else if( element ==
"SYMBOL" )
859 wxString symbolName = tokens[1];
860 wxString posX = tokens[2];
861 wxString posY = tokens[3];
862 wxString rotate_mirror_option = tokens[4];
864 symbolName.Replace(
'\\',
'/' );
872 ascFile.
Symbols.push_back( lt_symbol );
885 ascFile.
Symbols.push_back( lt_symbol );
889 else if( element ==
"WIRE" )
893 wxString startPointX = tokens[1];
894 wxString startPointY = tokens[2];
895 wxString endPointX = tokens[3];
896 wxString endPointY = tokens[4];
899 wire.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
900 wire.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
902 ascFile.
Wires.push_back( wire );
906 else if( element ==
"FLAG" )
910 wxString posX = tokens[1];
911 wxString posY = tokens[2];
912 wxString
name = tokens[3];
922 else if( element ==
"DATAFLAG" )
926 wxString posX = tokens[1];
927 wxString posY = tokens[2];
928 wxString expression = tokens[3];
932 flag.Expression = expression;
938 else if( element ==
"WINDOW" )
942 wxString number = tokens[1];
943 wxString windowPosX = tokens[2];
944 wxString windowPosY = tokens[3];
945 wxString justification = tokens[4];
946 wxString fontSize = tokens[5];
948 int windowNumber =
integerCheck( number, lineNumber, fileName );
954 if( candidate.WindowNumber == windowNumber )
964 window = &ascFile.
Symbols.back().Windows.back();
974 else if( element ==
"SYMATTR" )
980 wxString
name = tokens[1];
981 wxString value = tokens[2];
983 if( value == wxS(
"\"\"" ) )
984 value = wxEmptyString;
986 ascFile.
Symbols.back().SymAttributes[
name.Upper() ] = value;
988 else if( element ==
"LINE" )
992 wxString lineWidth = tokens[1];
993 wxString startPointX = tokens[2];
994 wxString startPointY = tokens[3];
995 wxString endPointX = tokens[4];
996 wxString endPointY = tokens[5];
1000 lt_line.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
1001 lt_line.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
1003 int lineStyleNumber = 0;
1005 if( tokens.size() == 7 )
1007 wxString lineStyle = tokens[6];
1008 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1013 ascFile.
Lines.push_back( lt_line );
1017 else if( element ==
"RECTANGLE" )
1022 wxString botRightX = tokens[2];
1023 wxString botRightY = tokens[3];
1024 wxString topLeftX = tokens[4];
1025 wxString topRightY = tokens[5];
1032 int lineStyleNumber = 0;
1034 if( tokens.size() == 7 )
1036 wxString lineStyle = tokens[6];
1037 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1046 else if( element ==
"CIRCLE" )
1050 wxString lineWidth = tokens[1];
1051 wxString botRightX = tokens[2];
1052 wxString botRightY = tokens[3];
1053 wxString topLeftX = tokens[4];
1054 wxString topRightY = tokens[5];
1058 circle.BotRight =
pointCheck( botRightX, botRightY, lineNumber, fileName );
1061 int lineStyleNumber = 0;
1063 if( tokens.size() == 7 )
1065 wxString lineStyle = tokens[6];
1066 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1075 else if( element ==
"ARC" )
1084 wxString lineWidth = tokens[1];
1085 wxString botRightX = tokens[2];
1086 wxString botRightY = tokens[3];
1087 wxString topLeftX = tokens[4];
1088 wxString topRightY = tokens[5];
1089 wxString arcStartPointX = tokens[6];
1090 wxString arcStartPointY = tokens[7];
1091 wxString arcEndPointX = tokens[8];
1092 wxString arcEndPointY = tokens[9];
1098 arc.
ArcEnd =
pointCheck( arcStartPointX, arcStartPointY, lineNumber, fileName );
1101 int lineStyleNumber = 0;
1103 if( tokens.size() == 11 )
1105 wxString lineStyle = tokens[10];
1106 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1111 ascFile.
Arcs.push_back( arc );
1115 else if( element ==
"IOPIN" )
1119 wxString pinLocationX = tokens[1];
1120 wxString pinLocationY = tokens[2];
1121 wxString pinPolarity = tokens[3];
1127 ascFile.
Iopins.push_back( iopin );
1130 else if( element ==
"TEXT" )
1136 wxString positionX = tokens[1];
1137 wxString positionY = tokens[2];
1138 wxString justification = tokens[3];
1139 wxString fontSize = tokens[4];
1140 wxString value = tokens[5];
1143 text.Offset =
pointCheck( positionX, positionY, lineNumber, fileName );
1147 if( value.StartsWith( wxS(
"!" ), &
text.Value ) )
1148 text.Value.Replace( wxS(
"! " ), wxS(
"\n" ) );
1149 else if( value.StartsWith( wxS(
";" ), &
text.Value ) )
1150 text.Value.Replace( wxS(
"; " ), wxS(
"\n" ) );
1154 text.Value.Replace( wxS(
"\\n" ), wxS(
"\n" ) );
1159 else if( element ==
"BUSTAP" )
1163 wxString startPointX = tokens[1];
1164 wxString startPointY = tokens[2];
1165 wxString endPointX = tokens[3];
1166 wxString endPointY = tokens[4];
1169 bustap.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
1170 bustap.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
1172 ascFile.
Bustap.push_back( bustap );
1176 else if( element ==
"VERSION" )
1178 wxString versionNumber = tokens[1];
1179 if( versionNumber.Contains(
'.' ) )
1181 wxString majorStr = versionNumber.BeforeFirst(
'.' );
1182 wxString minorStr = versionNumber.AfterFirst(
'.' );
1195 ascFiles.push_back( std::move( ascFile ) );