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:
252 aSymbolLibMap[symbol->
GetName()] = symbol;
257 Expecting(
"symbol, generator, or generator_version" );
271 if( CurTok() == T_LEFT )
275 if( CurTok() == T_symbol )
280 const std::vector<wxString>* embeddedFonts =
287 textItem->ResolveFont( embeddedFonts );
293 wxString msg = wxString::Format(
_(
"Cannot parse %s as a symbol" ),
294 GetTokenString( CurTok() ) );
305 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
306 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
313 std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
315 symbol->SetUnitCount( 1,
true );
319 if( !IsSymbol( token ) )
320 THROW_PARSE_ERROR(
_(
"Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
327 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
334 if(
static_cast<int>(
name.size() ) > bad_pos )
336 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
345 CurLineNumber(), CurOffset() );
350 symbol->SetLibId(
id );
352 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
354 if( token != T_LEFT )
362 symbol->SetGlobalPower();
365 if( token == T_RIGHT )
368 if( token == T_local )
369 symbol->SetLocalPower();
370 else if( token != T_global )
371 Expecting(
"global or local" );
388 case T_exclude_from_sim:
389 symbol->SetExcludedFromSim(
parseBool() );
394 symbol->SetExcludedFromBOM( !
parseBool() );
399 symbol->SetExcludedFromBoard( !
parseBool() );
403 case T_duplicate_pin_numbers_are_jumpers:
404 symbol->SetDuplicatePinNumbersAreJumpers(
parseBool() );
408 case T_jumper_pin_groups:
410 std::vector<std::set<wxString>>& groups = symbol->JumperPinGroups();
411 std::set<wxString>* currentGroup =
nullptr;
413 for( token = NextTok(); currentGroup || token != T_RIGHT; token = NextTok() )
415 switch(
static_cast<int>( token ) )
418 currentGroup = &groups.emplace_back();
422 currentGroup->insert( FromUTF8() );
426 currentGroup =
nullptr;
430 Expecting(
"list of pin names" );
445 if( !IsSymbol( token ) )
448 CurLineNumber(), CurOffset() );
456 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
458 symbol->SetParentName(
name );
467 if( !IsSymbol( token ) )
470 CurLineNumber(), CurOffset() );
478 name.Replace( wxS(
"{slash}" ), wxT(
"/" ) );
482 error.Printf(
_(
"Invalid symbol unit name prefix %s" ),
name.c_str() );
483 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
488 wxStringTokenizer tokenizer(
name,
"_" );
490 if( tokenizer.CountTokens() != 2 )
492 error.Printf(
_(
"Invalid symbol unit name suffix %s" ),
name.c_str() );
493 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
496 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
498 error.Printf(
_(
"Invalid symbol unit number %s" ),
name.c_str() );
499 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
502 m_unit =
static_cast<int>( tmp );
504 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
506 error.Printf(
_(
"Invalid symbol body style number %s" ),
name.c_str() );
507 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
513 symbol->SetBodyStyleCount(
m_bodyStyle,
false,
false );
515 if(
m_unit > symbol->GetUnitCount() )
516 symbol->SetUnitCount(
m_unit,
false );
518 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
520 if( token != T_LEFT )
530 if( IsSymbol( token ) )
531 symbol->GetUnitDisplayNames()[
m_unit] = FromUTF8();
546 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
549 symbol->AddDrawItem( item,
false );
553 Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
572 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
575 symbol->AddDrawItem( item,
false );
578 case T_embedded_fonts:
580 symbol->SetAreFontsEmbedded(
parseBool() );
585 case T_embedded_files:
588 embeddedFilesParser.SyncLineReaderWith( *
this );
592 embeddedFilesParser.
ParseEmbedded( symbol->GetEmbeddedFiles() );
596 wxLogError( e.
What() );
599 SyncLineReaderWith( embeddedFilesParser );
604 Expecting(
"pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
605 "rectangle, or text" );
609 symbol->GetDrawItems().sort();
612 const std::vector<wxString>* embeddedFonts = symbol->GetEmbeddedFiles()->UpdateFontFiles();
614 symbol->RunOnChildren(
618 textItem->ResolveFont( embeddedFonts );
625 symbol->SetHasDeMorganBodyStyles( symbol->HasLegacyAlternateBodyStyle() );
627 return symbol.release();
643 default: Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
657 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
659 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
667 constexpr double int_limit = std::numeric_limits<int>::max() * 0.7071;
669 return KiROUND( std::clamp( retval, -int_limit, int_limit ) );
676 strokeParser.SyncLineReaderWith( *
this );
679 SyncLineReaderWith( strokeParser );
685 wxCHECK_RET( CurTok() == T_fill,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a fill." );
692 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
694 if( token != T_LEFT )
714 default: Expecting(
"none, outline, hatch, reverse_hatch, "
715 "cross_hatch, color or background" );
736 Expecting(
"type or color" );
743 bool aEnforceMinTextSize )
745 wxCHECK_RET( aText && ( CurTok() == T_effects || CurTok() == T_href ),
746 "Cannot parse " + GetTokenString( CurTok() ) +
" as an EDA_TEXT." );
763 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
765 if( token == T_LEFT )
771 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
773 if( token == T_LEFT )
824 Expecting(
"face, size, thickness, line_spacing, bold, or italic" );
831 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
840 case T_mirror:
break;
841 default: Expecting(
"left, right, top, bottom, or mirror" );
850 wxString hyperlink = FromUTF8();
855 CurSource(), CurLine(), CurLineNumber(), CurOffset() );
874 Expecting(
"font, justify, hide or href" );
882 wxCHECK_RET( CurTok() == aHeaderType,
883 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
889 if( tok == T_version )
903 wxCHECK_RET( CurTok() == T_body_styles,
904 "Cannot parse " + GetTokenString( CurTok() ) +
" as a body_styles token." );
906 std::vector<wxString> names;
908 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
910 if( token == T_demorgan )
912 aSymbol->SetHasDeMorganBodyStyles(
true );
915 else if( !IsSymbol( token ) )
917 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
921 names.push_back( FromUTF8() );
925 aSymbol->SetBodyStyleNames( names );
931 wxCHECK_RET( CurTok() == T_pin_names,
932 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_name token." );
942 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
945 if( token == T_hide )
947 aSymbol->SetShowPinNames(
false );
951 if( token != T_LEFT )
966 aSymbol->SetShowPinNames( !
parseBool() );
971 Expecting(
"offset or hide" );
979 wxCHECK_RET( CurTok() == T_pin_numbers,
980 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_number token." );
989 for(
T token = NextTok(); token != T_RIGHT; token = NextTok() )
992 if( token == T_hide )
994 aSymbol->SetShowPinNumbers(
false );
998 if( token != T_LEFT )
1000 Expecting( T_LEFT );
1008 aSymbol->SetShowPinNumbers( !
parseBool() );
1013 Expecting(
"hide" );
1022 wxCHECK_MSG( CurTok() == T_property,
nullptr,
1023 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a property." ) );
1024 wxCHECK( aSymbol,
nullptr );
1029 bool isPrivate =
false;
1030 bool isVisible =
true;
1032 T token = NextTok();
1034 if( token == T_private )
1040 if( !IsSymbol( token ) )
1042 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
1048 if(
name.IsEmpty() )
1050 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
1064 auto field = std::make_unique<SCH_FIELD>( aSymbol.get(), fieldId,
name );
1065 field->SetPrivate( isPrivate );
1066 field->SetVisible( isVisible );
1070 if( !IsSymbol( token ) )
1072 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
1079 value = wxEmptyString;
1083 field->SetText( value );
1085 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1087 if( token != T_LEFT )
1088 Expecting( T_LEFT );
1100 field->SetPosition(
parseXY(
true ) );
1118 field->SetNameShown( show );
1122 case T_do_not_autoplace:
1125 field->SetCanAutoplace( !doNotAutoplace );
1130 Expecting(
"id, at, hide, show_name, do_not_autoplace, or effects" );
1136 if( field->IsMandatory() )
1138 existingField = aSymbol->GetField( field->GetId() );
1140 *existingField = *field;
1141 return existingField;
1143 else if(
name ==
"ki_keywords" )
1146 aSymbol->SetKeyWords( value );
1150 else if(
name ==
"ki_description" )
1152 aSymbol->SetDescription( value );
1155 else if(
name ==
"ki_fp_filters" )
1158 wxArrayString filters;
1159 wxStringTokenizer tokenizer( value,
" \t\r\n", wxTOKEN_STRTOK );
1161 while( tokenizer.HasMoreTokens() )
1163 wxString curr_token =
UnescapeString( tokenizer.GetNextToken() );
1164 filters.Add( curr_token );
1167 aSymbol->SetFPFilters( filters );
1170 else if(
name ==
"ki_locked" )
1174 aSymbol->LockUnits(
true );
1180 existingField = aSymbol->GetField( field->GetCanonicalName() );
1188 wxString base_name = field->GetCanonicalName();
1191 for(
int ii = 1; ii < 10 && existingField; ii++ )
1193 wxString newname = base_name;
1194 newname <<
'_' << ii;
1196 existingField = aSymbol->GetField( newname );
1198 if( !existingField )
1199 field->SetName( newname );
1203 if( !existingField )
1205 aSymbol->AddDrawItem( field.get(),
false );
1206 return field.release();
1219 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
1220 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
1226 bool hasMidPoint =
false;
1234 bool hasAngles =
false;
1243 if( token == T_private )
1245 arc->SetPrivate(
true );
1249 for( ; token != T_RIGHT; token = NextTok() )
1251 if( token != T_LEFT )
1252 Expecting( T_LEFT );
1275 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1277 if( token != T_LEFT )
1278 Expecting( T_LEFT );
1306 Expecting(
"at, length, or angles" );
1314 arc->SetStroke( stroke );
1320 arc->SetFillColor( fill.
m_Color );
1324 Expecting(
"start, mid, end, radius, stroke, or fill" );
1330 arc->SetArcGeometry( startPoint, midPoint, endPoint );
1341 EDA_ANGLE arc_start, arc_end, arc_angle;
1342 arc->CalcArcAngles( arc_start, arc_end );
1343 arc_angle = arc_end - arc_start;
1348 arc->SetStart( endPoint );
1349 arc->SetEnd( startPoint );
1352 arc->SetCenter( new_center );
1358 arc->SetCenter( new_center );
1362 else if( hasAngles )
1364 arc->SetCenter(
center );
1370 arc->SetStart( endPoint );
1371 arc->SetEnd( startPoint );
1375 EDA_ANGLE arc_start, arc_end, arc_angle;
1376 arc->CalcArcAngles( arc_start, arc_end );
1377 arc_angle = arc_end - arc_start;
1383 arc->SetStart( startPoint );
1384 arc->SetEnd( endPoint );
1392 arc->SetStart( startPoint );
1393 arc->SetEnd( endPoint );
1397 arc->SetCenter( new_center );
1403 wxFAIL_MSG(
"Setting arc without either midpoint or angles not implemented." );
1406 return arc.release();
1412 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
1413 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
1421 bezier->SetUnit(
m_unit );
1426 if( token == T_private )
1428 bezier->SetPrivate(
true );
1432 for( ; token != T_RIGHT; token = NextTok() )
1434 if( token != T_LEFT )
1435 Expecting( T_LEFT );
1445 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1447 if( token != T_LEFT )
1448 Expecting( T_LEFT );
1457 case 0: bezier->SetStart(
parseXY(
true ) );
break;
1458 case 1: bezier->SetBezierC1(
parseXY(
true ) );
break;
1459 case 2: bezier->SetBezierC2(
parseXY(
true ) );
break;
1460 case 3: bezier->SetEnd(
parseXY(
true ) );
break;
1461 default: Unexpected(
"control point" );
break;
1471 bezier->SetStroke( stroke );
1477 bezier->SetFillColor( fill.
m_Color );
1481 Expecting(
"pts, stroke, or fill" );
1485 bezier->RebuildBezierToSegmentsPointsList(
m_maxError );
1487 return bezier.release();
1493 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
1494 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
1509 if( token == T_private )
1511 circle->SetPrivate(
true );
1515 for( ; token != T_RIGHT; token = NextTok() )
1517 if( token != T_LEFT )
1518 Expecting( T_LEFT );
1536 circle->SetStroke( stroke );
1546 Expecting(
"center, radius, stroke, or fill" );
1579 Expecting(
"input, output, bidirectional, tri_state, passive, unspecified, "
1580 "power_in, power_out, open_collector, open_emitter, free or "
1602 Expecting(
"line, inverted, clock, inverted_clock, input_low, clock_low, "
1603 "output_low, edge_clock_high, non_logic" );
1608 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
1609 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a pin token." ) );
1612 std::unique_ptr<SCH_PIN>
pin = std::make_unique<SCH_PIN>(
nullptr );
1619 pin->SetType( parseType( token ) );
1623 pin->SetShape( parseShape( token ) );
1625 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1628 if( token == T_hide )
1630 pin->SetVisible(
false );
1634 if( token != T_LEFT )
1635 Expecting( T_LEFT );
1644 switch(
parseInt(
"pin orientation" ) )
1650 default: Expecting(
"0, 90, 180, or 270" );
1669 if( !IsSymbol( token ) )
1676 pin->SetName( wxEmptyString );
1680 pin->SetName( FromUTF8() );
1684 if( token != T_RIGHT )
1688 if( token == T_effects )
1695 pin->SetNameTextSize(
text.GetTextHeight() );
1700 Expecting(
"effects" );
1709 if( !IsSymbol( token ) )
1712 CurLineNumber(), CurOffset() );
1716 pin->SetNumber( wxEmptyString );
1720 pin->SetNumber( FromUTF8() );
1724 if( token != T_RIGHT )
1728 if( token == T_effects )
1735 pin->SetNumberTextSize(
text.GetTextHeight() );
1740 Expecting(
"effects" );
1752 if( !IsSymbol( token ) )
1755 CurLineNumber(), CurOffset() );
1761 alt.
m_Type = parseType( token );
1764 alt.
m_Shape = parseShape( token );
1766 pin->GetAlternates()[ alt.
m_Name ] = alt;
1773 Expecting(
"at, name, number, hide, length, or alternate" );
1777 return pin.release();
1783 wxCHECK_MSG( CurTok() == T_polyline,
nullptr,
1784 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a poly." ) );
1796 if( token == T_private )
1798 poly->SetPrivate(
true );
1802 for( ; token != T_RIGHT; token = NextTok() )
1804 if( token != T_LEFT )
1805 Expecting( T_LEFT );
1812 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1814 if( token != T_LEFT )
1815 Expecting( T_LEFT );
1822 poly->AddPoint(
parseXY(
true ) );
1831 poly->SetStroke( stroke );
1837 poly->SetFillColor( fill.
m_Color );
1841 Expecting(
"pts, stroke, or fill" );
1845 return poly.release();
1851 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
1852 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
1859 rectangle->SetUnit(
m_unit );
1864 if( token == T_private )
1866 rectangle->SetPrivate(
true );
1870 for( ; token != T_RIGHT; token = NextTok() )
1872 if( token != T_LEFT )
1873 Expecting( T_LEFT );
1880 rectangle->SetPosition(
parseXY(
true ) );
1885 rectangle->SetEnd(
parseXY(
true ) );
1896 rectangle->SetStroke( stroke );
1902 rectangle->SetFillColor( fill.
m_Color );
1906 Expecting(
"start, end, stroke, or fill" );
1910 return rectangle.release();
1916 wxCHECK_MSG( CurTok() == T_text,
nullptr,
1917 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text token." ) );
1920 std::unique_ptr<SCH_TEXT>
text = std::make_unique<SCH_TEXT>();
1927 if( token == T_private )
1929 text->SetPrivate(
true );
1933 if( !IsSymbol( token ) )
1935 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1939 text->SetText( FromUTF8() );
1941 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1943 if( token != T_LEFT )
1944 Expecting( T_LEFT );
1962 Expecting(
"at or effects" );
1967 if( !
text->IsVisible() )
1970 return text.release();
1976 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
1977 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
1989 bool foundEnd =
false;
1990 bool foundSize =
false;
1991 bool foundMargins =
false;
1993 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>(
LAYER_DEVICE );
1995 textBox->SetUnit(
m_unit );
1999 if( token == T_private )
2001 textBox->SetPrivate(
true );
2005 if( !IsSymbol( token ) )
2007 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
2011 textBox->SetText( FromUTF8() );
2013 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2015 if( token != T_LEFT )
2016 Expecting( T_LEFT );
2047 textBox->SetStroke( stroke );
2053 textBox->SetFillColor( fill.
m_Color );
2058 textBox->SetMarginLeft(
left );
2059 textBox->SetMarginTop( top );
2060 textBox->SetMarginRight(
right );
2061 textBox->SetMarginBottom( bottom );
2062 foundMargins =
true;
2071 Expecting(
"at, size, stroke, fill or effects" );
2075 textBox->SetPosition( pos );
2078 textBox->SetEnd(
end );
2079 else if( foundSize )
2080 textBox->SetEnd( pos + size );
2082 Expecting(
"size" );
2086 int margin = textBox->GetLegacyTextMargin();
2087 textBox->SetMarginLeft( margin );
2088 textBox->SetMarginTop( margin );
2089 textBox->SetMarginRight( margin );
2090 textBox->SetMarginBottom( margin );
2093 return textBox.release();
2099 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
2100 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
2106 wxString pageType = FromUTF8();
2108 if( !aPageInfo.
SetType( pageType ) )
2110 THROW_PARSE_ERROR(
_(
"Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
2137 if( token == T_portrait )
2142 else if( token != T_RIGHT )
2144 Expecting(
"portrait" );
2151 wxCHECK_RET( CurTok() == T_title_block,
2152 "Cannot parse " + GetTokenString( CurTok() ) +
" as a TITLE_BLOCK." );
2156 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2158 if( token != T_LEFT )
2159 Expecting( T_LEFT );
2167 aTitleBlock.
SetTitle( FromUTF8() );
2172 aTitleBlock.
SetDate( FromUTF8() );
2187 int commentNumber =
parseInt(
"comment" );
2189 switch( commentNumber )
2238 CurLine(), CurLineNumber(), CurOffset() );
2245 Expecting(
"title, date, rev, company, or comment" );
2255 wxCHECK_MSG( CurTok() == T_property,
nullptr,
2256 "Cannot parse " + GetTokenString( CurTok() ) +
" as a property token." );
2258 bool is_private =
false;
2260 T token = NextTok();
2262 if( token == T_private )
2268 if( !IsSymbol( token ) )
2270 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
2274 wxString
name = FromUTF8();
2276 if(
name.IsEmpty() )
2278 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
2284 if( !IsSymbol( token ) )
2286 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
2294 value = wxEmptyString;
2326 if(
name.CmpNoCase( wxT(
"Sheet name" ) ) == 0 )
2328 else if(
name.CmpNoCase( wxT(
"Sheet file" ) ) == 0 )
2343 if(
name.CmpNoCase( wxT(
"Intersheet References" ) ) == 0 )
2347 std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>( aParent, fieldId,
name );
2348 field->SetText( value );
2351 field->SetPrivate( is_private );
2353 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2355 if( token != T_LEFT )
2356 Expecting( T_LEFT );
2368 field->SetPosition(
parseXY() );
2386 field->SetNameShown( show );
2390 case T_do_not_autoplace:
2393 field->SetCanAutoplace( !doNotAutoplace );
2398 Expecting(
"id, at, hide, show_name, do_not_autoplace or effects" );
2402 return field.release();
2408 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
2409 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
2410 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
2412 T token = NextTok();
2414 if( !IsSymbol( token ) )
2416 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2420 wxString
name = FromUTF8();
2422 if(
name.IsEmpty() )
2424 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
2428 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet,
VECTOR2I( 0, 0 ),
name );
2440 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2443 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2445 if( token != T_LEFT )
2446 Expecting( T_LEFT );
2454 sheetPin->SetPosition(
parseXY() );
2456 double angle =
parseDouble(
"sheet pin angle (side)" );
2460 else if( angle == 90.0 )
2462 else if( angle == 180.0 )
2464 else if( angle == 270.0 )
2467 Expecting(
"0, 90, 180, or 270" );
2484 Expecting(
"at, uuid or effects" );
2488 return sheetPin.release();
2494 wxCHECK_RET( CurTok() == T_sheet_instances,
2495 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2496 wxCHECK( aScreen, );
2500 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2502 if( token != T_LEFT )
2503 Expecting( T_LEFT );
2521 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2523 if( token != T_LEFT )
2524 Expecting( T_LEFT );
2528 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
2531 size_t numReplacements = 0;
2549 for(
const wxString& ch : whitespaces )
2550 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
2555 if( numReplacements > 0 )
2562 Expecting(
"path or page" );
2567 && ( instance.
m_Path.empty() ) )
2583 Expecting(
"path" );
2591 wxCHECK_RET( CurTok() == T_symbol_instances,
2592 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
2593 wxCHECK( aScreen, );
2598 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2600 if( token != T_LEFT )
2601 Expecting( T_LEFT );
2618 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2620 if( token != T_LEFT )
2621 Expecting( T_LEFT );
2642 instance.
m_Value = wxEmptyString;
2644 instance.
m_Value = FromUTF8();
2661 Expecting(
"path, unit, value or footprint" );
2670 Expecting(
"path" );
2679 wxCHECK( aSheet !=
nullptr, );
2683 wxCHECK( screen !=
nullptr, );
2686 m_maxError = schematic->Settings().m_MaxError;
2688 if( aIsCopyableOnly )
2691 bool fileHasUuid =
false;
2705 if( !aIsCopyableOnly )
2710 if( CurTok() != T_kicad_sch )
2711 Expecting(
"kicad_sch" );
2730 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2732 if( aIsCopyableOnly && token == T_EOF )
2735 if( token != T_LEFT )
2736 Expecting( T_LEFT );
2770 case T_generator_version:
2796 if( aIsCopyableOnly )
2797 Unexpected( T_paper );
2807 if( aIsCopyableOnly )
2808 Unexpected( T_page );
2812 NeedSYMBOLorNUMBER();
2813 NeedSYMBOLorNUMBER();
2820 if( aIsCopyableOnly )
2821 Unexpected( T_title_block );
2835 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2837 if( token != T_LEFT )
2838 Expecting( T_LEFT );
2850 Expecting(
"symbol" );
2951 case T_netclass_flag:
2956 case T_global_label:
2957 case T_hierarchical_label:
2958 case T_directive_label:
2970 case T_sheet_instances:
2974 case T_symbol_instances:
2979 if( aIsCopyableOnly )
2980 Unexpected( T_bus_alias );
2985 case T_embedded_fonts:
2991 CurLineNumber(), CurOffset() );
2998 case T_embedded_files:
3004 CurLineNumber(), CurOffset() );
3007 embeddedFilesParser.SyncLineReaderWith( *
this );
3015 wxLogError( e.
What() );
3018 SyncLineReaderWith( embeddedFilesParser );
3024 Expecting(
"bitmap, bus, bus_alias, bus_entry, class_label, embedded_files, global_label, "
3025 "hierarchical_label, junction, label, line, no_connect, page, paper, rule_area, "
3026 "sheet, symbol, symbol_instances, text, title_block" );
3047 CurLineNumber(), CurOffset() );
3051 std::vector<std::string> fontNames;
3052 Fontconfig()->ListFonts( fontNames, std::string(
Pgm().GetLanguageTag().utf8_str() ),
3062 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
3063 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
3068 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
3070 std::set<int> fieldIDsRead;
3075 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3077 if( token != T_LEFT )
3078 Expecting( T_LEFT );
3090 if( !IsSymbol( token ) )
3093 CurLineNumber(), CurOffset() );
3096 libName = FromUTF8();
3100 libName.Replace(
"{slash}",
"/" );
3110 if( !IsSymbol( token ) && token != T_NUMBER )
3111 Expecting(
"symbol|number" );
3114 wxString
name = FromUTF8();
3118 name.Replace(
"{slash}",
"/" );
3124 if(
static_cast<int>(
name.size() ) > bad_pos )
3126 wxString msg = wxString::Format(
_(
"Symbol %s contains invalid character '%c'" ),
3134 CurLineNumber(), CurOffset() );
3137 symbol->SetLibId( libId );
3143 symbol->SetPosition(
parseXY() );
3145 switch(
static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
3148 case 90: transform =
TRANSFORM( 0, 1, -1, 0 );
break;
3149 case 180: transform =
TRANSFORM( -1, 0, 0, -1 );
break;
3150 case 270: transform =
TRANSFORM( 0, -1, 1, 0 );
break;
3151 default: Expecting(
"0, 90, 180, or 270" );
3154 symbol->SetTransform( transform );
3163 else if( token == T_y )
3166 Expecting(
"x or y" );
3172 symbol->SetUnit(
parseInt(
"symbol unit" ) );
3178 symbol->SetBodyStyle(
parseInt(
"symbol body style" ) );
3182 case T_exclude_from_sim:
3183 symbol->SetExcludedFromSim(
parseBool() );
3188 symbol->SetExcludedFromBOM( !
parseBool() );
3193 symbol->SetExcludedFromBoard( !
parseBool() );
3202 case T_fields_autoplaced:
3214 case T_default_instance:
3218 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3220 if( token != T_LEFT )
3221 Expecting( T_LEFT );
3242 symbol->SetValueFieldText( wxEmptyString );
3244 symbol->SetValueFieldText( FromUTF8() );
3253 symbol->SetFootprintFieldText( wxEmptyString );
3255 symbol->SetFootprintFieldText( FromUTF8() );
3261 Expecting(
"reference, unit, value or footprint" );
3270 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3272 if( token != T_LEFT )
3273 Expecting( T_LEFT );
3277 if( token != T_project )
3278 Expecting(
"project" );
3282 wxString projectName = FromUTF8();
3284 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3286 if( token != T_LEFT )
3287 Expecting( T_LEFT );
3291 if( token != T_path )
3292 Expecting(
"path" );
3301 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3303 if( token != T_LEFT )
3304 Expecting( T_LEFT );
3325 symbol->SetValueFieldText( wxEmptyString );
3327 symbol->SetValueFieldText( FromUTF8() );
3336 symbol->SetFootprintFieldText( wxEmptyString );
3338 symbol->SetFootprintFieldText( FromUTF8() );
3348 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3350 if( token != T_LEFT )
3351 Expecting( T_LEFT );
3359 variant.
m_Name = FromUTF8();
3368 case T_exclude_from_sim:
3381 wxString fieldName = FromUTF8();
3384 wxString fieldValue = FromUTF8();
3386 variant.
m_Fields[fieldName] = fieldValue;
3391 Expecting(
"dnp, exclude_from_sim, field, in_bom, or name" );
3402 Expecting(
"reference, unit, value, footprint, or variant" );
3406 symbol->AddHierarchicalReference( instance );
3422 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"0" ) );
3429 symbol->SetExcludedFromSim( field->
GetText() == wxS(
"N" ) );
3436 existing = symbol->GetField( field->
GetId() );
3438 existing = symbol->GetField( field->
GetName() );
3443 symbol->AddField( *field );
3446 symbol->UpdatePrefix();
3459 number = FromUTF8();
3461 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3463 if( token != T_LEFT )
3464 Expecting( T_LEFT );
3488 Expecting(
"alternate or uuid" );
3492 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(), number,
3498 Expecting(
"lib_id, lib_name, at, mirror, uuid, exclude_from_sim, on_board, in_bom, dnp, "
3499 "default_instance, property, pin, or instances" );
3503 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
3504 symbol->SetSchSymbolLibraryName( libName );
3507 symbol->ClearFlags();
3509 return symbol.release();
3515 wxCHECK_MSG( CurTok() == T_image,
nullptr,
3516 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
3519 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
3522 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3524 if( token != T_LEFT )
3525 Expecting( T_LEFT );
3532 bitmap->SetPosition(
parseXY() );
3558 data.reserve( 1 << 17 );
3560 while( token != T_RIGHT )
3562 if( !IsSymbol( token ) )
3563 Expecting(
"base64 image data" );
3569 wxMemoryBuffer buffer = wxBase64Decode( data );
3578 Expecting(
"at, scale, uuid or data" );
3591 return bitmap.release();
3597 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
3598 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
3604 std::vector<SCH_FIELD> fields;
3605 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
3606 std::set<int> fieldIDsRead;
3611 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3613 if( token != T_LEFT )
3614 Expecting( T_LEFT );
3621 sheet->SetPosition(
parseXY() );
3630 sheet->SetSize( size );
3635 case T_exclude_from_sim:
3636 sheet->SetExcludedFromSim(
parseBool() );
3641 sheet->SetExcludedFromBOM( !
parseBool() );
3646 sheet->SetExcludedFromBoard( !
parseBool() );
3655 case T_fields_autoplaced:
3663 sheet->SetBorderWidth( stroke.
GetWidth() );
3664 sheet->SetBorderColor( stroke.
GetColor() );
3669 sheet->SetBackgroundColor( fill.
m_Color );
3686 if( fields.empty() )
3692 fields.emplace_back( *field );
3703 std::vector<SCH_SHEET_INSTANCE> instances;
3705 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3707 if( token != T_LEFT )
3708 Expecting( T_LEFT );
3712 if( token != T_project )
3713 Expecting(
"project" );
3717 wxString projectName = FromUTF8();
3719 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3721 if( token != T_LEFT )
3722 Expecting( T_LEFT );
3726 if( token != T_path )
3727 Expecting(
"path" );
3736 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3738 if( token != T_LEFT )
3739 Expecting( T_LEFT );
3759 static std::vector<wxString> whitespaces =
3765 for( wxString ch : whitespaces )
3777 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3779 if( token != T_LEFT )
3780 Expecting( T_LEFT );
3788 variant.
m_Name = FromUTF8();
3797 case T_exclude_from_sim:
3810 wxString fieldName = FromUTF8();
3813 wxString fieldValue = FromUTF8();
3815 variant.
m_Fields[fieldName] = fieldValue;
3820 Expecting(
"dnp, exclude_from_sim, field, in_bom, or name" );
3831 Expecting(
"page or variant" );
3835 instances.emplace_back( instance );
3839 sheet->setInstances( instances );
3844 Expecting(
"at, size, stroke, background, instances, uuid, property, or pin" );
3848 sheet->SetFields( fields );
3850 return sheet.release();
3856 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
3857 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
3860 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
3862 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3864 if( token != T_LEFT )
3865 Expecting( T_LEFT );
3872 junction->SetPosition(
parseXY() );
3890 junction->SetColor(
color );
3902 Expecting(
"at, diameter, color or uuid" );
3906 return junction.release();
3912 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
3913 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
3916 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
3918 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3920 if( token != T_LEFT )
3921 Expecting( T_LEFT );
3928 no_connect->SetPosition(
parseXY() );
3939 Expecting(
"at or uuid" );
3943 return no_connect.release();
3949 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
3950 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
3954 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
3956 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
3958 if( token != T_LEFT )
3959 Expecting( T_LEFT );
3966 busEntry->SetPosition(
parseXY() );
3976 busEntry->SetSize( size );
3983 busEntry->SetStroke( stroke );
3993 Expecting(
"at, size, uuid or stroke" );
3997 return busEntry.release();
4019 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4021 if( token != T_LEFT )
4022 Expecting( T_LEFT );
4029 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4031 if( token != T_LEFT )
4032 Expecting( T_LEFT );
4039 polyline->AddPoint(
parseXY() );
4052 polyline->SetStroke( stroke );
4058 polyline->SetFillColor( fill.
m_Color );
4069 Expecting(
"pts, uuid, stroke, or fill" );
4073 return polyline.release();
4092 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
4095 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>(
VECTOR2I(), layer );
4097 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4099 if( token != T_LEFT )
4100 Expecting( T_LEFT );
4113 line->SetStartPoint(
parseXY() );
4121 line->SetEndPoint(
parseXY() );
4128 line->SetStroke( stroke );
4138 Expecting(
"at, uuid or stroke" );
4142 return line.release();
4148 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
4149 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
4157 std::unique_ptr<SCH_SHAPE> arc = std::make_unique<SCH_SHAPE>(
SHAPE_T::ARC );
4159 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4161 if( token != T_LEFT )
4162 Expecting( T_LEFT );
4185 arc->SetStroke( stroke );
4191 arc->SetFillColor( fill.
m_Color );
4197 const_cast<KIID&
>( arc->m_Uuid ) =
KIID( FromUTF8() );
4202 Expecting(
"start, mid, end, stroke, fill or uuid" );
4206 arc->SetArcGeometry( startPoint, midPoint, endPoint );
4208 return arc.release();
4214 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
4215 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
4224 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4226 if( token != T_LEFT )
4227 Expecting( T_LEFT );
4245 circle->SetStroke( stroke );
4262 Expecting(
"center, radius, stroke, fill or uuid" );
4275 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
4276 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
4281 std::unique_ptr<SCH_SHAPE> rectangle = std::make_unique<SCH_SHAPE>(
SHAPE_T::RECTANGLE );
4283 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4285 if( token != T_LEFT )
4286 Expecting( T_LEFT );
4293 rectangle->SetPosition(
parseXY() );
4298 rectangle->SetEnd(
parseXY() );
4309 rectangle->SetStroke( stroke );
4315 rectangle->SetFillColor( fill.
m_Color );
4321 const_cast<KIID&
>( rectangle->m_Uuid ) =
KIID( FromUTF8() );
4326 Expecting(
"start, end, stroke, fill or uuid" );
4330 return rectangle.release();
4336 wxCHECK_MSG( CurTok() == T_rule_area,
nullptr,
4337 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rule area." ) );
4342 std::unique_ptr<SCH_RULE_AREA> ruleArea = std::make_unique<SCH_RULE_AREA>();
4344 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4346 if( token != T_LEFT )
4347 Expecting( T_LEFT );
4361 ruleArea->SetPolyShape( sch_rule_poly );
4363 ruleArea->SetStroke( poly->GetStroke() );
4364 ruleArea->SetFillMode( poly->GetFillMode() );
4365 ruleArea->SetFillColor( poly->GetFillColor() );
4368 const_cast<KIID&
>( ruleArea->m_Uuid ) = poly->m_Uuid;
4372 case T_exclude_from_sim:
4373 ruleArea->SetExcludedFromSim(
parseBool() );
4378 ruleArea->SetExcludedFromBOM( !
parseBool() );
4383 ruleArea->SetExcludedFromBoard( !
parseBool() );
4393 Expecting(
"exclude_from_sim, on_board, in_bom, dnp, or polyline" );
4397 return ruleArea.release();
4403 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
4404 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
4409 std::unique_ptr<SCH_SHAPE> bezier = std::make_unique<SCH_SHAPE>(
SHAPE_T::BEZIER );
4411 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4413 if( token != T_LEFT )
4414 Expecting( T_LEFT );
4424 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
4426 if( token != T_LEFT )
4427 Expecting( T_LEFT );
4436 case 0: bezier->SetStart(
parseXY() );
break;
4437 case 1: bezier->SetBezierC1(
parseXY() );
break;
4438 case 2: bezier->SetBezierC2(
parseXY() );
break;
4439 case 3: bezier->SetEnd(
parseXY() );
break;
4440 default: Unexpected(
"control point" );
break;
4450 bezier->SetStroke( stroke );
4456 bezier->SetFillColor( fill.
m_Color );
4462 const_cast<KIID&
>( bezier->m_Uuid ) =
KIID( FromUTF8() );
4467 Expecting(
"pts, stroke, fill or uuid" );
4471 bezier->RebuildBezierToSegmentsPointsList(
m_maxError );
4473 return bezier.release();
4480 std::unique_ptr<SCH_TEXT>
text;
4484 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
4485 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
4486 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
4487 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
4488 case T_netclass_flag:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4489 case T_directive_label:
text = std::make_unique<SCH_DIRECTIVE_LABEL>();
break;
4491 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
4499 text->SetText( FromUTF8() );
4501 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4503 if( token != T_LEFT )
4504 Expecting( T_LEFT );
4510 case T_exclude_from_sim:
4521 switch(
static_cast<int>( label->GetTextAngle().AsDegrees() ) )
4537 Unexpected( T_shape );
4555 Expecting(
"input, output, bidirectional, tri_state, passive, dot, round, diamond"
4566 Unexpected( T_length );
4575 case T_fields_autoplaced:
4585 text->SetVisible(
true );
4610 Unexpected( T_property );
4630 Expecting(
"at, shape, iref, uuid or effects" );
4636 if( label && label->
GetFields().empty() )
4639 return text.release();
4645 wxCHECK_MSG( CurTok() == T_text_box,
nullptr,
4646 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text box." ) );
4648 std::unique_ptr<SCH_TEXTBOX> textBox = std::make_unique<SCH_TEXTBOX>();
4652 return textBox.release();
4658 wxCHECK_MSG( CurTok() == T_table_cell,
nullptr,
4659 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table cell." ) );
4661 std::unique_ptr<SCH_TABLECELL> cell = std::make_unique<SCH_TABLECELL>();
4665 return cell.release();
4681 bool foundEnd =
false;
4682 bool foundSize =
false;
4683 bool foundMargins =
false;
4687 aTextBox->
SetText( FromUTF8() );
4689 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4691 if( token != T_LEFT )
4692 Expecting( T_LEFT );
4698 case T_exclude_from_sim:
4729 cell->SetColSpan(
parseInt(
"column span" ) );
4730 cell->SetRowSpan(
parseInt(
"row span" ) );
4734 Expecting(
"at, size, stroke, fill, effects or uuid" );
4758 foundMargins =
true;
4774 Expecting(
"at, size, stroke, fill, effects, span or uuid" );
4776 Expecting(
"at, size, stroke, fill, effects or uuid" );
4784 else if( foundSize )
4785 aTextBox->
SetEnd( pos + size );
4787 Expecting(
"size" );
4802 wxCHECK_MSG( CurTok() == T_table,
nullptr,
4803 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a table." ) );
4809 std::unique_ptr<SCH_TABLE>
table = std::make_unique<SCH_TABLE>( defaultLineWidth );
4811 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4813 if( token != T_LEFT )
4814 Expecting( T_LEFT );
4820 case T_column_count:
4825 case T_column_widths:
4829 while( ( token = NextTok() ) != T_RIGHT )
4839 while( ( token = NextTok() ) != T_RIGHT )
4846 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4848 if( token != T_LEFT )
4849 Expecting( T_LEFT );
4853 if( token != T_table_cell )
4854 Expecting(
"table_cell" );
4862 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4864 if( token != T_LEFT )
4865 Expecting( T_LEFT );
4883 table->SetBorderStroke( borderStroke );
4887 Expecting(
"external, header or stroke" );
4895 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
4897 if( token != T_LEFT )
4898 Expecting( T_LEFT );
4916 table->SetSeparatorsStroke( separatorsStroke );
4920 Expecting(
"rows, cols, or stroke" );
4934 Expecting(
"columns, col_widths, row_heights, border, separators, uuid, header or cells" );
4938 return table.release();
4944 wxCHECK_RET( CurTok() == T_bus_alias,
4945 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
4946 wxCHECK( aScreen, );
4949 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>();
4960 busAlias->SetName( alias );
4965 if( token != T_members )
4966 Expecting(
"members" );
4970 while( token != T_RIGHT )
4972 if( !IsSymbol( token ) )
4973 Expecting(
"quoted string" );
4975 member = FromUTF8();
4980 busAlias->Members().emplace_back( member );
4995 while( ( token = NextTok() ) != T_RIGHT )
5000 KIID uuid( CurStr() );
5008 wxCHECK_RET( CurTok() == T_group,
5009 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as PCB_GROUP." ) );
5016 while( ( token = NextTok() ) != T_LEFT )
5018 if( token == T_STRING )
5019 groupInfo.
name = FromUTF8();
5021 Expecting(
"group name or locked" );
5024 for( ; token != T_RIGHT; token = NextTok() )
5026 if( token != T_LEFT )
5027 Expecting( T_LEFT );
5043 if( !IsSymbol( token ) && token != T_NUMBER )
5044 Expecting(
"symbol|number" );
5047 wxString
name = FromUTF8();
5051 name.Replace(
"{slash}",
"/" );
5057 if(
static_cast<int>(
name.size() ) > bad_pos )
5059 wxString msg = wxString::Format(
_(
"Group library link %s contains invalid character '%c'" ),
name,
5065 THROW_PARSE_ERROR(
_(
"Invalid library ID" ), CurSource(), CurLine(), CurLineNumber(), CurOffset() );
5079 Expecting(
"uuid, lib_id, members" );
5091 [&](
const KIID& aId )
5097 if( item->m_Uuid == aId )
5116 group->SetName( groupInfo.name );
5118 const_cast<KIID&
>(
group->m_Uuid ) = groupInfo.uuid;
5120 if( groupInfo.libId.IsValid() )
5121 group->SetDesignBlockLibId( groupInfo.libId );
5132 for(
const KIID& aUuid : groupInfo.memberUuids )
5134 if(
SCH_ITEM* gItem = getItem( aUuid ) )
5135 group->AddItem( gItem );
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)
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()
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 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
#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)
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