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" ) );
3489 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3497 existing = symbol->GetField( field->
GetId() );
3499 existing = symbol->GetField( field->
GetName() );
3504 symbol->AddField( *field );
3507 symbol->UpdatePrefix();
3520 number = FromUTF8();
3522 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3524 if( token != T_LEFT )
3525 Expecting( T_LEFT );
3549 Expecting(
"alternate or uuid" );
3553 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3559 Expecting(
"lib_id, lib_name, at, mirror, uuid, exclude_from_sim, on_board, in_bom, dnp, "
3560 "default_instance, property, pin, or instances" );
3564 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3565 symbol->SetSchSymbolLibraryName( libName );
3568 symbol->ClearFlags();
3570 return symbol.release();
3576 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3577 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3580 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3583 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3585 if( token != T_LEFT )
3586 Expecting( T_LEFT );
3593 bitmap->SetPosition(
parseXY() );
3619 data.reserve( 1 << 17 );
3621 while( token != T_RIGHT )
3623 if( !IsSymbol( token ) )
3624 Expecting(
"base64 image data" );
3630 wxMemoryBuffer buffer = wxBase64Decode( data );
3639 Expecting(
"at, scale, uuid or data" );
3652 return bitmap.release();
3658 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3659 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3665 std::vector<SCH_FIELD> fields;
3666 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3667 std::set<int> fieldIDsRead;
3672 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3674 if( token != T_LEFT )
3675 Expecting( T_LEFT );
3682 sheet->SetPosition(
parseXY() );
3691 sheet->SetSize( size );
3696 case T_exclude_from_sim:
3697 sheet->SetExcludedFromSim(
parseBool() );
3702 sheet->SetExcludedFromBOM( !
parseBool() );
3707 sheet->SetExcludedFromBoard( !
parseBool() );
3716 case T_fields_autoplaced:
3724 sheet->SetBorderWidth( stroke.
GetWidth() );
3725 sheet->SetBorderColor( stroke.
GetColor() );
3730 sheet->SetBackgroundColor( fill.
m_Color );
3747 if( fields.empty() )
3753 fields.emplace_back( *field );
3764 std::vector<SCH_SHEET_INSTANCE> instances;
3766 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3768 if( token != T_LEFT )
3769 Expecting( T_LEFT );
3773 if( token != T_project )
3774 Expecting(
"project" );
3778 wxString projectName = FromUTF8();
3780 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3782 if( token != T_LEFT )
3783 Expecting( T_LEFT );
3787 if( token != T_path )
3788 Expecting(
"path" );
3797 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3799 if( token != T_LEFT )
3800 Expecting( T_LEFT );
3820 static std::vector<wxString> whitespaces =
3826 for( wxString ch : whitespaces )
3838 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3840 if( token != T_LEFT )
3841 Expecting( T_LEFT );
3849 variant.
m_Name = FromUTF8();
3858 case T_exclude_from_sim:
3873 case T_in_pos_files:
3881 wxString fieldValue;
3883 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3885 if( token != T_LEFT )
3886 Expecting( T_LEFT );
3894 fieldName = FromUTF8();
3900 fieldValue = FromUTF8();
3905 Expecting(
"name or value" );
3909 variant.
m_Fields[fieldName] = fieldValue;
3914 Expecting(
"dnp, exclude_from_sim, field, in_bom, in_pos_files, name, or on_board" );
3924 Expecting(
"page or variant" );
3928 instances.emplace_back( instance );
3932 sheet->setInstances( instances );
3937 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3941 sheet->SetFields( fields );
3943 return sheet.release();
3949 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3950 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3953 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3955 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3957 if( token != T_LEFT )
3958 Expecting( T_LEFT );
3965 junction->SetPosition(
parseXY() );
3981 color.
a = std::clamp(
parseDouble(
"alpha" ), 0.0, 1.0 );
3983 junction->SetColor( color );
3995 Expecting(
"at, diameter, color or uuid" );
3999 return junction.release();
4005 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
4006 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
4009 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
4011 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4013 if( token != T_LEFT )
4014 Expecting( T_LEFT );
4021 no_connect->SetPosition(
parseXY() );
4032 Expecting(
"at or uuid" );
4036 return no_connect.release();
4042 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
4043 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
4047 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
4049 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4051 if( token != T_LEFT )
4052 Expecting( T_LEFT );
4059 busEntry->SetPosition(
parseXY() );
4069 busEntry->SetSize( size );
4076 busEntry->SetStroke( stroke );
4086 Expecting(
"at, size, uuid or stroke" );
4090 return busEntry.release();
4112 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4114 if( token != T_LEFT )
4115 Expecting( T_LEFT );
4122 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4124 if( token != T_LEFT )
4125 Expecting( T_LEFT );
4132 polyline->AddPoint(
parseXY() );
4145 polyline->SetStroke( stroke );
4151 polyline->SetFillColor( fill.
m_Color );
4162 Expecting(
"pts, uuid, stroke, or fill" );
4166 return polyline.release();
4185 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
4188 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
4190 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4192 if( token != T_LEFT )
4193 Expecting( T_LEFT );
4206 line->SetStartPoint(
parseXY() );
4214 line->SetEndPoint(
parseXY() );
4221 line->SetStroke( stroke );
4231 Expecting(
"at, uuid or stroke" );
4235 return line.release();
4241 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
4242 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
4250 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>(
SHAPE_T::ARC );
4252 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4254 if( token != T_LEFT )
4255 Expecting( T_LEFT );
4278 arc->SetStroke( stroke );
4284 arc->SetFillColor( fill.
m_Color );
4290 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
4295 Expecting(
"start, mid, end, stroke, fill or uuid" );
4299 arc->SetArcGeometry( startPoint, midPoint, endPoint );
4301 return arc.release();
4307 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
4308 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
4317 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4319 if( token != T_LEFT )
4320 Expecting( T_LEFT );
4338 circle->SetStroke( stroke );
4355 Expecting(
"center, radius, stroke, fill or uuid" );
4368 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
4369 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
4374 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>(
SHAPE_T::RECTANGLE );
4376 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4378 if( token != T_LEFT )
4379 Expecting( T_LEFT );
4386 rectangle->SetPosition(
parseXY() );
4391 rectangle->SetEnd(
parseXY() );
4402 rectangle->SetStroke( stroke );
4408 rectangle->SetFillColor( fill.
m_Color );
4414 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4419 Expecting(
"start, end, stroke, fill or uuid" );
4423 return rectangle.release();
4429 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4430 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4435 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4437 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4439 if( token != T_LEFT )
4440 Expecting( T_LEFT );
4454 ruleArea->SetPolyShape( sch_rule_poly );
4456 ruleArea->SetStroke( poly->GetStroke() );
4457 ruleArea->SetFillMode( poly->GetFillMode() );
4458 ruleArea->SetFillColor( poly->GetFillColor() );
4461 const_cast<KIID&
>( ruleArea->m_Uuid ) = poly->m_Uuid;
4465 case T_exclude_from_sim:
4466 ruleArea->SetExcludedFromSim(
parseBool() );
4471 ruleArea->SetExcludedFromBOM( !
parseBool() );
4476 ruleArea->SetExcludedFromBoard( !
parseBool() );
4486 Expecting(
"exclude_from_sim, on_board, in_bom, dnp, or polyline" );
4490 return ruleArea.release();
4496 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4497 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4502 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>(
SHAPE_T::BEZIER );
4504 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4506 if( token != T_LEFT )
4507 Expecting( T_LEFT );
4517 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4519 if( token != T_LEFT )
4520 Expecting( T_LEFT );
4529 case 0: bezier->SetStart(
parseXY() );
break;
4530 case 1: bezier->SetBezierC1(
parseXY() );
break;
4531 case 2: bezier->SetBezierC2(
parseXY() );
break;
4532 case 3: bezier->SetEnd(
parseXY() );
break;
4533 default: Unexpected(
"control point" );
break;
4543 bezier->SetStroke( stroke );
4549 bezier->SetFillColor( fill.
m_Color );
4555 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4560 Expecting(
"pts, stroke, fill or uuid" );
4564 bezier->RebuildBezierToSegmentsPointsList(
m_maxError );
4566 return bezier.release();
4573 std::unique_ptr<SCH_TEXT>
text;
4577 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4578 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4579 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4580 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4581 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4582 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4584 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4592 text->SetText( FromUTF8() );
4594 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4596 if( token != T_LEFT )
4597 Expecting( T_LEFT );
4603 case T_exclude_from_sim:
4614 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4630 Unexpected( T_shape );
4648 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4659 Unexpected( T_length );
4668 case T_fields_autoplaced:
4678 text->SetVisible(
true );
4703 Unexpected( T_property );
4723 Expecting(
"at, shape, iref, uuid or effects" );
4729 if( label && label->
GetFields().empty() )
4732 return text.release();
4738 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4739 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4741 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4745 return textBox.release();
4751 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4752 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4754 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4758 return cell.release();
4774 bool foundEnd =
false;
4775 bool foundSize =
false;
4776 bool foundMargins =
false;
4780 aTextBox->
SetText( FromUTF8() );
4782 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4784 if( token != T_LEFT )
4785 Expecting( T_LEFT );
4791 case T_exclude_from_sim:
4822 cell->SetColSpan(
parseInt(
"column span" ) );
4823 cell->SetRowSpan(
parseInt(
"row span" ) );
4827 Expecting(
"at, size, stroke, fill, effects or uuid" );
4851 foundMargins =
true;
4867 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4869 Expecting(
"at, size, stroke, fill, effects or uuid" );
4877 else if( foundSize )
4878 aTextBox->
SetEnd( pos + size );
4880 Expecting(
"size" );
4895 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4896 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4902 std::unique_ptr<SCH_TABLE>
table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4904 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4906 if( token != T_LEFT )
4907 Expecting( T_LEFT );
4913 case T_column_count:
4918 case T_column_widths:
4922 while( ( token = NextTok() ) != T_RIGHT )
4932 while( ( token = NextTok() ) != T_RIGHT )
4939 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4941 if( token != T_LEFT )
4942 Expecting( T_LEFT );
4946 if( token != T_table_cell )
4947 Expecting(
"table_cell" );
4955 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4957 if( token != T_LEFT )
4958 Expecting( T_LEFT );
4976 table->SetBorderStroke( borderStroke );
4980 Expecting(
"external, header or stroke" );
4988 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4990 if( token != T_LEFT )
4991 Expecting( T_LEFT );
5009 table->SetSeparatorsStroke( separatorsStroke );
5013 Expecting(
"rows, cols, or stroke" );
5027 Expecting(
"columns, col_widths, row_heights, border, separators, uuid, header or cells" );
5031 return table.release();
5037 wxCHECK_RET( CurTok() == T_bus_alias,
5038 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
5039 wxCHECK( aScreen, );
5042 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>();
5053 busAlias->SetName( alias );
5058 if( token != T_members )
5059 Expecting(
"members" );
5063 while( token != T_RIGHT )
5065 if( !IsSymbol( token ) )
5066 Expecting(
"quoted string" );
5068 member = FromUTF8();
5073 busAlias->Members().emplace_back( member );
5088 while( ( token = NextTok() ) != T_RIGHT )
5093 KIID uuid( CurStr() );
5101 wxCHECK_RET( CurTok() == T_group,
5102 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
5109 while( ( token = NextTok() ) != T_LEFT )
5111 if( token == T_STRING )
5112 groupInfo.
name = FromUTF8();
5114 Expecting(
"group name or locked" );
5117 for( ; token != T_RIGHT; token = NextTok() )
5119 if( token != T_LEFT )
5120 Expecting( T_LEFT );
5136 if( !IsSymbol( token ) && token != T_NUMBER )
5137 Expecting(
"symbol|number" );
5140 wxString
name = FromUTF8();
5144 name.Replace(
"{slash}",
"/" );
5150 if(
static_cast<int>(
name.size() ) > bad_pos )
5152 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
name,
5158 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
5172 Expecting(
"uuid, lib_id, members" );
5184 [&](
const KIID& aId )
5190 if( item->m_Uuid == aId )
5209 group->SetName( groupInfo.name );
5211 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo.uuid;
5213 if( groupInfo.libId.IsValid() )
5214 group->SetDesignBlockLibId( groupInfo.libId );
5225 for(
const KIID& aUuid : groupInfo.memberUuids )
5227 if(
SCH_ITEM* gItem = getItem( aUuid ) )
5228 group->AddItem( gItem );
5243 T token = NextTok();
5245 if( token == T_EOF )
5247 else if( token == T_LEFT )
5249 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