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 ),
97 const unsigned PROGRESS_DELTA = 500;
119 KIID id( FromUTF8() );
136 else if( token == T_no )
139 Expecting(
"yes or no" );
150 bool ret = aDefaultValue;
152 if( PrevTok() == T_LEFT )
157 if(
static_cast<int>( token ) ==
DSN_RIGHT )
158 return aDefaultValue;
162 else if( token == T_no )
165 Expecting(
"yes or no" );
172 return aDefaultValue;
190 bool versionChecked =
false;
201 versionChecked =
true;
204 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
206 if( token != T_LEFT )
232 case T_generator_version:
255 aSymbolLibMap[symbol->
GetName()] = symbol;
260 wxString warning = wxString::Format(
261 _(
"Error parsing symbol at line %d: %s\nSkipping symbol and continuing." ),
262 CurLineNumber(), e.
What() );
274 Expecting(
"symbol, generator, or generator_version" );
288 if( CurTok() == T_LEFT )
292 if( CurTok() == T_symbol )
297 const std::vector<wxString>* embeddedFonts =
304 textItem->ResolveFont( embeddedFonts );
310 wxString msg = wxString::Format(
_(
"Cannot parse %s as a symbol" ),
311 GetTokenString( CurTok() ) );
322 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
323 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
330 std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
332 symbol->SetUnitCount( 1,
true );
336 if( !IsSymbol( token ) )
337 THROW_PARSE_ERROR(
_(
"Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
344 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
351 if(
static_cast<int>(
name.size() ) > bad_pos )
353 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
362 CurLineNumber(), CurOffset() );
367 symbol->SetLibId(
id );
369 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
371 if( token != T_LEFT )
379 symbol->SetGlobalPower();
382 if( token == T_RIGHT )
385 if( token == T_local )
386 symbol->SetLocalPower();
387 else if( token != T_global )
388 Expecting(
"global or local" );
405 case T_exclude_from_sim:
406 symbol->SetExcludedFromSim(
parseBool() );
411 symbol->SetExcludedFromBOM( !
parseBool() );
416 symbol->SetExcludedFromBoard( !
parseBool() );
421 symbol->SetExcludedFromPosFiles( !
parseBool() );
425 case T_duplicate_pin_numbers_are_jumpers:
426 symbol->SetDuplicatePinNumbersAreJumpers(
parseBool() );
430 case T_jumper_pin_groups:
432 std::vector<std::set<wxString>>& groups = symbol->JumperPinGroups();
433 std::set<wxString>* currentGroup =
nullptr;
435 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
437 switch(
static_cast<int>( token ) )
440 currentGroup = &groups.emplace_back();
444 currentGroup->insert( FromUTF8() );
448 currentGroup =
nullptr;
452 Expecting(
"list of pin names" );
467 if( !IsSymbol( token ) )
470 CurLineNumber(), CurOffset() );
478 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
480 symbol->SetParentName(
name );
489 if( !IsSymbol( token ) )
492 CurLineNumber(), CurOffset() );
500 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
504 error.Printf(
_(
"Invalid symbol unit name prefix %s" ),
name.c_str() );
505 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
510 wxStringTokenizer tokenizer(
name,
"_" );
512 if( tokenizer.CountTokens() != 2 )
514 error.Printf(
_(
"Invalid symbol unit name suffix %s" ),
name.c_str() );
515 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
518 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
520 error.Printf(
_(
"Invalid symbol unit number %s" ),
name.c_str() );
521 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
524 m_unit =
static_cast<int>( tmp );
526 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
528 error.Printf(
_(
"Invalid symbol body style number %s" ),
name.c_str() );
529 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
535 symbol->SetBodyStyleCount(
m_bodyStyle,
false,
false );
537 if(
m_unit > symbol->GetUnitCount() )
538 symbol->SetUnitCount(
m_unit,
false );
540 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
542 if( token != T_LEFT )
552 if( IsSymbol( token ) )
553 symbol->GetUnitDisplayNames()[
m_unit] = FromUTF8();
568 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
571 symbol->AddDrawItem( item,
false );
575 Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
594 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
597 symbol->AddDrawItem( item,
false );
600 case T_embedded_fonts:
602 symbol->SetAreFontsEmbedded(
parseBool() );
607 case T_embedded_files:
610 embeddedFilesParser.SyncLineReaderWith( *
this );
614 embeddedFilesParser.
ParseEmbedded( symbol->GetEmbeddedFiles() );
621 SyncLineReaderWith( embeddedFilesParser );
626 Expecting(
"pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
627 "rectangle, or text" );
631 symbol->GetDrawItems().sort();
634 const std::vector<wxString>* embeddedFonts = symbol->GetEmbeddedFiles()->UpdateFontFiles();
636 symbol->RunOnChildren(
640 textItem->ResolveFont( embeddedFonts );
647 symbol->SetHasDeMorganBodyStyles( symbol->HasLegacyAlternateBodyStyle() );
649 return symbol.release();
665 default: Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
679 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
681 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
689 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
691 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
698 strokeParser.SyncLineReaderWith( *
this );
701 SyncLineReaderWith( strokeParser );
707 wxCHECK_RET( CurTok() == T_fill,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a fill." );
714 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
716 if( token != T_LEFT )
736 default: Expecting(
"none, outline, hatch, reverse_hatch, "
737 "cross_hatch, color or background" );
751 color.
a = std::clamp(
parseDouble(
"alpha" ), 0.0, 1.0 );
758 Expecting(
"type or color" );
765 bool aEnforceMinTextSize )
767 wxCHECK_RET( aText && ( CurTok() == T_effects || CurTok() == T_href ),
768 "Cannot parse " + GetTokenString( CurTok() ) +
" as an EDA_TEXT." );
785 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
787 if( token == T_LEFT )
793 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
795 if( token == T_LEFT )
835 color.
a = std::clamp(
parseDouble(
"alpha" ), 0.0, 1.0 );
846 Expecting(
"face, size, thickness, line_spacing, bold, or italic" );
853 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
862 case T_mirror:
break;
863 default: Expecting(
"left, right, top, bottom, or mirror" );
872 wxString hyperlink = FromUTF8();
877 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
896 Expecting(
"font, justify, hide or href" );
904 wxCHECK_RET( CurTok() == aHeaderType,
905 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
911 if( tok == T_version )
925 wxCHECK_RET( CurTok() == T_body_styles,
926 "Cannot parse " + GetTokenString( CurTok() ) +
" as a body_styles token." );
928 std::vector<wxString> names;
930 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
932 if( token == T_demorgan )
934 aSymbol->SetHasDeMorganBodyStyles(
true );
937 else if( !IsSymbol( token ) )
939 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
943 names.push_back( FromUTF8() );
947 aSymbol->SetBodyStyleNames( names );
953 wxCHECK_RET( CurTok() == T_pin_names,
954 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_name token." );
964 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
967 if( token == T_hide )
969 aSymbol->SetShowPinNames(
false );
973 if( token != T_LEFT )
988 aSymbol->SetShowPinNames( !
parseBool() );
993 Expecting(
"offset or hide" );
1001 wxCHECK_RET( CurTok() == T_pin_numbers,
1002 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_number token." );
1011 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
1014 if( token == T_hide )
1016 aSymbol->SetShowPinNumbers(
false );
1020 if( token != T_LEFT )
1022 Expecting( T_LEFT );
1030 aSymbol->SetShowPinNumbers( !
parseBool() );
1035 Expecting(
"hide" );
1044 wxCHECK_MSG( CurTok() == T_property,
nullptr,
1045 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a property." ) );
1046 wxCHECK( aSymbol,
nullptr );
1051 bool isPrivate =
false;
1052 bool isVisible =
true;
1054 T token = NextTok();
1056 if( token == T_private )
1062 if( !IsSymbol( token ) )
1064 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
1070 if(
name.IsEmpty() )
1072 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
1086 auto field = std::make_unique<SCH_FIELD>( aSymbol.get(), fieldId,
name );
1087 field->SetPrivate( isPrivate );
1088 field->SetVisible( isVisible );
1092 if( !IsSymbol( token ) )
1094 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
1101 value = wxEmptyString;
1105 field->SetText( value );
1107 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1109 if( token != T_LEFT )
1110 Expecting( T_LEFT );
1122 field->SetPosition(
parseXY(
true ) );
1140 field->SetNameShown( show );
1144 case T_do_not_autoplace:
1147 field->SetCanAutoplace( !doNotAutoplace );
1152 Expecting(
"id, at, hide, show_name, do_not_autoplace, or effects" );
1158 if( field->IsMandatory() )
1160 existingField = aSymbol->GetField( field->GetId() );
1162 *existingField = *field;
1163 return existingField;
1165 else if(
name ==
"ki_keywords" )
1168 aSymbol->SetKeyWords( value );
1172 else if(
name ==
"ki_description" )
1174 aSymbol->SetDescription( value );
1177 else if(
name ==
"ki_fp_filters" )
1180 wxArrayString filters;
1181 wxStringTokenizer tokenizer( value,
" \t\r\n", wxTOKEN_STRTOK );
1183 while( tokenizer.HasMoreTokens() )
1185 wxString curr_token =
UnescapeString( tokenizer.GetNextToken() );
1186 filters.Add( curr_token );
1189 aSymbol->SetFPFilters( filters );
1192 else if(
name ==
"ki_locked" )
1196 aSymbol->LockUnits(
true );
1202 existingField = aSymbol->GetField( field->GetCanonicalName() );
1210 wxString base_name = field->GetCanonicalName();
1213 for(
int ii = 1; ii < 10 && existingField; ii++ )
1215 wxString newname = base_name;
1216 newname <<
'_' << ii;
1218 existingField = aSymbol->GetField( newname );
1220 if( !existingField )
1221 field->SetName( newname );
1225 if( !existingField )
1227 aSymbol->AddDrawItem( field.get(),
false );
1228 return field.release();
1241 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
1242 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
1248 bool hasMidPoint =
false;
1256 bool hasAngles =
false;
1265 if( token == T_private )
1267 arc->SetPrivate(
true );
1271 for( ; token != T_RIGHT; token = NextTok() )
1273 if( token != T_LEFT )
1274 Expecting( T_LEFT );
1297 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1299 if( token != T_LEFT )
1300 Expecting( T_LEFT );
1328 Expecting(
"at, length, or angles" );
1336 arc->SetStroke( stroke );
1342 arc->SetFillColor( fill.
m_Color );
1346 Expecting(
"start, mid, end, radius, stroke, or fill" );
1352 arc->SetArcGeometry( startPoint, midPoint, endPoint );
1363 EDA_ANGLE arc_start, arc_end, arc_angle;
1364 arc->CalcArcAngles( arc_start, arc_end );
1365 arc_angle = arc_end - arc_start;
1370 arc->SetStart( endPoint );
1371 arc->SetEnd( startPoint );
1374 arc->SetCenter( new_center );
1380 arc->SetCenter( new_center );
1384 else if( hasAngles )
1386 arc->SetCenter(
center );
1392 arc->SetStart( endPoint );
1393 arc->SetEnd( startPoint );
1397 EDA_ANGLE arc_start, arc_end, arc_angle;
1398 arc->CalcArcAngles( arc_start, arc_end );
1399 arc_angle = arc_end - arc_start;
1405 arc->SetStart( startPoint );
1406 arc->SetEnd( endPoint );
1414 arc->SetStart( startPoint );
1415 arc->SetEnd( endPoint );
1419 arc->SetCenter( new_center );
1425 wxFAIL_MSG(
"Setting arc without either midpoint or angles not implemented." );
1428 return arc.release();
1434 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
1435 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
1443 bezier->SetUnit(
m_unit );
1448 if( token == T_private )
1450 bezier->SetPrivate(
true );
1454 for( ; token != T_RIGHT; token = NextTok() )
1456 if( token != T_LEFT )
1457 Expecting( T_LEFT );
1467 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1469 if( token != T_LEFT )
1470 Expecting( T_LEFT );
1479 case 0: bezier->SetStart(
parseXY(
true ) );
break;
1480 case 1: bezier->SetBezierC1(
parseXY(
true ) );
break;
1481 case 2: bezier->SetBezierC2(
parseXY(
true ) );
break;
1482 case 3: bezier->SetEnd(
parseXY(
true ) );
break;
1483 default: Unexpected(
"control point" );
break;
1493 bezier->SetStroke( stroke );
1499 bezier->SetFillColor( fill.
m_Color );
1503 Expecting(
"pts, stroke, or fill" );
1507 bezier->RebuildBezierToSegmentsPointsList(
m_maxError );
1509 return bezier.release();
1515 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
1516 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
1531 if( token == T_private )
1533 circle->SetPrivate(
true );
1537 for( ; token != T_RIGHT; token = NextTok() )
1539 if( token != T_LEFT )
1540 Expecting( T_LEFT );
1558 circle->SetStroke( stroke );
1568 Expecting(
"center, radius, stroke, or fill" );
1601 Expecting(
"input, output, bidirectional, tri_state, passive, unspecified, "
1602 "power_in, power_out, open_collector, open_emitter, free or "
1624 Expecting(
"line, inverted, clock, inverted_clock, input_low, clock_low, "
1625 "output_low, edge_clock_high, non_logic" );
1630 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
1631 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a pin token." ) );
1634 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>(
nullptr );
1641 pin->SetType( parseType( token ) );
1645 pin->SetShape( parseShape( token ) );
1647 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1650 if( token == T_hide )
1652 pin->SetVisible(
false );
1656 if( token != T_LEFT )
1657 Expecting( T_LEFT );
1666 switch(
parseInt(
"pin orientation" ) )
1672 default: Expecting(
"0, 90, 180, or 270" );
1691 if( !IsSymbol( token ) )
1698 pin->SetName( wxEmptyString );
1702 pin->SetName( FromUTF8() );
1706 if( token != T_RIGHT )
1710 if( token == T_effects )
1717 pin->SetNameTextSize(
text.GetTextHeight() );
1722 Expecting(
"effects" );
1731 if( !IsSymbol( token ) )
1734 CurLineNumber(), CurOffset() );
1738 pin->SetNumber( wxEmptyString );
1742 pin->SetNumber( FromUTF8() );
1746 if( token != T_RIGHT )
1750 if( token == T_effects )
1757 pin->SetNumberTextSize(
text.GetTextHeight() );
1762 Expecting(
"effects" );
1774 if( !IsSymbol( token ) )
1777 CurLineNumber(), CurOffset() );
1783 alt.
m_Type = parseType( token );
1786 alt.
m_Shape = parseShape( token );
1788 pin->GetAlternates()[ alt.
m_Name ] = alt;
1795 Expecting(
"at, name, number, hide, length, or alternate" );
1799 return pin.release();
1805 wxCHECK_MSG( CurTok() == T_polyline,
nullptr,
1806 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a poly." ) );
1818 if( token == T_private )
1820 poly->SetPrivate(
true );
1824 for( ; token != T_RIGHT; token = NextTok() )
1826 if( token != T_LEFT )
1827 Expecting( T_LEFT );
1834 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1836 if( token != T_LEFT )
1837 Expecting( T_LEFT );
1844 poly->AddPoint(
parseXY(
true ) );
1853 poly->SetStroke( stroke );
1859 poly->SetFillColor( fill.
m_Color );
1863 Expecting(
"pts, stroke, or fill" );
1867 return poly.release();
1873 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
1874 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
1881 rectangle->SetUnit(
m_unit );
1886 if( token == T_private )
1888 rectangle->SetPrivate(
true );
1892 for( ; token != T_RIGHT; token = NextTok() )
1894 if( token != T_LEFT )
1895 Expecting( T_LEFT );
1902 rectangle->SetPosition(
parseXY(
true ) );
1907 rectangle->SetEnd(
parseXY(
true ) );
1918 rectangle->SetStroke( stroke );
1924 rectangle->SetFillColor( fill.
m_Color );
1928 Expecting(
"start, end, stroke, or fill" );
1932 return rectangle.release();
1938 wxCHECK_MSG( CurTok() == T_text,
nullptr,
1939 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text token." ) );
1942 std::unique_ptr<SCH_TEXT>
text = std::make_unique<SCH_TEXT>();
1949 if( token == T_private )
1951 text->SetPrivate(
true );
1955 if( !IsSymbol( token ) )
1957 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1961 text->SetText( FromUTF8() );
1963 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1965 if( token != T_LEFT )
1966 Expecting( T_LEFT );
1984 Expecting(
"at or effects" );
1989 if( !
text->IsVisible() )
1992 return text.release();
1998 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
1999 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
2011 bool foundEnd =
false;
2012 bool foundSize =
false;
2013 bool foundMargins =
false;
2015 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>(
LAYER_DEVICE );
2017 textBox->SetUnit(
m_unit );
2021 if( token == T_private )
2023 textBox->SetPrivate(
true );
2027 if( !IsSymbol( token ) )
2029 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
2033 textBox->SetText( FromUTF8() );
2035 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2037 if( token != T_LEFT )
2038 Expecting( T_LEFT );
2069 textBox->SetStroke( stroke );
2075 textBox->SetFillColor( fill.
m_Color );
2080 textBox->SetMarginLeft(
left );
2081 textBox->SetMarginTop(
top );
2082 textBox->SetMarginRight(
right );
2083 textBox->SetMarginBottom( bottom );
2084 foundMargins =
true;
2093 Expecting(
"at, size, stroke, fill or effects" );
2097 textBox->SetPosition( pos );
2100 textBox->SetEnd(
end );
2101 else if( foundSize )
2102 textBox->SetEnd( pos + size );
2104 Expecting(
"size" );
2108 int margin = textBox->GetLegacyTextMargin();
2109 textBox->SetMarginLeft( margin );
2110 textBox->SetMarginTop( margin );
2111 textBox->SetMarginRight( margin );
2112 textBox->SetMarginBottom( margin );
2115 return textBox.release();
2121 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
2122 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
2128 wxString pageType = FromUTF8();
2130 if( !aPageInfo.
SetType( pageType ) )
2132 THROW_PARSE_ERROR(
_(
"Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
2159 if( token == T_portrait )
2164 else if( token != T_RIGHT )
2166 Expecting(
"portrait" );
2173 wxCHECK_RET( CurTok() == T_title_block,
2174 "Cannot parse " + GetTokenString( CurTok() ) +
" as a TITLE_BLOCK." );
2178 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2180 if( token != T_LEFT )
2181 Expecting( T_LEFT );
2189 aTitleBlock.
SetTitle( FromUTF8() );
2194 aTitleBlock.
SetDate( FromUTF8() );
2209 int commentNumber =
parseInt(
"comment" );
2211 switch( commentNumber )
2260 CurLine(), CurLineNumber(), CurOffset() );
2267 Expecting(
"title, date, rev, company, or comment" );
2277 wxCHECK_MSG( CurTok() == T_property,
nullptr,
2278 "Cannot parse " + GetTokenString( CurTok() ) +
" as a property token." );
2280 bool is_private =
false;
2282 T token = NextTok();
2284 if( token == T_private )
2290 if( !IsSymbol( token ) )
2292 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
2296 wxString
name = FromUTF8();
2298 if(
name.IsEmpty() )
2300 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
2306 if( !IsSymbol( token ) )
2308 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
2316 value = wxEmptyString;
2348 if(
name.CmpNoCase( wxT(
"Sheet name" ) ) == 0 )
2350 else if(
name.CmpNoCase( wxT(
"Sheet file" ) ) == 0 )
2365 if(
name.CmpNoCase( wxT(
"Intersheet References" ) ) == 0 )
2369 std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>( aParent, fieldId,
name );
2370 field->SetText( value );
2373 field->SetPrivate( is_private );
2375 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2377 if( token != T_LEFT )
2378 Expecting( T_LEFT );
2390 field->SetPosition(
parseXY() );
2408 field->SetNameShown( show );
2412 case T_do_not_autoplace:
2415 field->SetCanAutoplace( !doNotAutoplace );
2420 Expecting(
"id, at, hide, show_name, do_not_autoplace or effects" );
2424 return field.release();
2430 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
2431 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
2432 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
2434 T token = NextTok();
2436 if( !IsSymbol( token ) )
2438 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2442 wxString
name = FromUTF8();
2444 if(
name.IsEmpty() )
2446 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2450 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet,
VECTOR2I( 0, 0 ),
name );
2462 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2465 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2467 if( token != T_LEFT )
2468 Expecting( T_LEFT );
2476 sheetPin->SetPosition(
parseXY() );
2478 double angle =
parseDouble(
"sheet pin angle (side)" );
2482 else if( angle == 90.0 )
2484 else if( angle == 180.0 )
2486 else if( angle == 270.0 )
2489 Expecting(
"0, 90, 180, or 270" );
2506 Expecting(
"at, uuid or effects" );
2510 return sheetPin.release();
2516 wxCHECK_RET( CurTok() == T_sheet_instances,
2517 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2518 wxCHECK( aScreen, );
2522 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2524 if( token != T_LEFT )
2525 Expecting( T_LEFT );
2543 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2545 if( token != T_LEFT )
2546 Expecting( T_LEFT );
2550 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
2553 size_t numReplacements = 0;
2571 for(
const wxString& ch : whitespaces )
2572 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
2577 if( numReplacements > 0 )
2584 Expecting(
"path or page" );
2589 && ( instance.
m_Path.empty() ) )
2605 Expecting(
"path" );
2613 wxCHECK_RET( CurTok() == T_symbol_instances,
2614 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2615 wxCHECK( aScreen, );
2620 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2622 if( token != T_LEFT )
2623 Expecting( T_LEFT );
2640 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2642 if( token != T_LEFT )
2643 Expecting( T_LEFT );
2664 instance.
m_Value = wxEmptyString;
2666 instance.
m_Value = FromUTF8();
2683 Expecting(
"path, unit, value or footprint" );
2692 Expecting(
"path" );
2701 wxCHECK( aSheet !=
nullptr, );
2705 wxCHECK( screen !=
nullptr, );
2708 m_maxError = schematic->Settings().m_MaxError;
2710 if( aIsCopyableOnly )
2713 bool fileHasUuid =
false;
2727 if( !aIsCopyableOnly )
2732 if( CurTok() != T_kicad_sch )
2733 Expecting(
"kicad_sch" );
2752 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2754 if( aIsCopyableOnly && token == T_EOF )
2757 if( token != T_LEFT )
2758 Expecting( T_LEFT );
2792 case T_generator_version:
2818 if( aIsCopyableOnly )
2819 Unexpected( T_paper );
2829 if( aIsCopyableOnly )
2830 Unexpected( T_page );
2834 NeedSYMBOLorNUMBER();
2835 NeedSYMBOLorNUMBER();
2842 if( aIsCopyableOnly )
2843 Unexpected( T_title_block );
2857 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2859 if( token != T_LEFT )
2860 Expecting( T_LEFT );
2872 Expecting(
"symbol" );
2973 case T_netclass_flag:
2978 case T_global_label:
2979 case T_hierarchical_label:
2980 case T_directive_label:
2992 case T_sheet_instances:
2996 case T_symbol_instances:
3001 if( aIsCopyableOnly )
3002 Unexpected( T_bus_alias );
3007 case T_embedded_fonts:
3013 CurLineNumber(), CurOffset() );
3020 case T_embedded_files:
3026 CurLineNumber(), CurOffset() );
3029 embeddedFilesParser.SyncLineReaderWith( *
this );
3040 SyncLineReaderWith( embeddedFilesParser );
3046 Expecting(
"bitmap, bus, bus_alias, bus_entry, class_label, embedded_files, global_label, "
3047 "hierarchical_label, junction, label, line, no_connect, page, paper, rule_area, "
3048 "sheet, symbol, symbol_instances, text, title_block" );
3069 CurLineNumber(), CurOffset() );
3073 std::vector<std::string> fontNames;
3074 Fontconfig()->ListFonts( fontNames, std::string(
Pgm().GetLanguageTag().utf8_str() ),
3084 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
3085 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
3090 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
3092 std::set<int> fieldIDsRead;
3097 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3099 if( token != T_LEFT )
3100 Expecting( T_LEFT );
3112 if( !IsSymbol( token ) )
3115 CurLineNumber(), CurOffset() );
3118 libName = FromUTF8();
3122 libName.Replace(
"{slash}",
"/" );
3132 if( !IsSymbol( token ) && token != T_NUMBER )
3133 Expecting(
"symbol|number" );
3136 wxString
name = FromUTF8();
3140 name.Replace(
"{slash}",
"/" );
3146 if(
static_cast<int>(
name.size() ) > bad_pos )
3148 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
3156 CurLineNumber(), CurOffset() );
3159 symbol->SetLibId( libId );
3165 symbol->SetPosition(
parseXY() );
3167 switch(
static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
3170 case 90: transform =
TRANSFORM( 0, 1, -1, 0 );
break;
3171 case 180: transform =
TRANSFORM( -1, 0, 0, -1 );
break;
3172 case 270: transform =
TRANSFORM( 0, -1, 1, 0 );
break;
3173 default: Expecting(
"0, 90, 180, or 270" );
3176 symbol->SetTransform( transform );
3185 else if( token == T_y )
3188 Expecting(
"x or y" );
3194 symbol->SetUnit(
parseInt(
"symbol unit" ) );
3200 symbol->SetBodyStyle(
parseInt(
"symbol body style" ) );
3204 case T_exclude_from_sim:
3205 symbol->SetExcludedFromSim(
parseBool() );
3210 symbol->SetExcludedFromBOM( !
parseBool() );
3215 symbol->SetExcludedFromBoard( !
parseBool() );
3219 case T_in_pos_files:
3220 symbol->SetExcludedFromPosFiles( !
parseBool() );
3229 case T_fields_autoplaced:
3241 case T_default_instance:
3245 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3247 if( token != T_LEFT )
3248 Expecting( T_LEFT );
3269 symbol->SetValueFieldText( wxEmptyString );
3271 symbol->SetValueFieldText( FromUTF8() );
3280 symbol->SetFootprintFieldText( wxEmptyString );
3282 symbol->SetFootprintFieldText( FromUTF8() );
3288 Expecting(
"reference, unit, value or footprint" );
3297 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3299 if( token != T_LEFT )
3300 Expecting( T_LEFT );
3304 if( token != T_project )
3305 Expecting(
"project" );
3309 wxString projectName = FromUTF8();
3311 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3313 if( token != T_LEFT )
3314 Expecting( T_LEFT );
3318 if( token != T_path )
3319 Expecting(
"path" );
3328 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3330 if( token != T_LEFT )
3331 Expecting( T_LEFT );
3352 symbol->SetValueFieldText( wxEmptyString );
3354 symbol->SetValueFieldText( FromUTF8() );
3363 symbol->SetFootprintFieldText( wxEmptyString );
3365 symbol->SetFootprintFieldText( FromUTF8() );
3375 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3377 if( token != T_LEFT )
3378 Expecting( T_LEFT );
3386 variant.
m_Name = FromUTF8();
3395 case T_exclude_from_sim:
3410 case T_in_pos_files:
3418 wxString fieldValue;
3420 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3422 if( token != T_LEFT )
3423 Expecting( T_LEFT );
3431 fieldName = FromUTF8();
3437 fieldValue = FromUTF8();
3442 Expecting(
"name or value" );
3446 variant.
m_Fields[fieldName] = fieldValue;
3451 Expecting(
"dnp, exclude_from_sim, field, in_bom, in_pos_files, name, or on_board" );
3461 Expecting(
"reference, unit, value, footprint, or variant" );
3465 symbol->AddHierarchicalReference( instance );
3481 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3488 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3495 existing = symbol->GetField( field->
GetId() );
3497 existing = symbol->GetField( field->
GetName() );
3502 symbol->AddField( *field );
3505 symbol->UpdatePrefix();
3518 number = FromUTF8();
3520 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3522 if( token != T_LEFT )
3523 Expecting( T_LEFT );
3547 Expecting(
"alternate or uuid" );
3551 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3557 Expecting(
"lib_id, lib_name, at, mirror, uuid, exclude_from_sim, on_board, in_bom, dnp, "
3558 "default_instance, property, pin, or instances" );
3562 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3563 symbol->SetSchSymbolLibraryName( libName );
3566 symbol->ClearFlags();
3568 return symbol.release();
3574 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3575 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3578 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3581 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3583 if( token != T_LEFT )
3584 Expecting( T_LEFT );
3591 bitmap->SetPosition(
parseXY() );
3617 data.reserve( 1 << 17 );
3619 while( token != T_RIGHT )
3621 if( !IsSymbol( token ) )
3622 Expecting(
"base64 image data" );
3628 wxMemoryBuffer buffer = wxBase64Decode( data );
3637 Expecting(
"at, scale, uuid or data" );
3650 return bitmap.release();
3656 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3657 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3663 std::vector<SCH_FIELD> fields;
3664 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3665 std::set<int> fieldIDsRead;
3670 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3672 if( token != T_LEFT )
3673 Expecting( T_LEFT );
3680 sheet->SetPosition(
parseXY() );
3689 sheet->SetSize( size );
3694 case T_exclude_from_sim:
3695 sheet->SetExcludedFromSim(
parseBool() );
3700 sheet->SetExcludedFromBOM( !
parseBool() );
3705 sheet->SetExcludedFromBoard( !
parseBool() );
3714 case T_fields_autoplaced:
3722 sheet->SetBorderWidth( stroke.
GetWidth() );
3723 sheet->SetBorderColor( stroke.
GetColor() );
3728 sheet->SetBackgroundColor( fill.
m_Color );
3745 if( fields.empty() )
3751 fields.emplace_back( *field );
3762 std::vector<SCH_SHEET_INSTANCE> instances;
3764 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3766 if( token != T_LEFT )
3767 Expecting( T_LEFT );
3771 if( token != T_project )
3772 Expecting(
"project" );
3776 wxString projectName = FromUTF8();
3778 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3780 if( token != T_LEFT )
3781 Expecting( T_LEFT );
3785 if( token != T_path )
3786 Expecting(
"path" );
3795 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3797 if( token != T_LEFT )
3798 Expecting( T_LEFT );
3818 static std::vector<wxString> whitespaces =
3824 for( wxString ch : whitespaces )
3836 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3838 if( token != T_LEFT )
3839 Expecting( T_LEFT );
3847 variant.
m_Name = FromUTF8();
3856 case T_exclude_from_sim:
3871 case T_in_pos_files:
3879 wxString fieldValue;
3881 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3883 if( token != T_LEFT )
3884 Expecting( T_LEFT );
3892 fieldName = FromUTF8();
3898 fieldValue = FromUTF8();
3903 Expecting(
"name or value" );
3907 variant.
m_Fields[fieldName] = fieldValue;
3912 Expecting(
"dnp, exclude_from_sim, field, in_bom, in_pos_files, name, or on_board" );
3922 Expecting(
"page or variant" );
3926 instances.emplace_back( instance );
3930 sheet->setInstances( instances );
3935 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3939 sheet->SetFields( fields );
3941 return sheet.release();
3947 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3948 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3951 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3953 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3955 if( token != T_LEFT )
3956 Expecting( T_LEFT );
3963 junction->SetPosition(
parseXY() );
3979 color.
a = std::clamp(
parseDouble(
"alpha" ), 0.0, 1.0 );
3981 junction->SetColor( color );
3993 Expecting(
"at, diameter, color or uuid" );
3997 return junction.release();
4003 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
4004 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
4007 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
4009 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4011 if( token != T_LEFT )
4012 Expecting( T_LEFT );
4019 no_connect->SetPosition(
parseXY() );
4030 Expecting(
"at or uuid" );
4034 return no_connect.release();
4040 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
4041 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
4045 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
4047 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4049 if( token != T_LEFT )
4050 Expecting( T_LEFT );
4057 busEntry->SetPosition(
parseXY() );
4067 busEntry->SetSize( size );
4074 busEntry->SetStroke( stroke );
4084 Expecting(
"at, size, uuid or stroke" );
4088 return busEntry.release();
4110 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4112 if( token != T_LEFT )
4113 Expecting( T_LEFT );
4120 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4122 if( token != T_LEFT )
4123 Expecting( T_LEFT );
4130 polyline->AddPoint(
parseXY() );
4143 polyline->SetStroke( stroke );
4149 polyline->SetFillColor( fill.
m_Color );
4160 Expecting(
"pts, uuid, stroke, or fill" );
4164 return polyline.release();
4183 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
4186 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
4188 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4190 if( token != T_LEFT )
4191 Expecting( T_LEFT );
4204 line->SetStartPoint(
parseXY() );
4212 line->SetEndPoint(
parseXY() );
4219 line->SetStroke( stroke );
4229 Expecting(
"at, uuid or stroke" );
4233 return line.release();
4239 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
4240 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
4248 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>(
SHAPE_T::ARC );
4250 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4252 if( token != T_LEFT )
4253 Expecting( T_LEFT );
4276 arc->SetStroke( stroke );
4282 arc->SetFillColor( fill.
m_Color );
4288 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
4293 Expecting(
"start, mid, end, stroke, fill or uuid" );
4297 arc->SetArcGeometry( startPoint, midPoint, endPoint );
4299 return arc.release();
4305 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
4306 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
4315 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4317 if( token != T_LEFT )
4318 Expecting( T_LEFT );
4336 circle->SetStroke( stroke );
4353 Expecting(
"center, radius, stroke, fill or uuid" );
4366 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
4367 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
4372 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>(
SHAPE_T::RECTANGLE );
4374 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4376 if( token != T_LEFT )
4377 Expecting( T_LEFT );
4384 rectangle->SetPosition(
parseXY() );
4389 rectangle->SetEnd(
parseXY() );
4400 rectangle->SetStroke( stroke );
4406 rectangle->SetFillColor( fill.
m_Color );
4412 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4417 Expecting(
"start, end, stroke, fill or uuid" );
4421 return rectangle.release();
4427 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4428 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4433 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4435 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4437 if( token != T_LEFT )
4438 Expecting( T_LEFT );
4452 ruleArea->SetPolyShape( sch_rule_poly );
4454 ruleArea->SetStroke( poly->GetStroke() );
4455 ruleArea->SetFillMode( poly->GetFillMode() );
4456 ruleArea->SetFillColor( poly->GetFillColor() );
4459 const_cast<KIID&
>( ruleArea->m_Uuid ) = poly->m_Uuid;
4463 case T_exclude_from_sim:
4464 ruleArea->SetExcludedFromSim(
parseBool() );
4469 ruleArea->SetExcludedFromBOM( !
parseBool() );
4474 ruleArea->SetExcludedFromBoard( !
parseBool() );
4484 Expecting(
"exclude_from_sim, on_board, in_bom, dnp, or polyline" );
4488 return ruleArea.release();
4494 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4495 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4500 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>(
SHAPE_T::BEZIER );
4502 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4504 if( token != T_LEFT )
4505 Expecting( T_LEFT );
4515 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4517 if( token != T_LEFT )
4518 Expecting( T_LEFT );
4527 case 0: bezier->SetStart(
parseXY() );
break;
4528 case 1: bezier->SetBezierC1(
parseXY() );
break;
4529 case 2: bezier->SetBezierC2(
parseXY() );
break;
4530 case 3: bezier->SetEnd(
parseXY() );
break;
4531 default: Unexpected(
"control point" );
break;
4541 bezier->SetStroke( stroke );
4547 bezier->SetFillColor( fill.
m_Color );
4553 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4558 Expecting(
"pts, stroke, fill or uuid" );
4562 bezier->RebuildBezierToSegmentsPointsList(
m_maxError );
4564 return bezier.release();
4571 std::unique_ptr<SCH_TEXT>
text;
4575 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4576 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4577 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4578 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4579 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4580 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4582 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4590 text->SetText( FromUTF8() );
4592 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4594 if( token != T_LEFT )
4595 Expecting( T_LEFT );
4601 case T_exclude_from_sim:
4612 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4628 Unexpected( T_shape );
4646 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4657 Unexpected( T_length );
4666 case T_fields_autoplaced:
4676 text->SetVisible(
true );
4701 Unexpected( T_property );
4721 Expecting(
"at, shape, iref, uuid or effects" );
4727 if( label && label->
GetFields().empty() )
4730 return text.release();
4736 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4737 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4739 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4743 return textBox.release();
4749 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4750 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4752 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4756 return cell.release();
4772 bool foundEnd =
false;
4773 bool foundSize =
false;
4774 bool foundMargins =
false;
4778 aTextBox->
SetText( FromUTF8() );
4780 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4782 if( token != T_LEFT )
4783 Expecting( T_LEFT );
4789 case T_exclude_from_sim:
4820 cell->SetColSpan(
parseInt(
"column span" ) );
4821 cell->SetRowSpan(
parseInt(
"row span" ) );
4825 Expecting(
"at, size, stroke, fill, effects or uuid" );
4849 foundMargins =
true;
4865 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4867 Expecting(
"at, size, stroke, fill, effects or uuid" );
4875 else if( foundSize )
4876 aTextBox->
SetEnd( pos + size );
4878 Expecting(
"size" );
4893 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4894 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4900 std::unique_ptr<SCH_TABLE>
table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4902 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4904 if( token != T_LEFT )
4905 Expecting( T_LEFT );
4911 case T_column_count:
4916 case T_column_widths:
4920 while( ( token = NextTok() ) != T_RIGHT )
4930 while( ( token = NextTok() ) != T_RIGHT )
4937 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4939 if( token != T_LEFT )
4940 Expecting( T_LEFT );
4944 if( token != T_table_cell )
4945 Expecting(
"table_cell" );
4953 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4955 if( token != T_LEFT )
4956 Expecting( T_LEFT );
4974 table->SetBorderStroke( borderStroke );
4978 Expecting(
"external, header or stroke" );
4986 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4988 if( token != T_LEFT )
4989 Expecting( T_LEFT );
5007 table->SetSeparatorsStroke( separatorsStroke );
5011 Expecting(
"rows, cols, or stroke" );
5025 Expecting(
"columns, col_widths, row_heights, border, separators, uuid, header or cells" );
5029 return table.release();
5035 wxCHECK_RET( CurTok() == T_bus_alias,
5036 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
5037 wxCHECK( aScreen, );
5040 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>();
5051 busAlias->SetName( alias );
5056 if( token != T_members )
5057 Expecting(
"members" );
5061 while( token != T_RIGHT )
5063 if( !IsSymbol( token ) )
5064 Expecting(
"quoted string" );
5066 member = FromUTF8();
5071 busAlias->Members().emplace_back( member );
5086 while( ( token = NextTok() ) != T_RIGHT )
5091 KIID uuid( CurStr() );
5099 wxCHECK_RET( CurTok() == T_group,
5100 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
5107 while( ( token = NextTok() ) != T_LEFT )
5109 if( token == T_STRING )
5110 groupInfo.
name = FromUTF8();
5112 Expecting(
"group name or locked" );
5115 for( ; token != T_RIGHT; token = NextTok() )
5117 if( token != T_LEFT )
5118 Expecting( T_LEFT );
5134 if( !IsSymbol( token ) && token != T_NUMBER )
5135 Expecting(
"symbol|number" );
5138 wxString
name = FromUTF8();
5142 name.Replace(
"{slash}",
"/" );
5148 if(
static_cast<int>(
name.size() ) > bad_pos )
5150 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
name,
5156 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
5170 Expecting(
"uuid, lib_id, members" );
5182 [&](
const KIID& aId )
5188 if( item->m_Uuid == aId )
5207 group->SetName( groupInfo.name );
5209 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo.uuid;
5211 if( groupInfo.libId.IsValid() )
5212 group->SetDesignBlockLibId( groupInfo.libId );
5223 for(
const KIID& aUuid : groupInfo.memberUuids )
5225 if(
SCH_ITEM* gItem = getItem( aUuid ) )
5226 group->AddItem( gItem );
5241 T token = NextTok();
5243 if( token == T_EOF )
5245 else if( token == T_LEFT )
5247 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.
virtual void SetParent(EDA_ITEM *aParent)
EDA_ITEM * GetParent() const
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