30 #define wxUSE_BASE64 1 31 #include <wx/base64.h> 32 #include <wx/mstream.h> 33 #include <wx/tokenzr.h> 57 using namespace TSCHEMATIC_T;
61 unsigned aLineCount ) :
62 SCHEMATIC_LEXER( aLineReader ),
63 m_requiredVersion( 0 ),
67 m_progressReporter( aProgressReporter ),
68 m_lineReader( aLineReader ),
69 m_lastProgressLine( 0 ),
70 m_lineCount( aLineCount )
77 const unsigned PROGRESS_DELTA = 250;
99 KIID id( FromUTF8() );
116 else if( token == T_no )
119 Expecting(
"yes or no" );
133 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
135 if( token != T_LEFT )
140 if( token == T_symbol )
145 aSymbolLibMap[symbol->
GetName()] = symbol;
149 Expecting(
"symbol" );
157 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
158 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
165 std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
168 symbol->SetUnitCount( 1 );
175 if( !IsSymbol( token ) )
177 THROW_PARSE_ERROR(
_(
"Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(),
185 if(
id.Parse(
name ) >= 0 )
188 CurLineNumber(), CurOffset() );
193 symbol->SetLibId(
id );
195 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
197 if( token != T_LEFT )
216 if( token != T_hide )
219 symbol->SetShowPinNumbers(
false );
229 symbol->SetIncludeOnBoard(
parseBool() );
241 if( !IsSymbol( token ) )
244 CurLineNumber(), CurOffset() );
248 auto it = aSymbolLibMap.find(
name );
250 if( it == aSymbolLibMap.end() )
252 error.Printf(
_(
"No parent for extended symbol %s" ),
name.c_str() );
253 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
256 symbol->SetParent( it->second );
265 if( !IsSymbol( token ) )
268 CurLineNumber(), CurOffset() );
275 error.Printf(
_(
"Invalid symbol unit name prefix %s" ),
name.c_str() );
276 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
281 wxStringTokenizer tokenizer(
name,
"_" );
283 if( tokenizer.CountTokens() != 2 )
285 error.Printf(
_(
"Invalid symbol unit name suffix %s" ),
name.c_str() );
286 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
289 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
291 error.Printf(
_(
"Invalid symbol unit number %s" ),
name.c_str() );
292 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
295 m_unit = static_cast<int>( tmp );
297 if( !tokenizer.GetNextToken().ToLong( &tmp ) )
299 error.Printf(
_(
"Invalid symbol convert number %s" ),
name.c_str() );
300 THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
306 symbol->SetConversion(
true,
false );
308 if(
m_unit > symbol->GetUnitCount() )
309 symbol->SetUnitCount(
m_unit,
false );
311 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
313 if( token != T_LEFT )
329 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
332 symbol->AddDrawItem( item,
false );
336 Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
354 wxCHECK_MSG( item,
nullptr,
"Invalid draw item pointer." );
357 symbol->AddDrawItem( item,
false );
361 Expecting(
"pin_names, pin_numbers, arc, bezier, circle, pin, polyline, " 362 "rectangle, or text" );
366 symbol->GetDrawItems().sort();
369 return symbol.release();
378 return static_cast<LIB_ITEM*>(
parseArc() );
390 return static_cast<LIB_ITEM*>(
parsePin() );
402 return static_cast<LIB_TEXT*>(
parseText() );
406 Expecting(
"arc, bezier, circle, pin, polyline, rectangle, or text" );
418 if( strchr( CurText(),
',' ) !=
nullptr )
421 CurLine(), CurLineNumber(), CurOffset() );
426 double fval = strtod( CurText(), &tmp );
431 CurLineNumber(), CurOffset() );
434 if( CurText() == tmp )
437 CurLineNumber(), CurOffset() );
451 constexpr
double int_limit = std::numeric_limits<int>::max() * 0.7071;
453 return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
461 constexpr
double int_limit = std::numeric_limits<int>::max() * 0.7071;
463 return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
469 wxCHECK_RET( CurTok() == T_stroke,
470 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a stroke." ) );
474 aStroke.
SetColor( COLOR4D::UNSPECIFIED );
478 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
480 if( token != T_LEFT )
504 Expecting(
"solid, dash, dash_dot, dot or default" );
526 Expecting(
"width, type, or color" );
535 wxCHECK_RET( CurTok() == T_fill,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a fill." );
538 aFill.
m_Color = COLOR4D::UNSPECIFIED;
542 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
544 if( token != T_LEFT )
560 default: Expecting(
"none, outline, or background" );
581 Expecting(
"type or color" );
589 wxCHECK_RET( aText && CurTok() == T_effects,
590 "Cannot parse " + GetTokenString( CurTok() ) +
" as an EDA_TEXT." );
599 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
601 if( token == T_LEFT )
607 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
609 if( token == T_LEFT )
638 Expecting(
"size, bold, or italic" );
645 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
654 default: Expecting(
"left, right, top, bottom, or mirror" );
665 Expecting(
"font, justify, or hide" );
673 wxCHECK_RET( CurTok() == aHeaderType,
674 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a header." ) );
680 if( tok == T_version )
713 wxCHECK_RET( CurTok() == T_pin_names,
714 "Cannot parse " + GetTokenString( CurTok() ) +
" as a pin_name token." );
720 if( token == T_LEFT )
724 if( token != T_offset )
725 Expecting(
"offset" );
732 if( token == T_hide )
734 aSymbol->SetShowPinNames(
false );
737 else if( token != T_RIGHT )
740 CurLineNumber(), CurOffset() );
747 wxCHECK_MSG( CurTok() == T_property,
nullptr,
748 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a property." ) );
749 wxCHECK( aSymbol,
nullptr );
754 std::unique_ptr<LIB_FIELD> field = std::make_unique<LIB_FIELD>( aSymbol.get(),
759 if( !IsSymbol( token ) )
761 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
769 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
773 field->SetName(
name );
776 if( !IsSymbol( token ) )
778 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
785 field->SetText( value );
787 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
789 if( token != T_LEFT )
797 field->SetId(
parseInt(
"field ID" ) );
802 field->SetPosition(
parseXY() );
803 field->SetTextAngle( static_cast<int>(
parseDouble(
"text angle" ) * 10.0 ) );
812 Expecting(
"id, at or effects" );
821 int nextAvailableId = field->GetId() + 1;
824 nextAvailableId += 1;
826 field->SetId( nextAvailableId );
833 existingField = aSymbol->GetFieldById( field->GetId() );
835 *existingField = *field;
837 return existingField;
839 else if(
name ==
"ki_keywords" )
842 aSymbol->SetKeyWords( value );
845 else if(
name ==
"ki_description" )
848 aSymbol->SetDescription( value );
851 else if(
name ==
"ki_fp_filters" )
854 wxArrayString filters;
855 wxStringTokenizer tokenizer( value );
857 while( tokenizer.HasMoreTokens() )
860 filters.Add( curr_token );
863 aSymbol->SetFPFilters( filters );
866 else if(
name ==
"ki_locked" )
870 aSymbol->LockUnits(
true );
876 existingField = aSymbol->FindField( field->GetCanonicalName() );
878 #if 1 // Enable it to modify the name of the field to add if already existing 887 for(
int ii = 1; ii < 10 && existingField ; ii++ )
889 wxString newname = base_name;
890 newname <<
'_' << ii;
892 existingField = aSymbol->FindField( newname );
895 field->SetName( newname );
901 aSymbol->AddDrawItem( field.get(), false );
903 return field.release();
916 wxCHECK_MSG( CurTok() == T_arc,
nullptr,
917 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an arc." ) );
920 wxPoint startPoint( 1, 0 );
921 wxPoint midPoint( 1, 1 );
922 wxPoint endPoint( 0, 1 );
923 bool hasMidPoint =
false;
928 wxPoint center( 0, 0 );
931 bool hasAngles =
false;
933 std::unique_ptr<LIB_SHAPE> arc = std::make_unique<LIB_SHAPE>(
nullptr,
SHAPE_T::ARC );
938 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
940 if( token != T_LEFT )
964 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
966 if( token != T_LEFT )
995 Expecting(
"at, length, or angles" );
1003 arc->SetWidth( stroke.
GetWidth() );
1012 Expecting(
"start, mid, end, radius, stroke, or fill" );
1018 arc->SetArcGeometry( startPoint, midPoint, endPoint);
1020 else if( hasAngles )
1022 arc->SetStart( startPoint );
1023 arc->SetEnd( endPoint );
1032 if( !
TRANSFORM().MapAngles( &startAngle, &endAngle ) )
1034 wxPoint temp = arc->GetStart();
1035 arc->SetStart( arc->GetEnd() );
1036 arc->SetEnd( temp );
1039 arc->SetCenter( center );
1043 wxFAIL_MSG(
"Setting arc without either midpoint or angles not implemented." );
1046 return arc.release();
1052 wxCHECK_MSG( CurTok() == T_bezier,
nullptr,
1053 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bezier." ) );
1059 std::unique_ptr<LIB_SHAPE> bezier = std::make_unique<LIB_SHAPE>(
nullptr,
SHAPE_T::BEZIER );
1061 bezier->SetUnit(
m_unit );
1064 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1066 if( token != T_LEFT )
1067 Expecting( T_LEFT );
1077 for( token = NextTok(); token != T_RIGHT; token = NextTok(), ++ii )
1079 if( token != T_LEFT )
1080 Expecting( T_LEFT );
1089 case 0: bezier->SetStart(
parseXY() );
break;
1090 case 1: bezier->SetBezierC1(
parseXY() );
break;
1091 case 2: bezier->SetBezierC2(
parseXY() );
break;
1092 case 3: bezier->SetEnd(
parseXY() );
break;
1093 default: Unexpected(
"control point" );
break;
1103 bezier->SetWidth( stroke.
GetWidth() );
1112 Expecting(
"pts, stroke, or fill" );
1116 bezier->RebuildBezierToSegmentsPointsList( bezier->GetWidth() );
1118 return bezier.release();
1124 wxCHECK_MSG( CurTok() == T_circle,
nullptr,
1125 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a circle." ) );
1128 wxPoint center( 0, 0 );
1133 std::unique_ptr<LIB_SHAPE> circle = std::make_unique<LIB_SHAPE>(
nullptr,
SHAPE_T::CIRCLE );
1135 circle->SetUnit(
m_unit );
1138 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1140 if( token != T_LEFT )
1141 Expecting( T_LEFT );
1159 circle->SetWidth( stroke.
GetWidth() );
1168 Expecting(
"center, radius, stroke, or fill" );
1172 circle->SetCenter( center );
1173 circle->SetEnd( wxPoint( center.x + radius, center.y ) );
1175 return circle.release();
1200 Expecting(
"input, output, bidirectional, tri_state, passive, " 1201 "unspecified, power_in, power_out, open_collector, " 1202 "open_emitter, free or no_connect" );
1222 Expecting(
"line, inverted, clock, inverted_clock, input_low, " 1223 "clock_low, output_low, edge_clock_high, non_logic" );
1228 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
1229 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a pin token." ) );
1234 std::unique_ptr<LIB_PIN>
pin = std::make_unique<LIB_PIN>(
nullptr );
1241 pin->SetType( parseType( token ) );
1245 pin->SetShape( parseShape( token ) );
1247 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1249 if( token == T_hide )
1251 pin->SetVisible(
false );
1255 if( token != T_LEFT )
1256 Expecting( T_LEFT );
1265 switch(
parseInt(
"pin orientation" ) )
1268 case 90:
pin->SetOrientation(
PIN_UP );
break;
1271 default: Expecting(
"0, 90, 180, or 270" );
1285 if( !IsSymbol( token ) )
1294 pin->SetName( FromUTF8() );
1298 if( token != T_RIGHT )
1302 if( token == T_effects )
1309 pin->SetNameTextSize(
text.GetTextHeight() );
1314 Expecting(
"effects" );
1323 if( !IsSymbol( token ) )
1326 CurLineNumber(), CurOffset() );
1329 pin->SetNumber( FromUTF8() );
1332 if( token != T_RIGHT )
1336 if( token == T_effects )
1343 pin->SetNumberTextSize(
text.GetTextHeight() );
1348 Expecting(
"effects" );
1360 if( !IsSymbol( token ) )
1363 CurLineNumber(), CurOffset() );
1369 alt.
m_Type = parseType( token );
1372 alt.
m_Shape = parseShape( token );
1374 pin->GetAlternates()[ alt.
m_Name ] = alt;
1381 Expecting(
"at, name, number, length, or alternate" );
1385 return pin.release();
1391 wxCHECK_MSG( CurTok() == T_polyline,
nullptr,
1392 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a poly." ) );
1397 std::unique_ptr<LIB_SHAPE> poly = std::make_unique<LIB_SHAPE>(
nullptr,
SHAPE_T::POLY );
1402 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1404 if( token != T_LEFT )
1405 Expecting( T_LEFT );
1412 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1414 if( token != T_LEFT )
1415 Expecting( T_LEFT );
1431 poly->SetWidth( stroke.
GetWidth() );
1440 Expecting(
"pts, stroke, or fill" );
1444 return poly.release();
1450 wxCHECK_MSG( CurTok() == T_rectangle,
nullptr,
1451 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a rectangle." ) );
1456 std::unique_ptr<LIB_SHAPE> rectangle = std::make_unique<LIB_SHAPE>(
nullptr,
SHAPE_T::RECT );
1458 rectangle->SetUnit(
m_unit );
1461 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1463 if( token != T_LEFT )
1464 Expecting( T_LEFT );
1471 rectangle->SetPosition(
parseXY() );
1476 rectangle->SetEnd(
parseXY() );
1482 rectangle->SetWidth( stroke.
GetWidth() );
1491 Expecting(
"start, end, stroke, or fill" );
1495 return rectangle.release();
1501 wxCHECK_MSG( CurTok() == T_text,
nullptr,
1502 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a text token." ) );
1506 std::unique_ptr<LIB_TEXT>
text = std::make_unique<LIB_TEXT>(
nullptr );
1512 if( !IsSymbol( token ) )
1514 THROW_PARSE_ERROR(
_(
"Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1518 text->SetText( FromUTF8() );
1520 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1522 if( token != T_LEFT )
1523 Expecting( T_LEFT );
1540 Expecting(
"at or effects" );
1544 return text.release();
1550 wxCHECK_RET( ( CurTok() == T_page &&
m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
1551 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a PAGE_INFO." ) );
1557 wxString pageType = FromUTF8();
1559 if( !aPageInfo.
SetType( pageType ) )
1561 THROW_PARSE_ERROR(
_(
"Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
1588 if( token == T_portrait )
1593 else if( token != T_RIGHT )
1595 Expecting(
"portrait" );
1602 wxCHECK_RET( CurTok() == T_title_block,
1603 "Cannot parse " + GetTokenString( CurTok() ) +
" as a TITLE_BLOCK." );
1607 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1609 if( token != T_LEFT )
1610 Expecting( T_LEFT );
1618 aTitleBlock.
SetTitle( FromUTF8() );
1623 aTitleBlock.
SetDate( FromUTF8() );
1638 int commentNumber =
parseInt(
"comment" );
1640 switch( commentNumber )
1689 CurLine(), CurLineNumber(), CurOffset() );
1696 Expecting(
"title, date, rev, company, or comment" );
1706 wxCHECK_MSG( CurTok() == T_property,
nullptr,
1707 "Cannot parse " + GetTokenString( CurTok() ) +
" as a property token." );
1709 T token = NextTok();
1711 if( !IsSymbol( token ) )
1713 THROW_PARSE_ERROR(
_(
"Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
1717 wxString
name = FromUTF8();
1719 if(
name.IsEmpty() )
1721 THROW_PARSE_ERROR(
_(
"Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
1727 if( !IsSymbol( token ) )
1729 THROW_PARSE_ERROR(
_(
"Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
1734 wxString value = FromUTF8();
1736 std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>( wxDefaultPosition, -1,
1739 field->SetText( value );
1740 field->SetVisible(
true );
1742 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1744 if( token != T_LEFT )
1745 Expecting( T_LEFT );
1752 field->SetId(
parseInt(
"field ID" ) );
1757 field->SetPosition(
parseXY() );
1758 field->SetTextAngle( static_cast<int>(
parseDouble(
"text angle" ) * 10.0 ) );
1767 Expecting(
"at or effects" );
1771 return field.release();
1777 wxCHECK_MSG( aSheet !=
nullptr,
nullptr,
"" );
1778 wxCHECK_MSG( CurTok() == T_pin,
nullptr,
1779 "Cannot parse " + GetTokenString( CurTok() ) +
" as a sheet pin token." );
1781 T token = NextTok();
1783 if( !IsSymbol( token ) )
1785 THROW_PARSE_ERROR(
_(
"Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
1789 wxString
name = FromUTF8();
1791 if(
name.IsEmpty() )
1793 THROW_PARSE_ERROR(
_(
"Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
1797 auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet, wxPoint( 0, 0 ),
name );
1809 Expecting(
"input, output, bidirectional, tri_state, or passive" );
1812 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1814 if( token != T_LEFT )
1815 Expecting( T_LEFT );
1823 sheetPin->SetPosition(
parseXY() );
1829 else if(
angle == 90.0 )
1831 else if(
angle == 180.0 )
1833 else if(
angle == 270.0 )
1836 Expecting(
"0, 90, 180, or 270" );
1843 parseEDA_TEXT( static_cast<EDA_TEXT*>( sheetPin.get() ),
true );
1848 const_cast<KIID&>( sheetPin->m_Uuid ) =
parseKIID();
1853 Expecting(
"at, uuid or effects" );
1857 return sheetPin.release();
1863 wxCHECK_RET( CurTok() == T_sheet_instances,
1864 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
1865 wxCHECK( aScreen, );
1869 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1871 if( token != T_LEFT )
1872 Expecting( T_LEFT );
1886 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1888 if( token != T_LEFT )
1889 Expecting( T_LEFT );
1893 std::vector<wxString> whitespaces = { wxT(
"\r" ), wxT(
"\n" ), wxT(
"\t" ),
1896 size_t numReplacements = 0;
1905 for( wxString ch : whitespaces )
1906 numReplacements += instance.
m_PageNumber.Replace( ch, wxEmptyString );
1918 if( numReplacements > 0 )
1925 Expecting(
"path or page" );
1934 Expecting(
"path" );
1942 wxCHECK_RET( CurTok() == T_symbol_instances,
1943 "Cannot parse " + GetTokenString( CurTok() ) +
" as an instances token." );
1944 wxCHECK( aScreen, );
1948 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1950 if( token != T_LEFT )
1951 Expecting( T_LEFT );
1965 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1967 if( token != T_LEFT )
1968 Expecting( T_LEFT );
1987 instance.
m_Value = FromUTF8();
1998 Expecting(
"path, unit, value or footprint" );
2007 Expecting(
"path" );
2015 wxCHECK( aSheet !=
nullptr, );
2019 wxCHECK( screen !=
nullptr, );
2021 if( aIsCopyableOnly )
2026 if( !aIsCopyableOnly )
2031 if( CurTok() != T_kicad_sch )
2032 Expecting(
"kicad_sch" );
2039 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2041 if( aIsCopyableOnly && token == T_EOF )
2044 if( token != T_LEFT )
2045 Expecting( T_LEFT );
2064 if( aIsCopyableOnly )
2065 Unexpected( T_paper );
2075 if( aIsCopyableOnly )
2076 Unexpected( T_page );
2080 NeedSYMBOLorNUMBER();
2081 NeedSYMBOLorNUMBER();
2088 if( aIsCopyableOnly )
2089 Unexpected( T_title_block );
2103 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2105 if( token != T_LEFT )
2106 Expecting( T_LEFT );
2119 Expecting(
"symbol" );
2144 screen->
Append( static_cast<SCH_ITEM*>( sheet ) );
2168 case T_global_label:
2169 case T_hierarchical_label:
2173 case T_sheet_instances:
2177 case T_symbol_instances:
2182 if( aIsCopyableOnly )
2183 Unexpected( T_bus_alias );
2189 Expecting(
"symbol, paper, page, title_block, bitmap, sheet, junction, no_connect, " 2190 "bus_entry, line, bus, text, label, global_label, hierarchical_label, " 2191 "symbol_instances, or bus_alias" );
2201 wxCHECK_MSG( CurTok() == T_symbol,
nullptr,
2202 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a symbol." ) );
2208 std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
2210 std::set<int> fieldIDsRead;
2213 symbol->ClearFieldsAutoplaced();
2217 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2219 if( token != T_LEFT )
2220 Expecting( T_LEFT );
2232 if( !IsSymbol( token ) )
2235 CurLineNumber(), CurOffset() );
2238 libName = FromUTF8();
2247 if( !IsSymbol( token ) && token != T_NUMBER )
2248 Expecting(
"symbol|number" );
2252 if( libId.
Parse( FromUTF8() ) >= 0 )
2255 CurLineNumber(), CurOffset() );
2258 symbol->SetLibId( libId );
2264 symbol->SetPosition(
parseXY() );
2266 switch( static_cast<int>(
parseDouble(
"symbol orientation" ) ) )
2269 case 90: transform =
TRANSFORM( 0, -1, -1, 0 );
break;
2270 case 180: transform =
TRANSFORM( -1, 0, 0, 1 );
break;
2271 case 270: transform =
TRANSFORM( 0, 1, 1, 0 );
break;
2272 default: Expecting(
"0, 90, 180, or 270" );
2275 symbol->SetTransform( transform );
2284 else if( token == T_y )
2287 Expecting(
"x or y" );
2293 symbol->SetUnit(
parseInt(
"symbol unit" ) );
2298 symbol->SetConvert(
parseInt(
"symbol convert" ) );
2308 symbol->SetIncludeOnBoard(
parseBool() );
2312 case T_fields_autoplaced:
2313 symbol->SetFieldsAutoplaced();
2319 const_cast<KIID&>( symbol->m_Uuid ) =
parseKIID();
2335 if( fieldIDsRead.count( field->
GetId() ) )
2338 fieldIDsRead.insert( field->
GetId() );
2343 wxString refDesignator = field->
GetText();
2345 refDesignator.Replace(
"~",
" " );
2347 wxString prefix = refDesignator;
2349 while( prefix.Length() )
2351 if( ( prefix.Last() <
'0' || prefix.Last() >
'9') && prefix.Last() !=
'?' )
2354 prefix.RemoveLast();
2358 prefix.Trim(
true );
2359 prefix.Trim(
false );
2361 if( prefix.IsEmpty() )
2362 symbol->SetPrefix( wxString(
"U" ) );
2364 symbol->SetPrefix( prefix );
2367 if( symbol->GetFieldById( field->
GetId() ) )
2368 *symbol->GetFieldById( field->
GetId() ) = *field;
2370 symbol->AddField( *field );
2383 number = FromUTF8();
2385 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2387 if( token != T_LEFT )
2388 Expecting( T_LEFT );
2412 Expecting(
"alternate or uuid" );
2416 symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(),
2419 const_cast<KIID&>( symbol->GetRawPins().back()->m_Uuid ) = uuid;
2424 Expecting(
"lib_id, lib_name, at, mirror, uuid, property, pin, or instances" );
2428 if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
2429 symbol->SetSchSymbolLibraryName( libName );
2432 symbol->ClearFlags();
2434 return symbol.release();
2440 wxCHECK_MSG( CurTok() == T_image,
nullptr,
2441 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as an image." ) );
2444 std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
2446 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2448 if( token != T_LEFT )
2449 Expecting( T_LEFT );
2456 bitmap->SetPosition(
parseXY() );
2461 bitmap->GetImage()->SetScale(
parseDouble(
"image scale factor" ) );
2463 if( !std::isnormal( bitmap->GetImage()->GetScale() ) )
2464 bitmap->GetImage()->SetScale( 1.0 );
2471 const_cast<KIID&>( bitmap->m_Uuid ) =
parseKIID();
2483 data.reserve( 1 << 17 );
2485 while( token != T_RIGHT )
2487 if( !IsSymbol( token ) )
2488 Expecting(
"base64 image data" );
2494 wxMemoryBuffer buffer = wxBase64Decode( data );
2495 wxMemoryOutputStream stream( buffer.GetData(), buffer.GetBufSize() );
2496 wxImage*
image =
new wxImage();
2497 wxMemoryInputStream istream( stream );
2498 image->LoadFile( istream, wxBITMAP_TYPE_PNG );
2499 bitmap->GetImage()->SetImage(
image );
2500 bitmap->GetImage()->SetBitmap(
new wxBitmap( *
image ) );
2505 Expecting(
"at, scale, uuid or data" );
2509 return bitmap.release();
2515 wxCHECK_MSG( CurTok() == T_sheet,
nullptr,
2516 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a sheet." ) );
2522 std::vector<SCH_FIELD> fields;
2523 std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
2524 std::set<int> fieldIDsRead;
2527 sheet->ClearFieldsAutoplaced();
2529 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2531 if( token != T_LEFT )
2532 Expecting( T_LEFT );
2539 sheet->SetPosition(
parseXY() );
2548 sheet->SetSize( size );
2553 case T_fields_autoplaced:
2554 sheet->SetFieldsAutoplaced();
2560 sheet->SetBorderWidth( stroke.
GetWidth() );
2561 sheet->SetBorderColor( stroke.
GetColor() );
2566 sheet->SetBackgroundColor( fill.
m_Color );
2571 const_cast<KIID&>( sheet->m_Uuid ) =
parseKIID();
2583 if( fields.empty() )
2596 if( fieldIDsRead.count( field->
GetId() ) )
2599 fieldIDsRead.insert( field->
GetId() );
2601 fields.emplace_back( *field );
2610 Expecting(
"at, size, stroke, background, uuid, property, or pin" );
2614 sheet->SetFields( fields );
2616 return sheet.release();
2622 wxCHECK_MSG( CurTok() == T_junction,
nullptr,
2623 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a junction." ) );
2626 std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
2628 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2630 if( token != T_LEFT )
2631 Expecting( T_LEFT );
2638 junction->SetPosition(
parseXY() );
2656 junction->SetColor(
color );
2663 const_cast<KIID&>( junction->m_Uuid ) =
parseKIID();
2668 Expecting(
"at, diameter, color or uuid" );
2672 return junction.release();
2678 wxCHECK_MSG( CurTok() == T_no_connect,
nullptr,
2679 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a no connect." ) );
2682 std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
2684 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2686 if( token != T_LEFT )
2687 Expecting( T_LEFT );
2694 no_connect->SetPosition(
parseXY() );
2700 const_cast<KIID&>( no_connect->m_Uuid ) =
parseKIID();
2705 Expecting(
"at or uuid" );
2709 return no_connect.release();
2715 wxCHECK_MSG( CurTok() == T_bus_entry,
nullptr,
2716 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus entry." ) );
2720 std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
2722 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2724 if( token != T_LEFT )
2725 Expecting( T_LEFT );
2732 busEntry->SetPosition(
parseXY() );
2742 busEntry->SetSize( size );
2749 busEntry->SetStroke( stroke );
2754 const_cast<KIID&>( busEntry->m_Uuid ) =
parseKIID();
2759 Expecting(
"at, size, uuid or stroke" );
2763 return busEntry.release();
2779 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as a line." );
2782 std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>( wxPoint(), layer );
2784 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2786 if( token != T_LEFT )
2787 Expecting( T_LEFT );
2800 line->SetStartPoint(
parseXY() );
2808 line->SetEndPoint(
parseXY() );
2815 line->SetStroke( stroke );
2820 const_cast<KIID&>( line->m_Uuid ) =
parseKIID();
2825 Expecting(
"at, uuid or stroke" );
2829 return line.release();
2836 std::unique_ptr<SCH_TEXT>
text;
2840 case T_text:
text = std::make_unique<SCH_TEXT>();
break;
2841 case T_label:
text = std::make_unique<SCH_LABEL>();
break;
2842 case T_global_label:
text = std::make_unique<SCH_GLOBALLABEL>();
break;
2843 case T_hierarchical_label:
text = std::make_unique<SCH_HIERLABEL>();
break;
2845 wxCHECK_MSG(
false,
nullptr,
"Cannot parse " + GetTokenString( CurTok() ) +
" as text." );
2849 text->ClearFieldsAutoplaced();
2853 text->SetText( FromUTF8() );
2855 for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2857 if( token != T_LEFT )
2858 Expecting( T_LEFT );
2867 switch( static_cast<int>(
parseDouble(
"text angle" ) ) )
2884 Unexpected( T_shape );
2896 Expecting(
"input, output, bidirectional, tri_state, or passive" );
2902 case T_fields_autoplaced:
2903 text->SetFieldsAutoplaced();
2940 field->SetVisible(
true );
2964 Expecting(
"at, shape, iref, uuid or effects" );
2968 return text.release();
2974 wxCHECK_RET( CurTok() == T_bus_alias,
2975 wxT(
"Cannot parse " ) + GetTokenString( CurTok() ) + wxT(
" as a bus alias." ) );
2976 wxCHECK( aScreen, );
2979 std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
2990 busAlias->SetName( alias );
2995 if( token != T_members )
2996 Expecting(
"members" );
3000 while( token != T_RIGHT )
3002 if( !IsSymbol( token ) )
3003 Expecting(
"quoted string" );
3005 member = FromUTF8();
3010 busAlias->AddMember( member );
void SetMirrored(bool isMirrored)
Field Reference of part, i.e. "IC21".
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
int m_fieldId
The current field ID.
power input (GND, VCC for ICs). Must be connected to a power output.
#define TEXT_ANGLE_HORIZ
Frequent text rotations, used with {Set,Get}TextAngle(), in 0.1 degrees for now, hoping to migrate to...
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
LIB_FIELD * parseProperty(std::unique_ptr< LIB_SYMBOL > &aSymbol)
std::map< wxString, LIB_SYMBOL *, LibSymbolMapSort > LIB_SYMBOL_MAP
Symbol map used by symbol library object.
An abstract class from which implementation specific LINE_READERs may be derived to read single lines...
void SetWidth(int aWidth)
Schematic and symbol library s-expression file format parser definitions.
std::vector< SYMBOL_INSTANCE_REFERENCE > m_symbolInstances
The list of symbol instances loaded from the schematic file.
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
void SetRevision(const wxString &aRevision)
wxString GetName() const override
Define a symbol library graphical text item.
SCH_SHEET_PIN * parseSchSheetPin(SCH_SHEET *aSheet)
static constexpr double IU_PER_MM
Mock up a conversion function.
A progress reporter interface for use in multi-threaded environments.
void parseBusAlias(SCH_SCREEN *aScreen)
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax)
void SetItalic(bool isItalic)
Field object used in symbol libraries.
unsigned m_lastProgressLine
pin for passive symbols: must be connected, and can be connected to any pin
void SetTextPos(const wxPoint &aPoint)
bool SetType(const wxString &aStandardPageDescriptionName, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
LIB_SYMBOL * ParseSymbol(LIB_SYMBOL_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
int m_unit
The current unit being parsed.
void parseTITLE_BLOCK(TITLE_BLOCK &aTitleBlock)
unknown electrical properties: creates always a warning when connected
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
void SetPageSettings(const PAGE_INFO &aPageSettings)
void SetPlotStyle(PLOT_DASH_TYPE aPlotStyle)
static const wxChar Custom[]
"User" defined page type
void SetTextSize(const wxSize &aNewSize)
#define SEXPR_SYMBOL_LIB_FILE_VERSION
This file contains the file format version information for the s-expression schematic and symbol libr...
void NORMALIZE_ANGLE_POS(T &Angle)
SCH_SYMBOL * parseSchematicSymbol()
A logical library item identifier and consists of various portions much like a URI.
#define MIN_PAGE_SIZE_MILS
Min and max page sizes for clamping, in mils.
SCH_SCREEN * GetScreen() const
Define a library symbol object.
Hold the information shown in the lower right corner of a plot, printout, or editing view.
ELECTRICAL_PINTYPE m_Type
void parseSchSheetInstances(SCH_SHEET *aRootSheet, SCH_SCREEN *aScreen)
void parseSchSymbolInstances(SCH_SCREEN *aScreen)
virtual void SetParent(EDA_ITEM *aParent)
SCH_BUS_WIRE_ENTRY * parseBusEntry()
The base class for drawable items used by schematic library symbols.
int Mm2mils(double x)
Convert mm to mils.
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
LIB_SHAPE * parsePolyLine()
not internally connected (may be connected to anything)
virtual void SetVisible(bool aVisible)
Simple container to manage fill parameters.
#define MAX_PAGE_SIZE_EESCHEMA_MILS
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
void ParseLib(LIB_SYMBOL_MAP &aSymbolLibMap)
Field Value of part, i.e. "3.3K".
virtual void SetText(const wxString &aText)
void SetComment(int aIdx, const wxString &aComment)
wxString m_symbolName
The current symbol name.
virtual unsigned LineNumber() const
Return the line number of the last line read from this LINE_READER.
SCH_JUNCTION * parseJunction()
int m_convert
The current body style being parsed.
std::vector< SCH_SHEET_INSTANCE > m_sheetInstances
Describe the page size and margins of a paper page on which to eventually print or plot.
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
LIB_SHAPE * parseCircle()
int UpdateFieldOrdinals()
Order optional field indices.
SCH_NO_CONNECT * parseNoConnect()
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
void SetIntersheetRefs(const SCH_FIELD &aField)
void SetCompany(const wxString &aCompany)
A simple container for schematic symbol instance information.
const LINE_READER * m_lineReader
Define a sheet pin (label) used in sheets to create hierarchical schematics.
void SetFileFormatVersionAtLoad(int aVersion)
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
void SetTitle(const wxString &aTitle)
Object to handle a bitmap image that can be inserted in a schematic.
void SetHeightMils(int aHeightInMils)
wxString UnescapeString(const wxString &aSource)
SCH_SEXPR_PARSER(LINE_READER *aLineReader=nullptr, PROGRESS_REPORTER *aProgressReporter=nullptr, unsigned aLineCount=0)
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
void SetContentModified(bool aModified=true)
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
SCH_FIELD * GetIntersheetRefs()
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
LIB_ITEM * ParseDrawItem()
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
A simple container for sheet instance information.
void parsePAGE_INFO(PAGE_INFO &aPageInfo)
std::set< int > m_fieldIDsRead
Field IDs that have been read so far for the current symbol.
int m_requiredVersion
Set to the symbol library file version required.
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition (and transfers ownership of the pointer).
Segment description base class to describe items which have 2 end points (track, wire,...
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
void Append(SCH_ITEM *aItem)
SCH_BITMAP * parseImage()
void parsePinNames(std::unique_ptr< LIB_SYMBOL > &aSymbol)
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Simple container to manage line stroke parameters.
usual pin input: must be connected
KIID m_uuid
A unique identifier for each schematic file.
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
void SetWidthMils(int aWidthInMils)
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
const T & Clamp(const T &lower, const T &value, const T &upper)
Limit value within the range lower <= value <= upper.
void parseFill(FILL_PARAMS &aFill)
void ParseSchematic(SCH_SHEET *aSheet, bool aIsCopyablyOnly=false, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
Parse the internal LINE_READER object into aSheet.
Class for a wire to bus entry.
SCH_TEXT * parseSchText()
void SetColor(const COLOR4D &aColor)
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
input or output (like port for a microprocessor)
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
#define SEXPR_SCHEMATIC_FILE_VERSION
Schematic file version.
not connected (must be left open)
LIB_SHAPE * parseRectangle()
void SetPortrait(bool aIsPortrait)
Rotate the paper page 90 degrees.
Base class for any item which can be embedded within the SCHEMATIC container class,...
#define THROW_IO_ERROR(msg)
output of a regulator: intended to be connected to power input pins
virtual const wxString & GetText() const
Return the string associated with the text object.
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.
LIB_SHAPE * parseBezier()
PROGRESS_REPORTER * m_progressReporter
A color representation with 4 components: red, green, blue, alpha.
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).