41 const wxFileName& aLibraryFileName,
REPORTER* aReporter )
43 std::map<wxString, wxString> mapOfAscFiles;
44 std::map<wxString, wxString> mapOfAsyFiles;
60 std::queue<wxString> ascFileQueue;
61 ascFileQueue.push( aLibraryFileName.GetName().Lower() );
63 LTSPICE_FILE rootAscFile( ascFileQueue.front(), { 0, 0 } );
65 rootAscFile.
Sheet = aRootSheet;
68 int parentSheetIndex = 0;
71 std::vector<LTSPICE_FILE> ascFiles;
73 ascFiles.push_back( rootAscFile );
75 while( !ascFileQueue.empty() )
80 wxString ascFilePath = mapOfAscFiles[ ascFileQueue.front() ];
85 std::erase_if( newSubSchematicElements,
91 for(
LTSPICE_FILE& newSubSchematicElement : newSubSchematicElements )
93 wxString asyName = newSubSchematicElement.ElementName;
94 auto it = mapOfAsyFiles.find( asyName );
96 if( it == mapOfAsyFiles.end() )
106 newSubSchematicElement.ParentIndex = parentSheetIndex;
107 newSubSchematicElement.Screen = screen;
108 newSubSchematicElement.Sheet =
new SCH_SHEET();
110 ascFileQueue.push( newSubSchematicElement.ElementName );
111 ascFiles.push_back( newSubSchematicElement );
120 for(
unsigned int i = 0; i < ascFiles.size(); i++ )
123 wxString buffer =
SafeReadFile( mapOfAscFiles[ascFiles[i].ElementName], wxS(
"r" ) );
130 m_fileCache[ wxS(
"ascFiles" ) ][ wxS(
"parentFile" ) ] = buffer;
133 wxASSERT( file.Sheet ==
nullptr && file.Screen ==
nullptr );
142 std::map tempAsyMap =
ReadAsyFile( ascFiles[i], mapOfAsyFiles );
143 wxString ascFileName = ascFiles[i].ElementName;
146 LIB_SYMBOL tempLibSymbol( ascFiles[i].ElementName );
154 curSheet->
SetParent( ascFiles[ascFiles[i].ParentIndex].Sheet );
158 wxString sheetName = wxString::Format( wxS(
"%s-subsheet-%d" ),
159 ascFiles[i].ElementName,
162 sheetNameField->
SetText( sheetName );
163 fileNameSheet->
SetText( sheetName +
".kicad_sch" );
165 curSheet->
SetScreen( ascFiles[i].Screen );
167 curSheetPath = ascFiles[ascFiles[i].ParentIndex].SheetPath;
170 ascFiles[i].SheetPath = curSheetPath;
172 ascFiles[ascFiles[i].ParentIndex].Sheet->GetScreen()->Append( curSheet );
180 ascFiles[i].SheetPath.push_back( curSheet );
181 curSheetPath = ascFiles[i].SheetPath;
184 std::vector<wxString> subSchematicAsyFiles;
187 subSchematicAsyFiles.push_back( ascFile.ElementName );
192 parser.
Parse( &curSheetPath, lt_ascs, subSchematicAsyFiles );
203 std::map<wxString, wxString>& aMapOfAscFiles,
204 std::map<wxString, wxString>& aMapOfAsyFiles,
205 const std::vector<wxString>& aBaseDirs )
210 bool cont = aDir.GetFirst( &filename, wxEmptyString, wxDIR_FILES | wxDIR_HIDDEN );
214 wxFileName
path( aDir.GetName(), filename );
216 auto logToMap = [&]( std::map<wxString, wxString>& aMapToLogTo,
const wxString& aKey )
218 if( aMapToLogTo.count( aKey ) )
222 m_reporter->Report( wxString::Format(
_(
"File at '%s' was ignored. Using previously "
223 "found file at '%s' instead." ),
225 aMapToLogTo.at( aKey ) ) );
230 aMapToLogTo.emplace( aKey,
path.GetFullPath() );
235 wxString extension =
path.GetExt().Lower();
237 for(
size_t i = 0; i < aBaseDirs.size() + 1; i++ )
241 for(
size_t j = i; j < aBaseDirs.size(); j++ )
242 alias << aBaseDirs[j].Lower() <<
'/';
244 alias <<
path.GetName().Lower();
246 if( extension == wxS(
"asc" ) )
247 logToMap( aMapOfAscFiles, alias );
248 else if( extension == wxS(
"asy" ) )
249 logToMap( aMapOfAsyFiles, alias );
252 cont = aDir.GetNext( &filename );
258 bool cont = aDir.GetFirst( &filename, wxEmptyString, wxDIR_DIRS | wxDIR_HIDDEN );
262 wxFileName
path( aDir.GetName(), filename );
263 wxDir subDir(
path.GetFullPath() );
265 std::vector<wxString> newBase = aBaseDirs;
266 newBase.push_back( filename );
270 cont = aDir.GetNext( &filename );
557 const wxString& aAsyFileContent,
563 lt_symbol.
Name = aAscFileName;
567 for( wxString line : wxSplit( aAsyFileContent,
'\n' ) )
571 wxArrayString tokens = wxSplit( line,
' ' );
573 if( tokens.IsEmpty() )
576 wxString element = tokens[0].Upper();
578 if( element ==
"LINE" )
582 wxString lineWidth = tokens[1];
583 wxString startPointX = tokens[2];
584 wxString startPointY = tokens[3];
585 wxString endPointX = tokens[4];
586 wxString endPointY = tokens[5];
590 lt_line.
Start =
pointCheck( startPointX, startPointY, lineNumber, aAscFileName );
591 lt_line.
End =
pointCheck( endPointX, endPointY, lineNumber, aAscFileName );
593 int lineStyleNumber = 0;
595 if( tokens.size() == 7 )
597 wxString lineStyle = tokens[6];
598 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
603 lt_symbol.
Lines.push_back( lt_line );
605 else if( element ==
"RECTANGLE" )
609 wxString lineWidth = tokens[1];
610 wxString botRightX = tokens[2];
611 wxString botRightY = tokens[3];
612 wxString topLeftX = tokens[4];
613 wxString topRightY = tokens[5];
620 int lineStyleNumber = 0;
622 if( tokens.size() == 7 )
624 wxString lineStyle = tokens[6];
625 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
632 else if( element ==
"CIRCLE" )
640 wxString lineWidth = tokens[1];
641 wxString botRightX = tokens[2];
642 wxString botRightY = tokens[3];
643 wxString topLeftX = tokens[4];
644 wxString topRightY = tokens[5];
648 circle.BotRight =
pointCheck( botRightX, botRightY, lineNumber, aAscFileName );
649 circle.TopLeft =
pointCheck( topLeftX, topRightY, lineNumber, aAscFileName );
651 int lineStyleNumber = 0;
653 if( tokens.size() == 7 )
655 wxString lineStyle = tokens[6];
656 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
663 else if( element ==
"ARC" )
672 wxString lineWidth = tokens[1];
673 wxString botRightX = tokens[2];
674 wxString botRightY = tokens[3];
675 wxString topLeftX = tokens[4];
676 wxString topRightY = tokens[5];
677 wxString arcStartPointX = tokens[6];
678 wxString arcStartPointY = tokens[7];
679 wxString arcEndPointX = tokens[8];
680 wxString arcEndPointY = tokens[9];
686 arc.
ArcStart =
pointCheck( arcStartPointX, arcStartPointY, lineNumber, aAscFileName );
687 arc.
ArcEnd =
pointCheck( arcEndPointX, arcEndPointY, lineNumber, aAscFileName );
689 int lineStyleNumber = 0;
691 if( tokens.size() == 11 )
693 wxString lineStyle = tokens[10];
694 lineStyleNumber =
integerCheck( lineStyle, lineNumber, aAscFileName );
699 lt_symbol.
Arcs.push_back( arc );
701 else if( element ==
"WINDOW" )
705 wxString number = tokens[1];
706 wxString windowPosX = tokens[2];
707 wxString windowPosY = tokens[3];
708 wxString justification = tokens[4];
709 wxString fontSize = tokens[5];
721 lt_symbol.
Windows.push_back( window );
723 else if( element ==
"SYMATTR" )
729 wxString key = tokens[1];
730 wxString value = tokens[2];
732 if( value == wxS(
"\"\"" ) )
733 value = wxEmptyString;
737 else if( element ==
"PIN" )
741 wxString pinLocationX = tokens[1];
742 wxString pinLocationY = tokens[2];
743 wxString Justification = tokens[3];
744 wxString nameOffSet = tokens[4];
747 pin.PinLocation =
pointCheck( pinLocationX, pinLocationY, lineNumber,aAscFileName );
751 lt_symbol.
Pins.push_back(
pin );
753 else if( element ==
"PINATTR" )
759 wxString
name = tokens[1];
760 wxString Value = tokens[2];
762 lt_symbol.
Pins.back().PinAttribute.insert( {
name, Value } );
764 else if( element ==
"SYMBOLTYPE" )
768 wxString symbolType = tokens[1];
804 std::vector<LT_ASC> ascFiles;
806 for(
const auto& [ fileName, contents ] :
m_fileCache[ wxS(
"ascFiles" ) ] )
809 std::vector<LT_SYMBOL> symbolArray;
819 for( wxString line : wxSplit( contents,
'\n' ) )
823 wxArrayString tokens = wxSplit( line,
' ' );
825 if( tokens.IsEmpty() )
828 wxString element = tokens[0].Upper();
830 if( element ==
"SHEET" )
834 wxString sheetNumber = tokens[1];
835 wxString sheetWidth = tokens[2];
836 wxString sheetHeight = tokens[3];
841 else if( element ==
"SYMBOL" )
845 wxString symbolName = tokens[1];
846 wxString posX = tokens[2];
847 wxString posY = tokens[3];
848 wxString rotate_mirror_option = tokens[4];
850 symbolName.Replace(
'\\',
'/' );
858 ascFile.
Symbols.push_back( lt_symbol );
871 ascFile.
Symbols.push_back( lt_symbol );
875 else if( element ==
"WIRE" )
879 wxString startPointX = tokens[1];
880 wxString startPointY = tokens[2];
881 wxString endPointX = tokens[3];
882 wxString endPointY = tokens[4];
885 wire.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
886 wire.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
888 ascFile.
Wires.push_back( wire );
892 else if( element ==
"FLAG" )
896 wxString posX = tokens[1];
897 wxString posY = tokens[2];
898 wxString
name = tokens[3];
908 else if( element ==
"DATAFLAG" )
912 wxString posX = tokens[1];
913 wxString posY = tokens[2];
914 wxString expression = tokens[3];
918 flag.Expression = expression;
924 else if( element ==
"WINDOW" )
928 wxString number = tokens[1];
929 wxString windowPosX = tokens[2];
930 wxString windowPosY = tokens[3];
931 wxString justification = tokens[4];
932 wxString fontSize = tokens[5];
934 int windowNumber =
integerCheck( number, lineNumber, fileName );
940 if( candidate.WindowNumber == windowNumber )
950 window = &ascFile.
Symbols.back().Windows.back();
960 else if( element ==
"SYMATTR" )
966 wxString
name = tokens[1];
967 wxString value = tokens[2];
969 if( value == wxS(
"\"\"" ) )
970 value = wxEmptyString;
972 ascFile.
Symbols.back().SymAttributes[
name.Upper() ] = value;
974 else if( element ==
"LINE" )
978 wxString lineWidth = tokens[1];
979 wxString startPointX = tokens[2];
980 wxString startPointY = tokens[3];
981 wxString endPointX = tokens[4];
982 wxString endPointY = tokens[5];
986 lt_line.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
987 lt_line.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
989 int lineStyleNumber = 0;
991 if( tokens.size() == 7 )
993 wxString lineStyle = tokens[6];
994 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
999 ascFile.
Lines.push_back( lt_line );
1003 else if( element ==
"RECTANGLE" )
1008 wxString botRightX = tokens[2];
1009 wxString botRightY = tokens[3];
1010 wxString topLeftX = tokens[4];
1011 wxString topRightY = tokens[5];
1018 int lineStyleNumber = 0;
1020 if( tokens.size() == 7 )
1022 wxString lineStyle = tokens[6];
1023 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1032 else if( element ==
"CIRCLE" )
1036 wxString lineWidth = tokens[1];
1037 wxString botRightX = tokens[2];
1038 wxString botRightY = tokens[3];
1039 wxString topLeftX = tokens[4];
1040 wxString topRightY = tokens[5];
1044 circle.BotRight =
pointCheck( botRightX, botRightY, lineNumber, fileName );
1047 int lineStyleNumber = 0;
1049 if( tokens.size() == 7 )
1051 wxString lineStyle = tokens[6];
1052 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1061 else if( element ==
"ARC" )
1070 wxString lineWidth = tokens[1];
1071 wxString botRightX = tokens[2];
1072 wxString botRightY = tokens[3];
1073 wxString topLeftX = tokens[4];
1074 wxString topRightY = tokens[5];
1075 wxString arcStartPointX = tokens[6];
1076 wxString arcStartPointY = tokens[7];
1077 wxString arcEndPointX = tokens[8];
1078 wxString arcEndPointY = tokens[9];
1084 arc.
ArcEnd =
pointCheck( arcStartPointX, arcStartPointY, lineNumber, fileName );
1087 int lineStyleNumber = 0;
1089 if( tokens.size() == 11 )
1091 wxString lineStyle = tokens[10];
1092 lineStyleNumber =
integerCheck( lineStyle, lineNumber, fileName );
1097 ascFile.
Arcs.push_back( arc );
1101 else if( element ==
"IOPIN" )
1105 wxString pinLocationX = tokens[1];
1106 wxString pinLocationY = tokens[2];
1107 wxString pinPolarity = tokens[3];
1113 ascFile.
Iopins.push_back( iopin );
1116 else if( element ==
"TEXT" )
1122 wxString positionX = tokens[1];
1123 wxString positionY = tokens[2];
1124 wxString justification = tokens[3];
1125 wxString fontSize = tokens[4];
1126 wxString value = tokens[5];
1129 text.Offset =
pointCheck( positionX, positionY, lineNumber, fileName );
1133 if( value.StartsWith( wxS(
"!" ), &
text.Value ) )
1134 text.Value.Replace( wxS(
"! " ), wxS(
"\n" ) );
1135 else if( value.StartsWith( wxS(
";" ), &
text.Value ) )
1136 text.Value.Replace( wxS(
"; " ), wxS(
"\n" ) );
1140 text.Value.Replace( wxS(
"\\n" ), wxS(
"\n" ) );
1145 else if( element ==
"BUSTAP" )
1149 wxString startPointX = tokens[1];
1150 wxString startPointY = tokens[2];
1151 wxString endPointX = tokens[3];
1152 wxString endPointY = tokens[4];
1155 bustap.
Start =
pointCheck( startPointX, startPointY, lineNumber, fileName );
1156 bustap.
End =
pointCheck( endPointX, endPointY, lineNumber, fileName );
1158 ascFile.
Bustap.push_back( bustap );
1162 else if( element ==
"VERSION" )
1164 wxString versionNumber = tokens[1];
1165 if( versionNumber.Contains(
'.' ) )
1167 wxString majorStr = versionNumber.BeforeFirst(
'.' );
1168 wxString minorStr = versionNumber.AfterFirst(
'.' );
1181 ascFiles.push_back( std::move( ascFile ) );