31#include <fmt/format.h>
35#include <wx/mstream.h>
36#include <wx/tokenzr.h>
73using namespace TSCHEMATIC_T;
78 unsigned aLineCount,
SCH_SHEET* aRootSheet,
80 SCHEMATIC_LEXER( aLineReader ),
99 unsigned progressDelta = std::max( 50u,
m_lineCount / 10 );
118 KIID id( FromUTF8() );
135 else if( token == T_no )
138 Expecting(
"yes or no" );
149 bool ret = aDefaultValue;
151 if( PrevTok() == T_LEFT )
156 if(
static_cast<int>( token ) ==
DSN_RIGHT )
157 return aDefaultValue;
161 else if( token == T_no )
164 Expecting(
"yes or no" );
171 return aDefaultValue;
189 bool versionChecked =
false;
200 versionChecked =
true;
203 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
205 if( token != T_LEFT )
231 case T_generator_version:
254 aSymbolLibMap[symbol->
GetName()] = symbol;
259 wxString warning = wxString::Format(
260 _(
"Error parsing symbol at line %d: %s\nSkipping symbol and continuing." ),
261 CurLineNumber(), e.
What() );
273 Expecting(
"symbol, generator, or generator_version" );
287 if( CurTok() == T_LEFT )
291 if( CurTok() == T_symbol )
296 const std::vector<wxString>* embeddedFonts =
303 textItem->ResolveFont( embeddedFonts );
309 wxString msg = wxString::Format(
_(
"Cannot parse %s as a symbol" ),
310 GetTokenString( CurTok() ) );
321 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
322 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
329 std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
331 symbol->SetUnitCount( 1,
true );
335 if( !IsSymbol( token ) )
336 THROW_PARSE_ERROR(
_(
"Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
343 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
350 if(
static_cast<int>(
name.size() ) > bad_pos )
352 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
361 CurLineNumber(), CurOffset() );
366 symbol->SetLibId(
id );
368 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
370 if( token != T_LEFT )
378 symbol->SetGlobalPower();
381 if( token == T_RIGHT )
384 if( token == T_local )
385 symbol->SetLocalPower();
386 else if( token != T_global )
387 Expecting(
"global or local" );
404 case T_exclude_from_sim:
405 symbol->SetExcludedFromSim(
parseBool() );
410 symbol->SetExcludedFromBOM( !
parseBool() );
415 symbol->SetExcludedFromBoard( !
parseBool() );
420 symbol->SetExcludedFromPosFiles( !
parseBool() );
424 case T_duplicate_pin_numbers_are_jumpers:
425 symbol->SetDuplicatePinNumbersAreJumpers(
parseBool() );
429 case T_jumper_pin_groups:
431 std::vector<std::set<wxString>>& groups = symbol->JumperPinGroups();
432 std::set<wxString>* currentGroup =
nullptr;
434 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
436 switch(
static_cast<int>( token ) )
439 currentGroup = &groups.emplace_back();
443 currentGroup->insert( FromUTF8() );
447 currentGroup =
nullptr;
451 Expecting(
"list of pin names" );
466 if( !IsSymbol( token ) )
469 CurLineNumber(), CurOffset() );
477 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
479 symbol->SetParentName(
name );
488 if( !IsSymbol( token ) )
491 CurLineNumber(), CurOffset() );
499 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
503 error.Printf(
_(
"Invalid symbol unit name prefix %s" ),
name.c_str() );
504 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
509 wxStringTokenizer tokenizer(
name,
"_" );
511 if( tokenizer.CountTokens() != 2 )
513 error.Printf(
_(
"Invalid symbol unit name suffix %s" ),
name.c_str() );
514 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
517 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
519 error.Printf(
_(
"Invalid symbol unit number %s" ),
name.c_str() );
520 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
523 m_unit =
static_cast<int>( tmp );
525 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
527 error.Printf(
_(
"Invalid symbol body style number %s" ),
name.c_str() );
528 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
534 symbol->SetBodyStyleCount(
m_bodyStyle,
false,
false );
536 if(
m_unit > symbol->GetUnitCount() )
537 symbol->SetUnitCount(
m_unit,
false );
539 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
541 if( token != T_LEFT )
551 if( IsSymbol( token ) )
552 symbol->GetUnitDisplayNames()[
m_unit] = FromUTF8();
567 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
570 symbol->AddDrawItem( item,
false );
574 Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
593 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
596 symbol->AddDrawItem( item,
false );
599 case T_embedded_fonts:
601 symbol->SetAreFontsEmbedded(
parseBool() );
606 case T_embedded_files:
609 embeddedFilesParser.SyncLineReaderWith( *
this );
613 embeddedFilesParser.
ParseEmbedded( symbol->GetEmbeddedFiles() );
620 SyncLineReaderWith( embeddedFilesParser );
625 Expecting(
"pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
626 "rectangle, or text" );
630 symbol->GetDrawItems().sort();
633 const std::vector<wxString>* embeddedFonts = symbol->GetEmbeddedFiles()->UpdateFontFiles();
635 symbol->RunOnChildren(
639 textItem->ResolveFont( embeddedFonts );
646 symbol->SetHasDeMorganBodyStyles( symbol->HasLegacyAlternateBodyStyle() );
648 return symbol.release();
664 default: Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
678 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
680 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
688 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
690 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
697 strokeParser.SyncLineReaderWith( *
this );
700 SyncLineReaderWith( strokeParser );
706 wxCHECK_RET( CurTok() == T_fill,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a fill." );
713 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
715 if( token != T_LEFT )
735 default: Expecting(
"none, outline, hatch, reverse_hatch, "
736 "cross_hatch, color or background" );
750 color.
a = std::clamp(
parseDouble(
"alpha" ), 0.0, 1.0 );
757 Expecting(
"type or color" );
764 bool aEnforceMinTextSize )
766 wxCHECK_RET( aText && ( CurTok() == T_effects || CurTok() == T_href ),
767 "Cannot parse " + GetTokenString( CurTok() ) +
" as an EDA_TEXT." );
784 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
786 if( token == T_LEFT )
792 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
794 if( token == T_LEFT )
834 color.
a = std::clamp(
parseDouble(
"alpha" ), 0.0, 1.0 );
845 Expecting(
"face, size, thickness, line_spacing, bold, or italic" );
852 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
861 case T_mirror:
break;
862 default: Expecting(
"left, right, top, bottom, or mirror" );
871 wxString hyperlink = FromUTF8();
876 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
895 Expecting(
"font, justify, hide or href" );
903 if( CurTok() != aHeaderType )
906 GetTokenString( CurTok() ) ),
907 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
914 if( tok == T_version )
928 wxCHECK_RET( CurTok() == T_body_styles,
929 "Cannot parse " + GetTokenString( CurTok() ) +
" as a body_styles token." );
931 std::vector<wxString> names;
933 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
935 if( token == T_demorgan )
937 aSymbol->SetHasDeMorganBodyStyles(
true );
940 else if( !IsSymbol( token ) )
942 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
946 names.push_back( FromUTF8() );
950 aSymbol->SetBodyStyleNames( names );
956 wxCHECK_RET( CurTok() == T_pin_names,
957 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_name token." );
967 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
970 if( token == T_hide )
972 aSymbol->SetShowPinNames(
false );
976 if( token != T_LEFT )
991 aSymbol->SetShowPinNames( !
parseBool() );
996 Expecting(
"offset or hide" );
1004 wxCHECK_RET( CurTok() == T_pin_numbers,
1005 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_number token." );
1014 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
1017 if( token == T_hide )
1019 aSymbol->SetShowPinNumbers(
false );
1023 if( token != T_LEFT )
1025 Expecting( T_LEFT );
1033 aSymbol->SetShowPinNumbers( !
parseBool() );
1038 Expecting(
"hide" );
1047 wxCHECK_MSG( CurTok() == T_property,
nullptr,
1048 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a property." ) );
1049 wxCHECK( aSymbol,
nullptr );
1054 bool isPrivate =
false;
1055 bool isVisible =
true;
1057 T token = NextTok();
1059 if( token == T_private )
1065 if( !IsSymbol( token ) )
1067 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
1073 if(
name.IsEmpty() )
1075 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
1089 auto field = std::make_unique<SCH_FIELD>( aSymbol.get(), fieldId,
name );
1090 field->SetPrivate( isPrivate );
1091 field->SetVisible( isVisible );
1095 if( !IsSymbol( token ) )
1097 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
1104 value = wxEmptyString;
1108 field->SetText( value );
1110 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1112 if( token != T_LEFT )
1113 Expecting( T_LEFT );
1125 field->SetPosition(
parseXY(
true ) );
1143 field->SetNameShown( show );
1147 case T_do_not_autoplace:
1150 field->SetCanAutoplace( !doNotAutoplace );
1155 Expecting(
"id, at, hide, show_name, do_not_autoplace, or effects" );
1161 if( field->IsMandatory() )
1163 existingField = aSymbol->GetField( field->GetId() );
1165 *existingField = *field;
1166 return existingField;
1168 else if(
name ==
"ki_keywords" )
1171 aSymbol->SetKeyWords( value );
1175 else if(
name ==
"ki_description" )
1177 aSymbol->SetDescription( value );
1180 else if(
name ==
"ki_fp_filters" )
1183 wxArrayString filters;
1184 wxStringTokenizer tokenizer( value,
" \t\r\n", wxTOKEN_STRTOK );
1186 while( tokenizer.HasMoreTokens() )
1188 wxString curr_token =
UnescapeString( tokenizer.GetNextToken() );
1189 filters.Add( curr_token );
1192 aSymbol->SetFPFilters( filters );
1195 else if(
name ==
"ki_locked" )
1199 aSymbol->LockUnits(
true );
1205 existingField = aSymbol->GetField( field->GetCanonicalName() );
1213 wxString base_name = field->GetCanonicalName();
1216 for(
int ii = 1; ii < 10 && existingField; ii++ )
1218 wxString newname = base_name;
1219 newname <<
'_' << ii;
1221 existingField = aSymbol->GetField( newname );
1223 if( !existingField )
1224 field->SetName( newname );
1228 if( !existingField )
1230 aSymbol->AddDrawItem( field.get(),
false );
1231 return field.release();
1244 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
1245 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
1251 bool hasMidPoint =
false;
1259 bool hasAngles =
false;
1268 if( token == T_private )
1270 arc->SetPrivate(
true );
1274 for( ; token != T_RIGHT; token = NextTok() )
1276 if( token != T_LEFT )
1277 Expecting( T_LEFT );
1300 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1302 if( token != T_LEFT )
1303 Expecting( T_LEFT );
1331 Expecting(
"at, length, or angles" );
1339 arc->SetStroke( stroke );
1345 arc->SetFillColor( fill.
m_Color );
1349 Expecting(
"start, mid, end, radius, stroke, or fill" );
1355 arc->SetArcGeometry( startPoint, midPoint, endPoint );
1366 EDA_ANGLE arc_start, arc_end, arc_angle;
1367 arc->CalcArcAngles( arc_start, arc_end );
1368 arc_angle = arc_end - arc_start;
1373 arc->SetStart( endPoint );
1374 arc->SetEnd( startPoint );
1377 arc->SetCenter( new_center );
1383 arc->SetCenter( new_center );
1387 else if( hasAngles )
1389 arc->SetCenter(
center );
1395 arc->SetStart( endPoint );
1396 arc->SetEnd( startPoint );
1400 EDA_ANGLE arc_start, arc_end, arc_angle;
1401 arc->CalcArcAngles( arc_start, arc_end );
1402 arc_angle = arc_end - arc_start;
1408 arc->SetStart( startPoint );
1409 arc->SetEnd( endPoint );
1417 arc->SetStart( startPoint );
1418 arc->SetEnd( endPoint );
1422 arc->SetCenter( new_center );
1428 wxFAIL_MSG(
"Setting arc without either midpoint or angles not implemented." );
1431 return arc.release();
1437 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
1438 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
1446 bezier->SetUnit(
m_unit );
1451 if( token == T_private )
1453 bezier->SetPrivate(
true );
1457 for( ; token != T_RIGHT; token = NextTok() )
1459 if( token != T_LEFT )
1460 Expecting( T_LEFT );
1470 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1472 if( token != T_LEFT )
1473 Expecting( T_LEFT );
1482 case 0: bezier->SetStart(
parseXY(
true ) );
break;
1483 case 1: bezier->SetBezierC1(
parseXY(
true ) );
break;
1484 case 2: bezier->SetBezierC2(
parseXY(
true ) );
break;
1485 case 3: bezier->SetEnd(
parseXY(
true ) );
break;
1486 default: Unexpected(
"control point" );
break;
1496 bezier->SetStroke( stroke );
1502 bezier->SetFillColor( fill.
m_Color );
1506 Expecting(
"pts, stroke, or fill" );
1510 bezier->RebuildBezierToSegmentsPointsList(
m_maxError );
1512 return bezier.release();
1518 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
1519 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
1534 if( token == T_private )
1536 circle->SetPrivate(
true );
1540 for( ; token != T_RIGHT; token = NextTok() )
1542 if( token != T_LEFT )
1543 Expecting( T_LEFT );
1561 circle->SetStroke( stroke );
1571 Expecting(
"center, radius, stroke, or fill" );
1604 Expecting(
"input, output, bidirectional, tri_state, passive, unspecified, "
1605 "power_in, power_out, open_collector, open_emitter, free or "
1627 Expecting(
"line, inverted, clock, inverted_clock, input_low, clock_low, "
1628 "output_low, edge_clock_high, non_logic" );
1633 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
1634 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a pin token." ) );
1637 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>(
nullptr );
1644 pin->SetType( parseType( token ) );
1648 pin->SetShape( parseShape( token ) );
1650 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1653 if( token == T_hide )
1655 pin->SetVisible(
false );
1659 if( token != T_LEFT )
1660 Expecting( T_LEFT );
1669 switch(
parseInt(
"pin orientation" ) )
1675 default: Expecting(
"0, 90, 180, or 270" );
1694 if( !IsSymbol( token ) )
1701 pin->SetName( wxEmptyString );
1705 pin->SetName( FromUTF8() );
1709 if( token != T_RIGHT )
1713 if( token == T_effects )
1720 pin->SetNameTextSize(
text.GetTextHeight() );
1725 Expecting(
"effects" );
1734 if( !IsSymbol( token ) )
1737 CurLineNumber(), CurOffset() );
1741 pin->SetNumber( wxEmptyString );
1745 pin->SetNumber( FromUTF8() );
1749 if( token != T_RIGHT )
1753 if( token == T_effects )
1760 pin->SetNumberTextSize(
text.GetTextHeight() );
1765 Expecting(
"effects" );
1777 if( !IsSymbol( token ) )
1780 CurLineNumber(), CurOffset() );
1786 alt.
m_Type = parseType( token );
1789 alt.
m_Shape = parseShape( token );
1791 pin->GetAlternates()[ alt.
m_Name ] = alt;
1798 Expecting(
"at, name, number, hide, length, or alternate" );
1802 return pin.release();
1808 wxCHECK_MSG( CurTok() == T_polyline,
nullptr,
1809 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a poly." ) );
1821 if( token == T_private )
1823 poly->SetPrivate(
true );
1827 for( ; token != T_RIGHT; token = NextTok() )
1829 if( token != T_LEFT )
1830 Expecting( T_LEFT );
1837 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1839 if( token != T_LEFT )
1840 Expecting( T_LEFT );
1847 poly->AddPoint(
parseXY(
true ) );
1856 poly->SetStroke( stroke );
1862 poly->SetFillColor( fill.
m_Color );
1866 Expecting(
"pts, stroke, or fill" );
1870 return poly.release();
1876 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
1877 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
1884 rectangle->SetUnit(
m_unit );
1889 if( token == T_private )
1891 rectangle->SetPrivate(
true );
1895 for( ; token != T_RIGHT; token = NextTok() )
1897 if( token != T_LEFT )
1898 Expecting( T_LEFT );
1905 rectangle->SetPosition(
parseXY(
true ) );
1910 rectangle->SetEnd(
parseXY(
true ) );
1921 rectangle->SetStroke( stroke );
1927 rectangle->SetFillColor( fill.
m_Color );
1931 Expecting(
"start, end, stroke, or fill" );
1935 return rectangle.release();
1941 wxCHECK_MSG( CurTok() == T_text,
nullptr,
1942 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text token." ) );
1945 std::unique_ptr<SCH_TEXT>
text = std::make_unique<SCH_TEXT>();
1952 if( token == T_private )
1954 text->SetPrivate(
true );
1958 if( !IsSymbol( token ) )
1960 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1964 text->SetText( FromUTF8() );
1966 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1968 if( token != T_LEFT )
1969 Expecting( T_LEFT );
1987 Expecting(
"at or effects" );
1992 if( !
text->IsVisible() )
1995 return text.release();
2001 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
2002 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
2014 bool foundEnd =
false;
2015 bool foundSize =
false;
2016 bool foundMargins =
false;
2018 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>(
LAYER_DEVICE );
2020 textBox->SetUnit(
m_unit );
2024 if( token == T_private )
2026 textBox->SetPrivate(
true );
2030 if( !IsSymbol( token ) )
2032 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
2036 textBox->SetText( FromUTF8() );
2038 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2040 if( token != T_LEFT )
2041 Expecting( T_LEFT );
2072 textBox->SetStroke( stroke );
2078 textBox->SetFillColor( fill.
m_Color );
2083 textBox->SetMarginLeft(
left );
2084 textBox->SetMarginTop(
top );
2085 textBox->SetMarginRight(
right );
2086 textBox->SetMarginBottom( bottom );
2087 foundMargins =
true;
2096 Expecting(
"at, size, stroke, fill or effects" );
2100 textBox->SetPosition( pos );
2103 textBox->SetEnd(
end );
2104 else if( foundSize )
2105 textBox->SetEnd( pos + size );
2107 Expecting(
"size" );
2111 int margin = textBox->GetLegacyTextMargin();
2112 textBox->SetMarginLeft( margin );
2113 textBox->SetMarginTop( margin );
2114 textBox->SetMarginRight( margin );
2115 textBox->SetMarginBottom( margin );
2118 return textBox.release();
2124 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
2125 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
2131 wxString pageType = FromUTF8();
2133 if( !aPageInfo.
SetType( pageType ) )
2135 THROW_PARSE_ERROR(
_(
"Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
2162 if( token == T_portrait )
2167 else if( token != T_RIGHT )
2169 Expecting(
"portrait" );
2176 wxCHECK_RET( CurTok() == T_title_block,
2177 "Cannot parse " + GetTokenString( CurTok() ) +
" as a TITLE_BLOCK." );
2181 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2183 if( token != T_LEFT )
2184 Expecting( T_LEFT );
2192 aTitleBlock.
SetTitle( FromUTF8() );
2197 aTitleBlock.
SetDate( FromUTF8() );
2212 int commentNumber =
parseInt(
"comment" );
2214 switch( commentNumber )
2263 CurLine(), CurLineNumber(), CurOffset() );
2270 Expecting(
"title, date, rev, company, or comment" );
2280 wxCHECK_MSG( CurTok() == T_property,
nullptr,
2281 "Cannot parse " + GetTokenString( CurTok() ) +
" as a property token." );
2283 bool is_private =
false;
2285 T token = NextTok();
2287 if( token == T_private )
2293 if( !IsSymbol( token ) )
2295 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
2299 wxString
name = FromUTF8();
2301 if(
name.IsEmpty() )
2303 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
2309 if( !IsSymbol( token ) )
2311 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
2319 value = wxEmptyString;
2351 if(
name.CmpNoCase( wxT(
"Sheet name" ) ) == 0 )
2353 else if(
name.CmpNoCase( wxT(
"Sheet file" ) ) == 0 )
2368 if(
name.CmpNoCase( wxT(
"Intersheet References" ) ) == 0 )
2372 std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>( aParent, fieldId,
name );
2373 field->SetText( value );
2376 field->SetPrivate( is_private );
2378 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2380 if( token != T_LEFT )
2381 Expecting( T_LEFT );
2393 field->SetPosition(
parseXY() );
2411 field->SetNameShown( show );
2415 case T_do_not_autoplace:
2418 field->SetCanAutoplace( !doNotAutoplace );
2423 Expecting(
"id, at, hide, show_name, do_not_autoplace or effects" );
2427 return field.release();
2433 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
2434 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
2435 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
2437 T token = NextTok();
2439 if( !IsSymbol( token ) )
2441 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2445 wxString
name = FromUTF8();
2447 if(
name.IsEmpty() )
2449 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2453 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet,
VECTOR2I( 0, 0 ),
name );
2465 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2468 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2470 if( token != T_LEFT )
2471 Expecting( T_LEFT );
2479 sheetPin->SetPosition(
parseXY() );
2481 double angle =
parseDouble(
"sheet pin angle (side)" );
2485 else if( angle == 90.0 )
2487 else if( angle == 180.0 )
2489 else if( angle == 270.0 )
2492 Expecting(
"0, 90, 180, or 270" );
2509 Expecting(
"at, uuid or effects" );
2513 return sheetPin.release();
2519 wxCHECK_RET( CurTok() == T_sheet_instances,
2520 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2521 wxCHECK( aScreen, );
2525 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2527 if( token != T_LEFT )
2528 Expecting( T_LEFT );
2546 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2548 if( token != T_LEFT )
2549 Expecting( T_LEFT );
2553 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
2556 size_t numReplacements = 0;
2574 for(
const wxString& ch : whitespaces )
2575 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
2580 if( numReplacements > 0 )
2587 Expecting(
"path or page" );
2592 && ( instance.
m_Path.empty() ) )
2608 Expecting(
"path" );
2616 wxCHECK_RET( CurTok() == T_symbol_instances,
2617 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2618 wxCHECK( aScreen, );
2623 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2625 if( token != T_LEFT )
2626 Expecting( T_LEFT );
2643 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2645 if( token != T_LEFT )
2646 Expecting( T_LEFT );
2667 instance.
m_Value = wxEmptyString;
2669 instance.
m_Value = FromUTF8();
2686 Expecting(
"path, unit, value or footprint" );
2695 Expecting(
"path" );
2704 wxCHECK( aSheet !=
nullptr, );
2708 wxCHECK( screen !=
nullptr, );
2711 m_maxError = schematic->Settings().m_MaxError;
2713 if( aIsCopyableOnly )
2716 bool fileHasUuid =
false;
2730 if( !aIsCopyableOnly )
2735 if( CurTok() != T_kicad_sch )
2736 Expecting(
"kicad_sch" );
2755 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2757 if( aIsCopyableOnly && token == T_EOF )
2760 if( token != T_LEFT )
2761 Expecting( T_LEFT );
2795 case T_generator_version:
2821 if( aIsCopyableOnly )
2822 Unexpected( T_paper );
2832 if( aIsCopyableOnly )
2833 Unexpected( T_page );
2837 NeedSYMBOLorNUMBER();
2838 NeedSYMBOLorNUMBER();
2845 if( aIsCopyableOnly )
2846 Unexpected( T_title_block );
2860 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2862 if( token != T_LEFT )
2863 Expecting( T_LEFT );
2875 Expecting(
"symbol" );
2976 case T_netclass_flag:
2981 case T_global_label:
2982 case T_hierarchical_label:
2983 case T_directive_label:
2995 case T_sheet_instances:
2999 case T_symbol_instances:
3004 if( aIsCopyableOnly )
3005 Unexpected( T_bus_alias );
3010 case T_embedded_fonts:
3016 CurLineNumber(), CurOffset() );
3023 case T_embedded_files:
3029 CurLineNumber(), CurOffset() );
3032 embeddedFilesParser.SyncLineReaderWith( *
this );
3043 SyncLineReaderWith( embeddedFilesParser );
3049 Expecting(
"bitmap, bus, bus_alias, bus_entry, class_label, embedded_files, global_label, "
3050 "hierarchical_label, junction, label, line, no_connect, page, paper, rule_area, "
3051 "sheet, symbol, symbol_instances, text, title_block" );
3072 CurLineNumber(), CurOffset() );
3076 std::vector<std::string> fontNames;
3077 Fontconfig()->ListFonts( fontNames, std::string(
Pgm().GetLanguageTag().utf8_str() ),
3087 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
3088 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
3093 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
3095 std::set<int> fieldIDsRead;
3100 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3102 if( token != T_LEFT )
3103 Expecting( T_LEFT );
3115 if( !IsSymbol( token ) )
3118 CurLineNumber(), CurOffset() );
3121 libName = FromUTF8();
3125 libName.Replace(
"{slash}",
"/" );
3135 if( !IsSymbol( token ) && token != T_NUMBER )
3136 Expecting(
"symbol|number" );
3139 wxString
name = FromUTF8();
3143 name.Replace(
"{slash}",
"/" );
3149 if(
static_cast<int>(
name.size() ) > bad_pos )
3151 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
3159 CurLineNumber(), CurOffset() );
3162 symbol->SetLibId( libId );
3168 symbol->SetPosition(
parseXY() );
3170 switch(
static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
3173 case 90: transform =
TRANSFORM( 0, 1, -1, 0 );
break;
3174 case 180: transform =
TRANSFORM( -1, 0, 0, -1 );
break;
3175 case 270: transform =
TRANSFORM( 0, -1, 1, 0 );
break;
3176 default: Expecting(
"0, 90, 180, or 270" );
3179 symbol->SetTransform( transform );
3188 else if( token == T_y )
3191 Expecting(
"x or y" );
3197 symbol->SetUnit(
parseInt(
"symbol unit" ) );
3203 symbol->SetBodyStyle(
parseInt(
"symbol body style" ) );
3207 case T_exclude_from_sim:
3208 symbol->SetExcludedFromSim(
parseBool() );
3213 symbol->SetExcludedFromBOM( !
parseBool() );
3218 symbol->SetExcludedFromBoard( !
parseBool() );
3222 case T_in_pos_files:
3223 symbol->SetExcludedFromPosFiles( !
parseBool() );
3232 case T_fields_autoplaced:
3244 case T_default_instance:
3248 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3250 if( token != T_LEFT )
3251 Expecting( T_LEFT );
3272 symbol->SetValueFieldText( wxEmptyString );
3274 symbol->SetValueFieldText( FromUTF8() );
3283 symbol->SetFootprintFieldText( wxEmptyString );
3285 symbol->SetFootprintFieldText( FromUTF8() );
3291 Expecting(
"reference, unit, value or footprint" );
3300 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3302 if( token != T_LEFT )
3303 Expecting( T_LEFT );
3307 if( token != T_project )
3308 Expecting(
"project" );
3312 wxString projectName = FromUTF8();
3314 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3316 if( token != T_LEFT )
3317 Expecting( T_LEFT );
3321 if( token != T_path )
3322 Expecting(
"path" );
3331 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3333 if( token != T_LEFT )
3334 Expecting( T_LEFT );
3355 symbol->SetValueFieldText( wxEmptyString );
3357 symbol->SetValueFieldText( FromUTF8() );
3366 symbol->SetFootprintFieldText( wxEmptyString );
3368 symbol->SetFootprintFieldText( FromUTF8() );
3378 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3380 if( token != T_LEFT )
3381 Expecting( T_LEFT );
3389 variant.
m_Name = FromUTF8();
3398 case T_exclude_from_sim:
3413 case T_in_pos_files:
3421 wxString fieldValue;
3423 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3425 if( token != T_LEFT )
3426 Expecting( T_LEFT );
3434 fieldName = FromUTF8();
3440 fieldValue = FromUTF8();
3445 Expecting(
"name or value" );
3449 variant.
m_Fields[fieldName] = fieldValue;
3454 Expecting(
"dnp, exclude_from_sim, field, in_bom, in_pos_files, name, or on_board" );
3464 Expecting(
"reference, unit, value, footprint, or variant" );
3468 symbol->AddHierarchicalReference( instance );
3484 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3492 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3500 existing = symbol->GetField( field->
GetId() );
3502 existing = symbol->GetField( field->
GetName() );
3507 symbol->AddField( *field );
3510 symbol->UpdatePrefix();
3523 number = FromUTF8();
3525 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3527 if( token != T_LEFT )
3528 Expecting( T_LEFT );
3552 Expecting(
"alternate or uuid" );
3556 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3562 Expecting(
"lib_id, lib_name, at, mirror, uuid, exclude_from_sim, on_board, in_bom, dnp, "
3563 "default_instance, property, pin, or instances" );
3567 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3568 symbol->SetSchSymbolLibraryName( libName );
3571 symbol->ClearFlags();
3573 return symbol.release();
3579 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3580 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3583 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3586 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3588 if( token != T_LEFT )
3589 Expecting( T_LEFT );
3596 bitmap->SetPosition(
parseXY() );
3622 data.reserve( 1 << 17 );
3624 while( token != T_RIGHT )
3626 if( !IsSymbol( token ) )
3627 Expecting(
"base64 image data" );
3633 wxMemoryBuffer buffer = wxBase64Decode( data );
3642 Expecting(
"at, scale, uuid or data" );
3655 return bitmap.release();
3661 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3662 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3668 std::vector<SCH_FIELD> fields;
3669 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3670 std::set<int> fieldIDsRead;
3675 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3677 if( token != T_LEFT )
3678 Expecting( T_LEFT );
3685 sheet->SetPosition(
parseXY() );
3694 sheet->SetSize( size );
3699 case T_exclude_from_sim:
3700 sheet->SetExcludedFromSim(
parseBool() );
3705 sheet->SetExcludedFromBOM( !
parseBool() );
3710 sheet->SetExcludedFromBoard( !
parseBool() );
3719 case T_fields_autoplaced:
3727 sheet->SetBorderWidth( stroke.
GetWidth() );
3728 sheet->SetBorderColor( stroke.
GetColor() );
3733 sheet->SetBackgroundColor( fill.
m_Color );
3750 if( fields.empty() )
3756 fields.emplace_back( *field );
3767 std::vector<SCH_SHEET_INSTANCE> instances;
3769 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3771 if( token != T_LEFT )
3772 Expecting( T_LEFT );
3776 if( token != T_project )
3777 Expecting(
"project" );
3781 wxString projectName = FromUTF8();
3783 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3785 if( token != T_LEFT )
3786 Expecting( T_LEFT );
3790 if( token != T_path )
3791 Expecting(
"path" );
3800 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3802 if( token != T_LEFT )
3803 Expecting( T_LEFT );
3823 static std::vector<wxString> whitespaces =
3829 for( wxString ch : whitespaces )
3841 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3843 if( token != T_LEFT )
3844 Expecting( T_LEFT );
3852 variant.
m_Name = FromUTF8();
3861 case T_exclude_from_sim:
3876 case T_in_pos_files:
3884 wxString fieldValue;
3886 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3888 if( token != T_LEFT )
3889 Expecting( T_LEFT );
3897 fieldName = FromUTF8();
3903 fieldValue = FromUTF8();
3908 Expecting(
"name or value" );
3912 variant.
m_Fields[fieldName] = fieldValue;
3917 Expecting(
"dnp, exclude_from_sim, field, in_bom, in_pos_files, name, or on_board" );
3927 Expecting(
"page or variant" );
3931 instances.emplace_back( instance );
3935 sheet->setInstances( instances );
3940 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3944 sheet->SetFields( fields );
3946 return sheet.release();
3952 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3953 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3956 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3958 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3960 if( token != T_LEFT )
3961 Expecting( T_LEFT );
3968 junction->SetPosition(
parseXY() );
3984 color.
a = std::clamp(
parseDouble(
"alpha" ), 0.0, 1.0 );
3986 junction->SetColor( color );
3998 Expecting(
"at, diameter, color or uuid" );
4002 return junction.release();
4008 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
4009 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
4012 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
4014 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4016 if( token != T_LEFT )
4017 Expecting( T_LEFT );
4024 no_connect->SetPosition(
parseXY() );
4035 Expecting(
"at or uuid" );
4039 return no_connect.release();
4045 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
4046 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
4050 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
4052 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4054 if( token != T_LEFT )
4055 Expecting( T_LEFT );
4062 busEntry->SetPosition(
parseXY() );
4072 busEntry->SetSize( size );
4079 busEntry->SetStroke( stroke );
4089 Expecting(
"at, size, uuid or stroke" );
4093 return busEntry.release();
4115 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4117 if( token != T_LEFT )
4118 Expecting( T_LEFT );
4125 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4127 if( token != T_LEFT )
4128 Expecting( T_LEFT );
4135 polyline->AddPoint(
parseXY() );
4148 polyline->SetStroke( stroke );
4154 polyline->SetFillColor( fill.
m_Color );
4165 Expecting(
"pts, uuid, stroke, or fill" );
4169 return polyline.release();
4188 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
4191 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
4193 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4195 if( token != T_LEFT )
4196 Expecting( T_LEFT );
4209 line->SetStartPoint(
parseXY() );
4217 line->SetEndPoint(
parseXY() );
4224 line->SetStroke( stroke );
4234 Expecting(
"at, uuid or stroke" );
4238 return line.release();
4244 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
4245 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
4253 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>(
SHAPE_T::ARC );
4255 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4257 if( token != T_LEFT )
4258 Expecting( T_LEFT );
4281 arc->SetStroke( stroke );
4287 arc->SetFillColor( fill.
m_Color );
4293 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
4298 Expecting(
"start, mid, end, stroke, fill or uuid" );
4302 arc->SetArcGeometry( startPoint, midPoint, endPoint );
4304 return arc.release();
4310 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
4311 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
4320 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4322 if( token != T_LEFT )
4323 Expecting( T_LEFT );
4341 circle->SetStroke( stroke );
4358 Expecting(
"center, radius, stroke, fill or uuid" );
4371 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
4372 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
4377 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>(
SHAPE_T::RECTANGLE );
4379 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4381 if( token != T_LEFT )
4382 Expecting( T_LEFT );
4389 rectangle->SetPosition(
parseXY() );
4394 rectangle->SetEnd(
parseXY() );
4405 rectangle->SetStroke( stroke );
4411 rectangle->SetFillColor( fill.
m_Color );
4417 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4422 Expecting(
"start, end, stroke, fill or uuid" );
4426 return rectangle.release();
4432 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4433 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4438 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4440 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4442 if( token != T_LEFT )
4443 Expecting( T_LEFT );
4457 ruleArea->SetPolyShape( sch_rule_poly );
4459 ruleArea->SetStroke( poly->GetStroke() );
4460 ruleArea->SetFillMode( poly->GetFillMode() );
4461 ruleArea->SetFillColor( poly->GetFillColor() );
4464 const_cast<KIID&
>( ruleArea->m_Uuid ) = poly->m_Uuid;
4468 case T_exclude_from_sim:
4469 ruleArea->SetExcludedFromSim(
parseBool() );
4474 ruleArea->SetExcludedFromBOM( !
parseBool() );
4479 ruleArea->SetExcludedFromBoard( !
parseBool() );
4489 Expecting(
"exclude_from_sim, on_board, in_bom, dnp, or polyline" );
4493 return ruleArea.release();
4499 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4500 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4505 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>(
SHAPE_T::BEZIER );
4507 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4509 if( token != T_LEFT )
4510 Expecting( T_LEFT );
4520 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4522 if( token != T_LEFT )
4523 Expecting( T_LEFT );
4532 case 0: bezier->SetStart(
parseXY() );
break;
4533 case 1: bezier->SetBezierC1(
parseXY() );
break;
4534 case 2: bezier->SetBezierC2(
parseXY() );
break;
4535 case 3: bezier->SetEnd(
parseXY() );
break;
4536 default: Unexpected(
"control point" );
break;
4546 bezier->SetStroke( stroke );
4552 bezier->SetFillColor( fill.
m_Color );
4558 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4563 Expecting(
"pts, stroke, fill or uuid" );
4567 bezier->RebuildBezierToSegmentsPointsList(
m_maxError );
4569 return bezier.release();
4576 std::unique_ptr<SCH_TEXT>
text;
4580 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4581 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4582 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4583 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4584 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4585 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4587 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4595 text->SetText( FromUTF8() );
4597 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4599 if( token != T_LEFT )
4600 Expecting( T_LEFT );
4606 case T_exclude_from_sim:
4617 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4633 Unexpected( T_shape );
4651 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4662 Unexpected( T_length );
4671 case T_fields_autoplaced:
4681 text->SetVisible(
true );
4706 Unexpected( T_property );
4726 Expecting(
"at, shape, iref, uuid or effects" );
4732 if( label && label->
GetFields().empty() )
4735 return text.release();
4741 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4742 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4744 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4748 return textBox.release();
4754 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4755 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4757 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4761 return cell.release();
4777 bool foundEnd =
false;
4778 bool foundSize =
false;
4779 bool foundMargins =
false;
4783 aTextBox->
SetText( FromUTF8() );
4785 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4787 if( token != T_LEFT )
4788 Expecting( T_LEFT );
4794 case T_exclude_from_sim:
4825 cell->SetColSpan(
parseInt(
"column span" ) );
4826 cell->SetRowSpan(
parseInt(
"row span" ) );
4830 Expecting(
"at, size, stroke, fill, effects or uuid" );
4854 foundMargins =
true;
4870 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4872 Expecting(
"at, size, stroke, fill, effects or uuid" );
4880 else if( foundSize )
4881 aTextBox->
SetEnd( pos + size );
4883 Expecting(
"size" );
4898 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4899 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4905 std::unique_ptr<SCH_TABLE>
table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4907 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4909 if( token != T_LEFT )
4910 Expecting( T_LEFT );
4916 case T_column_count:
4921 case T_column_widths:
4925 while( ( token = NextTok() ) != T_RIGHT )
4935 while( ( token = NextTok() ) != T_RIGHT )
4942 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4944 if( token != T_LEFT )
4945 Expecting( T_LEFT );
4949 if( token != T_table_cell )
4950 Expecting(
"table_cell" );
4958 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4960 if( token != T_LEFT )
4961 Expecting( T_LEFT );
4979 table->SetBorderStroke( borderStroke );
4983 Expecting(
"external, header or stroke" );
4991 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4993 if( token != T_LEFT )
4994 Expecting( T_LEFT );
5012 table->SetSeparatorsStroke( separatorsStroke );
5016 Expecting(
"rows, cols, or stroke" );
5030 Expecting(
"columns, col_widths, row_heights, border, separators, uuid, header or cells" );
5034 return table.release();
5040 wxCHECK_RET( CurTok() == T_bus_alias,
5041 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
5042 wxCHECK( aScreen, );
5045 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>();
5056 busAlias->SetName( alias );
5061 if( token != T_members )
5062 Expecting(
"members" );
5066 while( token != T_RIGHT )
5068 if( !IsSymbol( token ) )
5069 Expecting(
"quoted string" );
5071 member = FromUTF8();
5076 busAlias->AddMember( member );
5091 while( ( token = NextTok() ) != T_RIGHT )
5096 KIID uuid( CurStr() );
5104 wxCHECK_RET( CurTok() == T_group,
5105 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
5112 while( ( token = NextTok() ) != T_LEFT )
5114 if( token == T_STRING )
5115 groupInfo.
name = FromUTF8();
5117 Expecting(
"group name or locked" );
5120 for( ; token != T_RIGHT; token = NextTok() )
5122 if( token != T_LEFT )
5123 Expecting( T_LEFT );
5139 if( !IsSymbol( token ) && token != T_NUMBER )
5140 Expecting(
"symbol|number" );
5143 wxString
name = FromUTF8();
5147 name.Replace(
"{slash}",
"/" );
5153 if(
static_cast<int>(
name.size() ) > bad_pos )
5155 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
name,
5161 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
5175 Expecting(
"uuid, lib_id, members" );
5187 [&](
const KIID& aId )
5193 if( item->m_Uuid == aId )
5212 group->SetName( groupInfo.name );
5214 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo.uuid;
5216 if( groupInfo.libId.IsValid() )
5217 group->SetDesignBlockLibId( groupInfo.libId );
5228 for(
const KIID& aUuid : groupInfo.memberUuids )
5230 if(
SCH_ITEM* gItem = getItem( aUuid ) )
5231 group->AddItem( gItem );
5246 T token = NextTok();
5248 if( token == T_EOF )
5250 else if( token == T_LEFT )
5252 else if( token == T_RIGHT )
constexpr EDA_IU_SCALE schIUScale
constexpr double ARC_LOW_DEF_MM
constexpr BOX2I KiROUND(const BOX2D &aBoxD)
void SetContentModified(bool aModified=true)
static const COLOR4D UNSPECIFIED
For legacy support; used as a value to indicate color hasn't been set yet.
KICAD_T Type() const
Returns the type of object.
EDA_ITEM * GetParent() const
virtual void SetParent(EDA_ITEM *aParent)
FILL_T GetFillMode() const
SHAPE_POLY_SET & GetPolyShape()
void SetFillColor(const COLOR4D &aColor)
int GetPointCount() const
void SetEnd(const VECTOR2I &aEnd)
void SetFillMode(FILL_T aFill)
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
void SetTextColor(const COLOR4D &aColor)
void SetTextSize(VECTOR2I aNewSize, bool aEnforceMinTextSize=true)
void SetUnresolvedFontName(const wxString &aFontName)
virtual const wxString & GetText() const
Return the string associated with the text object.
void SetTextPos(const VECTOR2I &aPoint)
void SetVertJustify(GR_TEXT_V_ALIGN_T aType)
void SetBoldFlag(bool aBold)
Set only the bold flag, without changing the font.
virtual void SetVisible(bool aVisible)
void SetLineSpacing(double aLineSpacing)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
static bool ValidateHyperlink(const wxString &aURL)
Check if aURL is a valid hyperlink.
void SetItalicFlag(bool aItalic)
Set only the italic flag, without changing the font.
void SetHyperlink(wxString aLink)
virtual void SetText(const wxString &aText)
virtual void SetTextAngle(const EDA_ANGLE &aAngle)
void SetHorizJustify(GR_TEXT_H_ALIGN_T aType)
void ParseEmbedded(EMBEDDED_FILES *aFiles)
const std::vector< wxString > * UpdateFontFiles()
Helper function to get a list of fonts for fontconfig to add to the library.
const std::vector< wxString > * GetFontFiles() const
If we just need the cached version of the font files, we can use this function which is const and wil...
void SetAreFontsEmbedded(bool aEmbedFonts)
Simple container to manage fill parameters.
Hold an error message and may be used when throwing exceptions containing meaningful error messages.
virtual const wxString What() const
A composite of Problem() and Where()
A color representation with 4 components: red, green, blue, alpha.
A logical library item identifier and consists of various portions much like a URI.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Define a library symbol object.
wxString GetName() const override
void RunOnChildren(const std::function< void(SCH_ITEM *)> &aFunction, RECURSE_MODE aMode) override
EMBEDDED_FILES * GetEmbeddedFiles() override
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
Describe the page size and margins of a paper page on which to eventually print or plot.
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
bool SetType(PAGE_SIZE_TYPE aPageSize, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
void SetWidthMM(double aWidthInMM)
void SetHeightMM(double aHeightInMM)
const PAGE_SIZE_TYPE & GetType() const
A progress reporter interface for use in multi-threaded environments.
A REFERENCE_IMAGE is a wrapper around a BITMAP_IMAGE that is displayed in an editor as a reference fo...
bool ReadImageFile(const wxString &aFullFilename)
Read and store an image file.
const BITMAP_BASE & GetImage() const
Get the underlying image.
double GetImageScale() const
void SetImageScale(double aScale)
Set the image "zoom" value.
Holds all the data relating to one schematic.
EMBEDDED_FILES * GetEmbeddedFiles() override
Object to handle a bitmap image that can be inserted in a schematic.
Class for a wire to bus entry.
void SetPinLength(int aLength)
virtual const wxString & GetText() const override
Return the string associated with the text object.
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
wxString GetName(bool aUseDefaultName=true) const
Return the field name (not translated).
SCH_FIELD * GetField(FIELD_T aFieldType)
Return a mandatory field in this label.
A set of SCH_ITEMs (i.e., without duplicates).
SCH_ITEM * ParseSymbolDrawItem()
SCH_SHAPE * parseSymbolPolyLine()
SCH_TABLE * parseSchTable()
bool m_appending
Appending load status.
unsigned m_lastProgressLine
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
SCH_SHAPE * parseSchCircle()
SCH_TEXT * parseSchText()
SCH_TABLECELL * parseSchTableCell()
void parseSchSymbolInstances(SCH_SCREEN *aScreen)
void parsePinNumbers(std::unique_ptr< LIB_SYMBOL > &aSymbol)
LIB_SYMBOL * parseLibSymbol(LIB_SYMBOL_MAP &aSymbolLibMap)
SCH_RULE_AREA * parseSchRuleArea()
SCH_ITEM * parseSymbolText()
PROGRESS_REPORTER * m_progressReporter
void parseFill(FILL_PARAMS &aFill)
SCH_TEXTBOX * parseSymbolTextBox()
void parseBusAlias(SCH_SCREEN *aScreen)
void parseTITLE_BLOCK(TITLE_BLOCK &aTitleBlock)
void parseGroupMembers(GROUP_INFO &aGroupInfo)
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.
int m_unit
The current unit being parsed.
SCH_SHAPE * parseSymbolBezier()
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax, bool aEnforceMinTextSize=true)
SCH_TEXTBOX * parseSchTextBox()
void resolveGroups(SCH_SCREEN *aParent)
SCH_SHEET * m_rootSheet
The rootsheet for full project loads or null for importing a schematic.
SCH_SHAPE * parseSchArc()
SCH_SHAPE * parseSchPolyLine()
SCH_BITMAP * parseImage()
SCH_SHAPE * parseSymbolCircle()
wxString m_generatorVersion
void ParseLib(LIB_SYMBOL_MAP &aSymbolLibMap)
SCH_PIN * parseSymbolPin()
std::vector< GROUP_INFO > m_groupInfos
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
void parseBodyStyles(std::unique_ptr< LIB_SYMBOL > &aSymbol)
void parseMargins(int &aLeft, int &aTop, int &aRight, int &aBottom)
wxString m_symbolName
The current symbol name.
VECTOR2I parseXY(bool aInvertY=false)
SCH_SHAPE * parseSymbolRectangle()
void parsePinNames(std::unique_ptr< LIB_SYMBOL > &aSymbol)
SCH_SHAPE * parseSchBezier()
std::vector< wxString > m_parseWarnings
Non-fatal warnings collected during parsing.
SCH_JUNCTION * parseJunction()
void ParseSchematic(SCH_SHEET *aSheet, bool aIsCopyablyOnly=false, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
Parse the internal LINE_READER object into aSheet.
SCH_SHEET_PIN * parseSchSheetPin(SCH_SHEET *aSheet)
int m_bodyStyle
The current body style being parsed.
SCH_NO_CONNECT * parseNoConnect()
SCH_SHAPE * parseSymbolArc()
SCH_BUS_WIRE_ENTRY * parseBusEntry()
SCH_SHAPE * parseSchRectangle()
SCH_FIELD * parseProperty(std::unique_ptr< LIB_SYMBOL > &aSymbol)
SCH_SYMBOL * parseSchematicSymbol()
void parseSchTextBoxContent(SCH_TEXTBOX *aTextBox)
bool parseMaybeAbsentBool(bool aDefaultValue)
Parses a boolean flag inside a list that existed before boolean normalization.
void parsePAGE_INFO(PAGE_INFO &aPageInfo)
int m_requiredVersion
Set to the symbol library file version required.
int m_maxError
Max deviation allowed when approximating bezier curves.
const LINE_READER * m_lineReader
LIB_SYMBOL * ParseSymbol(LIB_SYMBOL_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
Parse internal LINE_READER object into symbols and return all found.
void skipToBlockEnd(int aDepth=1)
Skip tokens until we reach the end of the current S-expression block.
void parseSchSheetInstances(SCH_SHEET *aRootSheet, SCH_SCREEN *aScreen)
SCH_IO_KICAD_SEXPR_PARSER(LINE_READER *aLineReader=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr, unsigned aLineCount=0, SCH_SHEET *aRootSheet=nullptr, bool aIsAppending=false)
Base class for any item which can be embedded within the SCHEMATIC container class,...
void SetFieldsAutoplaced(AUTOPLACE_ALGO aAlgo)
void SetShape(LABEL_FLAG_SHAPE aShape)
std::vector< SCH_FIELD > & GetFields()
Segment description base class to describe items which have 2 end points (track, wire,...
void SetStartPoint(const VECTOR2I &aPosition)
virtual void SetStroke(const STROKE_PARAMS &aStroke) override
void SetEndPoint(const VECTOR2I &aPosition)
void SetFileFormatVersionAtLoad(int aVersion)
std::vector< SCH_SHEET_INSTANCE > m_sheetInstances
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
void Append(SCH_ITEM *aItem, bool aUpdateLibSymbol=true)
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition.
void SetPageSettings(const PAGE_INFO &aPageSettings)
EE_RTREE & Items()
Get the full RTree, usually for iterating.
const KIID & GetUuid() const
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.
SCHEMATIC * Schematic() const
void FixupEmbeddedData()
After loading a file from disk, the library symbols do not yet contain the full data for their embedd...
int GetFileFormatVersionAtLoad() const
wxString GroupsSanityCheck(bool repair=false)
Consistency check of internal m_groups structure.
KIID m_uuid
A unique identifier for each schematic file.
std::vector< SCH_SYMBOL_INSTANCE > m_symbolInstances
The list of symbol instances loaded from the schematic file.
void SetPosition(const VECTOR2I &aPos) override
void SetStroke(const STROKE_PARAMS &aStroke) override
STROKE_PARAMS GetStroke() const override
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.
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Variant information for a schematic sheet.
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
SCH_SCREEN * GetScreen() const
Variant information for a schematic symbol.
void SetMarginBottom(int aBottom)
int GetLegacyTextMargin() const
void SetMarginLeft(int aLeft)
void SetMarginRight(int aRight)
void SetExcludedFromSim(bool aExclude, const SCH_SHEET_PATH *aInstance=nullptr, const wxString &aVariantName=wxEmptyString) override
void SetMarginTop(int aTop)
Represent a polyline containing arcs as well as line segments: A chain of connected line and/or arc s...
void SetClosed(bool aClosed)
Mark the line chain as closed (i.e.
const VECTOR2I & CPoint(int aIndex) const
Return a reference to a given point in the line chain.
Represent a set of closed polygons.
SHAPE_LINE_CHAIN & Outline(int aIndex)
Return the reference to aIndex-th outline in the set.
void ParseStroke(STROKE_PARAMS &aStroke)
Simple container to manage line stroke parameters.
void SetLineStyle(LINE_STYLE aLineStyle)
LINE_STYLE GetLineStyle() const
KIGFX::COLOR4D GetColor() const
Hold the information shown in the lower right corner of a plot, printout, or editing view.
void SetRevision(const wxString &aRevision)
void SetComment(int aIdx, const wxString &aComment)
void SetTitle(const wxString &aTitle)
void SetCompany(const wxString &aCompany)
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
std::map< wxString, wxString > m_Fields
bool m_ExcludedFromPosFiles
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
static constexpr EDA_ANGLE ANGLE_0
static constexpr EDA_ANGLE ANGLE_90
static constexpr EDA_ANGLE ANGLE_360
static constexpr EDA_ANGLE ANGLE_180
@ RECTANGLE
Use RECTANGLE instead of RECT to avoid collision in a Windows header.
@ FILLED_WITH_BG_BODYCOLOR
@ FILLED_SHAPE
Fill with object color.
FONTCONFIG * Fontconfig()
#define THROW_IO_ERROR(msg)
macro which captures the "call site" values of FILE_, __FUNCTION & LINE
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
#define KI_FALLTHROUGH
The KI_FALLTHROUGH macro is to be used when switch statement cases should purposely fallthrough from ...
#define MAX_PAGE_SIZE_EESCHEMA_MM
#define MIN_PAGE_SIZE_MM
Min and max page sizes for clamping, in mm.
PGM_BASE & Pgm()
The global program "get" accessor.
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
@ PT_INPUT
usual pin input: must be connected
@ PT_NC
not connected (must be left open)
@ PT_TRISTATE
tri 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.
@ PIN_UP
The pin extends upwards from the connection point: Probably on the bottom side of the symbol.
@ PIN_RIGHT
The pin extends rightwards from the connection point.
@ PIN_LEFT
The pin extends leftwards from the connection point: Probably on the right side of the symbol.
@ PIN_DOWN
The pin extends downwards from the connection: Probably on the top side of the symbol.
#define SEXPR_SYMBOL_LIB_FILE_VERSION
This file contains the file format version information for the s-expression schematic and symbol libr...
#define SEXPR_SCHEMATIC_FILE_VERSION
Schematic file version.
Class to handle a set of SCH_ITEMs.
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 ...
void fixupSchFillMode(SCH_SHAPE *aShape)
#define SIM_LEGACY_ENABLE_FIELD
#define SIM_LEGACY_ENABLE_FIELD_V7
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
wxString UnescapeString(const wxString &aSource)
A filename or source description, a problem input line, a line number, a byte offset,...
std::vector< KIID > memberUuids
ELECTRICAL_PINTYPE m_Type
A simple container for sheet instance information.
std::map< wxString, SCH_SHEET_VARIANT > m_Variants
A list of sheet variants.
A simple container for schematic symbol instance information.
std::map< wxString, SCH_SYMBOL_VARIANT > m_Variants
A list of symbol variants.
std::map< wxString, LIB_SYMBOL *, LibSymbolMapSort > LIB_SYMBOL_MAP
FIELD_T
The set of all field indices assuming an array like sequence that a SCH_COMPONENT or LIB_PART can hol...
@ USER
The field ID hasn't been set yet; field is invalid.
@ INTERSHEET_REFS
Global label cross-reference page numbers.
@ REFERENCE
Field Reference of part, i.e. "IC21".
@ VALUE
Field Value of part, i.e. "3.3K".
#define SHEET_MANDATORY_FIELDS
#define GLOBALLABEL_MANDATORY_FIELDS
wxString GetCanonicalFieldName(FIELD_T aFieldType)
KIBIS top(path, &reporter)
SHAPE_CIRCLE circle(c.m_circle_center, c.m_circle_radius)
static constexpr double IU_PER_MM
Mock up a conversion function.
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.
VECTOR2< int32_t > VECTOR2I