KiCad PCB EDA Suite
SCH_SEXPR_PARSER Class Reference

Object to parser s-expression symbol library and schematic file formats. More...

#include <sch_sexpr_parser.h>

Inheritance diagram for SCH_SEXPR_PARSER:

Public Member Functions

 SCH_SEXPR_PARSER (LINE_READER *aLineReader=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr, unsigned aLineCount=0, SCH_SHEET *aRootSheet=nullptr, bool aIsAppending=false)
 
void ParseLib (LIB_SYMBOL_MAP &aSymbolLibMap)
 
LIB_SYMBOLParseSymbol (LIB_SYMBOL_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
 
LIB_ITEMParseDrawItem ()
 
void ParseSchematic (SCH_SHEET *aSheet, bool aIsCopyablyOnly=false, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
 Parse the internal LINE_READER object into aSheet. More...
 
int GetParsedRequiredVersion () const
 

Private Member Functions

void checkpoint ()
 
KIID parseKIID ()
 
void parseHeader (TSCHEMATIC_T::T aHeaderType, int aFileVersion)
 
long parseHex ()
 
int parseInt ()
 
int parseInt (const char *aExpected)
 
int parseInternalUnits ()
 
int parseInternalUnits (const char *aExpected)
 
int parseInternalUnits (TSCHEMATIC_T::T aToken)
 
wxPoint parseXY ()
 
bool parseBool ()
 
void parseStroke (STROKE_PARAMS &aStroke)
 Parse stroke definition aStroke. More...
 
void parseFill (FILL_PARAMS &aFill)
 
void parseEDA_TEXT (EDA_TEXT *aText, bool aConvertOverbarSyntax)
 
void parsePinNames (std::unique_ptr< LIB_SYMBOL > &aSymbol)
 
LIB_FIELDparseProperty (std::unique_ptr< LIB_SYMBOL > &aSymbol)
 
LIB_SHAPEparseArc ()
 
LIB_SHAPEparseBezier ()
 
LIB_SHAPEparseCircle ()
 
LIB_PINparsePin ()
 
LIB_SHAPEparsePolyLine ()
 
LIB_SHAPEparseRectangle ()
 
LIB_TEXTparseText ()
 
LIB_TEXTBOXparseTextBox ()
 
void parsePAGE_INFO (PAGE_INFO &aPageInfo)
 
void parseTITLE_BLOCK (TITLE_BLOCK &aTitleBlock)
 
void parseSchSymbolInstances (SCH_SCREEN *aScreen)
 
void parseSchSheetInstances (SCH_SHEET *aRootSheet, SCH_SCREEN *aScreen)
 
SCH_SHEET_PINparseSchSheetPin (SCH_SHEET *aSheet)
 
SCH_FIELDparseSchField (SCH_ITEM *aParent)
 
SCH_SYMBOLparseSchematicSymbol ()
 
SCH_BITMAPparseImage ()
 
SCH_SHEETparseSheet ()
 
SCH_JUNCTIONparseJunction ()
 
SCH_NO_CONNECTparseNoConnect ()
 
SCH_BUS_WIRE_ENTRYparseBusEntry ()
 
SCH_LINEparseLine ()
 
SCH_SHAPEparseSchPolyLine ()
 
SCH_SHAPEparseSchArc ()
 
SCH_SHAPEparseSchCircle ()
 
SCH_SHAPEparseSchRectangle ()
 
SCH_SHAPEparseSchBezier ()
 
SCH_TEXTparseSchText ()
 
SCH_TEXTBOXparseSchTextBox ()
 
void parseBusAlias (SCH_SCREEN *aScreen)
 

Private Attributes

int m_requiredVersion
 Set to the symbol library file version required. More...
 
int m_fieldId
 The current field ID. More...
 
int m_unit
 The current unit being parsed. More...
 
int m_convert
 The current body style being parsed. More...
 
wxString m_symbolName
 The current symbol name. More...
 
bool m_appending
 Appending load status. More...
 
std::set< int > m_fieldIDsRead
 Field IDs that have been read so far for the current symbol. More...
 
std::set< KIIDm_uuids
 
PROGRESS_REPORTERm_progressReporter
 
const LINE_READERm_lineReader
 
unsigned m_lastProgressLine
 
unsigned m_lineCount
 
KIID m_rootUuid
 
SCH_SHEETm_rootSheet
 The rootsheet for full project loads or null for importing a schematic. More...
 

Detailed Description

Object to parser s-expression symbol library and schematic file formats.

Definition at line 77 of file sch_sexpr_parser.h.

Constructor & Destructor Documentation

◆ SCH_SEXPR_PARSER()

SCH_SEXPR_PARSER::SCH_SEXPR_PARSER ( LINE_READER aLineReader = nullptr,
PROGRESS_REPORTER aProgressReporter = nullptr,
unsigned  aLineCount = 0,
SCH_SHEET aRootSheet = nullptr,
bool  aIsAppending = false 
)

Definition at line 67 of file sch_sexpr_parser.cpp.

69 :
70 SCHEMATIC_LEXER( aLineReader ),
72 m_fieldId( 0 ),
73 m_unit( 1 ),
74 m_convert( 1 ),
75 m_appending( aIsAppending ),
76 m_progressReporter( aProgressReporter ),
77 m_lineReader( aLineReader ),
79 m_lineCount( aLineCount ),
80 m_rootSheet( aRootSheet )
81{
82}
int m_convert
The current body style being parsed.
int m_fieldId
The current field ID.
int m_unit
The current unit being parsed.
const LINE_READER * m_lineReader
int m_requiredVersion
Set to the symbol library file version required.
PROGRESS_REPORTER * m_progressReporter
unsigned m_lastProgressLine
SCH_SHEET * m_rootSheet
The rootsheet for full project loads or null for importing a schematic.
bool m_appending
Appending load status.

Member Function Documentation

◆ checkpoint()

void SCH_SEXPR_PARSER::checkpoint ( )
private

Definition at line 85 of file sch_sexpr_parser.cpp.

86{
87 const unsigned PROGRESS_DELTA = 250;
88
90 {
91 unsigned curLine = m_lineReader->LineNumber();
92
93 if( curLine > m_lastProgressLine + PROGRESS_DELTA )
94 {
95 m_progressReporter->SetCurrentProgress( ( (double) curLine )
96 / std::max( 1U, m_lineCount ) );
97
99 THROW_IO_ERROR( ( "Open cancelled by user." ) );
100
101 m_lastProgressLine = curLine;
102 }
103 }
104}
virtual unsigned LineNumber() const
Return the line number of the last line read from this LINE_READER.
Definition: richio.h:135
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References PROGRESS_REPORTER::KeepRefreshing(), LINE_READER::LineNumber(), m_lastProgressLine, m_lineCount, m_lineReader, m_progressReporter, PROGRESS_REPORTER::SetCurrentProgress(), and THROW_IO_ERROR.

Referenced by ParseSchematic().

◆ GetParsedRequiredVersion()

int SCH_SEXPR_PARSER::GetParsedRequiredVersion ( ) const
inline

Definition at line 111 of file sch_sexpr_parser.h.

111{ return m_requiredVersion; }

References m_requiredVersion.

Referenced by SCH_SEXPR_PLUGIN_CACHE::Load().

◆ parseArc()

LIB_SHAPE * SCH_SEXPR_PARSER::parseArc ( )
private

Definition at line 939 of file sch_sexpr_parser.cpp.

940{
941 wxCHECK_MSG( CurTok() == T_arc, nullptr,
942 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as an arc." ) );
943
944 T token;
945 VECTOR2I startPoint( 1, 0 ); // Initialize to a non-degenerate arc just for safety
946 VECTOR2I midPoint( 1, 1 );
947 VECTOR2I endPoint( 0, 1 );
948 bool hasMidPoint = false;
950 FILL_PARAMS fill;
951
952 // Parameters for legacy format
953 VECTOR2I center( 0, 0 );
954 EDA_ANGLE startAngle = ANGLE_0;
955 EDA_ANGLE endAngle = ANGLE_90;
956 bool hasAngles = false;
957
958 std::unique_ptr<LIB_SHAPE> arc = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::ARC );
959
960 arc->SetUnit( m_unit );
961 arc->SetConvert( m_convert );
962
963 token = NextTok();
964
965 if( token == T_private )
966 {
967 arc->SetPrivate( true );
968 token = NextTok();
969 }
970
971 for( ; token != T_RIGHT; token = NextTok() )
972 {
973 if( token != T_LEFT )
974 Expecting( T_LEFT );
975
976 token = NextTok();
977
978 switch( token )
979 {
980 case T_start:
981 startPoint = parseXY();
982 NeedRIGHT();
983 break;
984
985 case T_mid:
986 midPoint = parseXY();
987 NeedRIGHT();
988 hasMidPoint = true;
989 break;
990
991 case T_end:
992 endPoint = parseXY();
993 NeedRIGHT();
994 break;
995
996 case T_radius:
997 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
998 {
999 if( token != T_LEFT )
1000 Expecting( T_LEFT );
1001
1002 token = NextTok();
1003
1004 switch( token )
1005 {
1006 case T_at:
1007 center = parseXY();
1008 NeedRIGHT();
1009 break;
1010
1011 case T_length:
1012 parseInternalUnits( "radius length" );
1013 NeedRIGHT();
1014 break;
1015
1016 case T_angles:
1017 {
1018 startAngle = EDA_ANGLE( parseDouble( "start radius angle" ), DEGREES_T );
1019 endAngle = EDA_ANGLE( parseDouble( "end radius angle" ), DEGREES_T );
1020 startAngle.Normalize();
1021 endAngle.Normalize();
1022 NeedRIGHT();
1023 hasAngles = true;
1024 break;
1025 }
1026
1027 default:
1028 Expecting( "at, length, or angles" );
1029 }
1030 }
1031
1032 break;
1033
1034 case T_stroke:
1035 parseStroke( stroke );
1036 arc->SetStroke( stroke );
1037 break;
1038
1039 case T_fill:
1040 parseFill( fill );
1041 arc->SetFillMode( fill.m_FillType );
1042 arc->SetFillColor( fill.m_Color );
1043 break;
1044
1045 default:
1046 Expecting( "start, mid, end, radius, stroke, or fill" );
1047 }
1048 }
1049
1050 if( hasMidPoint )
1051 {
1052 arc->SetArcGeometry( startPoint, midPoint, endPoint );
1053
1054 #if 1
1055 // Should be not required. Unfortunately it is needed because some bugs created
1056 // incorrect data after conversion of old libraries to the new arc format using
1057 // startPoint, midPoint, endPoint
1058 // Until now, in Eeschema the arc angle should be <= 180 deg.
1059 // If > 180 (bug...) we need to swap arc ends.
1060 // However arc angle == 180 deg can also create issues in some cases (plotters, hittest)
1061 // so also avoid arc == 180 deg
1062 EDA_ANGLE arc_start, arc_end, arc_angle;
1063 arc->CalcArcAngles( arc_start, arc_end );
1064 arc_angle = arc_end - arc_start;
1065
1066 if( arc_angle > ANGLE_180 )
1067 {
1068 // Change arc to its complement (360deg - arc_angle)
1069 arc->SetStart( endPoint );
1070 arc->SetEnd( startPoint );
1071 VECTOR2I new_center = CalcArcCenter( arc->GetStart(), arc->GetEnd(),
1072 ANGLE_360 - arc_angle );
1073 arc->SetCenter( new_center );
1074 }
1075 else if( arc_angle == ANGLE_180 )
1076 {
1077 VECTOR2I new_center = CalcArcCenter( arc->GetStart(), arc->GetEnd(),
1078 EDA_ANGLE( 179.5, DEGREES_T ) );
1079 arc->SetCenter( new_center );
1080 }
1081 #endif
1082 }
1083 else if( hasAngles )
1084 {
1085 arc->SetCenter( center );
1086 /*
1087 * Older versions stored start-end with an implied winding, but the winding was different
1088 * between LibEdit and PCBNew. Since we now use a common class (EDA_SHAPE) for both we
1089 * need to flip one of them. LibEdit drew the short straw.
1090 */
1091 arc->SetStart( endPoint );
1092 arc->SetEnd( startPoint );
1093
1094 // Like previously, 180 degrees arcs that create issues are just modified
1095 // to be < 180 degrees to do not break some other functions ( Draw, Plot, HitTest)
1096 EDA_ANGLE arc_start, arc_end, arc_angle;
1097 arc->CalcArcAngles( arc_start, arc_end );
1098 arc_angle = arc_end - arc_start;
1099
1100 // The arc angle should be <= 180 deg.
1101 // If > 180 we need to swap arc ends (the first choice was not good)
1102 if( arc_angle > ANGLE_180 )
1103 {
1104 arc->SetStart( startPoint );
1105 arc->SetEnd( endPoint );
1106 }
1107 else if( arc_angle == ANGLE_180 )
1108 {
1109 arc->SetStart( startPoint );
1110 arc->SetEnd( endPoint );
1111 VECTOR2I new_center = CalcArcCenter( arc->GetStart(), arc->GetEnd(),
1112 EDA_ANGLE( 179.5, DEGREES_T ) );
1113 arc->SetCenter( new_center );
1114 }
1115 }
1116 else
1117 {
1118 wxFAIL_MSG( "Setting arc without either midpoint or angles not implemented." );
1119 }
1120
1121 return arc.release();
1122}
constexpr EDA_IU_SCALE schIUScale
Definition: base_units.h:111
EDA_ANGLE Normalize()
Definition: eda_angle.h:249
Simple container to manage fill parameters.
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.
void parseFill(FILL_PARAMS &aFill)
Simple container to manage line stroke parameters.
Definition: stroke_params.h:88
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
static constexpr EDA_ANGLE & ANGLE_180
Definition: eda_angle.h:427
@ DEGREES_T
Definition: eda_angle.h:31
static constexpr EDA_ANGLE & ANGLE_360
Definition: eda_angle.h:429
static constexpr EDA_ANGLE & ANGLE_90
Definition: eda_angle.h:425
static constexpr EDA_ANGLE & ANGLE_0
Definition: eda_angle.h:423
double parseDouble(LINE_READER &aReader, const char *aLine, const char **aOutput)
Parses an ASCII point string with possible leading whitespace into a double precision floating point ...
constexpr int MilsToIU(int mils) const
Definition: base_units.h:94
const VECTOR2I CalcArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
Definition: trigo.cpp:472

References ANGLE_0, ANGLE_180, ANGLE_360, ANGLE_90, ARC, CalcArcCenter(), DEFAULT, DEFAULT_LINE_WIDTH_MILS, DEGREES_T, FILL_PARAMS::m_Color, m_convert, FILL_PARAMS::m_FillType, m_unit, EDA_IU_SCALE::MilsToIU(), EDA_ANGLE::Normalize(), parseDouble(), parseFill(), parseInternalUnits(), parseStroke(), parseXY(), and schIUScale.

Referenced by ParseDrawItem().

◆ parseBezier()

LIB_SHAPE * SCH_SEXPR_PARSER::parseBezier ( )
private

Definition at line 1125 of file sch_sexpr_parser.cpp.

1126{
1127 wxCHECK_MSG( CurTok() == T_bezier, nullptr,
1128 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bezier." ) );
1129
1130 T token;
1132 FILL_PARAMS fill;
1133
1134 std::unique_ptr<LIB_SHAPE> bezier = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::BEZIER );
1135
1136 bezier->SetUnit( m_unit );
1137 bezier->SetConvert( m_convert );
1138
1139 token = NextTok();
1140
1141 if( token == T_private )
1142 {
1143 bezier->SetPrivate( true );
1144 token = NextTok();
1145 }
1146
1147 for( ; token != T_RIGHT; token = NextTok() )
1148 {
1149 if( token != T_LEFT )
1150 Expecting( T_LEFT );
1151
1152 token = NextTok();
1153
1154 switch( token )
1155 {
1156 case T_pts:
1157 {
1158 int ii = 0;
1159
1160 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1161 {
1162 if( token != T_LEFT )
1163 Expecting( T_LEFT );
1164
1165 token = NextTok();
1166
1167 if( token != T_xy )
1168 Expecting( "xy" );
1169
1170 switch( ii )
1171 {
1172 case 0: bezier->SetStart( parseXY() ); break;
1173 case 1: bezier->SetBezierC1( parseXY() ); break;
1174 case 2: bezier->SetBezierC2( parseXY() ); break;
1175 case 3: bezier->SetEnd( parseXY() ); break;
1176 default: Unexpected( "control point" ); break;
1177 }
1178
1179 NeedRIGHT();
1180 }
1181 }
1182 break;
1183
1184 case T_stroke:
1185 parseStroke( stroke );
1186 bezier->SetStroke( stroke );
1187 break;
1188
1189 case T_fill:
1190 parseFill( fill );
1191 bezier->SetFillMode( fill.m_FillType );
1192 bezier->SetFillColor( fill.m_Color );
1193 break;
1194
1195 default:
1196 Expecting( "pts, stroke, or fill" );
1197 }
1198 }
1199
1200 bezier->RebuildBezierToSegmentsPointsList( bezier->GetWidth() );
1201
1202 return bezier.release();
1203}

References BEZIER, DEFAULT, DEFAULT_LINE_WIDTH_MILS, FILL_PARAMS::m_Color, m_convert, FILL_PARAMS::m_FillType, m_unit, EDA_IU_SCALE::MilsToIU(), parseFill(), parseStroke(), parseXY(), and schIUScale.

Referenced by ParseDrawItem().

◆ parseBool()

bool SCH_SEXPR_PARSER::parseBool ( )
private

Definition at line 120 of file sch_sexpr_parser.cpp.

121{
122 T token = NextTok();
123
124 if( token == T_yes )
125 return true;
126 else if( token == T_no )
127 return false;
128 else
129 Expecting( "yes or no" );
130
131 return false;
132}

Referenced by parseSchematicSymbol(), and ParseSymbol().

◆ parseBusAlias()

void SCH_SEXPR_PARSER::parseBusAlias ( SCH_SCREEN aScreen)
private

Definition at line 3963 of file sch_sexpr_parser.cpp.

3964{
3965 wxCHECK_RET( CurTok() == T_bus_alias,
3966 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bus alias." ) );
3967 wxCHECK( aScreen, /* void */ );
3968
3969 T token;
3970 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
3971 wxString alias;
3972 wxString member;
3973
3974 NeedSYMBOL();
3975
3976 alias = FromUTF8();
3977
3978 if( m_requiredVersion < 20210621 )
3979 alias = ConvertToNewOverbarNotation( alias );
3980
3981 busAlias->SetName( alias );
3982
3983 NeedLEFT();
3984 token = NextTok();
3985
3986 if( token != T_members )
3987 Expecting( "members" );
3988
3989 token = NextTok();
3990
3991 while( token != T_RIGHT )
3992 {
3993 if( !IsSymbol( token ) )
3994 Expecting( "quoted string" );
3995
3996 member = FromUTF8();
3997
3998 if( m_requiredVersion < 20210621 )
3999 member = ConvertToNewOverbarNotation( member );
4000
4001 busAlias->Members().emplace_back( member );
4002
4003 token = NextTok();
4004 }
4005
4006 NeedRIGHT();
4007
4008 aScreen->AddBusAlias( busAlias );
4009}
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition (and transfers ownership of the pointer).
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.

References SCH_SCREEN::AddBusAlias(), ConvertToNewOverbarNotation(), and m_requiredVersion.

Referenced by ParseSchematic().

◆ parseBusEntry()

SCH_BUS_WIRE_ENTRY * SCH_SEXPR_PARSER::parseBusEntry ( )
private

Definition at line 3267 of file sch_sexpr_parser.cpp.

3268{
3269 wxCHECK_MSG( CurTok() == T_bus_entry, nullptr,
3270 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bus entry." ) );
3271
3272 T token;
3274 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
3275
3276 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3277 {
3278 if( token != T_LEFT )
3279 Expecting( T_LEFT );
3280
3281 token = NextTok();
3282
3283 switch( token )
3284 {
3285 case T_at:
3286 busEntry->SetPosition( parseXY() );
3287 NeedRIGHT();
3288 break;
3289
3290 case T_size:
3291 {
3292 wxSize size;
3293
3294 size.SetWidth( parseInternalUnits( "bus entry height" ) );
3295 size.SetHeight( parseInternalUnits( "bus entry width" ) );
3296 busEntry->SetSize( size );
3297 NeedRIGHT();
3298 break;
3299 }
3300
3301 case T_stroke:
3302 parseStroke( stroke );
3303 busEntry->SetStroke( stroke );
3304 break;
3305
3306 case T_uuid:
3307 NeedSYMBOL();
3308 const_cast<KIID&>( busEntry->m_Uuid ) = parseKIID();
3309 NeedRIGHT();
3310 break;
3311
3312 default:
3313 Expecting( "at, size, uuid or stroke" );
3314 }
3315 }
3316
3317 return busEntry.release();
3318}
Definition: kiid.h:48

References DEFAULT, DEFAULT_LINE_WIDTH_MILS, EDA_IU_SCALE::MilsToIU(), parseInternalUnits(), parseKIID(), parseStroke(), parseXY(), and schIUScale.

Referenced by ParseSchematic().

◆ parseCircle()

LIB_SHAPE * SCH_SEXPR_PARSER::parseCircle ( )
private

Definition at line 1206 of file sch_sexpr_parser.cpp.

1207{
1208 wxCHECK_MSG( CurTok() == T_circle, nullptr,
1209 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a circle." ) );
1210
1211 T token;
1212 VECTOR2I center( 0, 0 );
1213 int radius = 1; // defaulting to 0 could result in troublesome math....
1215 FILL_PARAMS fill;
1216
1217 std::unique_ptr<LIB_SHAPE> circle = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::CIRCLE );
1218
1219 circle->SetUnit( m_unit );
1220 circle->SetConvert( m_convert );
1221
1222 token = NextTok();
1223
1224 if( token == T_private )
1225 {
1226 circle->SetPrivate( true );
1227 token = NextTok();
1228 }
1229
1230 for( ; token != T_RIGHT; token = NextTok() )
1231 {
1232 if( token != T_LEFT )
1233 Expecting( T_LEFT );
1234
1235 token = NextTok();
1236
1237 switch( token )
1238 {
1239 case T_center:
1240 center = parseXY();
1241 NeedRIGHT();
1242 break;
1243
1244 case T_radius:
1245 radius = parseInternalUnits( "radius length" );
1246 NeedRIGHT();
1247 break;
1248
1249 case T_stroke:
1250 parseStroke( stroke );
1251 circle->SetStroke( stroke );
1252 break;
1253
1254 case T_fill:
1255 parseFill( fill );
1256 circle->SetFillMode( fill.m_FillType );
1257 circle->SetFillColor( fill.m_Color );
1258 break;
1259
1260 default:
1261 Expecting( "center, radius, stroke, or fill" );
1262 }
1263 }
1264
1265 circle->SetCenter( center );
1266 circle->SetEnd( VECTOR2I( center.x + radius, center.y ) );
1267
1268 return circle.release();
1269}
VECTOR2< int > VECTOR2I
Definition: vector2d.h:618

References CIRCLE, DEFAULT, DEFAULT_LINE_WIDTH_MILS, FILL_PARAMS::m_Color, m_convert, FILL_PARAMS::m_FillType, m_unit, EDA_IU_SCALE::MilsToIU(), parseFill(), parseInternalUnits(), parseStroke(), parseXY(), schIUScale, VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by ParseDrawItem().

◆ ParseDrawItem()

LIB_ITEM * SCH_SEXPR_PARSER::ParseDrawItem ( )

Definition at line 408 of file sch_sexpr_parser.cpp.

409{
410 switch( CurTok() )
411 {
412 case T_arc:
413 return parseArc();
414 break;
415
416 case T_bezier:
417 return parseBezier();
418 break;
419
420 case T_circle:
421 return parseCircle();
422 break;
423
424 case T_pin:
425 return parsePin();
426 break;
427
428 case T_polyline:
429 return parsePolyLine();
430 break;
431
432 case T_rectangle:
433 return parseRectangle();
434 break;
435
436 case T_text:
437 return parseText();
438 break;
439
440 case T_text_box:
441 return parseTextBox();
442 break;
443
444 default:
445 Expecting( "arc, bezier, circle, pin, polyline, rectangle, or text" );
446 }
447
448 return nullptr;
449}
LIB_SHAPE * parseBezier()
LIB_SHAPE * parseCircle()
LIB_SHAPE * parseRectangle()
LIB_SHAPE * parseArc()
LIB_SHAPE * parsePolyLine()
LIB_TEXTBOX * parseTextBox()

References parseArc(), parseBezier(), parseCircle(), parsePin(), parsePolyLine(), parseRectangle(), parseText(), and parseTextBox().

Referenced by ParseSymbol().

◆ parseEDA_TEXT()

void SCH_SEXPR_PARSER::parseEDA_TEXT ( EDA_TEXT aText,
bool  aConvertOverbarSyntax 
)
private

Definition at line 540 of file sch_sexpr_parser.cpp.

541{
542 wxCHECK_RET( aText && ( CurTok() == T_effects || CurTok() == T_href ),
543 "Cannot parse " + GetTokenString( CurTok() ) + " as an EDA_TEXT." );
544
545 // In version 20210606 the notation for overbars was changed from `~...~` to `~{...}`.
546 // We need to convert the old syntax to the new one.
547 if( aConvertOverbarSyntax && m_requiredVersion < 20210606 )
548 aText->SetText( ConvertToNewOverbarNotation( aText->GetText() ) );
549
550 T token;
551 wxString faceName;
552 COLOR4D color = COLOR4D::UNSPECIFIED;
553
554 // Various text objects (text boxes, schematic text, etc.) all have their own defaults,
555 // but the file format default is {center,center} so we have to set that before parsing.
558
559 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
560 {
561 if( token == T_LEFT )
562 token = NextTok();
563
564 switch( token )
565 {
566 case T_font:
567 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
568 {
569 if( token == T_LEFT )
570 token = NextTok();
571
572 switch( token )
573 {
574 case T_face:
575 NeedSYMBOL();
576 faceName = FromUTF8();
577 NeedRIGHT();
578 break;
579
580 case T_size:
581 {
582 wxSize sz;
583 sz.SetHeight( parseInternalUnits( "text height" ) );
584 sz.SetWidth( parseInternalUnits( "text width" ) );
585 aText->SetTextSize( sz );
586 NeedRIGHT();
587 break;
588 }
589
590 case T_thickness:
591 aText->SetTextThickness( parseInternalUnits( "text thickness" ) );
592 NeedRIGHT();
593 break;
594
595 case T_bold:
596 aText->SetBold( true );
597 break;
598
599 case T_italic:
600 aText->SetItalic( true );
601 break;
602
603 case T_color:
604 color.r = parseInt( "red" ) / 255.0;
605 color.g = parseInt( "green" ) / 255.0;
606 color.b = parseInt( "blue" ) / 255.0;
607 color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
608 aText->SetTextColor( color );
609 NeedRIGHT();
610 break;
611
612 case T_line_spacing:
613 aText->SetLineSpacing( parseDouble( "line spacing" ) );
614 NeedRIGHT();
615 break;
616
617 default:
618 Expecting( "face, size, thickness, line_spacing, bold, or italic" );
619 }
620 }
621
622 if( !faceName.IsEmpty() )
623 {
624 aText->SetFont( KIFONT::FONT::GetFont( faceName, aText->IsBold(),
625 aText->IsItalic() ) );
626 }
627
628 break;
629
630 case T_justify:
631 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
632 {
633 switch( token )
634 {
635 case T_left: aText->SetHorizJustify( GR_TEXT_H_ALIGN_LEFT ); break;
636 case T_right: aText->SetHorizJustify( GR_TEXT_H_ALIGN_RIGHT ); break;
637 case T_top: aText->SetVertJustify( GR_TEXT_V_ALIGN_TOP ); break;
638 case T_bottom: aText->SetVertJustify( GR_TEXT_V_ALIGN_BOTTOM ); break;
639 // Do not set mirror property for schematic text elements
640 case T_mirror: break;
641 default: Expecting( "left, right, top, bottom, or mirror" );
642 }
643 }
644
645 break;
646
647 case T_href:
648 {
649 NeedSYMBOL();
650 wxString hyperlink = FromUTF8();
651
652 if( !aText->ValidateHyperlink( hyperlink ) )
653 {
654 THROW_PARSE_ERROR( wxString::Format( _( "Invalid hyperlink url '%s'" ), hyperlink ),
655 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
656 }
657 else
658 {
659 aText->SetHyperlink( hyperlink );
660 }
661
662 NeedRIGHT();
663 }
664 break;
665
666 case T_hide:
667 aText->SetVisible( false );
668 break;
669
670 default:
671 Expecting( "font, justify, hide or href" );
672 }
673 }
674}
int color
Definition: DXF_plotter.cpp:57
void SetTextColor(const COLOR4D &aColor)
Definition: eda_text.h:204
bool IsItalic() const
Definition: eda_text.h:130
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:87
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
Definition: eda_text.cpp:248
virtual void SetVisible(bool aVisible)
Definition: eda_text.cpp:217
void SetLineSpacing(double aLineSpacing)
Definition: eda_text.cpp:339
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.cpp:185
void SetBold(bool aBold)
Definition: eda_text.cpp:209
static bool ValidateHyperlink(const wxString &aURL)
Check if aURL is a valid hyperlink.
Definition: eda_text.cpp:980
bool IsBold() const
Definition: eda_text.h:133
void SetHyperlink(wxString aLink)
Definition: eda_text.h:335
void SetTextSize(const VECTOR2I &aNewSize)
Definition: eda_text.cpp:347
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:163
void SetItalic(bool aItalic)
Definition: eda_text.cpp:201
void SetFont(KIFONT::FONT *aFont)
Definition: eda_text.cpp:331
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
Definition: eda_text.cpp:240
static FONT * GetFont(const wxString &aFontName=wxEmptyString, bool aBold=false, bool aItalic=false)
Definition: font.cpp:65
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:104
#define _(s)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
void Format(OUTPUTFORMATTER *out, int aNestLevel, int aCtl, const CPTREE &aTree)
Output a PTREE into s-expression format via an OUTPUTFORMATTER derivative.
Definition: ptree.cpp:200
@ GR_TEXT_H_ALIGN_CENTER
@ GR_TEXT_H_ALIGN_RIGHT
@ GR_TEXT_H_ALIGN_LEFT
@ GR_TEXT_V_ALIGN_BOTTOM
@ GR_TEXT_V_ALIGN_CENTER
@ GR_TEXT_V_ALIGN_TOP
constexpr T Clamp(const T &lower, const T &value, const T &upper)
Limit value within the range lower <= value <= upper.
Definition: util.h:64

References _, Clamp(), color, ConvertToNewOverbarNotation(), Format(), KIFONT::FONT::GetFont(), EDA_TEXT::GetText(), GR_TEXT_H_ALIGN_CENTER, GR_TEXT_H_ALIGN_LEFT, GR_TEXT_H_ALIGN_RIGHT, GR_TEXT_V_ALIGN_BOTTOM, GR_TEXT_V_ALIGN_CENTER, GR_TEXT_V_ALIGN_TOP, EDA_TEXT::IsBold(), EDA_TEXT::IsItalic(), m_requiredVersion, parseDouble(), parseInt(), parseInternalUnits(), EDA_TEXT::SetBold(), EDA_TEXT::SetFont(), EDA_TEXT::SetHorizJustify(), EDA_TEXT::SetHyperlink(), EDA_TEXT::SetItalic(), EDA_TEXT::SetLineSpacing(), EDA_TEXT::SetText(), EDA_TEXT::SetTextColor(), EDA_TEXT::SetTextSize(), EDA_TEXT::SetTextThickness(), EDA_TEXT::SetVertJustify(), EDA_TEXT::SetVisible(), THROW_PARSE_ERROR, and EDA_TEXT::ValidateHyperlink().

Referenced by parsePin(), parseProperty(), parseSchField(), parseSchSheetPin(), parseSchText(), parseSchTextBox(), parseText(), and parseTextBox().

◆ parseFill()

void SCH_SEXPR_PARSER::parseFill ( FILL_PARAMS aFill)
private

Definition at line 485 of file sch_sexpr_parser.cpp.

486{
487 wxCHECK_RET( CurTok() == T_fill, "Cannot parse " + GetTokenString( CurTok() ) + " as a fill." );
488
490 aFill.m_Color = COLOR4D::UNSPECIFIED;
491
492 T token;
493
494 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
495 {
496 if( token != T_LEFT )
497 Expecting( T_LEFT );
498
499 token = NextTok();
500
501 switch( token )
502 {
503 case T_type:
504 {
505 token = NextTok();
506
507 switch( token )
508 {
509 case T_none: aFill.m_FillType = FILL_T::NO_FILL; break;
510 case T_outline: aFill.m_FillType = FILL_T::FILLED_SHAPE; break;
511 case T_background: aFill.m_FillType = FILL_T::FILLED_WITH_BG_BODYCOLOR; break;
512 case T_color: aFill.m_FillType = FILL_T::FILLED_WITH_COLOR; break;
513 default: Expecting( "none, outline, color or background" );
514 }
515
516 NeedRIGHT();
517 break;
518 }
519
520 case T_color:
521 {
523
524 color.r = parseInt( "red" ) / 255.0;
525 color.g = parseInt( "green" ) / 255.0;
526 color.b = parseInt( "blue" ) / 255.0;
527 color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
528 aFill.m_Color = color;
529 NeedRIGHT();
530 break;
531 }
532
533 default:
534 Expecting( "type or color" );
535 }
536 }
537}
@ FILLED_WITH_COLOR
@ FILLED_WITH_BG_BODYCOLOR
@ FILLED_SHAPE

References Clamp(), color, FILLED_SHAPE, FILLED_WITH_BG_BODYCOLOR, FILLED_WITH_COLOR, FILL_PARAMS::m_Color, FILL_PARAMS::m_FillType, NO_FILL, parseDouble(), and parseInt().

Referenced by parseArc(), parseBezier(), parseCircle(), parsePolyLine(), parseRectangle(), parseSchArc(), parseSchBezier(), parseSchCircle(), parseSchPolyLine(), parseSchRectangle(), parseSchTextBox(), parseSheet(), and parseTextBox().

◆ parseHeader()

void SCH_SEXPR_PARSER::parseHeader ( TSCHEMATIC_T::T  aHeaderType,
int  aFileVersion 
)
private

Definition at line 677 of file sch_sexpr_parser.cpp.

678{
679 wxCHECK_RET( CurTok() == aHeaderType,
680 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a header." ) );
681
682 NeedLEFT();
683
684 T tok = NextTok();
685
686 if( tok == T_version )
687 {
688 m_requiredVersion = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
689
690 if( m_requiredVersion > aFileVersion )
691 throw FUTURE_FORMAT_ERROR( FromUTF8() );
692
693 NeedRIGHT();
694
695 // Skip the host name and host build version information.
696 NeedLEFT();
697 NeedSYMBOL();
698 NeedSYMBOL();
699
700 if( m_requiredVersion < 20200827 )
701 NeedSYMBOL();
702
703 NeedRIGHT();
704 }
705 else
706 {
707 m_requiredVersion = aFileVersion;
708
709 // Skip the host name and host build version information.
710 NeedSYMBOL();
711 NeedSYMBOL();
712 NeedRIGHT();
713 }
714}
Variant of PARSE_ERROR indicating that a syntax or related error was likely caused by a file generate...
Definition: ki_exception.h:175

References m_requiredVersion, and parseInt().

Referenced by ParseLib(), and ParseSchematic().

◆ parseHex()

long SCH_SEXPR_PARSER::parseHex ( )
inlineprivate

Definition at line 120 of file sch_sexpr_parser.h.

121 {
122 NextTok();
123 return strtol( CurText(), nullptr, 16 );
124 }

◆ parseImage()

SCH_BITMAP * SCH_SEXPR_PARSER::parseImage ( )
private

Definition at line 2909 of file sch_sexpr_parser.cpp.

2910{
2911 wxCHECK_MSG( CurTok() == T_image, nullptr,
2912 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as an image." ) );
2913
2914 T token;
2915 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
2916
2917 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2918 {
2919 if( token != T_LEFT )
2920 Expecting( T_LEFT );
2921
2922 token = NextTok();
2923
2924 switch( token )
2925 {
2926 case T_at:
2927 bitmap->SetPosition( parseXY() );
2928 NeedRIGHT();
2929 break;
2930
2931 case T_scale:
2932 bitmap->GetImage()->SetScale( parseDouble( "image scale factor" ) );
2933
2934 if( !std::isnormal( bitmap->GetImage()->GetScale() ) )
2935 bitmap->GetImage()->SetScale( 1.0 );
2936
2937 NeedRIGHT();
2938 break;
2939
2940 case T_uuid:
2941 NeedSYMBOL();
2942 const_cast<KIID&>( bitmap->m_Uuid ) = parseKIID();
2943 NeedRIGHT();
2944 break;
2945
2946 case T_data:
2947 {
2948 token = NextTok();
2949
2950 wxString data;
2951
2952 // Reserve 128K because most image files are going to be larger than the default
2953 // 1K that wxString reserves.
2954 data.reserve( 1 << 17 );
2955
2956 while( token != T_RIGHT )
2957 {
2958 if( !IsSymbol( token ) )
2959 Expecting( "base64 image data" );
2960
2961 data += FromUTF8();
2962 token = NextTok();
2963 }
2964
2965 wxMemoryBuffer buffer = wxBase64Decode( data );
2966 wxMemoryOutputStream stream( buffer.GetData(), buffer.GetBufSize() );
2967 wxImage* image = new wxImage();
2968 wxMemoryInputStream istream( stream );
2969 image->LoadFile( istream, wxBITMAP_TYPE_PNG );
2970 bitmap->GetImage()->SetImage( image );
2971 break;
2972 }
2973
2974 default:
2975 Expecting( "at, scale, uuid or data" );
2976 }
2977 }
2978
2979 return bitmap.release();
2980}

References image, parseDouble(), parseKIID(), and parseXY().

Referenced by ParseSchematic().

◆ parseInt() [1/2]

int SCH_SEXPR_PARSER::parseInt ( )
inlineprivate

Definition at line 126 of file sch_sexpr_parser.h.

127 {
128 return (int)strtol( CurText(), nullptr, 10 );
129 }

Referenced by parseEDA_TEXT(), parseFill(), parseHeader(), parseInt(), parseJunction(), parsePin(), parseProperty(), parseSchematicSymbol(), parseSchField(), parseSchSymbolInstances(), and parseTITLE_BLOCK().

◆ parseInt() [2/2]

int SCH_SEXPR_PARSER::parseInt ( const char *  aExpected)
inlineprivate

Definition at line 131 of file sch_sexpr_parser.h.

132 {
133 NeedNUMBER( aExpected );
134 return parseInt();
135 }

References parseInt().

◆ parseInternalUnits() [1/3]

int SCH_SEXPR_PARSER::parseInternalUnits ( )
private

Definition at line 452 of file sch_sexpr_parser.cpp.

453{
454 auto retval = parseDouble() * schIUScale.IU_PER_MM;
455
456 // Schematic internal units are represented as integers. Any values that are
457 // larger or smaller than the schematic units represent undefined behavior for
458 // the system. Limit values to the largest that can be displayed on the screen.
459 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071; // 0.7071 = roughly 1/sqrt(2)
460
461 return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
462}
const double IU_PER_MM
Definition: base_units.h:77
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:85

References EDA_IU_SCALE::IU_PER_MM, KiROUND(), parseDouble(), and schIUScale.

Referenced by parseArc(), parseBusEntry(), parseCircle(), parseEDA_TEXT(), parseInternalUnits(), parseJunction(), parsePin(), parsePinNames(), parseSchCircle(), parseSchText(), parseSheet(), and parseXY().

◆ parseInternalUnits() [2/3]

int SCH_SEXPR_PARSER::parseInternalUnits ( const char *  aExpected)
private

Definition at line 465 of file sch_sexpr_parser.cpp.

466{
467 auto retval = parseDouble( aExpected ) * schIUScale.IU_PER_MM;
468
469 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
470
471 return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
472}

References EDA_IU_SCALE::IU_PER_MM, KiROUND(), parseDouble(), and schIUScale.

◆ parseInternalUnits() [3/3]

int SCH_SEXPR_PARSER::parseInternalUnits ( TSCHEMATIC_T::T  aToken)
inlineprivate

Definition at line 141 of file sch_sexpr_parser.h.

142 {
143 return parseInternalUnits( GetTokenText( aToken ) );
144 }
const char * GetTokenText(T aTok)
The DSN namespace and returns the C string representing a SPECCTRA_DB::keyword.
Definition: specctra.cpp:70

References DSN::GetTokenText(), and parseInternalUnits().

◆ parseJunction()

SCH_JUNCTION * SCH_SEXPR_PARSER::parseJunction ( )
private

Definition at line 3174 of file sch_sexpr_parser.cpp.

3175{
3176 wxCHECK_MSG( CurTok() == T_junction, nullptr,
3177 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a junction." ) );
3178
3179 T token;
3180 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3181
3182 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3183 {
3184 if( token != T_LEFT )
3185 Expecting( T_LEFT );
3186
3187 token = NextTok();
3188
3189 switch( token )
3190 {
3191 case T_at:
3192 junction->SetPosition( parseXY() );
3193 NeedRIGHT();
3194 break;
3195
3196 case T_diameter:
3197 junction->SetDiameter( parseInternalUnits( "junction diameter" ) );
3198 NeedRIGHT();
3199 break;
3200
3201 case T_color:
3202 {
3203 COLOR4D color;
3204
3205 color.r = parseInt( "red" ) / 255.0;
3206 color.g = parseInt( "green" ) / 255.0;
3207 color.b = parseInt( "blue" ) / 255.0;
3208 color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
3209
3210 junction->SetColor( color );
3211 NeedRIGHT();
3212 break;
3213 }
3214
3215 case T_uuid:
3216 NeedSYMBOL();
3217 const_cast<KIID&>( junction->m_Uuid ) = parseKIID();
3218 NeedRIGHT();
3219 break;
3220
3221 default:
3222 Expecting( "at, diameter, color or uuid" );
3223 }
3224 }
3225
3226 return junction.release();
3227}

References Clamp(), color, parseDouble(), parseInt(), parseInternalUnits(), parseKIID(), and parseXY().

Referenced by ParseSchematic().

◆ parseKIID()

KIID SCH_SEXPR_PARSER::parseKIID ( )
private

Definition at line 107 of file sch_sexpr_parser.cpp.

108{
109 KIID id( FromUTF8() );
110
111 while( m_uuids.count( id ) )
112 id.Increment();
113
114 m_uuids.insert( id );
115
116 return id;
117}
std::set< KIID > m_uuids

References m_uuids.

Referenced by parseBusEntry(), parseImage(), parseJunction(), parseLine(), parseNoConnect(), ParseSchematic(), parseSchematicSymbol(), parseSchPolyLine(), parseSchSheetPin(), parseSchText(), and parseSheet().

◆ ParseLib()

void SCH_SEXPR_PARSER::ParseLib ( LIB_SYMBOL_MAP aSymbolLibMap)

Definition at line 135 of file sch_sexpr_parser.cpp.

136{
137 T token;
138
139 NeedLEFT();
140 NextTok();
141 parseHeader( T_kicad_symbol_lib, SEXPR_SYMBOL_LIB_FILE_VERSION );
142
143 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
144 {
145 if( token != T_LEFT )
146 Expecting( T_LEFT );
147
148 token = NextTok();
149
150 if( token == T_symbol )
151 {
152 m_unit = 1;
153 m_convert = 1;
154 LIB_SYMBOL* symbol = ParseSymbol( aSymbolLibMap, m_requiredVersion );
155 aSymbolLibMap[symbol->GetName()] = symbol;
156 }
157 else
158 {
159 Expecting( "symbol" );
160 }
161 }
162}
Define a library symbol object.
Definition: lib_symbol.h:99
wxString GetName() const override
Definition: lib_symbol.h:138
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
LIB_SYMBOL * ParseSymbol(LIB_SYMBOL_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
#define SEXPR_SYMBOL_LIB_FILE_VERSION
This file contains the file format version information for the s-expression schematic and symbol libr...

References LIB_SYMBOL::GetName(), m_convert, m_requiredVersion, m_unit, parseHeader(), ParseSymbol(), and SEXPR_SYMBOL_LIB_FILE_VERSION.

Referenced by SCH_SEXPR_PLUGIN_CACHE::Load().

◆ parseLine()

SCH_LINE * SCH_SEXPR_PARSER::parseLine ( )
private

Definition at line 3382 of file sch_sexpr_parser.cpp.

3383{
3384 // Note: T_polyline is deprecated in this code: it is now handled by
3385 // parseSchPolyLine() that can handle true polygons, and not only one segment.
3386
3387 T token;
3389 int layer;
3390
3391 switch( CurTok() )
3392 {
3393 case T_polyline: layer = LAYER_NOTES; break;
3394 case T_wire: layer = LAYER_WIRE; break;
3395 case T_bus: layer = LAYER_BUS; break;
3396 default:
3397 wxCHECK_MSG( false, nullptr, "Cannot parse " + GetTokenString( CurTok() ) + " as a line." );
3398 }
3399
3400 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>( VECTOR2I(), layer );
3401
3402 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3403 {
3404 if( token != T_LEFT )
3405 Expecting( T_LEFT );
3406
3407 token = NextTok();
3408
3409 switch( token )
3410 {
3411 case T_pts:
3412 NeedLEFT();
3413 token = NextTok();
3414
3415 if( token != T_xy )
3416 Expecting( "xy" );
3417
3418 line->SetStartPoint( parseXY() );
3419 NeedRIGHT();
3420 NeedLEFT();
3421 token = NextTok();
3422
3423 if( token != T_xy )
3424 Expecting( "xy" );
3425
3426 line->SetEndPoint( parseXY() );
3427 NeedRIGHT();
3428 NeedRIGHT();
3429 break;
3430
3431 case T_stroke:
3432 parseStroke( stroke );
3433 line->SetStroke( stroke );
3434 break;
3435
3436 case T_uuid:
3437 NeedSYMBOL();
3438 const_cast<KIID&>( line->m_Uuid ) = parseKIID();
3439 NeedRIGHT();
3440 break;
3441
3442 default:
3443 Expecting( "at, uuid or stroke" );
3444 }
3445 }
3446
3447 return line.release();
3448}
@ LAYER_WIRE
Definition: layer_ids.h:344
@ LAYER_NOTES
Definition: layer_ids.h:358
@ LAYER_BUS
Definition: layer_ids.h:345

References DEFAULT, DEFAULT_LINE_WIDTH_MILS, LAYER_BUS, LAYER_NOTES, LAYER_WIRE, EDA_IU_SCALE::MilsToIU(), parseKIID(), parseStroke(), parseXY(), and schIUScale.

Referenced by ParseSchematic().

◆ parseNoConnect()

SCH_NO_CONNECT * SCH_SEXPR_PARSER::parseNoConnect ( )
private

Definition at line 3230 of file sch_sexpr_parser.cpp.

3231{
3232 wxCHECK_MSG( CurTok() == T_no_connect, nullptr,
3233 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a no connect." ) );
3234
3235 T token;
3236 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
3237
3238 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3239 {
3240 if( token != T_LEFT )
3241 Expecting( T_LEFT );
3242
3243 token = NextTok();
3244
3245 switch( token )
3246 {
3247 case T_at:
3248 no_connect->SetPosition( parseXY() );
3249 NeedRIGHT();
3250 break;
3251
3252 case T_uuid:
3253 NeedSYMBOL();
3254 const_cast<KIID&>( no_connect->m_Uuid ) = parseKIID();
3255 NeedRIGHT();
3256 break;
3257
3258 default:
3259 Expecting( "at or uuid" );
3260 }
3261 }
3262
3263 return no_connect.release();
3264}

References parseKIID(), and parseXY().

Referenced by ParseSchematic().

◆ parsePAGE_INFO()

void SCH_SEXPR_PARSER::parsePAGE_INFO ( PAGE_INFO aPageInfo)
private

Definition at line 1761 of file sch_sexpr_parser.cpp.

1762{
1763 wxCHECK_RET( ( CurTok() == T_page && m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
1764 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a PAGE_INFO." ) );
1765
1766 T token;
1767
1768 NeedSYMBOL();
1769
1770 wxString pageType = FromUTF8();
1771
1772 if( !aPageInfo.SetType( pageType ) )
1773 {
1774 THROW_PARSE_ERROR( _( "Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
1775 CurOffset() );
1776 }
1777
1778 if( pageType == PAGE_INFO::Custom )
1779 {
1780 int width = EDA_UNIT_UTILS::Mm2mils( parseDouble( "width" ) ); // width stored in mm so we convert to mils
1781
1782 // Perform some controls to avoid crashes if the size is edited by hands
1783 if( width < MIN_PAGE_SIZE_MILS )
1784 width = MIN_PAGE_SIZE_MILS;
1785 else if( width > MAX_PAGE_SIZE_EESCHEMA_MILS )
1787
1788 int height = EDA_UNIT_UTILS::Mm2mils( parseDouble( "height" ) ); // height stored in mm so we convert to mils
1789
1790 if( height < MIN_PAGE_SIZE_MILS )
1791 height = MIN_PAGE_SIZE_MILS;
1792 else if( height > MAX_PAGE_SIZE_EESCHEMA_MILS )
1794
1795 aPageInfo.SetWidthMils( width );
1796 aPageInfo.SetHeightMils( height );
1797 }
1798
1799 token = NextTok();
1800
1801 if( token == T_portrait )
1802 {
1803 aPageInfo.SetPortrait( true );
1804 NeedRIGHT();
1805 }
1806 else if( token != T_RIGHT )
1807 {
1808 Expecting( "portrait" );
1809 }
1810}
void SetWidthMils(int aWidthInMils)
Definition: page_info.cpp:244
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
Definition: page_info.cpp:187
static const wxChar Custom[]
"User" defined page type
Definition: page_info.h:77
void SetHeightMils(int aHeightInMils)
Definition: page_info.cpp:258
bool SetType(const wxString &aStandardPageDescriptionName, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
Definition: page_info.cpp:120
int Mm2mils(double aVal)
Convert mm to mils.
Definition: eda_units.cpp:56
#define MIN_PAGE_SIZE_MILS
Min and max page sizes for clamping, in mils.
Definition: page_info.h:39
#define MAX_PAGE_SIZE_EESCHEMA_MILS
Definition: page_info.h:41

References _, PAGE_INFO::Custom, m_requiredVersion, MAX_PAGE_SIZE_EESCHEMA_MILS, MIN_PAGE_SIZE_MILS, EDA_UNIT_UTILS::Mm2mils(), parseDouble(), PAGE_INFO::SetHeightMils(), PAGE_INFO::SetPortrait(), PAGE_INFO::SetType(), PAGE_INFO::SetWidthMils(), and THROW_PARSE_ERROR.

Referenced by ParseSchematic().

◆ parsePin()

LIB_PIN * SCH_SEXPR_PARSER::parsePin ( )
private

Definition at line 1272 of file sch_sexpr_parser.cpp.

1273{
1274 auto parseType = [&]( T token ) -> ELECTRICAL_PINTYPE
1275 {
1276 switch( token )
1277 {
1278 case T_input: return ELECTRICAL_PINTYPE::PT_INPUT;
1279 case T_output: return ELECTRICAL_PINTYPE::PT_OUTPUT;
1280 case T_bidirectional: return ELECTRICAL_PINTYPE::PT_BIDI;
1281 case T_tri_state: return ELECTRICAL_PINTYPE::PT_TRISTATE;
1282 case T_passive: return ELECTRICAL_PINTYPE::PT_PASSIVE;
1283 case T_unspecified: return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1284 case T_power_in: return ELECTRICAL_PINTYPE::PT_POWER_IN;
1285 case T_power_out: return ELECTRICAL_PINTYPE::PT_POWER_OUT;
1286 case T_open_collector: return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
1287 case T_open_emitter: return ELECTRICAL_PINTYPE::PT_OPENEMITTER;
1288 case T_unconnected:
1289 case T_no_connect: return ELECTRICAL_PINTYPE::PT_NC;
1290 case T_free: return ELECTRICAL_PINTYPE::PT_NIC;
1291
1292 default:
1293 Expecting( "input, output, bidirectional, tri_state, passive, "
1294 "unspecified, power_in, power_out, open_collector, "
1295 "open_emitter, free or no_connect" );
1297 }
1298 };
1299
1300 auto parseShape = [&]( T token ) -> GRAPHIC_PINSHAPE
1301 {
1302 switch( token )
1303 {
1304 case T_line: return GRAPHIC_PINSHAPE::LINE;
1305 case T_inverted: return GRAPHIC_PINSHAPE::INVERTED;
1306 case T_clock: return GRAPHIC_PINSHAPE::CLOCK;
1307 case T_inverted_clock: return GRAPHIC_PINSHAPE::INVERTED_CLOCK;
1308 case T_input_low: return GRAPHIC_PINSHAPE::INPUT_LOW;
1309 case T_clock_low: return GRAPHIC_PINSHAPE::CLOCK_LOW;
1310 case T_output_low: return GRAPHIC_PINSHAPE::OUTPUT_LOW;
1311 case T_edge_clock_high: return GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK;
1312 case T_non_logic: return GRAPHIC_PINSHAPE::NONLOGIC;
1313
1314 default:
1315 Expecting( "line, inverted, clock, inverted_clock, input_low, "
1316 "clock_low, output_low, edge_clock_high, non_logic" );
1318 }
1319 };
1320
1321 wxCHECK_MSG( CurTok() == T_pin, nullptr,
1322 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a pin token." ) );
1323
1324 T token;
1325 wxString tmp;
1326 wxString error;
1327 std::unique_ptr<LIB_PIN> pin = std::make_unique<LIB_PIN>( nullptr );
1328
1329 pin->SetUnit( m_unit );
1330 pin->SetConvert( m_convert );
1331
1332 // Pin electrical type.
1333 token = NextTok();
1334 pin->SetType( parseType( token ) );
1335
1336 // Pin shape.
1337 token = NextTok();
1338 pin->SetShape( parseShape( token ) );
1339
1340 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1341 {
1342 if( token == T_hide )
1343 {
1344 pin->SetVisible( false );
1345 continue;
1346 }
1347
1348 if( token != T_LEFT )
1349 Expecting( T_LEFT );
1350
1351 token = NextTok();
1352
1353 switch( token )
1354 {
1355 case T_at:
1356 pin->SetPosition( parseXY() );
1357
1358 switch( parseInt( "pin orientation" ) )
1359 {
1360 case 0: pin->SetOrientation( PIN_RIGHT ); break;
1361 case 90: pin->SetOrientation( PIN_UP ); break;
1362 case 180: pin->SetOrientation( PIN_LEFT ); break;
1363 case 270: pin->SetOrientation( PIN_DOWN ); break;
1364 default: Expecting( "0, 90, 180, or 270" );
1365 }
1366
1367 NeedRIGHT();
1368 break;
1369
1370 case T_length:
1371 pin->SetLength( parseInternalUnits( "pin length" ) );
1372 NeedRIGHT();
1373 break;
1374
1375 case T_name:
1376 token = NextTok();
1377
1378 if( !IsSymbol( token ) )
1379 {
1380 THROW_PARSE_ERROR( _( "Invalid pin name" ), CurSource(), CurLine(), CurLineNumber(),
1381 CurOffset() );
1382 }
1383
1384 if( m_requiredVersion < 20210606 )
1385 pin->SetName( ConvertToNewOverbarNotation( FromUTF8() ) );
1386 else
1387 pin->SetName( FromUTF8() );
1388
1389 token = NextTok();
1390
1391 if( token != T_RIGHT )
1392 {
1393 token = NextTok();
1394
1395 if( token == T_effects )
1396 {
1397 // The EDA_TEXT font effects formatting is used so use and EDA_TEXT object
1398 // so duplicate parsing is not required.
1400
1401 parseEDA_TEXT( &text, true );
1402 pin->SetNameTextSize( text.GetTextHeight() );
1403 NeedRIGHT();
1404 }
1405 else
1406 {
1407 Expecting( "effects" );
1408 }
1409 }
1410
1411 break;
1412
1413 case T_number:
1414 token = NextTok();
1415
1416 if( !IsSymbol( token ) )
1417 {
1418 THROW_PARSE_ERROR( _( "Invalid pin number" ), CurSource(), CurLine(),
1419 CurLineNumber(), CurOffset() );
1420 }
1421
1422 pin->SetNumber( FromUTF8() );
1423 token = NextTok();
1424
1425 if( token != T_RIGHT )
1426 {
1427 token = NextTok();
1428
1429 if( token == T_effects )
1430 {
1431 // The EDA_TEXT font effects formatting is used so use and EDA_TEXT object
1432 // so duplicate parsing is not required.
1434
1435 parseEDA_TEXT( &text, false );
1436 pin->SetNumberTextSize( text.GetTextHeight() );
1437 NeedRIGHT();
1438 }
1439 else
1440 {
1441 Expecting( "effects" );
1442 }
1443 }
1444
1445 break;
1446
1447 case T_alternate:
1448 {
1449 LIB_PIN::ALT alt;
1450
1451 token = NextTok();
1452
1453 if( !IsSymbol( token ) )
1454 {
1455 THROW_PARSE_ERROR( _( "Invalid alternate pin name" ), CurSource(), CurLine(),
1456 CurLineNumber(), CurOffset() );
1457 }
1458
1459 alt.m_Name = FromUTF8();
1460
1461 token = NextTok();
1462 alt.m_Type = parseType( token );
1463
1464 token = NextTok();
1465 alt.m_Shape = parseShape( token );
1466
1467 pin->GetAlternates()[ alt.m_Name ] = alt;
1468
1469 NeedRIGHT();
1470 break;
1471 }
1472
1473 default:
1474 Expecting( "at, name, number, length, or alternate" );
1475 }
1476 }
1477
1478 return pin.release();
1479}
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:72
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax)
#define DEFAULT_SIZE_TEXT
This is the "default-of-the-default" hardcoded text size; individual application define their own def...
Definition: eda_text.h:61
@ PIN_LEFT
Definition: lib_pin.h:46
@ PIN_RIGHT
Definition: lib_pin.h:45
@ PIN_UP
Definition: lib_pin.h:47
@ PIN_DOWN
Definition: lib_pin.h:48
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition: pin_type.h:36
@ PT_INPUT
usual pin input: must be connected
@ PT_NC
not connected (must be left open)
@ PT_OUTPUT
usual output
@ PT_TRISTATE
tris state bus pin
@ PT_NIC
not internally connected (may be connected to anything)
@ PT_BIDI
input or output (like port for a microprocessor)
@ PT_OPENEMITTER
pin type open emitter
@ PT_POWER_OUT
output of a regulator: intended to be connected to power input pins
@ PT_OPENCOLLECTOR
pin type open collector
@ PT_POWER_IN
power input (GND, VCC for ICs). Must be connected to a power output.
@ PT_UNSPECIFIED
unknown electrical properties: creates always a warning when connected
@ PT_PASSIVE
pin for passive symbols: must be connected, and can be connected to any pin
GRAPHIC_PINSHAPE
Definition: pin_type.h:56
static std::shared_ptr< SHAPE > parseShape(SHAPE_TYPE expectedType, wxStringTokenizer &aTokens)
GRAPHIC_PINSHAPE m_Shape
Definition: lib_pin.h:58
ELECTRICAL_PINTYPE m_Type
Definition: lib_pin.h:59
wxString m_Name
Definition: lib_pin.h:57

References _, CLOCK, CLOCK_LOW, ConvertToNewOverbarNotation(), DEFAULT_SIZE_TEXT, FALLING_EDGE_CLOCK, INPUT_LOW, INVERTED, INVERTED_CLOCK, LINE, m_convert, LIB_PIN::ALT::m_Name, m_requiredVersion, LIB_PIN::ALT::m_Shape, LIB_PIN::ALT::m_Type, m_unit, EDA_IU_SCALE::MilsToIU(), NONLOGIC, OUTPUT_LOW, parseEDA_TEXT(), parseInt(), parseInternalUnits(), parseShape(), parseXY(), pin, PIN_DOWN, PIN_LEFT, PIN_RIGHT, PIN_UP, PT_BIDI, PT_INPUT, PT_NC, PT_NIC, PT_OPENCOLLECTOR, PT_OPENEMITTER, PT_OUTPUT, PT_PASSIVE, PT_POWER_IN, PT_POWER_OUT, PT_TRISTATE, PT_UNSPECIFIED, schIUScale, text, and THROW_PARSE_ERROR.

Referenced by ParseDrawItem().

◆ parsePinNames()

void SCH_SEXPR_PARSER::parsePinNames ( std::unique_ptr< LIB_SYMBOL > &  aSymbol)
private

Definition at line 717 of file sch_sexpr_parser.cpp.

718{
719 wxCHECK_RET( CurTok() == T_pin_names,
720 "Cannot parse " + GetTokenString( CurTok() ) + " as a pin_name token." );
721
722 T token = NextTok();
723
724 if( token == T_LEFT )
725 {
726 token = NextTok();
727
728 if( token != T_offset )
729 Expecting( "offset" );
730
731 aSymbol->SetPinNameOffset( parseInternalUnits( "pin name offset" ) );
732 NeedRIGHT();
733 token = NextTok(); // Either ) or hide
734 }
735
736 if( token == T_hide )
737 {
738 aSymbol->SetShowPinNames( false );
739 NeedRIGHT();
740 }
741 else if( token != T_RIGHT )
742 {
743 THROW_PARSE_ERROR( _( "Invalid pin names definition" ), CurSource(), CurLine(),
744 CurLineNumber(), CurOffset() );
745 }
746}

References _, parseInternalUnits(), and THROW_PARSE_ERROR.

Referenced by ParseSymbol().

◆ parsePolyLine()

LIB_SHAPE * SCH_SEXPR_PARSER::parsePolyLine ( )
private

Definition at line 1482 of file sch_sexpr_parser.cpp.

1483{
1484 wxCHECK_MSG( CurTok() == T_polyline, nullptr,
1485 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a poly." ) );
1486
1487 T token;
1489 FILL_PARAMS fill;
1490 std::unique_ptr<LIB_SHAPE> poly = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::POLY );
1491
1492 poly->SetUnit( m_unit );
1493 poly->SetConvert( m_convert );
1494
1495 token = NextTok();
1496
1497 if( token == T_private )
1498 {
1499 poly->SetPrivate( true );
1500 token = NextTok();
1501 }
1502
1503 for( ; token != T_RIGHT; token = NextTok() )
1504 {
1505 if( token != T_LEFT )
1506 Expecting( T_LEFT );
1507
1508 token = NextTok();
1509
1510 switch( token )
1511 {
1512 case T_pts:
1513 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1514 {
1515 if( token != T_LEFT )
1516 Expecting( T_LEFT );
1517
1518 token = NextTok();
1519
1520 if( token != T_xy )
1521 Expecting( "xy" );
1522
1523 poly->AddPoint( parseXY() );
1524
1525 NeedRIGHT();
1526 }
1527
1528 break;
1529
1530 case T_stroke:
1531 parseStroke( stroke );
1532 poly->SetStroke( stroke );
1533 break;
1534
1535 case T_fill:
1536 parseFill( fill );
1537 poly->SetFillMode( fill.m_FillType );
1538 poly->SetFillColor( fill.m_Color );
1539 break;
1540
1541 default:
1542 Expecting( "pts, stroke, or fill" );
1543 }
1544 }
1545
1546 return poly.release();
1547}

References DEFAULT, DEFAULT_LINE_WIDTH_MILS, FILL_PARAMS::m_Color, m_convert, FILL_PARAMS::m_FillType, m_unit, EDA_IU_SCALE::MilsToIU(), parseFill(), parseStroke(), parseXY(), POLY, and schIUScale.

Referenced by ParseDrawItem().

◆ parseProperty()

LIB_FIELD * SCH_SEXPR_PARSER::parseProperty ( std::unique_ptr< LIB_SYMBOL > &  aSymbol)
private

Definition at line 749 of file sch_sexpr_parser.cpp.

750{
751 wxCHECK_MSG( CurTok() == T_property, nullptr,
752 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a property." ) );
753 wxCHECK( aSymbol, nullptr );
754
755 wxString name;
756 wxString value;
757 std::unique_ptr<LIB_FIELD> field = std::make_unique<LIB_FIELD>( aSymbol.get(),
759
760 T token = NextTok();
761
762 if( !IsSymbol( token ) )
763 {
764 THROW_PARSE_ERROR( _( "Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
765 CurOffset() );
766 }
767
768 name = FromUTF8();
769
770 if( name.IsEmpty() )
771 {
772 THROW_PARSE_ERROR( _( "Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
773 CurOffset() );
774 }
775
776 field->SetName( name );
777
778 // Correctly set the ID based on canonical (untranslated) field name
779 // If ID is stored in the file (old versions), it will overwrite this
780 for( int ii = 0; ii < MANDATORY_FIELDS; ++ii )
781 {
782 if( !name.CmpNoCase( TEMPLATE_FIELDNAME::GetDefaultFieldName( ii ) ) )
783 {
784 field->SetId( ii );
785 break;
786 }
787 }
788
789 token = NextTok();
790
791 if( !IsSymbol( token ) )
792 {
793 THROW_PARSE_ERROR( _( "Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
794 CurOffset() );
795 }
796
797 // Empty property values are valid.
798 value = FromUTF8();
799
800 field->SetText( value );
801
802 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
803 {
804 if( token != T_LEFT )
805 Expecting( T_LEFT );
806
807 token = NextTok();
808
809 switch( token )
810 {
811 case T_id:
812 field->SetId( parseInt( "field ID" ) );
813 NeedRIGHT();
814 break;
815
816 case T_at:
817 field->SetPosition( parseXY() );
818 field->SetTextAngle( EDA_ANGLE( parseDouble( "text angle" ), DEGREES_T ) );
819 NeedRIGHT();
820 break;
821
822 case T_effects:
823 parseEDA_TEXT( static_cast<EDA_TEXT*>( field.get() ), field->GetId() == VALUE_FIELD );
824 break;
825
826 case T_show_name:
827 field->SetNameShown();
828 NeedRIGHT();
829 break;
830
831 case T_do_not_autoplace:
832 field->SetCanAutoplace( false );
833 NeedRIGHT();
834 break;
835
836 default:
837 Expecting( "id, at, show_name, do_not_autoplace, or effects" );
838 }
839 }
840
841 // Due to an bug when in #LIB_SYMBOL::Flatten, duplicate ids slipped through
842 // when writing files. This section replaces duplicate #LIB_FIELD indices on
843 // load.
844 if( m_fieldIDsRead.count( field->GetId() ) )
845 {
846 int nextAvailableId = field->GetId() + 1;
847
848 while( m_fieldIDsRead.count( nextAvailableId ) )
849 nextAvailableId += 1;
850
851 field->SetId( nextAvailableId );
852 }
853
854 LIB_FIELD* existingField;
855
856 if( field->GetId() < MANDATORY_FIELDS )
857 {
858 existingField = aSymbol->GetFieldById( field->GetId() );
859
860 *existingField = *field;
861 m_fieldIDsRead.insert( field->GetId() );
862 return existingField;
863 }
864 else if( name == "ki_keywords" )
865 {
866 // Not a LIB_FIELD object yet.
867 aSymbol->SetKeyWords( value );
868 return nullptr;
869 }
870 else if( name == "ki_description" )
871 {
872 // Not a LIB_FIELD object yet.
873 aSymbol->SetDescription( value );
874 return nullptr;
875 }
876 else if( name == "ki_fp_filters" )
877 {
878 // Not a LIB_FIELD object yet.
879 wxArrayString filters;
880 wxStringTokenizer tokenizer( value );
881
882 while( tokenizer.HasMoreTokens() )
883 {
884 wxString curr_token = UnescapeString( tokenizer.GetNextToken() );
885 filters.Add( curr_token );
886 }
887
888 aSymbol->SetFPFilters( filters );
889 return nullptr;
890 }
891 else if( name == "ki_locked" )
892 {
893 // This is a temporary LIB_FIELD object until interchangeable units are determined on
894 // the fly.
895 aSymbol->LockUnits( true );
896 return nullptr;
897 }
898 else
899 {
900 // At this point, a user field is read.
901 existingField = aSymbol->FindField( field->GetCanonicalName() );
902
903#if 1 // Enable it to modify the name of the field to add if already existing
904 // Disable it to skip the field having the same name as previous field
905 if( existingField )
906 {
907 // We cannot handle 2 fields with the same name, so because the field name
908 // is already in use, try to build a new name (oldname_x)
909 wxString base_name = field->GetCanonicalName();
910
911 // Arbitrary limit 10 attempts to find a new name
912 for( int ii = 1; ii < 10 && existingField; ii++ )
913 {
914 wxString newname = base_name;
915 newname << '_' << ii;
916
917 existingField = aSymbol->FindField( newname );
918
919 if( !existingField ) // the modified name is not found, use it
920 field->SetName( newname );
921 }
922 }
923#endif
924 if( !existingField )
925 {
926 aSymbol->AddDrawItem( field.get(), false );
927 m_fieldIDsRead.insert( field->GetId() );
928 return field.release();
929 }
930 else
931 {
932 // We cannot handle 2 fields with the same name, so skip this one
933 return nullptr;
934 }
935 }
936}
const char * name
Definition: DXF_plotter.cpp:56
Field object used in symbol libraries.
Definition: lib_field.h:61
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
Definition: lib_field.cpp:479
std::set< int > m_fieldIDsRead
Field IDs that have been read so far for the current symbol.
wxString UnescapeString(const wxString &aSource)
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslateForHI=false)
Return a default symbol field name for field aFieldNdx for all components.
@ VALUE_FIELD
Field Value of part, i.e. "3.3K".
@ MANDATORY_FIELDS
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.

References _, DEGREES_T, LIB_FIELD::GetCanonicalName(), TEMPLATE_FIELDNAME::GetDefaultFieldName(), m_fieldIDsRead, MANDATORY_FIELDS, name, parseDouble(), parseEDA_TEXT(), parseInt(), parseXY(), THROW_PARSE_ERROR, UnescapeString(), and VALUE_FIELD.

Referenced by ParseSymbol().

◆ parseRectangle()

LIB_SHAPE * SCH_SEXPR_PARSER::parseRectangle ( )
private

Definition at line 1550 of file sch_sexpr_parser.cpp.

1551{
1552 wxCHECK_MSG( CurTok() == T_rectangle, nullptr,
1553 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a rectangle." ) );
1554
1555 T token;
1557 FILL_PARAMS fill;
1558 std::unique_ptr<LIB_SHAPE> rectangle = std::make_unique<LIB_SHAPE>( nullptr, SHAPE_T::RECT );
1559
1560 rectangle->SetUnit( m_unit );
1561 rectangle->SetConvert( m_convert );
1562
1563 token = NextTok();
1564
1565 if( token == T_private )
1566 {
1567 rectangle->SetPrivate( true );
1568 token = NextTok();
1569 }
1570
1571 for( ; token != T_RIGHT; token = NextTok() )
1572 {
1573 if( token != T_LEFT )
1574 Expecting( T_LEFT );
1575
1576 token = NextTok();
1577
1578 switch( token )
1579 {
1580 case T_start:
1581 rectangle->SetPosition( parseXY() );
1582 NeedRIGHT();
1583 break;
1584
1585 case T_end:
1586 rectangle->SetEnd( parseXY() );
1587 NeedRIGHT();
1588 break;
1589
1590 case T_stroke:
1591 parseStroke( stroke );
1592 rectangle->SetStroke( stroke );
1593 break;
1594
1595 case T_fill:
1596 parseFill( fill );
1597 rectangle->SetFillMode( fill.m_FillType );
1598 rectangle->SetFillColor( fill.m_Color );
1599 break;
1600
1601 default:
1602 Expecting( "start, end, stroke, or fill" );
1603 }
1604 }
1605
1606 return rectangle.release();
1607}

References DEFAULT, DEFAULT_LINE_WIDTH_MILS, FILL_PARAMS::m_Color, m_convert, FILL_PARAMS::m_FillType, m_unit, EDA_IU_SCALE::MilsToIU(), parseFill(), parseStroke(), parseXY(), RECT, and schIUScale.

Referenced by ParseDrawItem().

◆ parseSchArc()

SCH_SHAPE * SCH_SEXPR_PARSER::parseSchArc ( )
private

Definition at line 3451 of file sch_sexpr_parser.cpp.

3452{
3453 wxCHECK_MSG( CurTok() == T_arc, nullptr,
3454 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as an arc." ) );
3455
3456 T token;
3457 VECTOR2I startPoint;
3458 VECTOR2I midPoint;
3459 VECTOR2I endPoint;
3461 FILL_PARAMS fill;
3462 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>( SHAPE_T::ARC );
3463
3464 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3465 {
3466 if( token != T_LEFT )
3467 Expecting( T_LEFT );
3468
3469 token = NextTok();
3470
3471 switch( token )
3472 {
3473 case T_start:
3474 startPoint = parseXY();
3475 NeedRIGHT();
3476 break;
3477
3478 case T_mid:
3479 midPoint = parseXY();
3480 NeedRIGHT();
3481 break;
3482
3483 case T_end:
3484 endPoint = parseXY();
3485 NeedRIGHT();
3486 break;
3487
3488 case T_stroke:
3489 parseStroke( stroke );
3490 arc->SetStroke( stroke );
3491 break;
3492
3493 case T_fill:
3494 parseFill( fill );
3495 arc->SetFillMode( fill.m_FillType );
3496 arc->SetFillColor( fill.m_Color );
3497 break;
3498
3499 case T_uuid:
3500 NeedSYMBOL();
3501 const_cast<KIID&>( arc->m_Uuid ) = KIID( FromUTF8() );
3502 NeedRIGHT();
3503 break;
3504
3505 default:
3506 Expecting( "start, mid, end, stroke, fill or uuid" );
3507 }
3508 }
3509
3510 arc->SetArcGeometry( startPoint, midPoint, endPoint );
3511
3512 return arc.release();
3513}

References ARC, DEFAULT, DEFAULT_LINE_WIDTH_MILS, FILL_PARAMS::m_Color, FILL_PARAMS::m_FillType, EDA_IU_SCALE::MilsToIU(), parseFill(), parseStroke(), parseXY(), and schIUScale.

Referenced by ParseSchematic().

◆ parseSchBezier()

SCH_SHAPE * SCH_SEXPR_PARSER::parseSchBezier ( )
private

Definition at line 3631 of file sch_sexpr_parser.cpp.

3632{
3633 wxCHECK_MSG( CurTok() == T_bezier, nullptr,
3634 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bezier." ) );
3635
3636 T token;
3638 FILL_PARAMS fill;
3639 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>( SHAPE_T::BEZIER );
3640
3641 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3642 {
3643 if( token != T_LEFT )
3644 Expecting( T_LEFT );
3645
3646 token = NextTok();
3647
3648 switch( token )
3649 {
3650 case T_pts:
3651 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3652 {
3653 if( token != T_LEFT )
3654 Expecting( T_LEFT );
3655
3656 token = NextTok();
3657
3658 if( token != T_xy )
3659 Expecting( "xy" );
3660
3661 bezier->AddPoint( parseXY() );
3662
3663 NeedRIGHT();
3664 }
3665
3666 break;
3667
3668 case T_stroke:
3669 parseStroke( stroke );
3670 bezier->SetStroke( stroke );
3671 break;
3672
3673 case T_fill:
3674 parseFill( fill );
3675 bezier->SetFillMode( fill.m_FillType );
3676 bezier->SetFillColor( fill.m_Color );
3677 break;
3678
3679 case T_uuid:
3680 NeedSYMBOL();
3681 const_cast<KIID&>( bezier->m_Uuid ) = KIID( FromUTF8() );
3682 NeedRIGHT();
3683 break;
3684
3685 default:
3686 Expecting( "pts, stroke, fill or uuid" );
3687 }
3688 }
3689
3690 return bezier.release();
3691}

References BEZIER, DEFAULT, DEFAULT_LINE_WIDTH_MILS, FILL_PARAMS::m_Color, FILL_PARAMS::m_FillType, EDA_IU_SCALE::MilsToIU(), parseFill(), parseStroke(), parseXY(), and schIUScale.

Referenced by ParseSchematic().

◆ parseSchCircle()

SCH_SHAPE * SCH_SEXPR_PARSER::parseSchCircle ( )
private

Definition at line 3516 of file sch_sexpr_parser.cpp.

3517{
3518 wxCHECK_MSG( CurTok() == T_circle, nullptr,
3519 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a circle." ) );
3520
3521 T token;
3522 VECTOR2I center;
3523 int radius = 0;
3525 FILL_PARAMS fill;
3526 std::unique_ptr<SCH_SHAPE> circle = std::make_unique<SCH_SHAPE>( SHAPE_T::CIRCLE );
3527
3528 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3529 {
3530 if( token != T_LEFT )
3531 Expecting( T_LEFT );
3532
3533 token = NextTok();
3534
3535 switch( token )
3536 {
3537 case T_center:
3538 center = parseXY();
3539 NeedRIGHT();
3540 break;
3541
3542 case T_radius:
3543 radius = parseInternalUnits( "radius length" );
3544 NeedRIGHT();
3545 break;
3546
3547 case T_stroke:
3548 parseStroke( stroke );
3549 circle->SetStroke( stroke );
3550 break;
3551
3552 case T_fill:
3553 parseFill( fill );
3554 circle->SetFillMode( fill.m_FillType );
3555 circle->SetFillColor( fill.m_Color );
3556 break;
3557
3558 case T_uuid:
3559 NeedSYMBOL();
3560 const_cast<KIID&>( circle->m_Uuid ) = KIID( FromUTF8() );
3561 NeedRIGHT();
3562 break;
3563
3564 default:
3565 Expecting( "center, radius, stroke, fill or uuid" );
3566 }
3567 }
3568
3569 circle->SetCenter( center );
3570 circle->SetEnd( VECTOR2I( center.x + radius, center.y ) );
3571
3572 return circle.release();
3573}

References CIRCLE, DEFAULT, DEFAULT_LINE_WIDTH_MILS, FILL_PARAMS::m_Color, FILL_PARAMS::m_FillType, EDA_IU_SCALE::MilsToIU(), parseFill(), parseInternalUnits(), parseStroke(), parseXY(), schIUScale, VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by ParseSchematic().

◆ ParseSchematic()

void SCH_SEXPR_PARSER::ParseSchematic ( SCH_SHEET aSheet,
bool  aIsCopyablyOnly = false,
int  aFileVersion = SEXPR_SCHEMATIC_FILE_VERSION 
)

Parse the internal LINE_READER object into aSheet.

When aIsCopyableOnly is true, only schematic objects that are viewable on the canvas for copy and paste purposes are parsed. Other schematic content such as bus definitions or instance data will throw an IO_ERROR exception.

When aIsCopyableOnly is false, full schematic file parsing is performed.

Note
This does not load any sub-sheets or decent complex sheet hierarchies.
Parameters
aSheetThe SCH_SHEET object to store the parsed schematic file.
aIsCopyableOnlyLoad only the schematic objects that can be copied into aSheet if true. Otherwise, load the full schematic file format.
aFileVersionThe schematic file version to parser. Defaults to the schematic file being parsed when aIsCopyableOnly is false.

Definition at line 2283 of file sch_sexpr_parser.cpp.

2284{
2285 wxCHECK( aSheet != nullptr, /* void */ );
2286
2287 SCH_SCREEN* screen = aSheet->GetScreen();
2288
2289 wxCHECK( screen != nullptr, /* void */ );
2290
2291 if( aIsCopyableOnly )
2292 m_requiredVersion = aFileVersion;
2293
2294 bool fileHasUuid = false;
2295
2296 T token;
2297
2298 if( !aIsCopyableOnly )
2299 {
2300 NeedLEFT();
2301 NextTok();
2302
2303 if( CurTok() != T_kicad_sch )
2304 Expecting( "kicad_sch" );
2305
2307
2308 // Prior to schematic file version 20210406, schematics did not have UUIDs so we need
2309 // to generate one for the root schematic for instance paths.
2310 if( m_requiredVersion < 20210406 )
2311 m_rootUuid = screen->GetUuid();
2312 }
2313
2315
2316 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2317 {
2318 if( aIsCopyableOnly && token == T_EOF )
2319 break;
2320
2321 if( token != T_LEFT )
2322 Expecting( T_LEFT );
2323
2324 token = NextTok();
2325
2326 checkpoint();
2327
2328 if( !aIsCopyableOnly && token == T_page && m_requiredVersion <= 20200506 )
2329 token = T_paper;
2330
2331 switch( token )
2332 {
2333 case T_uuid:
2334 NeedSYMBOL();
2335 screen->m_uuid = parseKIID();
2336
2337 // Set the root sheet UUID with the schematic file UUID. Root sheets are virtual
2338 // and always get a new UUID so this prevents file churn now that the root UUID
2339 // is saved in the symbol instance path.
2340 if( aSheet == m_rootSheet )
2341 {
2342 const_cast<KIID&>( aSheet->m_Uuid ) = screen->GetUuid();
2343 m_rootUuid = screen->GetUuid();
2344 fileHasUuid = true;
2345 }
2346
2347 NeedRIGHT();
2348 break;
2349
2350 case T_paper:
2351 {
2352 if( aIsCopyableOnly )
2353 Unexpected( T_paper );
2354
2355 PAGE_INFO pageInfo;
2356 parsePAGE_INFO( pageInfo );
2357 screen->SetPageSettings( pageInfo );
2358 break;
2359 }
2360
2361 case T_page:
2362 {
2363 if( aIsCopyableOnly )
2364 Unexpected( T_page );
2365
2366 // Only saved for top-level sniffing in Kicad Manager frame and other external
2367 // tool usage with flat hierarchies
2368 NeedSYMBOLorNUMBER();
2369 NeedSYMBOLorNUMBER();
2370 NeedRIGHT();
2371 break;
2372 }
2373
2374 case T_title_block:
2375 {
2376 if( aIsCopyableOnly )
2377 Unexpected( T_title_block );
2378
2379 TITLE_BLOCK tb;
2380 parseTITLE_BLOCK( tb );
2381 screen->SetTitleBlock( tb );
2382 break;
2383 }
2384
2385 case T_lib_symbols:
2386 {
2387 // Dummy map. No derived symbols are allowed in the library cache.
2388 LIB_SYMBOL_MAP symbolLibMap;
2389 LIB_SYMBOL* symbol;
2390
2391 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2392 {
2393 if( token != T_LEFT )
2394 Expecting( T_LEFT );
2395
2396 token = NextTok();
2397
2398 switch( token )
2399 {
2400 case T_symbol:
2401 symbol = ParseSymbol( symbolLibMap, m_requiredVersion );
2402 symbol->UpdateFieldOrdinals();
2403 screen->AddLibSymbol( symbol );
2404 break;
2405
2406 default:
2407 Expecting( "symbol" );
2408 }
2409 }
2410
2411 break;
2412 }
2413
2414 case T_symbol:
2415 screen->Append( static_cast<SCH_ITEM*>( parseSchematicSymbol() ) );
2416 break;
2417
2418 case T_image:
2419 screen->Append( static_cast<SCH_ITEM*>( parseImage() ) );
2420 break;
2421
2422 case T_sheet:
2423 {
2424 SCH_SHEET* sheet = parseSheet();
2425
2426 // Set the parent to aSheet. This effectively creates a method to find
2427 // the root sheet from any sheet so a pointer to the root sheet does not
2428 // need to be stored globally. Note: this is not the same as a hierarchy.
2429 // Complex hierarchies can have multiple copies of a sheet. This only
2430 // provides a simple tree to find the root sheet.
2431 sheet->SetParent( aSheet );
2432 screen->Append( sheet );
2433 break;
2434 }
2435
2436 case T_junction:
2437 screen->Append( parseJunction() );
2438 break;
2439
2440 case T_no_connect:
2441 screen->Append( parseNoConnect() );
2442 break;
2443
2444 case T_bus_entry:
2445 screen->Append( parseBusEntry() );
2446 break;
2447
2448 case T_polyline:
2449 {
2450 // polyline keyword is used in eeschema both for SCH_SHAPE and SCH_LINE items.
2451 // In symbols it describes a polygon, having n corners and can be filled
2452 // In schematic it describes a line (with no fill descr), but could be extended to a
2453 // polygon (for instance when importing files) because the schematic handles all
2454 // SCH_SHAPE.
2455
2456 // parseSchPolyLine() returns always a SCH_SHAPE, io convert it to a simple SCH_LINE
2457 // For compatibility reasons, keep SCH_SHAPE for a polygon and convert to SCH_LINE
2458 // when the item has only 2 corners, similar to a SCH_LINE
2459 SCH_SHAPE* poly = parseSchPolyLine();
2460
2461 if( poly->GetPointCount() > 2 )
2462 {
2463 screen->Append( poly );
2464 }
2465 else
2466 {
2467 // For SCH_SHAPE having only 2 points, this is a "old" SCH_LINE entity.
2468 // So convert the SCH_SHAPE to a simple SCH_LINE
2469 SCH_LINE* line = new SCH_LINE( VECTOR2I(), LAYER_NOTES );
2470 SHAPE_LINE_CHAIN& outline = poly->GetPolyShape().Outline(0);
2471 line->SetStartPoint( outline.CPoint(0) );
2472 line->SetEndPoint( outline.CPoint(1) );
2473 line->SetStroke( poly->GetStroke() );
2474 const_cast<KIID&>( line->m_Uuid ) = poly->m_Uuid;
2475
2476 screen->Append( line );
2477
2478 delete poly;
2479 }
2480 }
2481 break;
2482
2483 case T_bus:
2484 case T_wire:
2485 screen->Append( parseLine() );
2486 break;
2487
2488 case T_arc:
2489 screen->Append( parseSchArc() );
2490 break;
2491
2492 case T_circle:
2493 screen->Append( parseSchCircle() );
2494 break;
2495
2496 case T_rectangle:
2497 screen->Append( parseSchRectangle() );
2498 break;
2499
2500 case T_bezier:
2501 screen->Append( parseSchBezier() );
2502 break;
2503
2504 case T_netclass_flag: // present only during early development of 7.0
2506
2507 case T_text:
2508 case T_label:
2509 case T_global_label:
2510 case T_hierarchical_label:
2511 case T_directive_label:
2512 screen->Append( parseSchText() );
2513 break;
2514
2515 case T_text_box:
2516 screen->Append( parseSchTextBox() );
2517 break;
2518
2519 case T_sheet_instances:
2520 parseSchSheetInstances( aSheet, screen );
2521 break;
2522
2523 case T_symbol_instances:
2524 parseSchSymbolInstances( screen );
2525 break;
2526
2527 case T_bus_alias:
2528 if( aIsCopyableOnly )
2529 Unexpected( T_bus_alias );
2530
2531 parseBusAlias( screen );
2532 break;
2533
2534 default:
2535 Expecting( "symbol, paper, page, title_block, bitmap, sheet, junction, no_connect, "
2536 "bus_entry, line, bus, text, label, class_label, global_label, "
2537 "hierarchical_label, symbol_instances, or bus_alias" );
2538 }
2539 }
2540
2541 // Older s-expression schematics may not have a UUID so use the one automatically generated
2542 // as the virtual root sheet UUID.
2543 if( ( aSheet == m_rootSheet ) && !fileHasUuid )
2544 {
2545 const_cast<KIID&>( aSheet->m_Uuid ) = screen->GetUuid();
2546 m_rootUuid = screen->GetUuid();
2547 }
2548
2549 screen->UpdateLocalLibSymbolLinks();
2550
2551 if( m_requiredVersion < 20200828 )
2553}
const KIID m_Uuid
Definition: eda_item.h:492
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:100
SHAPE_POLY_SET & GetPolyShape()
Definition: eda_shape.h:247
int GetPointCount() const
Definition: eda_shape.cpp:1254
int UpdateFieldOrdinals()
Order optional field indices.
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:54
Base class for any item which can be embedded within the SCHEMATIC container class,...
Definition: sch_item.h:147
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:40
void SetStartPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:139
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
Definition: sch_line.h:178
void SetEndPoint(const VECTOR2I &aPosition)
Definition: sch_line.h:144
void SetFileFormatVersionAtLoad(int aVersion)
Definition: sch_screen.h:128
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition: sch_screen.h:157
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
Definition: sch_screen.cpp:145
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: sch_screen.h:132
const KIID & GetUuid() const
Definition: sch_screen.h:526
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
void SetLegacySymbolInstanceData()
Update the symbol value and footprint instance data for legacy designs.
KIID m_uuid
A unique identifier for each schematic file.
Definition: sch_screen.h:642
void parseBusAlias(SCH_SCREEN *aScreen)
void parseSchSheetInstances(SCH_SHEET *aRootSheet, SCH_SCREEN *aScreen)
SCH_BUS_WIRE_ENTRY * parseBusEntry()
SCH_JUNCTION * parseJunction()
SCH_NO_CONNECT * parseNoConnect()
SCH_SHAPE * parseSchCircle()
SCH_SHAPE * parseSchRectangle()
SCH_SYMBOL * parseSchematicSymbol()
SCH_BITMAP * parseImage()
SCH_SHAPE * parseSchBezier()
SCH_SHAPE * parseSchArc()
SCH_SHEET * parseSheet()
void parseTITLE_BLOCK(TITLE_BLOCK &aTitleBlock)
SCH_TEXTBOX * parseSchTextBox()
SCH_TEXT * parseSchText()
void parseSchSymbolInstances(SCH_SCREEN *aScreen)
void parsePAGE_INFO(PAGE_INFO &aPageInfo)
SCH_SHAPE * parseSchPolyLine()
STROKE_PARAMS GetStroke() const override
Definition: sch_shape.h:64
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:57
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:106
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Hold the information shown in the lower right corner of a plot, printout, or editing view.
Definition: title_block.h:41
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
Definition: macros.h:83
#define SEXPR_SCHEMATIC_FILE_VERSION
Schematic file version.
std::map< wxString, LIB_SYMBOL *, LibSymbolMapSort > LIB_SYMBOL_MAP

References SCH_SCREEN::AddLibSymbol(), SCH_SCREEN::Append(), checkpoint(), SHAPE_LINE_CHAIN::CPoint(), EDA_SHAPE::GetPointCount(), EDA_SHAPE::GetPolyShape(), SCH_SHEET::GetScreen(), SCH_SHAPE::GetStroke(), SCH_SCREEN::GetUuid(), KI_FALLTHROUGH, LAYER_NOTES, m_requiredVersion, m_rootSheet, m_rootUuid, SCH_SCREEN::m_uuid, EDA_ITEM::m_Uuid, SHAPE_POLY_SET::Outline(), parseBusAlias(), parseBusEntry(), parseHeader(), parseImage(), parseJunction(), parseKIID(), parseLine(), parseNoConnect(), parsePAGE_INFO(), parseSchArc(), parseSchBezier(), parseSchCircle(), parseSchematicSymbol(), parseSchPolyLine(), parseSchRectangle(), parseSchSheetInstances(), parseSchSymbolInstances(), parseSchText(), parseSchTextBox(), parseSheet(), ParseSymbol(), parseTITLE_BLOCK(), SCH_LINE::SetEndPoint(), SCH_SCREEN::SetFileFormatVersionAtLoad(), SCH_SCREEN::SetLegacySymbolInstanceData(), SCH_SCREEN::SetPageSettings(), EDA_ITEM::SetParent(), SCH_LINE::SetStartPoint(), SCH_LINE::SetStroke(), SCH_SCREEN::SetTitleBlock(), SEXPR_SCHEMATIC_FILE_VERSION, LIB_SYMBOL::UpdateFieldOrdinals(), and SCH_SCREEN::UpdateLocalLibSymbolLinks().

Referenced by SCH_SEXPR_PLUGIN::LoadContent(), SCH_SEXPR_PLUGIN::loadFile(), and KI_TEST::LoadSheetSchematicContents().

◆ parseSchematicSymbol()

SCH_SYMBOL * SCH_SEXPR_PARSER::parseSchematicSymbol ( )
private

Definition at line 2556 of file sch_sexpr_parser.cpp.

2557{
2558 wxCHECK_MSG( CurTok() == T_symbol, nullptr,
2559 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a symbol." ) );
2560
2561 T token;
2562 wxString libName;
2563 SCH_FIELD* field;
2564 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
2565 TRANSFORM transform;
2566 std::set<int> fieldIDsRead;
2567
2568 // We'll reset this if we find a fields_autoplaced token
2569 symbol->ClearFieldsAutoplaced();
2570
2572 m_fieldIDsRead.clear();
2573
2574 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2575 {
2576 if( token != T_LEFT )
2577 Expecting( T_LEFT );
2578
2579 token = NextTok();
2580
2581 switch( token )
2582 {
2583 case T_lib_name:
2584 {
2585 LIB_ID libId;
2586
2587 token = NextTok();
2588
2589 if( !IsSymbol( token ) )
2590 {
2591 THROW_PARSE_ERROR( _( "Invalid symbol library name" ), CurSource(), CurLine(),
2592 CurLineNumber(), CurOffset() );
2593 }
2594
2595 libName = FromUTF8();
2596 NeedRIGHT();
2597 break;
2598 }
2599
2600 case T_lib_id:
2601 {
2602 token = NextTok();
2603
2604 if( !IsSymbol( token ) && token != T_NUMBER )
2605 Expecting( "symbol|number" );
2606
2607 LIB_ID libId;
2608 wxString name = FromUTF8();
2609 int bad_pos = libId.Parse( name );
2610
2611 if( bad_pos >= 0 )
2612 {
2613 if( static_cast<int>( name.size() ) > bad_pos )
2614 {
2615 wxString msg = wxString::Format(
2616 _( "Symbol %s contains invalid character '%c'" ), name,
2617 name[bad_pos] );
2618
2619 THROW_PARSE_ERROR( msg, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
2620 }
2621
2622 THROW_PARSE_ERROR( _( "Invalid symbol library ID" ), CurSource(), CurLine(),
2623 CurLineNumber(), CurOffset() );
2624 }
2625
2626 symbol->SetLibId( libId );
2627 NeedRIGHT();
2628 break;
2629 }
2630
2631 case T_at:
2632 symbol->SetPosition( parseXY() );
2633
2634 switch( static_cast<int>( parseDouble( "symbol orientation" ) ) )
2635 {
2636 case 0: transform = TRANSFORM(); break;
2637 case 90: transform = TRANSFORM( 0, -1, -1, 0 ); break;
2638 case 180: transform = TRANSFORM( -1, 0, 0, 1 ); break;
2639 case 270: transform = TRANSFORM( 0, 1, 1, 0 ); break;
2640 default: Expecting( "0, 90, 180, or 270" );
2641 }
2642
2643 symbol->SetTransform( transform );
2644 NeedRIGHT();
2645 break;
2646
2647 case T_mirror:
2648 token = NextTok();
2649
2650 if( token == T_x )
2651 symbol->SetOrientation( SYM_MIRROR_X );
2652 else if( token == T_y )
2653 symbol->SetOrientation( SYM_MIRROR_Y );
2654 else
2655 Expecting( "x or y" );
2656
2657 NeedRIGHT();
2658 break;
2659
2660 case T_unit:
2661 symbol->SetUnit( parseInt( "symbol unit" ) );
2662 NeedRIGHT();
2663 break;
2664
2665 case T_convert:
2666 symbol->SetConvert( parseInt( "symbol convert" ) );
2667 NeedRIGHT();
2668 break;
2669
2670 case T_in_bom:
2671 symbol->SetIncludeInBom( parseBool() );
2672 NeedRIGHT();
2673 break;
2674
2675 case T_on_board:
2676 symbol->SetIncludeOnBoard( parseBool() );
2677 NeedRIGHT();
2678 break;
2679
2680 case T_dnp:
2681 symbol->SetDNP( parseBool() );
2682 NeedRIGHT();
2683 break;
2684
2685 case T_fields_autoplaced:
2686 symbol->SetFieldsAutoplaced();
2687 NeedRIGHT();
2688 break;
2689
2690 case T_uuid:
2691 NeedSYMBOL();
2692 const_cast<KIID&>( symbol->m_Uuid ) = parseKIID();
2693 NeedRIGHT();
2694 break;
2695
2696 case T_default_instance:
2697 {
2698 SCH_SYMBOL_INSTANCE defaultInstance;
2699
2700 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2701 {
2702 if( token != T_LEFT )
2703 Expecting( T_LEFT );
2704
2705 token = NextTok();
2706
2707 switch( token )
2708 {
2709 case T_reference:
2710 NeedSYMBOL();
2711 defaultInstance.m_Reference = FromUTF8();
2712 NeedRIGHT();
2713 break;
2714
2715 case T_unit:
2716 defaultInstance.m_Unit = parseInt( "symbol unit" );
2717 NeedRIGHT();
2718 break;
2719
2720 case T_value:
2721 NeedSYMBOL();
2722 symbol->SetValueFieldText( FromUTF8() );
2723 NeedRIGHT();
2724 break;
2725
2726 case T_footprint:
2727 NeedSYMBOL();
2728 symbol->SetFootprintFieldText( FromUTF8() );
2729 NeedRIGHT();
2730 break;
2731
2732 default:
2733 Expecting( "reference, unit, value or footprint" );
2734 }
2735 }
2736
2737 break;
2738 }
2739
2740 case T_instances:
2741 {
2742 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2743 {
2744 if( token != T_LEFT )
2745 Expecting( T_LEFT );
2746
2747 token = NextTok();
2748
2749 if( token != T_project )
2750 Expecting( "project" );
2751
2752 NeedSYMBOL();
2753
2754 wxString projectName = FromUTF8();
2755
2756 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2757 {
2758 if( token != T_LEFT )
2759 Expecting( T_LEFT );
2760
2761 token = NextTok();
2762
2763 if( token != T_path )
2764 Expecting( "path" );
2765
2766 SCH_SYMBOL_INSTANCE instance;
2767
2768 instance.m_ProjectName = projectName;
2769
2770 NeedSYMBOL();
2771 instance.m_Path = KIID_PATH( FromUTF8() );
2772
2773 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2774 {
2775 if( token != T_LEFT )
2776 Expecting( T_LEFT );
2777
2778 token = NextTok();
2779
2780 switch( token )
2781 {
2782 case T_reference:
2783 NeedSYMBOL();
2784 instance.m_Reference = FromUTF8();
2785 NeedRIGHT();
2786 break;
2787
2788 case T_unit:
2789 instance.m_Unit = parseInt( "symbol unit" );
2790 NeedRIGHT();
2791 break;
2792
2793 case T_value:
2794 NeedSYMBOL();
2795 symbol->SetValueFieldText( FromUTF8() );
2796 NeedRIGHT();
2797 break;
2798
2799 case T_footprint:
2800 NeedSYMBOL();
2801 symbol->SetFootprintFieldText( FromUTF8() );
2802 NeedRIGHT();
2803 break;
2804
2805 default:
2806 Expecting( "reference, unit, value or footprint" );
2807 }
2808
2809 symbol->AddHierarchicalReference( instance );
2810 }
2811 }
2812 }
2813
2814 break;
2815 }
2816
2817 case T_property:
2818 // The field parent symbol must be set and its orientation must be set before
2819 // the field positions are set.
2820 field = parseSchField( symbol.get() );
2821
2822 if( m_fieldIDsRead.count( field->GetId() ) )
2823 {
2824 int nextAvailableId = field->GetId() + 1;
2825
2826 while( m_fieldIDsRead.count( nextAvailableId ) )
2827 nextAvailableId += 1;
2828
2829 field->SetId( nextAvailableId );
2830 }
2831
2832 if( symbol->GetFieldById( field->GetId() ) )
2833 *symbol->GetFieldById( field->GetId() ) = *field;
2834 else
2835 symbol->AddField( *field );
2836
2837 if( field->GetId() == REFERENCE_FIELD )
2838 symbol->UpdatePrefix();
2839
2840 m_fieldIDsRead.insert( field->GetId() );
2841
2842 delete field;
2843 break;
2844
2845 case T_pin:
2846 {
2847 // Read an alternate pin designation
2848 wxString number;
2849 KIID uuid;
2850 wxString alt;
2851
2852 NeedSYMBOL();
2853 number = FromUTF8();
2854
2855 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2856 {
2857 if( token != T_LEFT )
2858 Expecting( T_LEFT );
2859
2860 token = NextTok();
2861
2862 switch( token )
2863 {
2864 case T_alternate:
2865 NeedSYMBOL();
2866 alt = FromUTF8();
2867 NeedRIGHT();
2868 break;
2869
2870 case T_uuid:
2871 NeedSYMBOL();
2872
2873 // First version to write out pin uuids accidentally wrote out the symbol's
2874 // uuid for each pin, so ignore uuids coming from that version.
2875 if( m_requiredVersion >= 20210126 )
2876 uuid = parseKIID();
2877
2878 NeedRIGHT();
2879 break;
2880
2881 default:
2882 Expecting( "alternate or uuid" );
2883 }
2884 }
2885
2886 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(),
2887 number, alt ) );
2888
2889 const_cast<KIID&>( symbol->GetRawPins().back()->m_Uuid ) = uuid;
2890 }
2891 break;
2892
2893 default:
2894 Expecting( "lib_id, lib_name, at, mirror, uuid, on_board, in_bom, dnp, "
2895 "default_instance, property, pin, or instances" );
2896 }
2897 }
2898
2899 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
2900 symbol->SetSchSymbolLibraryName( libName );
2901
2902 // Ensure edit/status flags are cleared after these initializations:
2903 symbol->ClearFlags();
2904
2905 return symbol.release();
2906}
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:49
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:50
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:51
int GetId() const
Definition: sch_field.h:125
void SetId(int aId)
Definition: sch_field.cpp:138
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:47
@ SYM_MIRROR_Y
@ SYM_MIRROR_X
A simple container for schematic symbol instance information.
@ REFERENCE_FIELD
Field Reference of part, i.e. "IC21".

References _, Format(), SCH_FIELD::GetId(), m_fieldId, m_fieldIDsRead, SCH_SYMBOL_INSTANCE::m_Path, SCH_SYMBOL_INSTANCE::m_ProjectName, SCH_SYMBOL_INSTANCE::m_Reference, m_requiredVersion, SCH_SYMBOL_INSTANCE::m_Unit, MANDATORY_FIELDS, name, LIB_ID::Parse(), parseBool(), parseDouble(), parseInt(), parseKIID(), parseSchField(), parseXY(), REFERENCE_FIELD, SCH_FIELD::SetId(), SYM_MIRROR_X, SYM_MIRROR_Y, and THROW_PARSE_ERROR.

Referenced by ParseSchematic().

◆ parseSchField()

SCH_FIELD * SCH_SEXPR_PARSER::parseSchField ( SCH_ITEM aParent)
private

Definition at line 1917 of file sch_sexpr_parser.cpp.

1918{
1919 wxCHECK_MSG( CurTok() == T_property, nullptr,
1920 "Cannot parse " + GetTokenString( CurTok() ) + " as a property token." );
1921
1922 T token = NextTok();
1923
1924 if( !IsSymbol( token ) )
1925 {
1926 THROW_PARSE_ERROR( _( "Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
1927 CurOffset() );
1928 }
1929
1930 wxString name = FromUTF8();
1931
1932 if( name.IsEmpty() )
1933 {
1934 THROW_PARSE_ERROR( _( "Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
1935 CurOffset() );
1936 }
1937
1938 token = NextTok();
1939
1940 if( !IsSymbol( token ) )
1941 {
1942 THROW_PARSE_ERROR( _( "Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
1943 CurOffset() );
1944 }
1945
1946 // Empty property values are valid.
1947 wxString value = FromUTF8();
1948
1949 std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>( wxDefaultPosition, -1,
1950 aParent, name );
1951
1952 field->SetText( value );
1953 field->SetVisible( true );
1954
1955 // Correctly set the ID based on canonical (untranslated) field name
1956 // If ID is stored in the file (old versions), it will overwrite this
1957 if( aParent->Type() == SCH_SYMBOL_T )
1958 {
1959 for( int ii = 0; ii < MANDATORY_FIELDS; ++ii )
1960 {
1961 if( name == TEMPLATE_FIELDNAME::GetDefaultFieldName( ii, false ) )
1962 {
1963 field->SetId( ii );
1964 break;
1965 }
1966 }
1967 }
1968 else if( aParent->Type() == SCH_SHEET_T )
1969 {
1970 for( int ii = 0; ii < SHEET_MANDATORY_FIELDS; ++ii )
1971 {
1972 if( name == SCH_SHEET::GetDefaultFieldName( ii, false ) )
1973 {
1974 field->SetId( ii );
1975 break;
1976 }
1977 }
1978 }
1979
1980 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1981 {
1982 if( token != T_LEFT )
1983 Expecting( T_LEFT );
1984
1985 token = NextTok();
1986
1987 switch( token )
1988 {
1989 case T_id:
1990 field->SetId( parseInt( "field ID" ) );
1991 NeedRIGHT();
1992 break;
1993
1994 case T_at:
1995 field->SetPosition( parseXY() );
1996 field->SetTextAngle( EDA_ANGLE( parseDouble( "text angle" ), DEGREES_T ) );
1997 NeedRIGHT();
1998 break;
1999
2000 case T_effects:
2001 parseEDA_TEXT( static_cast<EDA_TEXT*>( field.get() ), field->GetId() == VALUE_FIELD );
2002 break;
2003
2004 case T_show_name:
2005 field->SetNameShown();
2006 NeedRIGHT();
2007 break;
2008
2009 case T_do_not_autoplace:
2010 field->SetCanAutoplace( false );
2011 NeedRIGHT();
2012 break;
2013
2014 default:
2015 Expecting( "id, at, show_name, do_not_autoplace or effects" );
2016 }
2017 }
2018
2019 return field.release();
2020}
KICAD_T Type() const
Returns the type of object.
Definition: eda_item.h:97
static const wxString GetDefaultFieldName(int aFieldNdx, bool aTranslated=true)
Definition: sch_sheet.cpp:55
@ SHEET_MANDATORY_FIELDS
The first 2 are mandatory, and must be instantiated in SCH_SHEET.
Definition: sch_sheet.h:49
@ SCH_SYMBOL_T
Definition: typeinfo.h:156
@ SCH_SHEET_T
Definition: typeinfo.h:158

References _, DEGREES_T, SCH_SHEET::GetDefaultFieldName(), TEMPLATE_FIELDNAME::GetDefaultFieldName(), MANDATORY_FIELDS, name, parseDouble(), parseEDA_TEXT(), parseInt(), parseXY(), SCH_SHEET_T, SCH_SYMBOL_T, SHEET_MANDATORY_FIELDS, THROW_PARSE_ERROR, EDA_ITEM::Type(), and VALUE_FIELD.

Referenced by parseSchematicSymbol(), parseSchText(), and parseSheet().

◆ parseSchPolyLine()

SCH_SHAPE * SCH_SEXPR_PARSER::parseSchPolyLine ( )
private

Definition at line 3321 of file sch_sexpr_parser.cpp.

3322{
3323 T token;
3325 FILL_PARAMS fill;
3326 int layer = LAYER_NOTES;
3327
3328 std::unique_ptr<SCH_SHAPE> polyline = std::make_unique<SCH_SHAPE>( SHAPE_T::POLY, layer );
3329
3330 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3331 {
3332 if( token != T_LEFT )
3333 Expecting( T_LEFT );
3334
3335 token = NextTok();
3336
3337 switch( token )
3338 {
3339 case T_pts:
3340 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3341 {
3342 if( token != T_LEFT )
3343 Expecting( T_LEFT );
3344
3345 token = NextTok();
3346
3347 if( token != T_xy )
3348 Expecting( "xy" );
3349
3350 polyline->AddPoint( parseXY() );
3351
3352 NeedRIGHT();
3353 }
3354 break;
3355
3356 case T_stroke:
3357 parseStroke( stroke );
3358 polyline->SetStroke( stroke );
3359 break;
3360
3361 case T_fill:
3362 parseFill( fill );
3363 polyline->SetFillMode( fill.m_FillType );
3364 polyline->SetFillColor( fill.m_Color );
3365 break;
3366
3367 case T_uuid:
3368 NeedSYMBOL();
3369 const_cast<KIID&>( polyline->m_Uuid ) = parseKIID();
3370 NeedRIGHT();
3371 break;
3372
3373 default:
3374 Expecting( "pts, uuid, stroke, or fill" );
3375 }
3376 }
3377
3378 return polyline.release();
3379}

References DEFAULT, DEFAULT_LINE_WIDTH_MILS, LAYER_NOTES, FILL_PARAMS::m_Color, FILL_PARAMS::m_FillType, EDA_IU_SCALE::MilsToIU(), parseFill(), parseKIID(), parseStroke(), parseXY(), POLY, and schIUScale.

Referenced by ParseSchematic().

◆ parseSchRectangle()

SCH_SHAPE * SCH_SEXPR_PARSER::parseSchRectangle ( )
private

Definition at line 3576 of file sch_sexpr_parser.cpp.

3577{
3578 wxCHECK_MSG( CurTok() == T_rectangle, nullptr,
3579 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a rectangle." ) );
3580
3581 T token;
3583 FILL_PARAMS fill;
3584 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>( SHAPE_T::RECT );
3585
3586 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3587 {
3588 if( token != T_LEFT )
3589 Expecting( T_LEFT );
3590
3591 token = NextTok();
3592
3593 switch( token )
3594 {
3595 case T_start:
3596 rectangle->SetPosition( parseXY() );
3597 NeedRIGHT();
3598 break;
3599
3600 case T_end:
3601 rectangle->SetEnd( parseXY() );
3602 NeedRIGHT();
3603 break;
3604
3605 case T_stroke:
3606 parseStroke( stroke );
3607 rectangle->SetStroke( stroke );
3608 break;
3609
3610 case T_fill:
3611 parseFill( fill );
3612 rectangle->SetFillMode( fill.m_FillType );
3613 rectangle->SetFillColor( fill.m_Color );
3614 break;
3615
3616 case T_uuid:
3617 NeedSYMBOL();
3618 const_cast<KIID&>( rectangle->m_Uuid ) = KIID( FromUTF8() );
3619 NeedRIGHT();
3620 break;
3621
3622 default:
3623 Expecting( "start, end, stroke, fill or uuid" );
3624 }
3625 }
3626
3627 return rectangle.release();
3628}

References DEFAULT, DEFAULT_LINE_WIDTH_MILS, FILL_PARAMS::m_Color, FILL_PARAMS::m_FillType, EDA_IU_SCALE::MilsToIU(), parseFill(), parseStroke(), parseXY(), RECT, and schIUScale.

Referenced by ParseSchematic().

◆ parseSchSheetInstances()

void SCH_SEXPR_PARSER::parseSchSheetInstances ( SCH_SHEET aRootSheet,
SCH_SCREEN aScreen 
)
private

Definition at line 2109 of file sch_sexpr_parser.cpp.

2110{
2111 wxCHECK_RET( CurTok() == T_sheet_instances,
2112 "Cannot parse " + GetTokenString( CurTok() ) + " as an instances token." );
2113 wxCHECK( aScreen, /* void */ );
2114
2115 T token;
2116
2117 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2118 {
2119 if( token != T_LEFT )
2120 Expecting( T_LEFT );
2121
2122 token = NextTok();
2123
2124 switch( token )
2125 {
2126 case T_path:
2127 {
2128 NeedSYMBOL();
2129
2130 SCH_SHEET_INSTANCE instance;
2131
2132 instance.m_Path = KIID_PATH( FromUTF8() );
2133
2134 if( ( !m_appending && aRootSheet->GetScreen() == aScreen ) &&
2135 ( aScreen->GetFileFormatVersionAtLoad() < 20221002 ) )
2136 instance.m_Path.insert( instance.m_Path.begin(), m_rootUuid );
2137
2138 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2139 {
2140 if( token != T_LEFT )
2141 Expecting( T_LEFT );
2142
2143 token = NextTok();
2144
2145 std::vector<wxString> whitespaces = { wxT( "\r" ), wxT( "\n" ), wxT( "\t" ),
2146 wxT( " " ) };
2147
2148 size_t numReplacements = 0;
2149
2150 switch( token )
2151 {
2152 case T_page:
2153 NeedSYMBOL();
2154 instance.m_PageNumber = FromUTF8();
2155
2156 // Empty page numbers are not permitted
2157 if( instance.m_PageNumber.IsEmpty() )
2158 {
2159 // Use hash character instead
2160 instance.m_PageNumber = wxT( "#" );
2161 numReplacements++;
2162 }
2163 else
2164 {
2165 // Whitespaces are not permitted
2166 for( wxString ch : whitespaces )
2167 numReplacements += instance.m_PageNumber.Replace( ch, wxEmptyString );
2168
2169 }
2170
2171 // Set the file as modified so the user can be warned.
2172 if( numReplacements > 0 )
2173 aScreen->SetContentModified();
2174
2175 NeedRIGHT();
2176 break;
2177
2178 default:
2179 Expecting( "path or page" );
2180 }
2181 }
2182
2183 if( ( aScreen->GetFileFormatVersionAtLoad() >= 20221110 )
2184 && ( instance.m_Path.empty() ) )
2185 {
2186 SCH_SHEET_PATH rootSheetPath;
2187
2188 rootSheetPath.push_back( aRootSheet );
2189 rootSheetPath.SetPageNumber( instance.m_PageNumber );
2190 }
2191 else
2192 {
2193 aScreen->m_sheetInstances.emplace_back( instance );
2194 }
2195
2196 break;
2197 }
2198
2199 default:
2200 Expecting( "path" );
2201 }
2202 }
2203}
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
std::vector< SCH_SHEET_INSTANCE > m_sheetInstances
Definition: sch_screen.h:634
int GetFileFormatVersionAtLoad() const
Definition: sch_screen.h:129
Handle access to a stack of flattened SCH_SHEET objects by way of a path for creating a flattened sch...
void SetPageNumber(const wxString &aPageNumber)
Set the sheet instance user definable page number.
void push_back(SCH_SHEET *aSheet)
Forwarded method from std::vector.
A simple container for sheet instance information.

References SCH_SCREEN::GetFileFormatVersionAtLoad(), SCH_SHEET::GetScreen(), m_appending, SCH_SHEET_INSTANCE::m_PageNumber, SCH_SHEET_INSTANCE::m_Path, m_rootUuid, SCH_SCREEN::m_sheetInstances, SCH_SHEET_PATH::push_back(), BASE_SCREEN::SetContentModified(), and SCH_SHEET_PATH::SetPageNumber().

Referenced by ParseSchematic().

◆ parseSchSheetPin()

SCH_SHEET_PIN * SCH_SEXPR_PARSER::parseSchSheetPin ( SCH_SHEET aSheet)
private

Definition at line 2023 of file sch_sexpr_parser.cpp.

2024{
2025 wxCHECK_MSG( aSheet != nullptr, nullptr, "" );
2026 wxCHECK_MSG( CurTok() == T_pin, nullptr,
2027 "Cannot parse " + GetTokenString( CurTok() ) + " as a sheet pin token." );
2028
2029 T token = NextTok();
2030
2031 if( !IsSymbol( token ) )
2032 {
2033 THROW_PARSE_ERROR( _( "Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2034 CurOffset() );
2035 }
2036
2037 wxString name = FromUTF8();
2038
2039 if( name.IsEmpty() )
2040 {
2041 THROW_PARSE_ERROR( _( "Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2042 CurOffset() );
2043 }
2044
2045 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet, VECTOR2I( 0, 0 ), name );
2046
2047 token = NextTok();
2048
2049 switch( token )
2050 {
2051 case T_input: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_INPUT ); break;
2052 case T_output: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT ); break;
2053 case T_bidirectional: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_BIDI ); break;
2054 case T_tri_state: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_TRISTATE ); break;
2055 case T_passive: sheetPin->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED ); break;
2056 default:
2057 Expecting( "input, output, bidirectional, tri_state, or passive" );
2058 }
2059
2060 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2061 {
2062 if( token != T_LEFT )
2063 Expecting( T_LEFT );
2064
2065 token = NextTok();
2066
2067 switch( token )
2068 {
2069 case T_at:
2070 {
2071 sheetPin->SetPosition( parseXY() );
2072
2073 double angle = parseDouble( "sheet pin angle (side)" );
2074
2075 if( angle == 0.0 )
2076 sheetPin->SetSide( SHEET_SIDE::RIGHT );
2077 else if( angle == 90.0 )
2078 sheetPin->SetSide( SHEET_SIDE::TOP );
2079 else if( angle == 180.0 )
2080 sheetPin->SetSide( SHEET_SIDE::LEFT );
2081 else if( angle == 270.0 )
2082 sheetPin->SetSide( SHEET_SIDE::BOTTOM );
2083 else
2084 Expecting( "0, 90, 180, or 270" );
2085
2086 NeedRIGHT();
2087 break;
2088 }
2089
2090 case T_effects:
2091 parseEDA_TEXT( static_cast<EDA_TEXT*>( sheetPin.get() ), true );
2092 break;
2093
2094 case T_uuid:
2095 NeedSYMBOL();
2096 const_cast<KIID&>( sheetPin->m_Uuid ) = parseKIID();
2097 NeedRIGHT();
2098 break;
2099
2100 default:
2101 Expecting( "at, uuid or effects" );
2102 }
2103 }
2104
2105 return sheetPin.release();
2106}
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
@ L_BIDI
Definition: sch_text.h:99
@ L_TRISTATE
Definition: sch_text.h:100
@ L_UNSPECIFIED
Definition: sch_text.h:101
@ L_OUTPUT
Definition: sch_text.h:98
@ L_INPUT
Definition: sch_text.h:97

References _, PNS::angle(), BOTTOM, L_BIDI, L_INPUT, L_OUTPUT, L_TRISTATE, L_UNSPECIFIED, LEFT, name, parseDouble(), parseEDA_TEXT(), parseKIID(), parseXY(), RIGHT, THROW_PARSE_ERROR, and TOP.

Referenced by parseSheet().

◆ parseSchSymbolInstances()

void SCH_SEXPR_PARSER::parseSchSymbolInstances ( SCH_SCREEN aScreen)
private

Definition at line 2206 of file sch_sexpr_parser.cpp.

2207{
2208 wxCHECK_RET( CurTok() == T_symbol_instances,
2209 "Cannot parse " + GetTokenString( CurTok() ) + " as an instances token." );
2210 wxCHECK( aScreen, /* void */ );
2211 wxCHECK( m_rootUuid != NilUuid(), /* void */ );
2212
2213 T token;
2214
2215 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2216 {
2217 if( token != T_LEFT )
2218 Expecting( T_LEFT );
2219
2220 token = NextTok();
2221
2222 switch( token )
2223 {
2224 case T_path:
2225 {
2226 NeedSYMBOL();
2227
2228 SCH_SYMBOL_INSTANCE instance;
2229
2230 instance.m_Path = KIID_PATH( FromUTF8() );
2231
2232 if( !m_appending )
2233 instance.m_Path.insert( instance.m_Path.begin(), m_rootUuid );
2234
2235 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2236 {
2237 if( token != T_LEFT )
2238 Expecting( T_LEFT );
2239
2240 token = NextTok();
2241
2242 switch( token )
2243 {
2244 case T_reference:
2245 NeedSYMBOL();
2246 instance.m_Reference = FromUTF8();
2247 NeedRIGHT();
2248 break;
2249
2250 case T_unit:
2251 instance.m_Unit = parseInt( "symbol unit" );
2252 NeedRIGHT();
2253 break;
2254
2255 case T_value:
2256 NeedSYMBOL();
2257 instance.m_Value = FromUTF8();
2258 NeedRIGHT();
2259 break;
2260
2261 case T_footprint:
2262 NeedSYMBOL();
2263 instance.m_Footprint = FromUTF8();
2264 NeedRIGHT();
2265 break;
2266
2267 default:
2268 Expecting( "path, unit, value or footprint" );
2269 }
2270 }
2271
2272 aScreen->m_symbolInstances.emplace_back( instance );
2273 break;
2274 }
2275
2276 default:
2277 Expecting( "path" );
2278 }
2279 }
2280}
std::vector< SCH_SYMBOL_INSTANCE > m_symbolInstances
The list of symbol instances loaded from the schematic file.
Definition: sch_screen.h:633
KIID & NilUuid()
Definition: kiid.cpp:67

References m_appending, SCH_SYMBOL_INSTANCE::m_Footprint, SCH_SYMBOL_INSTANCE::m_Path, SCH_SYMBOL_INSTANCE::m_Reference, m_rootUuid, SCH_SCREEN::m_symbolInstances, SCH_SYMBOL_INSTANCE::m_Unit, SCH_SYMBOL_INSTANCE::m_Value, NilUuid(), and parseInt().

Referenced by ParseSchematic().

◆ parseSchText()

SCH_TEXT * SCH_SEXPR_PARSER::parseSchText ( )
private

Definition at line 3694 of file sch_sexpr_parser.cpp.

3695{
3696 T token;
3697 std::unique_ptr<SCH_TEXT> text;
3698
3699 switch( CurTok() )
3700 {
3701 case T_text: text = std::make_unique<SCH_TEXT>(); break;
3702 case T_label: text = std::make_unique<SCH_LABEL>(); break;
3703 case T_global_label: text = std::make_unique<SCH_GLOBALLABEL>(); break;
3704 case T_hierarchical_label: text = std::make_unique<SCH_HIERLABEL>(); break;
3705 case T_netclass_flag: text = std::make_unique<SCH_DIRECTIVE_LABEL>(); break;
3706 case T_directive_label: text = std::make_unique<SCH_DIRECTIVE_LABEL>(); break;
3707 default:
3708 wxCHECK_MSG( false, nullptr, "Cannot parse " + GetTokenString( CurTok() ) + " as text." );
3709 }
3710
3711 // We'll reset this if we find a fields_autoplaced token
3712 text->ClearFieldsAutoplaced();
3713
3714 NeedSYMBOL();
3715
3716 text->SetText( FromUTF8() );
3717
3718 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3719 {
3720 if( token != T_LEFT )
3721 Expecting( T_LEFT );
3722
3723 token = NextTok();
3724
3725 switch( token )
3726 {
3727 case T_at:
3728 text->SetPosition( parseXY() );
3729
3730 switch( static_cast<int>( parseDouble( "text angle" ) ) )
3731 {
3732 case 0: text->SetTextSpinStyle( TEXT_SPIN_STYLE::RIGHT ); break;
3733 case 90: text->SetTextSpinStyle( TEXT_SPIN_STYLE::UP ); break;
3734 case 180: text->SetTextSpinStyle( TEXT_SPIN_STYLE::LEFT ); break;
3735 case 270: text->SetTextSpinStyle( TEXT_SPIN_STYLE::BOTTOM ); break;
3736 default:
3737 wxFAIL;
3738 text->SetTextSpinStyle( TEXT_SPIN_STYLE::RIGHT );
3739 break;
3740 }
3741
3742 NeedRIGHT();
3743 break;
3744
3745 case T_shape:
3746 {
3747 if( text->Type() == SCH_TEXT_T || text->Type() == SCH_LABEL_T )
3748 Unexpected( T_shape );
3749
3750 SCH_LABEL_BASE* label = static_cast<SCH_LABEL_BASE*>( text.get() );
3751
3752 token = NextTok();
3753
3754 switch( token )
3755 {
3756 case T_input: label->SetShape( LABEL_FLAG_SHAPE::L_INPUT ); break;
3757 case T_output: label->SetShape( LABEL_FLAG_SHAPE::L_OUTPUT ); break;
3758 case T_bidirectional: label->SetShape( LABEL_FLAG_SHAPE::L_BIDI ); break;
3759 case T_tri_state: label->SetShape( LABEL_FLAG_SHAPE::L_TRISTATE ); break;
3760 case T_passive: label->SetShape( LABEL_FLAG_SHAPE::L_UNSPECIFIED ); break;
3761 case T_dot: label->SetShape( LABEL_FLAG_SHAPE::F_DOT ); break;
3762 case T_round: label->SetShape( LABEL_FLAG_SHAPE::F_ROUND ); break;
3763 case T_diamond: label->SetShape( LABEL_FLAG_SHAPE::F_DIAMOND ); break;
3764 case T_rectangle: label->SetShape( LABEL_FLAG_SHAPE::F_RECTANGLE ); break;
3765 default:
3766 Expecting( "input, output, bidirectional, tri_state, passive, dot, round, diamond"
3767 "or rectangle" );
3768 }
3769
3770 NeedRIGHT();
3771 break;
3772 }
3773
3774 case T_length:
3775 {
3776 if( text->Type() != SCH_DIRECTIVE_LABEL_T )
3777 Unexpected( T_length );
3778
3779 SCH_DIRECTIVE_LABEL* label = static_cast<SCH_DIRECTIVE_LABEL*>( text.get() );
3780
3781 label->SetPinLength( parseInternalUnits( "pin length" ) );
3782 NeedRIGHT();
3783 }
3784 break;
3785
3786 case T_fields_autoplaced:
3787 text->SetFieldsAutoplaced();
3788 NeedRIGHT();
3789 break;
3790
3791 case T_effects:
3792 parseEDA_TEXT( static_cast<EDA_TEXT*>( text.get() ), true );
3793
3794 // Spin style is defined differently for graphical text (#SCH_TEXT) objects.
3795 if( text->Type() == SCH_TEXT_T )
3796 {
3797 if( text->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT
3798 && text->GetTextAngle().IsVertical() )
3799 {
3800 // The vertically aligned text angle is always 90 (labels use 270 for the
3801 // down direction) combined with the text justification flags.
3802 text->SetTextSpinStyle( TEXT_SPIN_STYLE::BOTTOM );
3803 }
3804 else if( text->GetHorizJustify() == GR_TEXT_H_ALIGN_RIGHT
3805 && text->GetTextAngle().IsHorizontal() )
3806 {
3807 // The horizontally aligned text angle is always 0 (labels use 180 for the
3808 // left direction) combined with the text justification flags.
3809 text->SetTextSpinStyle( TEXT_SPIN_STYLE::LEFT );
3810 }
3811 }
3812
3813 break;
3814
3815 case T_iref: // legacy format; current is a T_property (aka SCH_FIELD)
3816 if( text->Type() == SCH_GLOBAL_LABEL_T )
3817 {
3818 SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( text.get() );
3819 SCH_FIELD* field = &label->GetFields()[0];
3820
3821 field->SetTextPos( parseXY() );
3822 NeedRIGHT();
3823
3824 field->SetVisible( true );
3825 }
3826 break;
3827
3828 case T_uuid:
3829 NeedSYMBOL();
3830 const_cast<KIID&>( text->m_Uuid ) = parseKIID();
3831 NeedRIGHT();
3832 break;
3833
3834 case T_property:
3835 {
3836 if( text->Type() == SCH_TEXT_T )
3837 Unexpected( T_property );
3838
3839 SCH_FIELD* field = parseSchField( text.get() );
3840
3841 // If the field is a Intersheetrefs it is not handled like other fields:
3842 // It always exists and is the first in list
3843 if( text->Type() == SCH_GLOBAL_LABEL_T
3844 && ( field->GetInternalName() == wxT( "Intersheet References" ) // old name in V6.0
3845 || field->GetInternalName() == wxT( "Intersheetrefs" ) ) ) // Current name
3846 {
3847 SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( text.get() );
3848 label->GetFields()[0] = *field;
3849 }
3850 else
3851 {
3852 static_cast<SCH_LABEL_BASE*>( text.get() )->GetFields().emplace_back( *field );
3853 }
3854
3855 delete field;
3856 break;
3857 }
3858
3859 default:
3860 Expecting( "at, shape, iref, uuid or effects" );
3861 }
3862 }
3863
3864 SCH_LABEL_BASE* label = dynamic_cast<SCH_LABEL_BASE*>( text.get() );
3865
3866 if( label && label->GetFields().empty() )
3867 label->SetFieldsAutoplaced();
3868
3869 return text.release();
3870}
void SetTextPos(const VECTOR2I &aPoint)
Definition: eda_text.cpp:371
void SetPinLength(int aLength)
Definition: sch_label.h:297
const wxString & GetInternalName()
Get the initial name of the field set at creation (or set by SetName()).
Definition: sch_field.h:123
void SetFieldsAutoplaced()
Definition: sch_item.h:426
void SetShape(LABEL_FLAG_SHAPE aShape) override
Definition: sch_label.h:74
std::vector< SCH_FIELD > & GetFields()
Definition: sch_label.h:90
@ F_DOT
Definition: sch_text.h:104
@ F_ROUND
Definition: sch_text.h:105
@ F_DIAMOND
Definition: sch_text.h:106
@ F_RECTANGLE
Definition: sch_text.h:107
@ SCH_DIRECTIVE_LABEL_T
Definition: typeinfo.h:154
@ SCH_LABEL_T
Definition: typeinfo.h:151
@ SCH_TEXT_T
Definition: typeinfo.h:150
@ SCH_GLOBAL_LABEL_T
Definition: typeinfo.h:152

References TEXT_SPIN_STYLE::BOTTOM, F_DIAMOND, F_DOT, F_RECTANGLE, F_ROUND, SCH_LABEL_BASE::GetFields(), SCH_FIELD::GetInternalName(), GR_TEXT_H_ALIGN_RIGHT, L_BIDI, L_INPUT, L_OUTPUT, L_TRISTATE, L_UNSPECIFIED, TEXT_SPIN_STYLE::LEFT, parseDouble(), parseEDA_TEXT(), parseInternalUnits(), parseKIID(), parseSchField(), parseXY(), TEXT_SPIN_STYLE::RIGHT, SCH_DIRECTIVE_LABEL_T, SCH_GLOBAL_LABEL_T, SCH_LABEL_T, SCH_TEXT_T, SCH_ITEM::SetFieldsAutoplaced(), SCH_DIRECTIVE_LABEL::SetPinLength(), SCH_LABEL_BASE::SetShape(), EDA_TEXT::SetTextPos(), EDA_TEXT::SetVisible(), text, and TEXT_SPIN_STYLE::UP.

Referenced by ParseSchematic().

◆ parseSchTextBox()

SCH_TEXTBOX * SCH_SEXPR_PARSER::parseSchTextBox ( )
private

Definition at line 3873 of file sch_sexpr_parser.cpp.

3874{
3875 wxCHECK_MSG( CurTok() == T_text_box, nullptr,
3876 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a text box." ) );
3877
3878 T token;
3879 VECTOR2I pos;
3880 VECTOR2I end;
3881 VECTOR2I size;
3882 bool foundEnd = false;
3883 bool foundSize = false;
3885 FILL_PARAMS fill;
3886 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
3887
3888 NeedSYMBOL();
3889
3890 textBox->SetText( FromUTF8() );
3891
3892 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3893 {
3894 if( token != T_LEFT )
3895 Expecting( T_LEFT );
3896
3897 token = NextTok();
3898
3899 switch( token )
3900 {
3901 case T_start: // Legacy token during 6.99 development; fails to handle angle
3902 pos = parseXY();
3903 NeedRIGHT();
3904 break;
3905
3906 case T_end: // Legacy token during 6.99 development; fails to handle angle
3907 end = parseXY();
3908 foundEnd = true;
3909 NeedRIGHT();
3910 break;
3911
3912 case T_at:
3913 pos = parseXY();
3914 textBox->SetTextAngle( EDA_ANGLE( parseDouble( "textbox angle" ), DEGREES_T ) );
3915 NeedRIGHT();
3916 break;
3917
3918 case T_size:
3919 size = parseXY();
3920 foundSize = true;
3921 NeedRIGHT();
3922 break;
3923
3924 case T_stroke:
3925 parseStroke( stroke );
3926 textBox->SetStroke( stroke );
3927 break;
3928
3929 case T_fill:
3930 parseFill( fill );
3931 textBox->SetFillMode( fill.m_FillType );
3932 textBox->SetFillColor( fill.m_Color );
3933 break;
3934
3935 case T_effects:
3936 parseEDA_TEXT( static_cast<EDA_TEXT*>( textBox.get() ), false );
3937 break;
3938
3939 case T_uuid:
3940 NeedSYMBOL();
3941 const_cast<KIID&>( textBox->m_Uuid ) = KIID( FromUTF8() );
3942 NeedRIGHT();
3943 break;
3944
3945 default:
3946 Expecting( "at, size, stroke, fill, effects or uuid" );
3947 }
3948 }
3949
3950 textBox->SetPosition( pos );
3951
3952 if( foundEnd )
3953 textBox->SetEnd( end );
3954 else if( foundSize )
3955 textBox->SetEnd( pos + size );
3956 else
3957 Expecting( "size" );
3958
3959 return textBox.release();
3960}

References DEFAULT, DEFAULT_LINE_WIDTH_MILS, DEGREES_T, FILL_PARAMS::m_Color, FILL_PARAMS::m_FillType, EDA_IU_SCALE::MilsToIU(), parseDouble(), parseEDA_TEXT(), parseFill(), parseStroke(), parseXY(), and schIUScale.

Referenced by ParseSchematic().

◆ parseSheet()

SCH_SHEET * SCH_SEXPR_PARSER::parseSheet ( )
private

Definition at line 2983 of file sch_sexpr_parser.cpp.

2984{
2985 wxCHECK_MSG( CurTok() == T_sheet, nullptr,
2986 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a sheet." ) );
2987
2988 T token;
2990 FILL_PARAMS fill;
2991 SCH_FIELD* field;
2992 std::vector<SCH_FIELD> fields;
2993 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
2994 std::set<int> fieldIDsRead;
2995
2996 // We'll reset this if we find a fields_autoplaced token
2997 sheet->ClearFieldsAutoplaced();
2998
2999 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3000 {
3001 if( token != T_LEFT )
3002 Expecting( T_LEFT );
3003
3004 token = NextTok();
3005
3006 switch( token )
3007 {
3008 case T_at:
3009 sheet->SetPosition( parseXY() );
3010 NeedRIGHT();
3011 break;
3012
3013 case T_size:
3014 {
3015 wxSize size;
3016 size.SetWidth( parseInternalUnits( "sheet width" ) );
3017 size.SetHeight( parseInternalUnits( "sheet height" ) );
3018 sheet->SetSize( size );
3019 NeedRIGHT();
3020 break;
3021 }
3022
3023 case T_fields_autoplaced:
3024 sheet->SetFieldsAutoplaced();
3025 NeedRIGHT();
3026 break;
3027
3028 case T_stroke:
3029 parseStroke( stroke );
3030 sheet->SetBorderWidth( stroke.GetWidth() );
3031 sheet->SetBorderColor( stroke.GetColor() );
3032 break;
3033
3034 case T_fill:
3035 parseFill( fill );
3036 sheet->SetBackgroundColor( fill.m_Color );
3037 break;
3038
3039 case T_uuid:
3040 NeedSYMBOL();
3041 const_cast<KIID&>( sheet->m_Uuid ) = parseKIID();
3042 NeedRIGHT();
3043 break;
3044
3045 case T_property:
3046 field = parseSchField( sheet.get() );
3047
3048 if( m_requiredVersion <= 20200310 )
3049 {
3050 // Earlier versions had the wrong ids (and names) saved for sheet fields.
3051 // Fortunately they only saved the sheetname and sheetfilepath (and always
3052 // in that order), so we can hack in a recovery.
3053 if( fields.empty() )
3054 field->SetId( SHEETNAME );
3055 else
3056 field->SetId( SHEETFILENAME );
3057 }
3058
3059 // It would appear the problem persists past 20200310, but this time with the
3060 // earlier ids being re-used for later (user) fields. The easiest (and most
3061 // complete) solution is to disallow multiple instances of the same id (for all
3062 // files since the source of the error *might* in fact be hand-edited files).
3063 //
3064 // While no longer used, -1 is still a valid id for user field. We convert it to
3065 // the first available ID after the mandatory fields
3066
3067 if( field->GetId() < 0 )
3068 field->SetId( SHEET_MANDATORY_FIELDS );
3069
3070 while( !fieldIDsRead.insert( field->GetId() ).second )
3071 field->SetId( field->GetId() + 1 );
3072
3073 fields.emplace_back( *field );
3074 delete field;
3075 break;
3076
3077 case T_pin:
3078 sheet->AddPin( parseSchSheetPin( sheet.get() ) );
3079 break;
3080
3081 case T_instances:
3082 {
3083 std::vector<SCH_SHEET_INSTANCE> instances;
3084
3085 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3086 {
3087 if( token != T_LEFT )
3088 Expecting( T_LEFT );
3089
3090 token = NextTok();
3091
3092 if( token != T_project )
3093 Expecting( "project" );
3094
3095 NeedSYMBOL();
3096
3097 wxString projectName = FromUTF8();
3098
3099 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3100 {
3101 if( token != T_LEFT )
3102 Expecting( T_LEFT );
3103
3104 token = NextTok();
3105
3106 if( token != T_path )
3107 Expecting( "path" );
3108
3109 SCH_SHEET_INSTANCE instance;
3110
3111 instance.m_ProjectName = projectName;
3112
3113 NeedSYMBOL();
3114 instance.m_Path = KIID_PATH( FromUTF8() );
3115
3116 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3117 {
3118 if( token != T_LEFT )
3119 Expecting( T_LEFT );
3120
3121 token = NextTok();
3122
3123 switch( token )
3124 {
3125 case T_page:
3126 {
3127 NeedSYMBOL();
3128 instance.m_PageNumber = FromUTF8();
3129
3130 // Empty page numbers are not permitted
3131 if( instance.m_PageNumber.IsEmpty() )
3132 {
3133 // Use hash character instead
3134 instance.m_PageNumber = wxT( "#" );
3135 }
3136 else
3137 {
3138 // Whitespaces are not permitted
3139 std::vector<wxString> whitespaces = { wxT( "\r" ), wxT( "\n" ),
3140 wxT( "\t" ), wxT( " " ) };
3141
3142 for( wxString ch : whitespaces )
3143 instance.m_PageNumber.Replace( ch, wxEmptyString );
3144 }
3145
3146 NeedRIGHT();
3147 break;
3148 }
3149
3150 default:
3151 Expecting( "page" );
3152 }
3153 }
3154
3155 instances.emplace_back( instance );
3156 }
3157 }
3158
3159 sheet->setInstances( instances );
3160 break;
3161 }
3162
3163 default:
3164 Expecting( "at, size, stroke, background, instances, uuid, property, or pin" );
3165 }
3166 }
3167
3168 sheet->SetFields( fields );
3169
3170 return sheet.release();
3171}
SCH_SHEET_PIN * parseSchSheetPin(SCH_SHEET *aSheet)
@ SHEETNAME
Definition: sch_sheet.h:45
@ SHEETFILENAME
Definition: sch_sheet.h:46

References DEFAULT, DEFAULT_LINE_WIDTH_MILS, STROKE_PARAMS::GetColor(), SCH_FIELD::GetId(), STROKE_PARAMS::GetWidth(), FILL_PARAMS::m_Color, SCH_SHEET_INSTANCE::m_PageNumber, SCH_SHEET_INSTANCE::m_Path, SCH_SHEET_INSTANCE::m_ProjectName, m_requiredVersion, EDA_IU_SCALE::MilsToIU(), parseFill(), parseInternalUnits(), parseKIID(), parseSchField(), parseSchSheetPin(), parseStroke(), parseXY(), schIUScale, SCH_FIELD::SetId(), SHEET_MANDATORY_FIELDS, SHEETFILENAME, and SHEETNAME.

Referenced by ParseSchematic().

◆ parseStroke()

void SCH_SEXPR_PARSER::parseStroke ( STROKE_PARAMS aStroke)
private

Parse stroke definition aStroke.

Parameters
aStrokeDefA reference to the STROKE_PARAMS structure to write to.

Definition at line 475 of file sch_sexpr_parser.cpp.

476{
477 STROKE_PARAMS_PARSER strokeParser( reader, schIUScale.IU_PER_MM );
478 strokeParser.SyncLineReaderWith( *this );
479
480 strokeParser.ParseStroke( aStroke );
481 SyncLineReaderWith( strokeParser );
482}

References EDA_IU_SCALE::IU_PER_MM, STROKE_PARAMS_PARSER::ParseStroke(), and schIUScale.

Referenced by parseArc(), parseBezier(), parseBusEntry(), parseCircle(), parseLine(), parsePolyLine(), parseRectangle(), parseSchArc(), parseSchBezier(), parseSchCircle(), parseSchPolyLine(), parseSchRectangle(), parseSchTextBox(), parseSheet(), and parseTextBox().

◆ ParseSymbol()

LIB_SYMBOL * SCH_SEXPR_PARSER::ParseSymbol ( LIB_SYMBOL_MAP aSymbolLibMap,
int  aFileVersion = SEXPR_SYMBOL_LIB_FILE_VERSION 
)

Definition at line 165 of file sch_sexpr_parser.cpp.

166{
167 wxCHECK_MSG( CurTok() == T_symbol, nullptr,
168 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a symbol." ) );
169
170 T token;
171 long tmp;
172 wxString name;
173 wxString error;
174 wxString unitDisplayName;
175 LIB_ITEM* item;
176 std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
177
178 m_requiredVersion = aFileVersion;
179 symbol->SetUnitCount( 1 );
180
182 m_fieldIDsRead.clear();
183
184 token = NextTok();
185
186 if( !IsSymbol( token ) )
187 {
188 THROW_PARSE_ERROR( _( "Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(),
189 CurOffset() );
190 }
191
192 name = FromUTF8();
193
194 LIB_ID id;
195 int bad_pos = id.Parse( name );
196
197 if( bad_pos >= 0 )
198 {
199 if( static_cast<int>( name.size() ) > bad_pos )
200 {
201 wxString msg = wxString::Format(
202 _( "Symbol %s contains invalid character '%c'" ), name,
203 name[bad_pos] );
204
205 THROW_PARSE_ERROR( msg, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
206 }
207
208
209 THROW_PARSE_ERROR( _( "Invalid library identifier" ), CurSource(), CurLine(),
210 CurLineNumber(), CurOffset() );
211 }
212
213 m_symbolName = id.GetLibItemName().wx_str();
214 symbol->SetName( m_symbolName );
215 symbol->SetLibId( id );
216
217 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
218 {
219 if( token != T_LEFT )
220 Expecting( T_LEFT );
221
222 token = NextTok();
223
224 switch( token )
225 {
226 case T_power:
227 symbol->SetPower();
228 NeedRIGHT();
229 break;
230
231 case T_pin_names:
232 parsePinNames( symbol );
233 break;
234
235 case T_pin_numbers:
236 token = NextTok();
237
238 if( token != T_hide )
239 Expecting( "hide" );
240
241 symbol->SetShowPinNumbers( false );
242 NeedRIGHT();
243 break;
244
245 case T_in_bom:
246 symbol->SetIncludeInBom( parseBool() );
247 NeedRIGHT();
248 break;
249
250 case T_on_board:
251 symbol->SetIncludeOnBoard( parseBool() );
252 NeedRIGHT();
253 break;
254
255 case T_property:
256 parseProperty( symbol );
257 break;
258
259 case T_extends:
260 {
261 token = NextTok();
262
263 if( !IsSymbol( token ) )
264 {
265 THROW_PARSE_ERROR( _( "Invalid parent symbol name" ), CurSource(), CurLine(),
266 CurLineNumber(), CurOffset() );
267 }
268
269 name = FromUTF8();
270 auto it = aSymbolLibMap.find( name );
271
272 if( it == aSymbolLibMap.end() )
273 {
274 error.Printf( _( "No parent for extended symbol %s" ), name.c_str() );
275 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
276 }
277
278 symbol->SetParent( it->second );
279 NeedRIGHT();
280 break;
281 }
282
283 case T_symbol:
284 {
285 token = NextTok();
286
287 if( !IsSymbol( token ) )
288 {
289 THROW_PARSE_ERROR( _( "Invalid symbol unit name" ), CurSource(), CurLine(),
290 CurLineNumber(), CurOffset() );
291 }
292
293 name = FromUTF8();
294
295 if( !name.StartsWith( m_symbolName ) )
296 {
297 error.Printf( _( "Invalid symbol unit name prefix %s" ), name.c_str() );
298 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
299 }
300
301 name = name.Right( name.Length() - m_symbolName.Length() - 1 );
302
303 wxStringTokenizer tokenizer( name, "_" );
304
305 if( tokenizer.CountTokens() != 2 )
306 {
307 error.Printf( _( "Invalid symbol unit name suffix %s" ), name.c_str() );
308 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
309 }
310
311 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
312 {
313 error.Printf( _( "Invalid symbol unit number %s" ), name.c_str() );
314 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
315 }
316
317 m_unit = static_cast<int>( tmp );
318
319 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
320 {
321 error.Printf( _( "Invalid symbol convert number %s" ), name.c_str() );
322 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
323 }
324
325 m_convert = static_cast<int>( tmp );
326
327 if( m_convert > 1 )
328 symbol->SetConversion( true, false );
329
330 if( m_unit > symbol->GetUnitCount() )
331 symbol->SetUnitCount( m_unit, false );
332
333 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
334 {
335 if( token != T_LEFT )
336 Expecting( T_LEFT );
337
338 token = NextTok();
339
340 switch( token )
341 {
342 case T_unit_name:
343 token = NextTok();
344
345 if( IsSymbol( token ) )
346 {
347 unitDisplayName = FromUTF8();
348 symbol->SetUnitDisplayName( m_unit, unitDisplayName );
349 }
350 NeedRIGHT();
351 break;
352
353 case T_arc:
354 case T_bezier:
355 case T_circle:
356 case T_pin:
357 case T_polyline:
358 case T_rectangle:
359 case T_text:
360 case T_text_box:
361 item = ParseDrawItem();
362
363 wxCHECK_MSG( item, nullptr, "Invalid draw item pointer." );
364
365 item->SetParent( symbol.get() );
366 symbol->AddDrawItem( item, false );
367 break;
368
369 default:
370 Expecting( "arc, bezier, circle, pin, polyline, rectangle, or text" );
371 };
372 }
373
374 m_unit = 1;
375 m_convert = 1;
376 break;
377 }
378
379 case T_arc:
380 case T_bezier:
381 case T_circle:
382 case T_pin:
383 case T_polyline:
384 case T_rectangle:
385 case T_text:
386 case T_text_box:
387 item = ParseDrawItem();
388
389 wxCHECK_MSG( item, nullptr, "Invalid draw item pointer." );
390
391 item->SetParent( symbol.get() );
392 symbol->AddDrawItem( item, false );
393 break;
394
395 default:
396 Expecting( "pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
397 "rectangle, or text" );
398 }
399 }
400
401 symbol->GetDrawItems().sort();
402 m_symbolName.clear();
403
404 return symbol.release();
405}
The base class for drawable items used by schematic library symbols.
Definition: lib_item.h:61
LIB_ITEM * ParseDrawItem()
LIB_FIELD * parseProperty(std::unique_ptr< LIB_SYMBOL > &aSymbol)
wxString m_symbolName
The current symbol name.
void parsePinNames(std::unique_ptr< LIB_SYMBOL > &aSymbol)

References _, Format(), m_convert, m_fieldId, m_fieldIDsRead, m_requiredVersion, m_symbolName, m_unit, MANDATORY_FIELDS, name, LIB_ID::Parse(), parseBool(), ParseDrawItem(), parsePinNames(), parseProperty(), EDA_ITEM::SetParent(), and THROW_PARSE_ERROR.

Referenced by ParseLib(), SCH_SEXPR_PLUGIN::ParseLibSymbol(), and ParseSchematic().

◆ parseText()

LIB_TEXT * SCH_SEXPR_PARSER::parseText ( )
private

Definition at line 1610 of file sch_sexpr_parser.cpp.

1611{
1612 wxCHECK_MSG( CurTok() == T_text, nullptr,
1613 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a text token." ) );
1614
1615 T token;
1616 std::unique_ptr<LIB_TEXT> text = std::make_unique<LIB_TEXT>( nullptr );
1617
1618 text->SetUnit( m_unit );
1619 text->SetConvert( m_convert );
1620 token = NextTok();
1621
1622 if( token == T_private )
1623 {
1624 text->SetPrivate( true );
1625 token = NextTok();
1626 }
1627
1628 if( !IsSymbol( token ) )
1629 {
1630 THROW_PARSE_ERROR( _( "Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1631 CurOffset() );
1632 }
1633
1634 text->SetText( FromUTF8() );
1635
1636 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1637 {
1638 if( token != T_LEFT )
1639 Expecting( T_LEFT );
1640
1641 token = NextTok();
1642
1643 switch( token )
1644 {
1645 case T_at:
1646 text->SetPosition( parseXY() );
1647 // Yes, LIB_TEXT is really decidegrees even though all the others are degrees. :(
1648 text->SetTextAngle( EDA_ANGLE( parseDouble( "text angle" ), TENTHS_OF_A_DEGREE_T ) );
1649 NeedRIGHT();
1650 break;
1651
1652 case T_effects:
1653 parseEDA_TEXT( static_cast<EDA_TEXT*>( text.get() ), true );
1654 break;
1655
1656 default:
1657 Expecting( "at or effects" );
1658 }
1659 }
1660
1661 return text.release();
1662}
@ TENTHS_OF_A_DEGREE_T
Definition: eda_angle.h:30

References _, m_convert, m_unit, parseDouble(), parseEDA_TEXT(), parseXY(), TENTHS_OF_A_DEGREE_T, text, and THROW_PARSE_ERROR.

Referenced by ParseDrawItem().

◆ parseTextBox()

LIB_TEXTBOX * SCH_SEXPR_PARSER::parseTextBox ( )
private

Definition at line 1665 of file sch_sexpr_parser.cpp.

1666{
1667 wxCHECK_MSG( CurTok() == T_text_box, nullptr,
1668 wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a text box." ) );
1669
1670 T token;
1671 VECTOR2I pos;
1672 VECTOR2I end;
1673 VECTOR2I size;
1674 bool foundEnd = false;
1675 bool foundSize = false;
1677 FILL_PARAMS fill;
1678 std::unique_ptr<LIB_TEXTBOX> textBox = std::make_unique<LIB_TEXTBOX>( nullptr );
1679
1680 token = NextTok();
1681
1682 if( token == T_private )
1683 {
1684 textBox->SetPrivate( true );
1685 token = NextTok();
1686 }
1687
1688 if( !IsSymbol( token ) )
1689 {
1690 THROW_PARSE_ERROR( _( "Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1691 CurOffset() );
1692 }
1693
1694 textBox->SetText( FromUTF8() );
1695
1696 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1697 {
1698 if( token != T_LEFT )
1699 Expecting( T_LEFT );
1700
1701 token = NextTok();
1702
1703 switch( token )
1704 {
1705 case T_start: // Legacy token during 6.99 development; fails to handle angle
1706 pos = parseXY();
1707 NeedRIGHT();
1708 break;
1709
1710 case T_end: // Legacy token during 6.99 development; fails to handle angle
1711 end = parseXY();
1712 foundEnd = true;
1713 NeedRIGHT();
1714 break;
1715
1716 case T_at:
1717 pos = parseXY();
1718 textBox->SetTextAngle( EDA_ANGLE( parseDouble( "textbox angle" ), DEGREES_T ) );
1719 NeedRIGHT();
1720 break;
1721
1722 case T_size:
1723 size = parseXY();
1724 foundSize = true;
1725 NeedRIGHT();
1726 break;
1727
1728 case T_stroke:
1729 parseStroke( stroke );
1730 textBox->SetStroke( stroke );
1731 break;
1732
1733 case T_fill:
1734 parseFill( fill );
1735 textBox->SetFillMode( fill.m_FillType );
1736 textBox->SetFillColor( fill.m_Color );
1737 break;
1738
1739 case T_effects:
1740 parseEDA_TEXT( static_cast<EDA_TEXT*>( textBox.get() ), false );
1741 break;
1742
1743 default:
1744 Expecting( "at, size, stroke, fill or effects" );
1745 }
1746 }
1747
1748 textBox->SetPosition( pos );
1749
1750 if( foundEnd )
1751 textBox->SetEnd( end );
1752 else if( foundSize )
1753 textBox->SetEnd( pos + size );
1754 else
1755 Expecting( "size" );
1756
1757 return textBox.release();
1758}

References _, DEFAULT, DEFAULT_LINE_WIDTH_MILS, DEGREES_T, FILL_PARAMS::m_Color, FILL_PARAMS::m_FillType, EDA_IU_SCALE::MilsToIU(), parseDouble(), parseEDA_TEXT(), parseFill(), parseStroke(), parseXY(), schIUScale, and THROW_PARSE_ERROR.

Referenced by ParseDrawItem().

◆ parseTITLE_BLOCK()

void SCH_SEXPR_PARSER::parseTITLE_BLOCK ( TITLE_BLOCK aTitleBlock)
private

Definition at line 1813 of file sch_sexpr_parser.cpp.

1814{
1815 wxCHECK_RET( CurTok() == T_title_block,
1816 "Cannot parse " + GetTokenString( CurTok() ) + " as a TITLE_BLOCK." );
1817
1818 T token;
1819
1820 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1821 {
1822 if( token != T_LEFT )
1823 Expecting( T_LEFT );
1824
1825 token = NextTok();
1826
1827 switch( token )
1828 {
1829 case T_title:
1830 NextTok();
1831 aTitleBlock.SetTitle( FromUTF8() );
1832 break;
1833
1834 case T_date:
1835 NextTok();
1836 aTitleBlock.SetDate( FromUTF8() );
1837 break;
1838
1839 case T_rev:
1840 NextTok();
1841 aTitleBlock.SetRevision( FromUTF8() );
1842 break;
1843
1844 case T_company:
1845 NextTok();
1846 aTitleBlock.SetCompany( FromUTF8() );
1847 break;
1848
1849 case T_comment:
1850 {
1851 int commentNumber = parseInt( "comment" );
1852
1853 switch( commentNumber )
1854 {
1855 case 1:
1856 NextTok();
1857 aTitleBlock.SetComment( 0, FromUTF8() );
1858 break;
1859
1860 case 2:
1861 NextTok();
1862 aTitleBlock.SetComment( 1, FromUTF8() );
1863 break;
1864
1865 case 3:
1866 NextTok();
1867 aTitleBlock.SetComment( 2, FromUTF8() );
1868 break;
1869
1870 case 4:
1871 NextTok();
1872 aTitleBlock.SetComment( 3, FromUTF8() );
1873 break;
1874
1875 case 5:
1876 NextTok();
1877 aTitleBlock.SetComment( 4, FromUTF8() );
1878 break;
1879
1880 case 6:
1881 NextTok();
1882 aTitleBlock.SetComment( 5, FromUTF8() );
1883 break;
1884
1885 case 7:
1886 NextTok();
1887 aTitleBlock.SetComment( 6, FromUTF8() );
1888 break;
1889
1890 case 8:
1891 NextTok();
1892 aTitleBlock.SetComment( 7, FromUTF8() );
1893 break;
1894
1895 case 9:
1896 NextTok();
1897 aTitleBlock.SetComment( 8, FromUTF8() );
1898 break;
1899
1900 default:
1901 THROW_PARSE_ERROR( _( "Invalid title block comment number" ), CurSource(),
1902 CurLine(), CurLineNumber(), CurOffset() );
1903 }
1904
1905 break;
1906 }
1907
1908 default:
1909 Expecting( "title, date, rev, company, or comment" );
1910 }
1911
1912 NeedRIGHT();
1913 }
1914}
void SetRevision(const wxString &aRevision)
Definition: title_block.h:81
void SetComment(int aIdx, const wxString &aComment)
Definition: title_block.h:101
void SetTitle(const wxString &aTitle)
Definition: title_block.h:58
void SetCompany(const wxString &aCompany)
Definition: title_block.h:91
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
Definition: title_block.h:71

References _, parseInt(), TITLE_BLOCK::SetComment(), TITLE_BLOCK::SetCompany(), TITLE_BLOCK::SetDate(), TITLE_BLOCK::SetRevision(), TITLE_BLOCK::SetTitle(), and THROW_PARSE_ERROR.

Referenced by ParseSchematic().

◆ parseXY()

Member Data Documentation

◆ m_appending

bool SCH_SEXPR_PARSER::m_appending
private

Appending load status.

Definition at line 209 of file sch_sexpr_parser.h.

Referenced by parseSchSheetInstances(), and parseSchSymbolInstances().

◆ m_convert

int SCH_SEXPR_PARSER::m_convert
private

The current body style being parsed.

Definition at line 207 of file sch_sexpr_parser.h.

Referenced by parseArc(), parseBezier(), parseCircle(), ParseLib(), parsePin(), parsePolyLine(), parseRectangle(), ParseSymbol(), and parseText().

◆ m_fieldId

int SCH_SEXPR_PARSER::m_fieldId
private

The current field ID.

Definition at line 205 of file sch_sexpr_parser.h.

Referenced by parseSchematicSymbol(), and ParseSymbol().

◆ m_fieldIDsRead

std::set<int> SCH_SEXPR_PARSER::m_fieldIDsRead
private

Field IDs that have been read so far for the current symbol.

Definition at line 212 of file sch_sexpr_parser.h.

Referenced by parseProperty(), parseSchematicSymbol(), and ParseSymbol().

◆ m_lastProgressLine

unsigned SCH_SEXPR_PARSER::m_lastProgressLine
private

Definition at line 218 of file sch_sexpr_parser.h.

Referenced by checkpoint().

◆ m_lineCount

unsigned SCH_SEXPR_PARSER::m_lineCount
private

Definition at line 219 of file sch_sexpr_parser.h.

Referenced by checkpoint().

◆ m_lineReader

const LINE_READER* SCH_SEXPR_PARSER::m_lineReader
private

Definition at line 217 of file sch_sexpr_parser.h.

Referenced by checkpoint().

◆ m_progressReporter

PROGRESS_REPORTER* SCH_SEXPR_PARSER::m_progressReporter
private

Definition at line 216 of file sch_sexpr_parser.h.

Referenced by checkpoint().

◆ m_requiredVersion

int SCH_SEXPR_PARSER::m_requiredVersion
private

◆ m_rootSheet

SCH_SHEET* SCH_SEXPR_PARSER::m_rootSheet
private

The rootsheet for full project loads or null for importing a schematic.

Definition at line 224 of file sch_sexpr_parser.h.

Referenced by ParseSchematic().

◆ m_rootUuid

KIID SCH_SEXPR_PARSER::m_rootUuid
private

◆ m_symbolName

wxString SCH_SEXPR_PARSER::m_symbolName
private

The current symbol name.

Definition at line 208 of file sch_sexpr_parser.h.

Referenced by ParseSymbol().

◆ m_unit

int SCH_SEXPR_PARSER::m_unit
private

The current unit being parsed.

Definition at line 206 of file sch_sexpr_parser.h.

Referenced by parseArc(), parseBezier(), parseCircle(), ParseLib(), parsePin(), parsePolyLine(), parseRectangle(), ParseSymbol(), and parseText().

◆ m_uuids

std::set<KIID> SCH_SEXPR_PARSER::m_uuids
private

Definition at line 214 of file sch_sexpr_parser.h.

Referenced by parseKIID().


The documentation for this class was generated from the following files: