KiCad PCB EDA Suite
SCH_SEXPR_PARSER Class Reference

Object to parser s-expression symbol library and schematic file formats. More...

#include <sch_sexpr_parser.h>

Inheritance diagram for SCH_SEXPR_PARSER:

Public Member Functions

 SCH_SEXPR_PARSER (LINE_READER *aLineReader=nullptr)
 
void ParseLib (LIB_PART_MAP &aSymbolLibMap)
 
LIB_PARTParseSymbol (LIB_PART_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
 
LIB_ITEMParseDrawItem ()
 
void ParseSchematic (SCH_SHEET *aSheet, bool aIsCopyablyOnly=false, int aFileVersion=SEXPR_SCHEMATIC_FILE_VERSION)
 Parse the internal LINE_READER object into aSheet. More...
 
bool IsTooRecent () const
 Return whether a version number, if any was parsed, was too recent. More...
 

Private Member Functions

void parseHeader (TSCHEMATIC_T::T aHeaderType, int aFileVersion)
 
long parseHex ()
 
int parseInt ()
 
int parseInt (const char *aExpected)
 
double parseDouble ()
 Parse the current token as an ASCII numeric string with possible leading whitespace into a double precision floating point number. More...
 
double parseDouble (const char *aExpected)
 
double parseDouble (TSCHEMATIC_T::T aToken)
 
int parseInternalUnits ()
 
int parseInternalUnits (const char *aExpected)
 
int parseInternalUnits (TSCHEMATIC_T::T aToken)
 
wxPoint parseXY ()
 
bool parseBool ()
 
void parseStroke (STROKE_PARAMS &aStroke)
 Parse stroke definition aStroke. More...
 
void parseFill (FILL_PARAMS &aFill)
 
void parseEDA_TEXT (EDA_TEXT *aText)
 
void parsePinNames (std::unique_ptr< LIB_PART > &aSymbol)
 
void parseProperty (std::unique_ptr< LIB_PART > &aSymbol)
 
LIB_ARCparseArc ()
 
LIB_BEZIERparseBezier ()
 
LIB_CIRCLEparseCircle ()
 
LIB_PINparsePin ()
 
LIB_POLYLINEparsePolyLine ()
 
LIB_RECTANGLEparseRectangle ()
 
LIB_TEXTparseText ()
 
void parsePAGE_INFO (PAGE_INFO &aPageInfo)
 
void parseTITLE_BLOCK (TITLE_BLOCK &aTitleBlock)
 
void parseSchSymbolInstances (SCH_SCREEN *aScreen)
 
SCH_SHEET_PINparseSchSheetPin (SCH_SHEET *aSheet)
 
SCH_FIELDparseSchField (SCH_ITEM *aParent)
 
SCH_COMPONENTparseSchematicSymbol ()
 
SCH_BITMAPparseImage ()
 
SCH_SHEETparseSheet ()
 
SCH_JUNCTIONparseJunction ()
 
SCH_NO_CONNECTparseNoConnect ()
 
SCH_BUS_WIRE_ENTRYparseBusEntry ()
 
SCH_LINEparseLine ()
 
SCH_TEXTparseSchText ()
 
void parseBusAlias (SCH_SCREEN *aScreen)
 

Private Attributes

int m_requiredVersion
 Set to the symbol library file version required. More...
 
int m_fieldId
 The current field ID. More...
 
int m_unit
 The current unit being parsed. More...
 
int m_convert
 The current body style being parsed. More...
 
wxString m_symbolName
 The current symbol name. More...
 

Detailed Description

Object to parser s-expression symbol library and schematic file formats.

Definition at line 79 of file sch_sexpr_parser.h.

Constructor & Destructor Documentation

◆ SCH_SEXPR_PARSER()

SCH_SEXPR_PARSER::SCH_SEXPR_PARSER ( LINE_READER aLineReader = nullptr)

Definition at line 61 of file sch_sexpr_parser.cpp.

61  :
62  SCHEMATIC_LEXER( aLineReader ),
63  m_requiredVersion( 0 ),
64  m_fieldId( 0 ),
65  m_unit( 1 ),
66  m_convert( 1 )
67 {
68 }
int m_fieldId
The current field ID.
int m_unit
The current unit being parsed.
int m_convert
The current body style being parsed.
int m_requiredVersion
Set to the symbol library file version required.

Member Function Documentation

◆ IsTooRecent()

bool SCH_SEXPR_PARSER::IsTooRecent ( ) const

Return whether a version number, if any was parsed, was too recent.

Definition at line 86 of file sch_sexpr_parser.cpp.

87 {
89 }
#define SEXPR_SYMBOL_LIB_FILE_VERSION
This file contains the file format version information for the s-expression schematic and symbol libr...
int m_requiredVersion
Set to the symbol library file version required.

References m_requiredVersion, and SEXPR_SYMBOL_LIB_FILE_VERSION.

◆ parseArc()

LIB_ARC * SCH_SEXPR_PARSER::parseArc ( )
private

Definition at line 840 of file sch_sexpr_parser.cpp.

841 {
842  wxCHECK_MSG( CurTok() == T_arc, nullptr,
843  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as an arc token." ) );
844 
845  T token;
846  wxPoint startPoint;
847  wxPoint midPoint;
848  wxPoint endPoint;
849  wxPoint pos;
850  FILL_PARAMS fill;
851  bool hasMidPoint = false;
852  std::unique_ptr<LIB_ARC> arc( new LIB_ARC( nullptr ) );
853 
854  arc->SetUnit( m_unit );
855  arc->SetConvert( m_convert );
856 
857  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
858  {
859  if( token != T_LEFT )
860  Expecting( T_LEFT );
861 
862  token = NextTok();
863 
864  switch( token )
865  {
866  case T_start:
867  startPoint = parseXY();
868  NeedRIGHT();
869  break;
870 
871  case T_mid:
872  midPoint = parseXY();
873  NeedRIGHT();
874  hasMidPoint = true;
875  break;
876 
877  case T_end:
878  endPoint = parseXY();
879  NeedRIGHT();
880  break;
881 
882  case T_radius:
883  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
884  {
885  if( token != T_LEFT )
886  Expecting( T_LEFT );
887 
888  token = NextTok();
889 
890  switch( token )
891  {
892  case T_at:
893  pos = parseXY();
894  NeedRIGHT();
895  break;
896 
897  case T_length:
898  arc->SetRadius( parseInternalUnits( "radius length" ) );
899  NeedRIGHT();
900  break;
901 
902  case T_angles:
903  {
904  int angle1 = KiROUND( parseDouble( "start radius angle" ) * 10.0 );
905  int angle2 = KiROUND( parseDouble( "end radius angle" ) * 10.0 );
906 
907  NORMALIZE_ANGLE_POS( angle1 );
908  NORMALIZE_ANGLE_POS( angle2 );
909  arc->SetFirstRadiusAngle( angle1 );
910  arc->SetSecondRadiusAngle( angle2 );
911  NeedRIGHT();
912  break;
913  }
914 
915  default:
916  Expecting( "at, length, or angle" );
917  }
918  }
919 
920  break;
921 
922  case T_stroke:
923  NeedLEFT();
924  token = NextTok();
925 
926  if( token != T_width )
927  Expecting( "width" );
928 
929  arc->SetWidth( parseInternalUnits( "stroke width" ) );
930  NeedRIGHT(); // Closes width token;
931  NeedRIGHT(); // Closes stroke token;
932  break;
933 
934  case T_fill:
935  parseFill( fill );
936  arc->SetFillMode( fill.m_FillType );
937  break;
938 
939  default:
940  Expecting( "start, end, radius, stroke, or fill" );
941  }
942  }
943 
944  arc->SetPosition( pos );
945  arc->SetStart( startPoint );
946  arc->SetEnd( endPoint );
947 
948  if( hasMidPoint )
949  {
950  VECTOR2I center = GetArcCenter( arc->GetStart(), midPoint, arc->GetEnd() );
951 
952  arc->SetPosition( wxPoint( center.x, center.y ) );
953 
954  // @todo Calculate the radius.
955 
956  arc->CalcRadiusAngles();
957  }
958 
959  return arc.release();
960 }
int m_unit
The current unit being parsed.
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:276
Simple container to manage fill parameters.
int m_convert
The current body style being parsed.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
void parseFill(FILL_PARAMS &aFill)
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
const VECTOR2I GetArcCenter(const VECTOR2I &aStart, const VECTOR2I &aMid, const VECTOR2I &aEnd)
Determine the center of an arc or circle given three points on its circumference.
Definition: trigo.cpp:405

References GetArcCenter(), KiROUND(), m_convert, FILL_PARAMS::m_FillType, m_unit, NORMALIZE_ANGLE_POS(), parseDouble(), parseFill(), parseInternalUnits(), parseXY(), VECTOR2< T >::x, and VECTOR2< T >::y.

Referenced by ParseDrawItem().

◆ parseBezier()

LIB_BEZIER * SCH_SEXPR_PARSER::parseBezier ( )
private

Definition at line 963 of file sch_sexpr_parser.cpp.

964 {
965  wxCHECK_MSG( CurTok() == T_bezier, nullptr,
966  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bezier." ) );
967 
968  T token;
969  FILL_PARAMS fill;
970  std::unique_ptr<LIB_BEZIER> bezier( new LIB_BEZIER( nullptr ) );
971 
972  bezier->SetUnit( m_unit );
973  bezier->SetConvert( m_convert );
974 
975  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
976  {
977  if( token != T_LEFT )
978  Expecting( T_LEFT );
979 
980  token = NextTok();
981 
982  switch( token )
983  {
984  case T_pts:
985  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
986  {
987  if( token != T_LEFT )
988  Expecting( T_LEFT );
989 
990  token = NextTok();
991 
992  if( token != T_xy )
993  Expecting( "xy" );
994 
995  bezier->AddPoint( parseXY() );
996 
997  NeedRIGHT();
998  }
999 
1000  break;
1001 
1002  case T_stroke:
1003  NeedLEFT();
1004  token = NextTok();
1005 
1006  if( token != T_width )
1007  Expecting( "width" );
1008 
1009  bezier->SetWidth( parseInternalUnits( "stroke width" ) );
1010  NeedRIGHT(); // Closes width token;
1011  NeedRIGHT(); // Closes stroke token;
1012  break;
1013 
1014  case T_fill:
1015  parseFill( fill );
1016  bezier->SetFillMode( fill.m_FillType );
1017  break;
1018 
1019  default:
1020  Expecting( "pts, stroke, or fill" );
1021  }
1022  }
1023 
1024  return bezier.release();
1025 }
int m_unit
The current unit being parsed.
Simple container to manage fill parameters.
int m_convert
The current body style being parsed.
void parseFill(FILL_PARAMS &aFill)
Define a bezier curve graphic body item.
Definition: lib_bezier.h:34

References m_convert, FILL_PARAMS::m_FillType, m_unit, parseFill(), parseInternalUnits(), and parseXY().

Referenced by ParseDrawItem().

◆ parseBool()

bool SCH_SEXPR_PARSER::parseBool ( )
private

Definition at line 71 of file sch_sexpr_parser.cpp.

72 {
73  T token = NextTok();
74 
75  if( token == T_yes )
76  return true;
77  else if( token == T_no )
78  return false;
79  else
80  Expecting( "yes or no" );
81 
82  return false;
83 }

Referenced by parseSchematicSymbol(), and ParseSymbol().

◆ parseBusAlias()

void SCH_SEXPR_PARSER::parseBusAlias ( SCH_SCREEN aScreen)
private

Definition at line 2704 of file sch_sexpr_parser.cpp.

2705 {
2706  wxCHECK_RET( CurTok() == T_bus_alias,
2707  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bus alias." ) );
2708  wxCHECK( aScreen, /* void */ );
2709 
2710  T token;
2711  auto busAlias = std::make_shared< BUS_ALIAS >( aScreen );
2712 
2713  NeedSYMBOL();
2714  busAlias->SetName( FromUTF8() );
2715  NeedLEFT();
2716  token = NextTok();
2717 
2718  if( token != T_members )
2719  Expecting( "members" );
2720 
2721  token = NextTok();
2722 
2723  while( token != T_RIGHT )
2724  {
2725  if( !IsSymbol( token ) )
2726  Expecting( "quoted string" );
2727 
2728  busAlias->AddMember( FromUTF8() );
2729  token = NextTok();
2730  }
2731 
2732  NeedRIGHT();
2733 
2734  aScreen->AddBusAlias( busAlias );
2735 }
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Adds a bus alias definition (and transfers ownership of the pointer)

References SCH_SCREEN::AddBusAlias().

Referenced by ParseSchematic().

◆ parseBusEntry()

SCH_BUS_WIRE_ENTRY * SCH_SEXPR_PARSER::parseBusEntry ( )
private

Definition at line 2513 of file sch_sexpr_parser.cpp.

2514 {
2515  wxCHECK_MSG( CurTok() == T_bus_entry, nullptr,
2516  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bus entry." ) );
2517 
2518  T token;
2519  STROKE_PARAMS stroke;
2520  std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry( new SCH_BUS_WIRE_ENTRY() );
2521 
2522  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2523  {
2524  if( token != T_LEFT )
2525  Expecting( T_LEFT );
2526 
2527  token = NextTok();
2528 
2529  switch( token )
2530  {
2531  case T_at:
2532  busEntry->SetPosition( parseXY() );
2533  NeedRIGHT();
2534  break;
2535 
2536  case T_size:
2537  {
2538  wxSize size;
2539 
2540  size.SetWidth( parseInternalUnits( "bus entry height" ) );
2541  size.SetHeight( parseInternalUnits( "bus entry width" ) );
2542  busEntry->SetSize( size );
2543  NeedRIGHT();
2544  break;
2545  }
2546 
2547  case T_stroke:
2548  parseStroke( stroke );
2549  busEntry->SetStroke( stroke );
2550  break;
2551 
2552  default:
2553  Expecting( "at, size, or stroke" );
2554  }
2555  }
2556 
2557  return busEntry.release();
2558 }
Simple container to manage line stroke parameters.
Definition: sch_item.h:153
Class for a wire to bus entry.
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.

References parseInternalUnits(), parseStroke(), and parseXY().

Referenced by ParseSchematic().

◆ parseCircle()

LIB_CIRCLE * SCH_SEXPR_PARSER::parseCircle ( )
private

Definition at line 1028 of file sch_sexpr_parser.cpp.

1029 {
1030  wxCHECK_MSG( CurTok() == T_circle, nullptr,
1031  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a circle token." ) );
1032 
1033  T token;
1034  FILL_PARAMS fill;
1035  std::unique_ptr<LIB_CIRCLE> circle( new LIB_CIRCLE( nullptr ) );
1036 
1037  circle->SetUnit( m_unit );
1038  circle->SetConvert( m_convert );
1039 
1040  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1041  {
1042  if( token != T_LEFT )
1043  Expecting( T_LEFT );
1044 
1045  token = NextTok();
1046 
1047  switch( token )
1048  {
1049  case T_center:
1050  circle->SetPosition( parseXY() );
1051  NeedRIGHT();
1052  break;
1053 
1054  case T_radius:
1055  circle->SetRadius( parseInternalUnits( "radius length" ) );
1056  NeedRIGHT();
1057  break;
1058 
1059  case T_stroke:
1060  NeedLEFT();
1061  token = NextTok();
1062 
1063  if( token != T_width )
1064  Expecting( "width" );
1065 
1066  circle->SetWidth( parseInternalUnits( "stroke width" ) );
1067  NeedRIGHT(); // Closes width token;
1068  NeedRIGHT(); // Closes stroke token;
1069  break;
1070 
1071  case T_fill:
1072  parseFill( fill );
1073  circle->SetFillMode( fill.m_FillType );
1074  break;
1075 
1076  default:
1077  Expecting( "start, end, radius, stroke, or fill" );
1078  }
1079  }
1080 
1081  return circle.release();
1082 }
int m_unit
The current unit being parsed.
Simple container to manage fill parameters.
int m_convert
The current body style being parsed.
void parseFill(FILL_PARAMS &aFill)

References m_convert, FILL_PARAMS::m_FillType, m_unit, parseFill(), parseInternalUnits(), and parseXY().

Referenced by ParseDrawItem().

◆ parseDouble() [1/3]

double SCH_SEXPR_PARSER::parseDouble ( )
private

Parse the current token as an ASCII numeric string with possible leading whitespace into a double precision floating point number.

Exceptions
IO_ERRORif an error occurs attempting to convert the current token.
Returns
The result of the parsed token.

Definition at line 396 of file sch_sexpr_parser.cpp.

397 {
398  char* tmp;
399 
400  errno = 0;
401 
402  double fval = strtod( CurText(), &tmp );
403 
404  if( errno )
405  {
406  wxString error;
407  error.Printf( _( "Invalid floating point number in\nfile: \"%s\"\nline: %d\noffset: %d" ),
408  CurSource().c_str(), CurLineNumber(), CurOffset() );
409 
410  THROW_IO_ERROR( error );
411  }
412 
413  if( CurText() == tmp )
414  {
415  wxString error;
416  error.Printf( _( "Missing floating point number in\nfile: \"%s\"\nline: %d\noffset: %d" ),
417  CurSource().c_str(), CurLineNumber(), CurOffset() );
418 
419  THROW_IO_ERROR( error );
420  }
421 
422  return fval;
423 }
#define _(s)
Definition: 3d_actions.cpp:33
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, and THROW_IO_ERROR.

Referenced by parseArc(), parseDouble(), parseFill(), parseImage(), parseInternalUnits(), parseJunction(), parsePAGE_INFO(), parseProperty(), parseSchematicSymbol(), parseSchField(), parseSchSheetPin(), parseSchText(), parseStroke(), and parseText().

◆ parseDouble() [2/3]

double SCH_SEXPR_PARSER::parseDouble ( const char *  aExpected)
inlineprivate

Definition at line 115 of file sch_sexpr_parser.h.

116  {
117  NeedNUMBER( aExpected );
118  return parseDouble();
119  }
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

References parseDouble().

◆ parseDouble() [3/3]

double SCH_SEXPR_PARSER::parseDouble ( TSCHEMATIC_T::T  aToken)
inlineprivate

Definition at line 121 of file sch_sexpr_parser.h.

122  {
123  return parseDouble( GetTokenText( aToken ) );
124  }
const char * GetTokenText(T aTok)
Function GetTokenText is in the DSN namespace and returns the C string representing a SPECCTRA_DB::ke...
Definition: specctra.cpp:69
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

References DSN::GetTokenText(), and parseDouble().

◆ ParseDrawItem()

LIB_ITEM * SCH_SEXPR_PARSER::ParseDrawItem ( )

Definition at line 356 of file sch_sexpr_parser.cpp.

357 {
358  switch( CurTok() )
359  {
360  case T_arc:
361  return static_cast<LIB_ITEM*>( parseArc() );
362  break;
363 
364  case T_bezier:
365  return static_cast<LIB_ITEM*>( parseBezier() );
366  break;
367 
368  case T_circle:
369  return static_cast<LIB_ITEM*>( parseCircle() );
370  break;
371 
372  case T_pin:
373  return static_cast<LIB_ITEM*>( parsePin() );
374  break;
375 
376  case T_polyline:
377  return static_cast<LIB_ITEM*>( parsePolyLine() );
378  break;
379 
380  case T_rectangle:
381  return static_cast<LIB_ITEM*>( parseRectangle() );
382  break;
383 
384  case T_text:
385  return static_cast<LIB_TEXT*>( parseText() );
386  break;
387 
388  default:
389  Expecting( "arc, bezier, circle, pin, polyline, rectangle, or text" );
390  }
391 
392  return nullptr;
393 }
LIB_POLYLINE * parsePolyLine()
LIB_RECTANGLE * parseRectangle()
LIB_BEZIER * parseBezier()
LIB_CIRCLE * parseCircle()

References parseArc(), parseBezier(), parseCircle(), parsePin(), parsePolyLine(), parseRectangle(), and parseText().

Referenced by ParseSymbol().

◆ parseEDA_TEXT()

void SCH_SEXPR_PARSER::parseEDA_TEXT ( EDA_TEXT aText)
private

Definition at line 547 of file sch_sexpr_parser.cpp.

548 {
549  wxCHECK_RET( aText && CurTok() == T_effects,
550  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as EDA_TEXT." ) );
551 
552  T token;
553 
554  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
555  {
556  if( token == T_LEFT )
557  token = NextTok();
558 
559  switch( token )
560  {
561  case T_font:
562  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
563  {
564  if( token == T_LEFT )
565  token = NextTok();
566 
567  switch( token )
568  {
569  case T_size:
570  {
571  wxSize sz;
572  sz.SetHeight( parseInternalUnits( "text height" ) );
573  sz.SetWidth( parseInternalUnits( "text width" ) );
574  aText->SetTextSize( sz );
575  NeedRIGHT();
576  break;
577  }
578 
579  case T_thickness:
580  aText->SetTextThickness( parseInternalUnits( "text thickness" ) );
581  NeedRIGHT();
582  break;
583 
584  case T_bold:
585  aText->SetBold( true );
586  break;
587 
588  case T_italic:
589  aText->SetItalic( true );
590  break;
591 
592  default:
593  Expecting( "size, bold, or italic" );
594  }
595  }
596 
597  break;
598 
599  case T_justify:
600  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
601  {
602  switch( token )
603  {
604  case T_left:
606  break;
607 
608  case T_right:
610  break;
611 
612  case T_top:
614  break;
615 
616  case T_bottom:
618  break;
619 
620  case T_mirror:
621  aText->SetMirrored( true );
622  break;
623 
624  default:
625  Expecting( "left, right, top, bottom, or mirror" );
626  }
627  }
628 
629  break;
630 
631  case T_hide:
632  aText->SetVisible( false );
633  break;
634 
635  default:
636  Expecting( "font, justify, or hide" );
637  }
638  }
639 }
void SetMirrored(bool isMirrored)
Definition: eda_text.h:188
void SetItalic(bool isItalic)
Definition: eda_text.h:179
void SetVisible(bool aVisible)
Definition: eda_text.h:185
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:238
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:203
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:202
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:158
void SetBold(bool aBold)
Definition: eda_text.h:182

References GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_HJUSTIFY_RIGHT, GR_TEXT_VJUSTIFY_BOTTOM, GR_TEXT_VJUSTIFY_TOP, parseInternalUnits(), EDA_TEXT::SetBold(), EDA_TEXT::SetHorizJustify(), EDA_TEXT::SetItalic(), EDA_TEXT::SetMirrored(), EDA_TEXT::SetTextSize(), EDA_TEXT::SetTextThickness(), EDA_TEXT::SetVertJustify(), and EDA_TEXT::SetVisible().

Referenced by parsePin(), parseProperty(), parseSchField(), parseSchSheetPin(), parseSchText(), and parseText().

◆ parseFill()

void SCH_SEXPR_PARSER::parseFill ( FILL_PARAMS aFill)
private

Definition at line 491 of file sch_sexpr_parser.cpp.

492 {
493  wxCHECK_RET( CurTok() == T_fill,
494  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as fill." ) );
495 
496  aFill.m_FillType = NO_FILL;
497  aFill.m_Color = COLOR4D::UNSPECIFIED;
498 
499  T token;
500 
501  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
502  {
503  if( token != T_LEFT )
504  Expecting( T_LEFT );
505 
506  token = NextTok();
507 
508  switch( token )
509  {
510  case T_type:
511  {
512  token = NextTok();
513 
514  switch( token )
515  {
516  case T_none: aFill.m_FillType = NO_FILL; break;
517  case T_outline: aFill.m_FillType = FILLED_SHAPE; break;
518  case T_background: aFill.m_FillType = FILLED_WITH_BG_BODYCOLOR; break;
519  default:
520  Expecting( "none, outline, or background" );
521  }
522 
523  NeedRIGHT();
524  break;
525  }
526 
527  case T_color:
528  {
529  COLOR4D color;
530 
531  color.r = parseInt( "red" ) / 255.0;
532  color.g = parseInt( "green" ) / 255.0;
533  color.b = parseInt( "blue" ) / 255.0;
534  color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
535  aFill.m_Color = color;
536  NeedRIGHT();
537  break;
538  }
539 
540  default:
541  Expecting( "type or color" );
542  }
543  }
544 }
int color
Definition: DXF_plotter.cpp:61
const T & Clamp(const T &lower, const T &value, const T &upper)
Function Clamp limits value within the range lower <= value <= upper.
Definition: util.h:46
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:99

References Clamp(), color, FILLED_SHAPE, FILLED_WITH_BG_BODYCOLOR, FILL_PARAMS::m_Color, FILL_PARAMS::m_FillType, NO_FILL, parseDouble(), and parseInt().

Referenced by parseArc(), parseBezier(), parseCircle(), parsePolyLine(), parseRectangle(), and parseSheet().

◆ parseHeader()

void SCH_SEXPR_PARSER::parseHeader ( TSCHEMATIC_T::T  aHeaderType,
int  aFileVersion 
)
private

Definition at line 642 of file sch_sexpr_parser.cpp.

643 {
644  wxCHECK_RET( CurTok() == aHeaderType,
645  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a header." ) );
646 
647  NeedLEFT();
648 
649  T tok = NextTok();
650 
651  if( tok == T_version )
652  {
653  m_requiredVersion = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
654  NeedRIGHT();
655 
656  // Skip the host name and host build version information.
657  NeedLEFT();
658  NeedSYMBOL();
659  NeedSYMBOL();
660 
661  if( m_requiredVersion < 20200827 )
662  NeedSYMBOL();
663 
664  NeedRIGHT();
665  }
666  else
667  {
668  m_requiredVersion = aFileVersion;
669 
670  // Skip the host name and host build version information.
671  NeedSYMBOL();
672  NeedSYMBOL();
673  NeedRIGHT();
674  }
675 }
int m_requiredVersion
Set to the symbol library file version required.

References m_requiredVersion, and parseInt().

Referenced by ParseLib(), and ParseSchematic().

◆ parseHex()

long SCH_SEXPR_PARSER::parseHex ( )
inlineprivate

Definition at line 89 of file sch_sexpr_parser.h.

90  {
91  NextTok();
92  return strtol( CurText(), NULL, 16 );
93  }
#define NULL

References NULL.

◆ parseImage()

SCH_BITMAP * SCH_SEXPR_PARSER::parseImage ( )
private

Definition at line 2264 of file sch_sexpr_parser.cpp.

2265 {
2266  wxCHECK_MSG( CurTok() == T_image, nullptr,
2267  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as an image." ) );
2268 
2269  T token;
2270  std::unique_ptr<SCH_BITMAP> bitmap( new SCH_BITMAP() );
2271 
2272  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2273  {
2274  if( token != T_LEFT )
2275  Expecting( T_LEFT );
2276 
2277  token = NextTok();
2278 
2279  switch( token )
2280  {
2281  case T_at:
2282  bitmap->SetPosition( parseXY() );
2283  NeedRIGHT();
2284  break;
2285 
2286  case T_scale:
2287  bitmap->GetImage()->SetScale( parseDouble( "image scale factor" ) );
2288 
2289  if( !std::isnormal( bitmap->GetImage()->GetScale() ) )
2290  bitmap->GetImage()->SetScale( 1.0 );
2291 
2292  NeedRIGHT();
2293  break;
2294 
2295  case T_data:
2296  {
2297  token = NextTok();
2298 
2299  wxString data;
2300 
2301  // Reserve 128K because most image files are going to be larger than the default
2302  // 1K that wxString reserves.
2303  data.reserve( 1 << 17 );
2304 
2305  while( token != T_RIGHT )
2306  {
2307  if( !IsSymbol( token ) )
2308  Expecting( "base64 image data" );
2309 
2310  data += FromUTF8();
2311  token = NextTok();
2312  }
2313 
2314  wxMemoryBuffer buffer = wxBase64Decode( data );
2315  wxMemoryOutputStream stream( buffer.GetData(), buffer.GetBufSize() );
2316  wxImage* image = new wxImage();
2317  wxMemoryInputStream istream( stream );
2318  image->LoadFile( istream, wxBITMAP_TYPE_PNG );
2319  bitmap->GetImage()->SetImage( image );
2320  bitmap->GetImage()->SetBitmap( new wxBitmap( *image ) );
2321  break;
2322  }
2323 
2324  default:
2325  Expecting( "at, scale, or data" );
2326  }
2327  }
2328 
2329  return bitmap.release();
2330 }
Object to handle a bitmap image that can be inserted in a schematic.
Definition: sch_bitmap.h:42
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

References parseDouble(), and parseXY().

Referenced by ParseSchematic().

◆ parseInt() [1/2]

int SCH_SEXPR_PARSER::parseInt ( )
inlineprivate

Definition at line 95 of file sch_sexpr_parser.h.

96  {
97  return (int)strtol( CurText(), NULL, 10 );
98  }
#define NULL

References NULL.

Referenced by parseFill(), parseHeader(), parseInt(), parseJunction(), parsePin(), parseProperty(), parseSchematicSymbol(), parseSchField(), parseSchSymbolInstances(), parseStroke(), and parseTITLE_BLOCK().

◆ parseInt() [2/2]

int SCH_SEXPR_PARSER::parseInt ( const char *  aExpected)
inlineprivate

Definition at line 100 of file sch_sexpr_parser.h.

101  {
102  NeedNUMBER( aExpected );
103  return parseInt();
104  }

References parseInt().

◆ parseInternalUnits() [1/3]

int SCH_SEXPR_PARSER::parseInternalUnits ( )
inlineprivate

Definition at line 126 of file sch_sexpr_parser.h.

127  {
128  auto retval = parseDouble() * IU_PER_MM;
129 
130  // Schematic internal units are represented as integers. Any values that are
131  // larger or smaller than the schematic units represent undefined behavior for
132  // the system. Limit values to the largest that can be displayed on the screen.
133  double int_limit = std::numeric_limits<int>::max() * 0.7071; // 0.7071 = roughly 1/sqrt(2)
134 
135  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
136  }
static constexpr double IU_PER_MM
Mock up a conversion function.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

References IU_PER_MM, KiROUND(), and parseDouble().

Referenced by parseArc(), parseBezier(), parseBusEntry(), parseCircle(), parseEDA_TEXT(), parseInternalUnits(), parseJunction(), parsePin(), parsePinNames(), parsePolyLine(), parseRectangle(), parseSheet(), parseStroke(), and parseXY().

◆ parseInternalUnits() [2/3]

int SCH_SEXPR_PARSER::parseInternalUnits ( const char *  aExpected)
inlineprivate

Definition at line 138 of file sch_sexpr_parser.h.

139  {
140  auto retval = parseDouble( aExpected ) * IU_PER_MM;
141 
142  double int_limit = std::numeric_limits<int>::max() * 0.7071;
143 
144  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
145  }
static constexpr double IU_PER_MM
Mock up a conversion function.
constexpr ret_type KiROUND(fp_type v)
Round a floating point number to an integer using "round halfway cases away from zero".
Definition: util.h:68
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

References IU_PER_MM, KiROUND(), and parseDouble().

◆ parseInternalUnits() [3/3]

int SCH_SEXPR_PARSER::parseInternalUnits ( TSCHEMATIC_T::T  aToken)
inlineprivate

Definition at line 147 of file sch_sexpr_parser.h.

148  {
149  return parseInternalUnits( GetTokenText( aToken ) );
150  }
const char * GetTokenText(T aTok)
Function GetTokenText is in the DSN namespace and returns the C string representing a SPECCTRA_DB::ke...
Definition: specctra.cpp:69

References DSN::GetTokenText(), and parseInternalUnits().

◆ parseJunction()

SCH_JUNCTION * SCH_SEXPR_PARSER::parseJunction ( )
private

Definition at line 2432 of file sch_sexpr_parser.cpp.

2433 {
2434  wxCHECK_MSG( CurTok() == T_junction, nullptr,
2435  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a junction." ) );
2436 
2437  T token;
2438  std::unique_ptr<SCH_JUNCTION> junction( new SCH_JUNCTION() );
2439 
2440  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2441  {
2442  if( token != T_LEFT )
2443  Expecting( T_LEFT );
2444 
2445  token = NextTok();
2446 
2447  switch( token )
2448  {
2449  case T_at:
2450  junction->SetPosition( parseXY() );
2451  NeedRIGHT();
2452  break;
2453 
2454  case T_diameter:
2455  junction->SetDiameter( parseInternalUnits( "junction diameter" ) );
2456  NeedRIGHT();
2457  break;
2458 
2459  case T_color:
2460  {
2461  COLOR4D color;
2462 
2463  color.r = parseInt( "red" ) / 255.0;
2464  color.g = parseInt( "green" ) / 255.0;
2465  color.b = parseInt( "blue" ) / 255.0;
2466  color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
2467 
2468  junction->SetColor( color );
2469  NeedRIGHT();
2470  break;
2471  }
2472 
2473  default:
2474  Expecting( "at" );
2475  }
2476  }
2477 
2478  return junction.release();
2479 }
int color
Definition: DXF_plotter.cpp:61
const T & Clamp(const T &lower, const T &value, const T &upper)
Function Clamp limits value within the range lower <= value <= upper.
Definition: util.h:46
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:99

References Clamp(), color, parseDouble(), parseInt(), parseInternalUnits(), and parseXY().

Referenced by ParseSchematic().

◆ ParseLib()

void SCH_SEXPR_PARSER::ParseLib ( LIB_PART_MAP aSymbolLibMap)

Definition at line 92 of file sch_sexpr_parser.cpp.

93 {
94  T token;
95 
96  NeedLEFT();
97  NextTok();
98  parseHeader( T_kicad_symbol_lib, SEXPR_SYMBOL_LIB_FILE_VERSION );
99 
100  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
101  {
102  if( token != T_LEFT )
103  Expecting( T_LEFT );
104 
105  token = NextTok();
106 
107  if( token == T_symbol )
108  {
109  m_unit = 1;
110  m_convert = 1;
111  LIB_PART* symbol = ParseSymbol( aSymbolLibMap, m_requiredVersion );
112  aSymbolLibMap[symbol->GetName()] = symbol;
113  }
114  else
115  {
116  Expecting( "symbol" );
117  }
118  }
119 }
LIB_PART * ParseSymbol(LIB_PART_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
wxString GetName() const override
int m_unit
The current unit being parsed.
#define SEXPR_SYMBOL_LIB_FILE_VERSION
This file contains the file format version information for the s-expression schematic and symbol libr...
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
int m_convert
The current body style being parsed.
Define a library symbol object.
int m_requiredVersion
Set to the symbol library file version required.

References LIB_PART::GetName(), m_convert, m_requiredVersion, m_unit, parseHeader(), ParseSymbol(), and SEXPR_SYMBOL_LIB_FILE_VERSION.

◆ parseLine()

SCH_LINE * SCH_SEXPR_PARSER::parseLine ( )
private

Definition at line 2561 of file sch_sexpr_parser.cpp.

2562 {
2563  T token;
2564  STROKE_PARAMS stroke;
2565  std::unique_ptr<SCH_LINE> line( new SCH_LINE() );
2566 
2567  switch( CurTok() )
2568  {
2569  case T_polyline: line->SetLayer( LAYER_NOTES ); break;
2570  case T_wire: line->SetLayer( LAYER_WIRE ); break;
2571  case T_bus: line->SetLayer( LAYER_BUS ); break;
2572  default:
2573  wxCHECK_MSG( false, nullptr,
2574  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a line." ) );
2575  }
2576 
2577  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2578  {
2579  if( token != T_LEFT )
2580  Expecting( T_LEFT );
2581 
2582  token = NextTok();
2583 
2584  switch( token )
2585  {
2586  case T_pts:
2587  NeedLEFT();
2588  token = NextTok();
2589 
2590  if( token != T_xy )
2591  Expecting( "xy" );
2592 
2593  line->SetStartPoint( parseXY() );
2594  NeedRIGHT();
2595  NeedLEFT();
2596  token = NextTok();
2597 
2598  if( token != T_xy )
2599  Expecting( "xy" );
2600 
2601  line->SetEndPoint( parseXY() );
2602  NeedRIGHT();
2603  NeedRIGHT();
2604  break;
2605 
2606  case T_stroke:
2607  parseStroke( stroke );
2608  line->SetStroke( stroke );
2609  break;
2610 
2611  default:
2612  Expecting( "at or stroke" );
2613  }
2614  }
2615 
2616  return line.release();
2617 }
Segment description base class to describe items which have 2 end points (track, wire,...
Definition: sch_line.h:37
Simple container to manage line stroke parameters.
Definition: sch_item.h:153
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.

References LAYER_BUS, LAYER_NOTES, LAYER_WIRE, parseStroke(), and parseXY().

Referenced by ParseSchematic().

◆ parseNoConnect()

SCH_NO_CONNECT * SCH_SEXPR_PARSER::parseNoConnect ( )
private

Definition at line 2482 of file sch_sexpr_parser.cpp.

2483 {
2484  wxCHECK_MSG( CurTok() == T_no_connect, nullptr,
2485  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a no connect." ) );
2486 
2487  T token;
2488  std::unique_ptr<SCH_NO_CONNECT> no_connect( new SCH_NO_CONNECT() );
2489 
2490  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2491  {
2492  if( token != T_LEFT )
2493  Expecting( T_LEFT );
2494 
2495  token = NextTok();
2496 
2497  switch( token )
2498  {
2499  case T_at:
2500  no_connect->SetPosition( parseXY() );
2501  NeedRIGHT();
2502  break;
2503 
2504  default:
2505  Expecting( "at" );
2506  }
2507  }
2508 
2509  return no_connect.release();
2510 }

References parseXY().

Referenced by ParseSchematic().

◆ parsePAGE_INFO()

void SCH_SEXPR_PARSER::parsePAGE_INFO ( PAGE_INFO aPageInfo)
private

Definition at line 1478 of file sch_sexpr_parser.cpp.

1479 {
1480  wxCHECK_RET( ( CurTok() == T_page && m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
1481  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a PAGE_INFO." ) );
1482 
1483  T token;
1484 
1485  NeedSYMBOL();
1486 
1487  wxString pageType = FromUTF8();
1488 
1489  if( !aPageInfo.SetType( pageType ) )
1490  {
1491  wxString err;
1492  err.Printf( _( "Page type \"%s\" is not valid " ), GetChars( FromUTF8() ) );
1493  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
1494  }
1495 
1496  if( pageType == PAGE_INFO::Custom )
1497  {
1498  double width = parseDouble( "width" ); // width in mm
1499 
1500  // Perform some controls to avoid crashes if the size is edited by hands
1501  if( width < 100.0 )
1502  width = 100.0;
1503  else if( width > 1200.0 )
1504  width = 1200.0;
1505 
1506  double height = parseDouble( "height" ); // height in mm
1507 
1508  if( height < 100.0 )
1509  height = 100.0;
1510  else if( height > 1200.0 )
1511  height = 1200.0;
1512 
1513  aPageInfo.SetWidthMils( Mm2mils( width ) );
1514  aPageInfo.SetHeightMils( Mm2mils( height ) );
1515  }
1516 
1517  token = NextTok();
1518 
1519  if( token == T_portrait )
1520  {
1521  aPageInfo.SetPortrait( true );
1522  NeedRIGHT();
1523  }
1524  else if( token != T_RIGHT )
1525  {
1526  Expecting( "portrait" );
1527  }
1528 }
int Mm2mils(double x)
Convert mm to mils.
Definition: base_units.h:62
bool SetType(const wxString &aStandardPageDescriptionName, bool aIsPortrait=false)
Function SetType sets the name of the page type and also the sizes and margins commonly associated wi...
Definition: page_info.cpp:119
static const wxChar Custom[]
"User" defined page type
Definition: page_info.h:79
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:162
void SetHeightMils(int aHeightInMils)
Definition: page_info.cpp:257
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:153
int m_requiredVersion
Set to the symbol library file version required.
#define _(s)
Definition: 3d_actions.cpp:33
void SetWidthMils(int aWidthInMils)
Definition: page_info.cpp:243
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
void SetPortrait(bool aIsPortrait)
Function SetPortrait will rotate the paper page 90 degrees.
Definition: page_info.cpp:186

References _, PAGE_INFO::Custom, GetChars(), m_requiredVersion, Mm2mils(), parseDouble(), PAGE_INFO::SetHeightMils(), PAGE_INFO::SetPortrait(), PAGE_INFO::SetType(), PAGE_INFO::SetWidthMils(), and THROW_PARSE_ERROR.

Referenced by ParseSchematic().

◆ parsePin()

LIB_PIN * SCH_SEXPR_PARSER::parsePin ( )
private

Definition at line 1085 of file sch_sexpr_parser.cpp.

1086 {
1087  auto parseType = [&]( T token ) -> ELECTRICAL_PINTYPE
1088  {
1089  switch( token )
1090  {
1091  case T_input: return ELECTRICAL_PINTYPE::PT_INPUT;
1092  case T_output: return ELECTRICAL_PINTYPE::PT_OUTPUT;
1093  case T_bidirectional: return ELECTRICAL_PINTYPE::PT_BIDI;
1094  case T_tri_state: return ELECTRICAL_PINTYPE::PT_TRISTATE;
1095  case T_passive: return ELECTRICAL_PINTYPE::PT_PASSIVE;
1096  case T_unspecified: return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1097  case T_power_in: return ELECTRICAL_PINTYPE::PT_POWER_IN;
1098  case T_power_out: return ELECTRICAL_PINTYPE::PT_POWER_OUT;
1099  case T_open_collector: return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
1100  case T_open_emitter: return ELECTRICAL_PINTYPE::PT_OPENEMITTER;
1101  case T_unconnected: return ELECTRICAL_PINTYPE::PT_NC;
1102 
1103  default:
1104  Expecting( "input, output, bidirectional, tri_state, passive, "
1105  "unspecified, power_in, power_out, open_collector, "
1106  "open_emitter, or unconnected" );
1108  }
1109  };
1110 
1111  auto parseShape = [&]( T token ) -> GRAPHIC_PINSHAPE
1112  {
1113  switch( token )
1114  {
1115  case T_line: return GRAPHIC_PINSHAPE::LINE;
1116  case T_inverted: return GRAPHIC_PINSHAPE::INVERTED;
1117  case T_clock: return GRAPHIC_PINSHAPE::CLOCK;
1118  case T_inverted_clock: return GRAPHIC_PINSHAPE::INVERTED_CLOCK;
1119  case T_input_low: return GRAPHIC_PINSHAPE::INPUT_LOW;
1120  case T_clock_low: return GRAPHIC_PINSHAPE::CLOCK_LOW;
1121  case T_output_low: return GRAPHIC_PINSHAPE::OUTPUT_LOW;
1122  case T_edge_clock_high: return GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK;
1123  case T_non_logic: return GRAPHIC_PINSHAPE::NONLOGIC;
1124 
1125  default:
1126  Expecting( "line, inverted, clock, inverted_clock, input_low, "
1127  "clock_low, output_low, edge_clock_high, non_logic" );
1128  return GRAPHIC_PINSHAPE::LINE;
1129  }
1130  };
1131 
1132  wxCHECK_MSG( CurTok() == T_pin, nullptr,
1133  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a pin token." ) );
1134 
1135  T token;
1136  wxString tmp;
1137  wxString error;
1138  std::unique_ptr<LIB_PIN> pin( new LIB_PIN( nullptr ) );
1139 
1140  pin->SetUnit( m_unit );
1141  pin->SetConvert( m_convert );
1142 
1143  // Pin electrical type.
1144  token = NextTok();
1145  pin->SetType( parseType( token ) );
1146 
1147  // Pin shape.
1148  token = NextTok();
1149  pin->SetShape( parseShape( token ) );
1150 
1151  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1152  {
1153  if( token == T_hide )
1154  {
1155  pin->SetVisible( false );
1156  continue;
1157  }
1158 
1159  if( token != T_LEFT )
1160  Expecting( T_LEFT );
1161 
1162  token = NextTok();
1163 
1164  switch( token )
1165  {
1166  case T_at:
1167  pin->SetPosition( parseXY() );
1168 
1169  switch( parseInt( "pin orientation" ) )
1170  {
1171  case 0:
1172  pin->SetOrientation( PIN_RIGHT );
1173  break;
1174 
1175  case 90:
1176  pin->SetOrientation( PIN_UP );
1177  break;
1178 
1179  case 180:
1180  pin->SetOrientation( PIN_LEFT );
1181  break;
1182 
1183  case 270:
1184  pin->SetOrientation( PIN_DOWN );
1185  break;
1186 
1187  default:
1188  Expecting( "0, 90, 180, or 270" );
1189  }
1190 
1191  NeedRIGHT();
1192  break;
1193 
1194  case T_length:
1195  pin->SetLength( parseInternalUnits( "pin length" ) );
1196  NeedRIGHT();
1197  break;
1198 
1199  case T_name:
1200  token = NextTok();
1201 
1202  if( !IsSymbol( token ) )
1203  {
1204  error.Printf( _( "Invalid pin name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1205  CurSource().c_str(), CurLineNumber(), CurOffset() );
1206  THROW_IO_ERROR( error );
1207  }
1208 
1209  pin->SetName( FromUTF8() );
1210  token = NextTok();
1211 
1212  if( token != T_RIGHT )
1213  {
1214  token = NextTok();
1215 
1216  if( token == T_effects )
1217  {
1218  // The EDA_TEXT font effects formatting is used so use and EDA_TEXT object
1219  // so duplicate parsing is not required.
1220  EDA_TEXT text;
1221 
1222  parseEDA_TEXT( &text );
1223  pin->SetNameTextSize( text.GetTextHeight() );
1224  NeedRIGHT();
1225  }
1226  else
1227  {
1228  Expecting( "effects" );
1229  }
1230  }
1231 
1232  break;
1233 
1234  case T_number:
1235  token = NextTok();
1236 
1237  if( !IsSymbol( token ) )
1238  {
1239  error.Printf( _( "Invalid pin number in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1240  CurSource().c_str(), CurLineNumber(), CurOffset() );
1241  THROW_IO_ERROR( error );
1242  }
1243 
1244  pin->SetNumber( FromUTF8() );
1245  token = NextTok();
1246 
1247  if( token != T_RIGHT )
1248  {
1249  token = NextTok();
1250 
1251  if( token == T_effects )
1252  {
1253  // The EDA_TEXT font effects formatting is used so use and EDA_TEXT object
1254  // so duplicate parsing is not required.
1255  EDA_TEXT text;
1256 
1257  parseEDA_TEXT( &text );
1258  pin->SetNumberTextSize( text.GetTextHeight() );
1259  NeedRIGHT();
1260  }
1261  else
1262  {
1263  Expecting( "effects" );
1264  }
1265  }
1266 
1267  break;
1268 
1269  case T_alternate:
1270  {
1271  LIB_PIN::ALT alt;
1272 
1273  token = NextTok();
1274 
1275  if( !IsSymbol( token ) )
1276  {
1277  error.Printf( _( "Invalid alternate pin name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1278  CurSource().c_str(), CurLineNumber(), CurOffset() );
1279  THROW_IO_ERROR( error );
1280  }
1281 
1282  alt.m_Name = FromUTF8();
1283 
1284  token = NextTok();
1285  alt.m_Type = parseType( token );
1286 
1287  token = NextTok();
1288  alt.m_Shape = parseShape( token );
1289 
1290  pin->GetAlternates()[ alt.m_Name ] = alt;
1291 
1292  NeedRIGHT();
1293  }
1294  break;
1295 
1296  default:
1297  Expecting( "at, name, number, length, or alternate" );
1298  }
1299  }
1300 
1301  return pin.release();
1302 }
power input (GND, VCC for ICs). Must be connected to a power output.
void parseEDA_TEXT(EDA_TEXT *aText)
pin for passive components: must be connected, and can be connected to any pin
int m_unit
The current unit being parsed.
unknown electrical properties: creates always a warning when connected
Definition: lib_pin.h:50
GRAPHIC_PINSHAPE
Definition: pin_type.h:53
ELECTRICAL_PINTYPE m_Type
Definition: lib_pin.h:62
int GetTextHeight() const
Definition: eda_text.h:245
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:113
int m_convert
The current body style being parsed.
wxString m_Name
Definition: lib_pin.h:60
ELECTRICAL_PINTYPE
The component library pin object electrical types used in ERC tests.
Definition: pin_type.h:34
#define _(s)
Definition: 3d_actions.cpp:33
usual pin input: must be connected
input or output (like port for a microprocessor)
not connected (must be left open)
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
output of a regulator: intended to be connected to power input pins
GRAPHIC_PINSHAPE m_Shape
Definition: lib_pin.h:61

References _, CLOCK, CLOCK_LOW, FALLING_EDGE_CLOCK, EDA_TEXT::GetTextHeight(), INPUT_LOW, INVERTED, INVERTED_CLOCK, LINE, m_convert, LIB_PIN::ALT::m_Name, LIB_PIN::ALT::m_Shape, LIB_PIN::ALT::m_Type, m_unit, NONLOGIC, OUTPUT_LOW, parseEDA_TEXT(), parseInt(), parseInternalUnits(), parseXY(), PIN_DOWN, PIN_LEFT, PIN_RIGHT, PIN_UP, PT_BIDI, PT_INPUT, PT_NC, PT_OPENCOLLECTOR, PT_OPENEMITTER, PT_OUTPUT, PT_PASSIVE, PT_POWER_IN, PT_POWER_OUT, PT_TRISTATE, PT_UNSPECIFIED, and THROW_IO_ERROR.

Referenced by ParseDrawItem().

◆ parsePinNames()

void SCH_SEXPR_PARSER::parsePinNames ( std::unique_ptr< LIB_PART > &  aSymbol)
private

Definition at line 678 of file sch_sexpr_parser.cpp.

679 {
680  wxCHECK_RET( CurTok() == T_pin_names,
681  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
682  wxT( " as a pin_name token." ) );
683 
684  wxString error;
685 
686  T token = NextTok();
687 
688  if( token == T_LEFT )
689  {
690  token = NextTok();
691 
692  if( token != T_offset )
693  Expecting( "offset" );
694 
695  aSymbol->SetPinNameOffset( parseInternalUnits( "pin name offset" ) );
696  NeedRIGHT();
697  token = NextTok(); // Either ) or hide
698  }
699 
700  if( token == T_hide )
701  {
702  aSymbol->SetShowPinNames( false );
703  NeedRIGHT();
704  }
705  else if( token != T_RIGHT )
706  {
707  error.Printf(
708  _( "Invalid symbol names definition in\nfile: \"%s\"\nline: %d\noffset: %d" ),
709  CurSource().c_str(), CurLineNumber(), CurOffset() );
710  THROW_IO_ERROR( error );
711  }
712 }
#define _(s)
Definition: 3d_actions.cpp:33
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, parseInternalUnits(), and THROW_IO_ERROR.

Referenced by ParseSymbol().

◆ parsePolyLine()

LIB_POLYLINE * SCH_SEXPR_PARSER::parsePolyLine ( )
private

Definition at line 1305 of file sch_sexpr_parser.cpp.

1306 {
1307  wxCHECK_MSG( CurTok() == T_polyline, nullptr,
1308  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a polyline." ) );
1309 
1310  T token;
1311  FILL_PARAMS fill;
1312  std::unique_ptr<LIB_POLYLINE> polyLine( new LIB_POLYLINE( nullptr ) );
1313 
1314  polyLine->SetUnit( m_unit );
1315  polyLine->SetConvert( m_convert );
1316 
1317  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1318  {
1319  if( token != T_LEFT )
1320  Expecting( T_LEFT );
1321 
1322  token = NextTok();
1323 
1324  switch( token )
1325  {
1326  case T_pts:
1327  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1328  {
1329  if( token != T_LEFT )
1330  Expecting( T_LEFT );
1331 
1332  token = NextTok();
1333 
1334  if( token != T_xy )
1335  Expecting( "xy" );
1336 
1337  polyLine->AddPoint( parseXY() );
1338 
1339  NeedRIGHT();
1340  }
1341 
1342  break;
1343 
1344  case T_stroke:
1345  NeedLEFT();
1346  token = NextTok();
1347 
1348  if( token != T_width )
1349  Expecting( "width" );
1350 
1351  polyLine->SetWidth( parseInternalUnits( "stroke width" ) );
1352  NeedRIGHT(); // Closes width token;
1353  NeedRIGHT(); // Closes stroke token;
1354  break;
1355 
1356  case T_fill:
1357  parseFill( fill );
1358  polyLine->SetFillMode( fill.m_FillType );
1359  break;
1360 
1361  default:
1362  Expecting( "pts, stroke, or fill" );
1363  }
1364  }
1365 
1366  return polyLine.release();
1367 }
int m_unit
The current unit being parsed.
Simple container to manage fill parameters.
int m_convert
The current body style being parsed.
void parseFill(FILL_PARAMS &aFill)

References m_convert, FILL_PARAMS::m_FillType, m_unit, parseFill(), parseInternalUnits(), and parseXY().

Referenced by ParseDrawItem().

◆ parseProperty()

void SCH_SEXPR_PARSER::parseProperty ( std::unique_ptr< LIB_PART > &  aSymbol)
private

Definition at line 715 of file sch_sexpr_parser.cpp.

716 {
717  wxCHECK_RET( CurTok() == T_property,
718  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
719  wxT( " as a property token." ) );
720  wxCHECK( aSymbol, /* void */ );
721 
722  wxString error;
723  wxString name;
724  wxString value;
725  std::unique_ptr<LIB_FIELD> field( new LIB_FIELD( aSymbol.get(), MANDATORY_FIELDS ) );
726 
727  T token = NextTok();
728 
729  if( !IsSymbol( token ) )
730  {
731  error.Printf( _( "Invalid property name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
732  CurSource().c_str(), CurLineNumber(), CurOffset() );
733  THROW_IO_ERROR( error );
734  }
735 
736  name = FromUTF8();
737 
738  if( name.IsEmpty() )
739  {
740  error.Printf( _( "Empty property name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
741  CurSource().c_str(), CurLineNumber(), CurOffset() );
742  THROW_IO_ERROR( error );
743  }
744 
745  field->SetName( name );
746  token = NextTok();
747 
748  if( !IsSymbol( token ) )
749  {
750  error.Printf( _( "Invalid property value in\nfile: \"%s\"\nline: %d\noffset: %d" ),
751  CurSource().c_str(), CurLineNumber(), CurOffset() );
752  THROW_IO_ERROR( error );
753  }
754 
755  // Empty property values are valid.
756  value = FromUTF8();
757 
758  field->SetText( value );
759 
760  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
761  {
762  if( token != T_LEFT )
763  Expecting( T_LEFT );
764 
765  token = NextTok();
766 
767  switch( token )
768  {
769  case T_id:
770  field->SetId( parseInt( "field ID" ) );
771  NeedRIGHT();
772  break;
773 
774  case T_at:
775  field->SetPosition( parseXY() );
776  field->SetTextAngle( static_cast<int>( parseDouble( "text angle" ) * 10.0 ) );
777  NeedRIGHT();
778  break;
779 
780  case T_effects:
781  parseEDA_TEXT( static_cast<EDA_TEXT*>( field.get() ) );
782  break;
783 
784  default:
785  Expecting( "id, at or effects" );
786  }
787  }
788 
789  LIB_FIELD* existingField;
790 
791  if( field->GetId() < MANDATORY_FIELDS )
792  {
793  existingField = aSymbol->GetField( field->GetId() );
794 
795  *existingField = *field;
796  }
797  else if( name == "ki_keywords" )
798  {
799  // Not a LIB_FIELD object yet.
800  aSymbol->SetKeyWords( value );
801  }
802  else if( name == "ki_description" )
803  {
804  // Not a LIB_FIELD object yet.
805  aSymbol->SetDescription( value );
806  }
807  else if( name == "ki_fp_filters" )
808  {
809  // Not a LIB_FIELD object yet.
810  wxArrayString filters;
811  wxStringTokenizer tokenizer( value );
812 
813  while( tokenizer.HasMoreTokens() )
814  filters.Add( tokenizer.GetNextToken() );
815 
816  aSymbol->SetFootprintFilters( filters );
817  }
818  else if( name == "ki_locked" )
819  {
820  // This is a temporary LIB_FIELD object until interchangeable units are determined on
821  // the fly.
822  aSymbol->LockUnits( true );
823  }
824  else
825  {
826  existingField = aSymbol->GetField( field->GetId() );
827 
828  if( !existingField )
829  {
830  aSymbol->AddDrawItem( field.release() );
831  }
832  else
833  {
834  *existingField = *field;
835  }
836  }
837 }
void parseEDA_TEXT(EDA_TEXT *aText)
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
Field object used in symbol libraries.
Definition: lib_field.h:59
const char * name
Definition: DXF_plotter.cpp:60
#define _(s)
Definition: 3d_actions.cpp:33
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, MANDATORY_FIELDS, name, parseDouble(), parseEDA_TEXT(), parseInt(), parseXY(), and THROW_IO_ERROR.

Referenced by ParseSymbol().

◆ parseRectangle()

LIB_RECTANGLE * SCH_SEXPR_PARSER::parseRectangle ( )
private

Definition at line 1370 of file sch_sexpr_parser.cpp.

1371 {
1372  wxCHECK_MSG( CurTok() == T_rectangle, nullptr,
1373  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a rectangle token." ) );
1374 
1375  T token;
1376  FILL_PARAMS fill;
1377  std::unique_ptr<LIB_RECTANGLE> rectangle( new LIB_RECTANGLE( nullptr ) );
1378 
1379  rectangle->SetUnit( m_unit );
1380  rectangle->SetConvert( m_convert );
1381 
1382  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1383  {
1384  if( token != T_LEFT )
1385  Expecting( T_LEFT );
1386 
1387  token = NextTok();
1388 
1389  switch( token )
1390  {
1391  case T_start:
1392  rectangle->SetPosition( parseXY() );
1393  NeedRIGHT();
1394  break;
1395 
1396  case T_end:
1397  rectangle->SetEnd( parseXY() );
1398  NeedRIGHT();
1399  break;
1400 
1401  case T_stroke:
1402  NeedLEFT();
1403  token = NextTok();
1404 
1405  if( token != T_width )
1406  Expecting( "width" );
1407 
1408  rectangle->SetWidth( parseInternalUnits( "stroke width" ) );
1409  NeedRIGHT(); // Closes width token;
1410  NeedRIGHT(); // Closes stroke token;
1411  break;
1412 
1413  case T_fill:
1414  parseFill( fill );
1415  rectangle->SetFillMode( fill.m_FillType );
1416  break;
1417 
1418  default:
1419  Expecting( "start, end, stroke, or fill" );
1420  }
1421  }
1422 
1423  return rectangle.release();
1424 }
int m_unit
The current unit being parsed.
Simple container to manage fill parameters.
int m_convert
The current body style being parsed.
void parseFill(FILL_PARAMS &aFill)

References m_convert, FILL_PARAMS::m_FillType, m_unit, parseFill(), parseInternalUnits(), and parseXY().

Referenced by ParseDrawItem().

◆ ParseSchematic()

void SCH_SEXPR_PARSER::ParseSchematic ( SCH_SHEET aSheet,
bool  aIsCopyablyOnly = false,
int  aFileVersion = SEXPR_SCHEMATIC_FILE_VERSION 
)

Parse the internal LINE_READER object into aSheet.

When aIsCopyableOnly is true, only schematic objects that are viewable on the canvas for copy and paste purposes are parsed. Other schematic content such as bus definitions or instance data will throw an IO_ERROR exception.

When aIsCopyableOnly is false, full schematic file parsing is performed.

Note
This does not load any sub-sheets or decent complex sheet hierarchies.
Parameters
aSheetThe SCH_SHEET object to store the parsed schematic file.
aIsCopyableOnlyLoad only the schematic objects that can be copied into aSheet if true. Otherwise, load the full schematic file format.
aFileVersionThe schematic file version to parser. Defaults to the schematic file being parsed when aIsCopyableOnly is false.

Definition at line 1876 of file sch_sexpr_parser.cpp.

1877 {
1878  wxCHECK( aSheet != nullptr, /* void */ );
1879 
1880  SCH_SCREEN* screen = aSheet->GetScreen();
1881 
1882  wxCHECK( screen != nullptr, /* void */ );
1883 
1884  if( aIsCopyableOnly )
1885  m_requiredVersion = aFileVersion;
1886 
1887  T token;
1888 
1889  if( !aIsCopyableOnly )
1890  {
1891  NeedLEFT();
1892  NextTok();
1893 
1894  if( CurTok() != T_kicad_sch )
1895  Expecting( "kicad_sch" );
1896 
1897  parseHeader( T_kicad_sch, SEXPR_SCHEMATIC_FILE_VERSION );
1898  }
1899 
1900  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1901  {
1902  if( aIsCopyableOnly && token == T_EOF )
1903  break;
1904 
1905  if( token != T_LEFT )
1906  Expecting( T_LEFT );
1907 
1908  token = NextTok();
1909 
1910  if( !aIsCopyableOnly && token == T_page && m_requiredVersion <= 20200506 )
1911  token = T_paper;
1912 
1913  switch( token )
1914  {
1915  case T_paper:
1916  {
1917  if( aIsCopyableOnly )
1918  Unexpected( T_paper );
1919 
1920  PAGE_INFO pageInfo;
1921  parsePAGE_INFO( pageInfo );
1922  screen->SetPageSettings( pageInfo );
1923  break;
1924  }
1925 
1926  case T_page:
1927  {
1928  if( aIsCopyableOnly )
1929  Unexpected( T_page );
1930 
1931  // Only saved for top-level sniffing in Kicad Manager frame and other external
1932  // tool usage with flat hierarchies
1933  NeedSYMBOLorNUMBER();
1934  NeedSYMBOLorNUMBER();
1935  NeedRIGHT();
1936  break;
1937  }
1938 
1939  case T_title_block:
1940  {
1941  if( aIsCopyableOnly )
1942  Unexpected( T_title_block );
1943 
1944  TITLE_BLOCK tb;
1945  parseTITLE_BLOCK( tb );
1946  screen->SetTitleBlock( tb );
1947  break;
1948  }
1949 
1950  case T_lib_symbols:
1951  {
1952  // Dummy map. No derived symbols are allowed in the library cache.
1953  LIB_PART_MAP symbolLibMap;
1954 
1955  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1956  {
1957  if( token != T_LEFT )
1958  Expecting( T_LEFT );
1959 
1960  token = NextTok();
1961 
1962  switch( token )
1963  {
1964  case T_symbol:
1965  screen->AddLibSymbol( ParseSymbol( symbolLibMap ) );
1966  break;
1967 
1968  default:
1969  Expecting( "symbol" );
1970  }
1971  }
1972 
1973  break;
1974  }
1975 
1976  case T_symbol:
1977  screen->Append( static_cast<SCH_ITEM*>( parseSchematicSymbol() ) );
1978  break;
1979 
1980  case T_image:
1981  screen->Append( static_cast<SCH_ITEM*>( parseImage() ) );
1982  break;
1983 
1984  case T_sheet:
1985  {
1986  SCH_SHEET* sheet = parseSheet();
1987 
1988  // Set the parent to aSheet. This effectively creates a method to find
1989  // the root sheet from any sheet so a pointer to the root sheet does not
1990  // need to be stored globally. Note: this is not the same as a hierarchy.
1991  // Complex hierarchies can have multiple copies of a sheet. This only
1992  // provides a simple tree to find the root sheet.
1993  sheet->SetParent( aSheet );
1994  screen->Append( static_cast<SCH_ITEM*>( sheet ) );
1995  break;
1996  }
1997 
1998  case T_junction:
1999  screen->Append( static_cast<SCH_ITEM*>( parseJunction() ) );
2000  break;
2001 
2002  case T_no_connect:
2003  screen->Append( static_cast<SCH_ITEM*>( parseNoConnect() ) );
2004  break;
2005 
2006  case T_bus_entry:
2007  screen->Append( static_cast<SCH_ITEM*>( parseBusEntry() ) );
2008  break;
2009 
2010  case T_polyline:
2011  case T_bus:
2012  case T_wire:
2013  screen->Append( static_cast<SCH_ITEM*>( parseLine() ) );
2014  break;
2015 
2016  case T_text:
2017  case T_label:
2018  case T_global_label:
2019  case T_hierarchical_label:
2020  screen->Append( static_cast<SCH_ITEM*>( parseSchText() ) );
2021  break;
2022 
2023  case T_symbol_instances:
2024  if( aIsCopyableOnly )
2025  Unexpected( T_symbol_instances );
2026 
2027  parseSchSymbolInstances( screen );
2028  break;
2029 
2030  case T_bus_alias:
2031  if( aIsCopyableOnly )
2032  Unexpected( T_bus_alias );
2033 
2034  parseBusAlias( screen );
2035  break;
2036 
2037  default:
2038  Expecting( "symbol, paper, page, title_block, bitmap, sheet, junction, no_connect, "
2039  "bus_entry, line, bus, text, label, global_label, hierarchical_label, "
2040  "symbol_instances, or bus_alias" );
2041  }
2042  }
2043 
2044  screen->UpdateLocalLibSymbolLinks();
2045 }
LIB_PART * ParseSymbol(LIB_PART_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
void parseBusAlias(SCH_SCREEN *aScreen)
std::map< wxString, LIB_PART *, LibPartMapSort > LIB_PART_MAP
Part map used by part library object.
void parseTITLE_BLOCK(TITLE_BLOCK &aTitleBlock)
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: sch_screen.h:181
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:282
TITLE_BLOCK holds the information shown in the lower right corner of a plot, printout,...
Definition: title_block.h:40
void parseSchSymbolInstances(SCH_SCREEN *aScreen)
virtual void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:196
SCH_BUS_WIRE_ENTRY * parseBusEntry()
void UpdateLocalLibSymbolLinks()
Initialize the LIB_PART reference for each SCH_COMPONENT found in this schematic with the local proje...
Definition: sch_screen.cpp:714
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
SCH_JUNCTION * parseJunction()
PAGE_INFO describes the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:54
SCH_NO_CONNECT * parseNoConnect()
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition: sch_screen.h:192
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:216
void parsePAGE_INFO(PAGE_INFO &aPageInfo)
int m_requiredVersion
Set to the symbol library file version required.
void AddLibSymbol(LIB_PART *aLibSymbol)
Add aLibSymbol to the the library symbol map.
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:131
SCH_BITMAP * parseImage()
SCH_TEXT * parseSchText()
#define SEXPR_SCHEMATIC_FILE_VERSION
Symbol library file version.
SCH_COMPONENT * parseSchematicSymbol()
SCH_SHEET * parseSheet()

References SCH_SCREEN::AddLibSymbol(), SCH_SCREEN::Append(), SCH_SHEET::GetScreen(), m_requiredVersion, parseBusAlias(), parseBusEntry(), parseHeader(), parseImage(), parseJunction(), parseLine(), parseNoConnect(), parsePAGE_INFO(), parseSchematicSymbol(), parseSchSymbolInstances(), parseSchText(), parseSheet(), ParseSymbol(), parseTITLE_BLOCK(), SCH_SCREEN::SetPageSettings(), EDA_ITEM::SetParent(), SCH_SCREEN::SetTitleBlock(), SEXPR_SCHEMATIC_FILE_VERSION, and SCH_SCREEN::UpdateLocalLibSymbolLinks().

Referenced by SCH_SEXPR_PLUGIN::LoadContent(), and SCH_SEXPR_PLUGIN::loadFile().

◆ parseSchematicSymbol()

SCH_COMPONENT * SCH_SEXPR_PARSER::parseSchematicSymbol ( )
private

Definition at line 2048 of file sch_sexpr_parser.cpp.

2049 {
2050  wxCHECK_MSG( CurTok() == T_symbol, nullptr,
2051  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a symbol." ) );
2052 
2053  T token;
2054  wxString tmp;
2055  wxString error;
2056  wxString libName;
2057  SCH_FIELD* field;
2058  std::unique_ptr<SCH_COMPONENT> symbol( new SCH_COMPONENT() );
2059  TRANSFORM transform;
2060  std::set<int> fieldIDsRead;
2061 
2063 
2064  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2065  {
2066  if( token != T_LEFT )
2067  Expecting( T_LEFT );
2068 
2069  token = NextTok();
2070 
2071  switch( token )
2072  {
2073  case T_lib_name:
2074  {
2075  LIB_ID libId;
2076 
2077  token = NextTok();
2078 
2079  if( !IsSymbol( token ) )
2080  {
2081  error.Printf( _( "Invalid symbol library name in\nfile: \"%s\"\n"
2082  "line: %d\noffset: %d" ),
2083  CurSource().c_str(), CurLineNumber(), CurOffset() );
2084  THROW_IO_ERROR( error );
2085  }
2086 
2087  libName = FromUTF8();
2088  NeedRIGHT();
2089  break;
2090  }
2091 
2092  case T_lib_id:
2093  {
2094  token = NextTok();
2095 
2096  if( !IsSymbol( token ) && token != T_NUMBER )
2097  Expecting( "symbol|number" );
2098 
2099  LIB_ID libId;
2100 
2101  if( libId.Parse( FromUTF8(), LIB_ID::ID_SCH ) >= 0 )
2102  {
2103  error.Printf( _( "Invalid symbol library ID in\nfile: \"%s\"\nline: %d\n"
2104  "offset: %d" ),
2105  GetChars( CurSource() ), CurLineNumber(), CurOffset() );
2106  THROW_IO_ERROR( error );
2107  }
2108 
2109  symbol->SetLibId( libId );
2110  NeedRIGHT();
2111  break;
2112  }
2113 
2114  case T_at:
2115  symbol->SetPosition( parseXY() );
2116 
2117  switch( static_cast<int>( parseDouble( "symbol orientation" ) ) )
2118  {
2119  case 0: transform = TRANSFORM(); break;
2120  case 90: transform = TRANSFORM( 0, -1, -1, 0 ); break;
2121  case 180: transform = TRANSFORM( -1, 0, 0, 1 ); break;
2122  case 270: transform = TRANSFORM( 0, 1, 1, 0 ); break;
2123  default: Expecting( "0, 90, 180, or 270" );
2124  }
2125 
2126  symbol->SetTransform( transform );
2127  NeedRIGHT();
2128  break;
2129 
2130  case T_mirror:
2131  token = NextTok();
2132 
2133  if( token == T_x )
2134  symbol->SetOrientation( CMP_MIRROR_X );
2135  else if( token == T_y )
2136  symbol->SetOrientation( CMP_MIRROR_Y );
2137  else
2138  Expecting( "x or y" );
2139 
2140  NeedRIGHT();
2141  break;
2142 
2143  case T_unit:
2144  symbol->SetUnit( parseInt( "symbol unit" ) );
2145  NeedRIGHT();
2146  break;
2147 
2148  case T_convert:
2149  symbol->SetConvert( parseInt( "symbol convert" ) );
2150  NeedRIGHT();
2151  break;
2152 
2153  case T_in_bom:
2154  symbol->SetIncludeInBom( parseBool() );
2155  NeedRIGHT();
2156  break;
2157 
2158  case T_on_board:
2159  symbol->SetIncludeOnBoard( parseBool() );
2160  NeedRIGHT();
2161  break;
2162 
2163  case T_uuid:
2164  NeedSYMBOL();
2165  const_cast<KIID&>( symbol->m_Uuid ) = KIID( FromUTF8() );
2166  NeedRIGHT();
2167  break;
2168 
2169  case T_property:
2170  {
2171  // The field parent symbol must be set and it's orientation must be set before
2172  // the field positions are set.
2173  field = parseSchField( symbol.get() );
2174 
2175  // It would appear that at some point we allowed duplicate ids to slip through
2176  // when writing files. The easiest (and most complete) solution is to disallow
2177  // multiple instances of the same id (for all files since the source of the error
2178  // *might* in fact be hand-edited files).
2179  //
2180  // While no longer used, -1 is still a valid id for user fields and will
2181  // get written out as the next unused number on save.
2182  if( fieldIDsRead.count( field->GetId() ) )
2183  field->SetId( -1 );
2184  else
2185  fieldIDsRead.insert( field->GetId() );
2186 
2187  // Set the default symbol reference prefix.
2188  if( field->GetId() == REFERENCE )
2189  {
2190  wxString refDesignator = field->GetText();
2191 
2192  refDesignator.Replace( "~", " " );
2193 
2194  wxString prefix = refDesignator;
2195 
2196  while( prefix.Length() )
2197  {
2198  if( ( prefix.Last() < '0' || prefix.Last() > '9') && prefix.Last() != '?' )
2199  break;
2200 
2201  prefix.RemoveLast();
2202  }
2203 
2204  // Avoid a prefix containing trailing/leading spaces
2205  prefix.Trim( true );
2206  prefix.Trim( false );
2207 
2208  if( prefix.IsEmpty() )
2209  symbol->SetPrefix( wxString( "U" ) );
2210  else
2211  symbol->SetPrefix( prefix );
2212  }
2213 
2214  if( symbol->GetField( field->GetId() ) )
2215  *symbol->GetField( field->GetId() ) = *field;
2216  else
2217  symbol->AddField( *field );
2218 
2219  delete field;
2220  break;
2221  }
2222 
2223  case T_pin:
2224  {
2225  SCH_PIN* pin = new SCH_PIN( nullptr, symbol.get() );
2226 
2227  NeedSYMBOL();
2228  pin->SetNumber( FromUTF8() );
2229 
2230  token = NextTok();
2231 
2232  if( token == T_alternate )
2233  {
2234  NeedSYMBOL();
2235  pin->SetAlt( FromUTF8() );
2236  NeedRIGHT();
2237  }
2238  else
2239  {
2240  Expecting( "alternate" );
2241  }
2242 
2243  symbol->GetPins().push_back( pin );
2244 
2245  NeedRIGHT();
2246  }
2247  break;
2248 
2249  default:
2250  Expecting( "lib_id, lib_name, at, mirror, uuid, property, pin, or instances" );
2251  }
2252  }
2253 
2254  if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
2255  symbol->SetSchSymbolLibraryName( libName );
2256 
2257  // Ensure edit/status flags are cleared after these initializations:
2258  symbol->ClearFlags();
2259 
2260  return symbol.release();
2261 }
int m_fieldId
The current field ID.
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
int GetId() const
Definition: sch_field.h:114
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
Field Reference of part, i.e. "IC21".
Definition: common.h:68
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:45
void SetNumber(const wxString &aNumber)
Definition: sch_pin.h:113
static const wxChar * GetChars(const wxString &s)
Function GetChars returns a wxChar* to the actual wxChar* data within a wxString, and is helpful for ...
Definition: macros.h:153
#define _(s)
Definition: 3d_actions.cpp:33
void SetAlt(const wxString &aAlt)
Definition: sch_pin.h:73
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
Schematic symbol object.
Definition: sch_component.h:80
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
void SetId(int aId)
Definition: sch_field.cpp:76
int Parse(const UTF8 &aId, LIB_ID_TYPE aType, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:122
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:127

References _, CMP_MIRROR_X, CMP_MIRROR_Y, GetChars(), SCH_FIELD::GetId(), EDA_TEXT::GetText(), LIB_ID::ID_SCH, m_fieldId, MANDATORY_FIELDS, LIB_ID::Parse(), parseBool(), parseDouble(), parseInt(), parseSchField(), parseXY(), REFERENCE, SCH_PIN::SetAlt(), SCH_FIELD::SetId(), SCH_PIN::SetNumber(), and THROW_IO_ERROR.

Referenced by ParseSchematic().

◆ parseSchField()

SCH_FIELD * SCH_SEXPR_PARSER::parseSchField ( SCH_ITEM aParent)
private

Definition at line 1637 of file sch_sexpr_parser.cpp.

1638 {
1639  wxCHECK_MSG( CurTok() == T_property, nullptr,
1640  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1641  wxT( " as a property token." ) );
1642 
1643  wxString error;
1644  wxString name;
1645  wxString value;
1646 
1647  T token = NextTok();
1648 
1649  if( !IsSymbol( token ) )
1650  {
1651  error.Printf( _( "Invalid property name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1652  CurSource().c_str(), CurLineNumber(), CurOffset() );
1653  THROW_IO_ERROR( error );
1654  }
1655 
1656  name = FromUTF8();
1657 
1658  if( name.IsEmpty() )
1659  {
1660  error.Printf( _( "Empty property name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1661  CurSource().c_str(), CurLineNumber(), CurOffset() );
1662  THROW_IO_ERROR( error );
1663  }
1664 
1665  token = NextTok();
1666 
1667  if( !IsSymbol( token ) )
1668  {
1669  error.Printf( _( "Invalid property value in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1670  CurSource().c_str(), CurLineNumber(), CurOffset() );
1671  THROW_IO_ERROR( error );
1672  }
1673 
1674  // Empty property values are valid.
1675  value = FromUTF8();
1676 
1677  std::unique_ptr<SCH_FIELD> field( new SCH_FIELD( wxDefaultPosition, -1, aParent, name ) );
1678 
1679  field->SetText( value );
1680  field->SetVisible( true );
1681 
1682  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1683  {
1684  if( token != T_LEFT )
1685  Expecting( T_LEFT );
1686 
1687  token = NextTok();
1688 
1689  switch( token )
1690  {
1691  case T_id:
1692  field->SetId( parseInt( "field ID" ) );
1693  NeedRIGHT();
1694  break;
1695 
1696  case T_at:
1697  field->SetPosition( parseXY() );
1698  field->SetTextAngle( static_cast<int>( parseDouble( "text angle" ) * 10.0 ) );
1699  NeedRIGHT();
1700  break;
1701 
1702  case T_effects:
1703  parseEDA_TEXT( static_cast<EDA_TEXT*>( field.get() ) );
1704  break;
1705 
1706  default:
1707  Expecting( "at or effects" );
1708  }
1709  }
1710 
1711  return field.release();
1712 }
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
void parseEDA_TEXT(EDA_TEXT *aText)
const char * name
Definition: DXF_plotter.cpp:60
#define _(s)
Definition: 3d_actions.cpp:33
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, name, parseDouble(), parseEDA_TEXT(), parseInt(), parseXY(), and THROW_IO_ERROR.

Referenced by parseSchematicSymbol(), and parseSheet().

◆ parseSchSheetPin()

SCH_SHEET_PIN * SCH_SEXPR_PARSER::parseSchSheetPin ( SCH_SHEET aSheet)
private

Definition at line 1715 of file sch_sexpr_parser.cpp.

1716 {
1717  wxCHECK_MSG( aSheet != nullptr, nullptr, "" );
1718  wxCHECK_MSG( CurTok() == T_pin, nullptr,
1719  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1720  wxT( " as a sheet pin token." ) );
1721 
1722  wxString error;
1723  wxString name;
1724  wxString shape;
1725 
1726  T token = NextTok();
1727 
1728  if( !IsSymbol( token ) )
1729  {
1730  error.Printf( _( "Invalid sheet pin name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1731  CurSource().c_str(), CurLineNumber(), CurOffset() );
1732  THROW_IO_ERROR( error );
1733  }
1734 
1735  name = FromUTF8();
1736 
1737  if( name.IsEmpty() )
1738  {
1739  error.Printf( _( "Empty sheet pin name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1740  CurSource().c_str(), CurLineNumber(), CurOffset() );
1741  THROW_IO_ERROR( error );
1742  }
1743 
1744  std::unique_ptr<SCH_SHEET_PIN> sheetPin( new SCH_SHEET_PIN( aSheet, wxPoint( 0, 0 ), name ) );
1745 
1746  token = NextTok();
1747 
1748  switch( token )
1749  {
1750  case T_input: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_INPUT ); break;
1751  case T_output: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_OUTPUT ); break;
1752  case T_bidirectional: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_BIDI ); break;
1753  case T_tri_state: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_TRISTATE ); break;
1754  case T_passive: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_UNSPECIFIED ); break;
1755  default:
1756  Expecting( "input, output, bidirectional, tri_state, or passive" );
1757  }
1758 
1759  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1760  {
1761  if( token != T_LEFT )
1762  Expecting( T_LEFT );
1763 
1764  token = NextTok();
1765 
1766  switch( token )
1767  {
1768  case T_at:
1769  {
1770  sheetPin->SetPosition( parseXY() );
1771 
1772  double angle = parseDouble( "sheet pin angle (side)" );
1773 
1774  if( angle == 0.0 )
1775  sheetPin->SetEdge( SHEET_RIGHT_SIDE );
1776  else if( angle == 90.0 )
1777  sheetPin->SetEdge( SHEET_TOP_SIDE );
1778  else if( angle == 180.0 )
1779  sheetPin->SetEdge( SHEET_LEFT_SIDE );
1780  else if( angle == 270.0 )
1781  sheetPin->SetEdge( SHEET_BOTTOM_SIDE );
1782  else
1783  Expecting( "0, 90, 180, or 270" );
1784 
1785  NeedRIGHT();
1786  break;
1787  }
1788 
1789  case T_effects:
1790  parseEDA_TEXT( static_cast<EDA_TEXT*>( sheetPin.get() ) );
1791  break;
1792 
1793  default:
1794  Expecting( "at or effects" );
1795  }
1796  }
1797 
1798  return sheetPin.release();
1799 }
void parseEDA_TEXT(EDA_TEXT *aText)
Define a sheet pin (label) used in sheets to create hierarchical schematics.
Definition: sch_sheet.h:84
const char * name
Definition: DXF_plotter.cpp:60
#define _(s)
Definition: 3d_actions.cpp:33
static DIRECTION_45::AngleType angle(const VECTOR2I &a, const VECTOR2I &b)
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, PNS::angle(), name, parseDouble(), parseEDA_TEXT(), parseXY(), PS_BIDI, PS_INPUT, PS_OUTPUT, PS_TRISTATE, PS_UNSPECIFIED, SHEET_BOTTOM_SIDE, SHEET_LEFT_SIDE, SHEET_RIGHT_SIDE, SHEET_TOP_SIDE, and THROW_IO_ERROR.

Referenced by parseSheet().

◆ parseSchSymbolInstances()

void SCH_SEXPR_PARSER::parseSchSymbolInstances ( SCH_SCREEN aScreen)
private

Definition at line 1802 of file sch_sexpr_parser.cpp.

1803 {
1804  wxCHECK_RET( CurTok() == T_symbol_instances,
1805  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1806  wxT( " as a instances token." ) );
1807  wxCHECK( aScreen, /* void */ );
1808 
1809  T token;
1810 
1811  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1812  {
1813  if( token != T_LEFT )
1814  Expecting( T_LEFT );
1815 
1816  token = NextTok();
1817 
1818  switch( token )
1819  {
1820  case T_path:
1821  {
1822  NeedSYMBOL();
1823 
1825 
1826  instance.m_Path = KIID_PATH( FromUTF8() );
1827 
1828  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1829  {
1830  if( token != T_LEFT )
1831  Expecting( T_LEFT );
1832 
1833  token = NextTok();
1834 
1835  switch( token )
1836  {
1837  case T_reference:
1838  NeedSYMBOL();
1839  instance.m_Reference = FromUTF8();
1840  NeedRIGHT();
1841  break;
1842 
1843  case T_unit:
1844  instance.m_Unit = parseInt( "symbol unit" );
1845  NeedRIGHT();
1846  break;
1847 
1848  case T_value:
1849  NeedSYMBOL();
1850  instance.m_Value = FromUTF8();
1851  NeedRIGHT();
1852  break;
1853 
1854  case T_footprint:
1855  NeedSYMBOL();
1856  instance.m_Footprint = FromUTF8();
1857  NeedRIGHT();
1858  break;
1859 
1860  default:
1861  Expecting( "path, unit, value or footprint" );
1862  }
1863  }
1864 
1865  aScreen->m_symbolInstances.emplace_back( instance );
1866  break;
1867  }
1868 
1869  default:
1870  Expecting( "path" );
1871  }
1872  }
1873 }
A simple container for schematic symbol instance infromation.
std::vector< COMPONENT_INSTANCE_REFERENCE > m_symbolInstances
The list of symbol instances loaded from the schematic file.
Definition: sch_screen.h:139

References COMPONENT_INSTANCE_REFERENCE::m_Footprint, COMPONENT_INSTANCE_REFERENCE::m_Path, COMPONENT_INSTANCE_REFERENCE::m_Reference, SCH_SCREEN::m_symbolInstances, COMPONENT_INSTANCE_REFERENCE::m_Unit, COMPONENT_INSTANCE_REFERENCE::m_Value, and parseInt().

Referenced by ParseSchematic().

◆ parseSchText()

SCH_TEXT * SCH_SEXPR_PARSER::parseSchText ( )
private

Definition at line 2620 of file sch_sexpr_parser.cpp.

2621 {
2622  T token;
2623  std::unique_ptr<SCH_TEXT> text;
2624 
2625  switch( CurTok() )
2626  {
2627  case T_text: text.reset( new SCH_TEXT ); break;
2628  case T_label: text.reset( new SCH_LABEL ); break;
2629  case T_global_label: text.reset( new SCH_GLOBALLABEL ); break;
2630  case T_hierarchical_label: text.reset( new SCH_HIERLABEL ); break;
2631  default:
2632  wxCHECK_MSG( false, nullptr,
2633  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as text." ) );
2634  }
2635 
2636  NeedSYMBOL();
2637 
2638  text->SetText( FromUTF8() );
2639 
2640  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2641  {
2642  if( token != T_LEFT )
2643  Expecting( T_LEFT );
2644 
2645  token = NextTok();
2646 
2647  switch( token )
2648  {
2649  case T_at:
2650  {
2651  text->SetPosition( parseXY() );
2652 
2653  switch( static_cast<int>( parseDouble( "text angle" ) ) )
2654  {
2655  case 0: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::RIGHT ); break;
2656  case 90: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::UP ); break;
2657  case 180: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::LEFT ); break;
2658  case 270: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::BOTTOM ); break;
2659  default:
2660  wxFAIL;
2661  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::RIGHT );
2662  break;
2663  }
2664 
2665  NeedRIGHT();
2666  break;
2667  }
2668 
2669  case T_shape:
2670  {
2671  if( text->Type() == SCH_TEXT_T || text->Type() == SCH_LABEL_T )
2672  Unexpected( T_shape );
2673 
2674  token = NextTok();
2675 
2676  switch( token )
2677  {
2678  case T_input: text->SetShape( PINSHEETLABEL_SHAPE::PS_INPUT ); break;
2679  case T_output: text->SetShape( PINSHEETLABEL_SHAPE::PS_OUTPUT ); break;
2680  case T_bidirectional: text->SetShape( PINSHEETLABEL_SHAPE::PS_BIDI ); break;
2681  case T_tri_state: text->SetShape( PINSHEETLABEL_SHAPE::PS_TRISTATE ); break;
2682  case T_passive: text->SetShape( PINSHEETLABEL_SHAPE::PS_UNSPECIFIED ); break;
2683  default:
2684  Expecting( "input, output, bidirectional, tri_state, or passive" );
2685  }
2686 
2687  NeedRIGHT();
2688  break;
2689  }
2690 
2691  case T_effects:
2692  parseEDA_TEXT( static_cast<EDA_TEXT*>( text.get() ) );
2693  break;
2694 
2695  default:
2696  Expecting( "at, shape, or effects" );
2697  }
2698  }
2699 
2700  return text.release();
2701 }
void parseEDA_TEXT(EDA_TEXT *aText)
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

References LABEL_SPIN_STYLE::BOTTOM, LABEL_SPIN_STYLE::LEFT, parseDouble(), parseEDA_TEXT(), parseXY(), PS_BIDI, PS_INPUT, PS_OUTPUT, PS_TRISTATE, PS_UNSPECIFIED, LABEL_SPIN_STYLE::RIGHT, SCH_LABEL_T, SCH_TEXT_T, and LABEL_SPIN_STYLE::UP.

Referenced by ParseSchematic().

◆ parseSheet()

SCH_SHEET * SCH_SEXPR_PARSER::parseSheet ( )
private

Definition at line 2333 of file sch_sexpr_parser.cpp.

2334 {
2335  wxCHECK_MSG( CurTok() == T_sheet, nullptr,
2336  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a sheet." ) );
2337 
2338  T token;
2339  STROKE_PARAMS stroke;
2340  FILL_PARAMS fill;
2341  SCH_FIELD* field;
2342  std::vector<SCH_FIELD> fields;
2343  std::unique_ptr<SCH_SHEET> sheet( new SCH_SHEET() );
2344  std::set<int> fieldIDsRead;
2345 
2346  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2347  {
2348  if( token != T_LEFT )
2349  Expecting( T_LEFT );
2350 
2351  token = NextTok();
2352 
2353  switch( token )
2354  {
2355  case T_at:
2356  sheet->SetPosition( parseXY() );
2357  NeedRIGHT();
2358  break;
2359 
2360  case T_size:
2361  {
2362  wxSize size;
2363  size.SetWidth( parseInternalUnits( "sheet width" ) );
2364  size.SetHeight( parseInternalUnits( "sheet height" ) );
2365  sheet->SetSize( size );
2366  NeedRIGHT();
2367  break;
2368  }
2369 
2370  case T_stroke:
2371  parseStroke( stroke );
2372  sheet->SetBorderWidth( stroke.GetWidth() );
2373  sheet->SetBorderColor( stroke.GetColor() );
2374  break;
2375 
2376  case T_fill:
2377  parseFill( fill );
2378  sheet->SetBackgroundColor( fill.m_Color );
2379  break;
2380 
2381  case T_uuid:
2382  NeedSYMBOL();
2383  const_cast<KIID&>( sheet->m_Uuid ) = KIID( FromUTF8() );
2384  NeedRIGHT();
2385  break;
2386 
2387  case T_property:
2388  field = parseSchField( sheet.get() );
2389 
2390  if( m_requiredVersion <= 20200310 )
2391  {
2392  // Earlier versions had the wrong ids (and names) saved for sheet fields.
2393  // Fortunately they only saved the sheetname and sheetfilepath (and always
2394  // in that order), so we can hack in a recovery.
2395  if( fields.empty() )
2396  field->SetId( SHEETNAME );
2397  else
2398  field->SetId( SHEETFILENAME );
2399  }
2400 
2401  // It would appear the problem persists past 20200310, but this time with the
2402  // earlier ids being re-used for later (user) fields. The easiest (and most
2403  // complete) solution is to disallow multiple instances of the same id (for all
2404  // files since the source of the error *might* in fact be hand-edited files).
2405  //
2406  // While no longer used, -1 is still a valid id for user fields and will
2407  // get written out as the next unused number on save.
2408  if( fieldIDsRead.count( field->GetId() ) )
2409  field->SetId( -1 );
2410  else
2411  fieldIDsRead.insert( field->GetId() );
2412 
2413  fields.emplace_back( *field );
2414  delete field;
2415  break;
2416 
2417  case T_pin:
2418  sheet->AddPin( parseSchSheetPin( sheet.get() ) );
2419  break;
2420 
2421  default:
2422  Expecting( "at, size, stroke, background, uuid, property, or pin" );
2423  }
2424  }
2425 
2426  sheet->SetFields( fields );
2427 
2428  return sheet.release();
2429 }
SCH_FIELD instances are attached to a component and provide a place for the component's value,...
Definition: sch_field.h:52
SCH_SHEET_PIN * parseSchSheetPin(SCH_SHEET *aSheet)
int GetId() const
Definition: sch_field.h:114
Definition: common.h:68
Simple container to manage fill parameters.
int GetWidth() const
Definition: sch_item.h:169
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:216
COLOR4D GetColor() const
Definition: sch_item.h:175
int m_requiredVersion
Set to the symbol library file version required.
Simple container to manage line stroke parameters.
Definition: sch_item.h:153
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
void parseFill(FILL_PARAMS &aFill)
void SetId(int aId)
Definition: sch_field.cpp:76
void parseStroke(STROKE_PARAMS &aStroke)
Parse stroke definition aStroke.

References STROKE_PARAMS::GetColor(), SCH_FIELD::GetId(), STROKE_PARAMS::GetWidth(), FILL_PARAMS::m_Color, m_requiredVersion, parseFill(), parseInternalUnits(), parseSchField(), parseSchSheetPin(), parseStroke(), parseXY(), SCH_FIELD::SetId(), SHEETFILENAME, and SHEETNAME.

Referenced by ParseSchematic().

◆ parseStroke()

void SCH_SEXPR_PARSER::parseStroke ( STROKE_PARAMS aStroke)
private

Parse stroke definition aStroke.

Parameters
aStrokeDefA reference to the STROKE_PARAMS structure to write to.

Definition at line 426 of file sch_sexpr_parser.cpp.

427 {
428  wxCHECK_RET( CurTok() == T_stroke,
429  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a stroke." ) );
430 
431  aStroke.SetWidth( Mils2iu( DEFAULT_LINE_THICKNESS ) );
432  aStroke.SetType( PLOT_DASH_TYPE::DEFAULT );
433  aStroke.SetColor( COLOR4D::UNSPECIFIED );
434 
435  T token;
436 
437  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
438  {
439  if( token != T_LEFT )
440  Expecting( T_LEFT );
441 
442  token = NextTok();
443 
444  switch( token )
445  {
446  case T_width:
447  aStroke.SetWidth( parseInternalUnits( "stroke width" ) );
448  NeedRIGHT();
449  break;
450 
451  case T_type:
452  {
453  token = NextTok();
454 
455  switch( token )
456  {
457  case T_dash: aStroke.SetType( PLOT_DASH_TYPE::DASH ); break;
458  case T_dot: aStroke.SetType( PLOT_DASH_TYPE::DOT ); break;
459  case T_dash_dot: aStroke.SetType( PLOT_DASH_TYPE::DASHDOT ); break;
460  case T_solid: aStroke.SetType( PLOT_DASH_TYPE::SOLID ); break;
461  default:
462  Expecting( "solid, dash, dash_dot, or dot" );
463  }
464 
465  NeedRIGHT();
466  break;
467  }
468 
469  case T_color:
470  {
471  COLOR4D color;
472 
473  color.r = parseInt( "red" ) / 255.0;
474  color.g = parseInt( "green" ) / 255.0;
475  color.b = parseInt( "blue" ) / 255.0;
476  color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
477 
478  aStroke.SetColor( color );
479  NeedRIGHT();
480  break;
481  }
482 
483  default:
484  Expecting( "width, type, or color" );
485  }
486 
487  }
488 }
void SetWidth(int aWidth)
Definition: sch_item.h:170
int color
Definition: DXF_plotter.cpp:61
void SetType(PLOT_DASH_TYPE aType)
Definition: sch_item.h:173
#define DEFAULT_LINE_THICKNESS
The default wire width in mils. (can be changed in preference menu)
const T & Clamp(const T &lower, const T &value, const T &upper)
Function Clamp limits value within the range lower <= value <= upper.
Definition: util.h:46
void SetColor(const COLOR4D &aColor)
Definition: sch_item.h:176
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
COLOR4D is the color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:99

References Clamp(), color, DASH, DASHDOT, DEFAULT, DEFAULT_LINE_THICKNESS, DOT, parseDouble(), parseInt(), parseInternalUnits(), STROKE_PARAMS::SetColor(), STROKE_PARAMS::SetType(), STROKE_PARAMS::SetWidth(), and SOLID.

Referenced by parseBusEntry(), parseLine(), and parseSheet().

◆ ParseSymbol()

LIB_PART * SCH_SEXPR_PARSER::ParseSymbol ( LIB_PART_MAP aSymbolLibMap,
int  aFileVersion = SEXPR_SYMBOL_LIB_FILE_VERSION 
)

Definition at line 122 of file sch_sexpr_parser.cpp.

123 {
124  wxCHECK_MSG( CurTok() == T_symbol, nullptr,
125  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a symbol." ) );
126 
127  T token;
128  long tmp;
129  wxString name;
130  wxString error;
131  LIB_ITEM* item;
132  std::unique_ptr<LIB_PART> symbol( new LIB_PART( wxEmptyString ) );
133 
134  m_requiredVersion = aFileVersion;
135  symbol->SetUnitCount( 1 );
136 
138 
139  token = NextTok();
140 
141  if( !IsSymbol( token ) )
142  {
143  error.Printf( _( "Invalid symbol name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
144  CurSource().c_str(), CurLineNumber(), CurOffset() );
145  THROW_IO_ERROR( error );
146  }
147 
148  name = FromUTF8();
149 
150  LIB_ID id;
151 
152  if( id.Parse( name, LIB_ID::ID_SCH ) >= 0 )
153  {
154  error.Printf( _( "Invalid library identifier in\nfile: \"%s\"\nline: %d\noffset: %d" ),
155  CurSource().c_str(), CurLineNumber(), CurOffset() );
156  THROW_IO_ERROR( error );
157  }
158 
159  m_symbolName = id.GetLibItemName().wx_str();
160  symbol->SetName( m_symbolName );
161  symbol->SetLibId( id );
162 
163  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
164  {
165  if( token != T_LEFT )
166  Expecting( T_LEFT );
167 
168  token = NextTok();
169 
170  switch( token )
171  {
172  case T_power:
173  symbol->SetPower();
174  NeedRIGHT();
175  break;
176 
177  case T_pin_names:
178  parsePinNames( symbol );
179  break;
180 
181  case T_pin_numbers:
182  token = NextTok();
183 
184  if( token != T_hide )
185  Expecting( "hide" );
186 
187  symbol->SetShowPinNumbers( false );
188  NeedRIGHT();
189  break;
190 
191  case T_in_bom:
192  symbol->SetIncludeInBom( parseBool() );
193  NeedRIGHT();
194  break;
195 
196  case T_on_board:
197  symbol->SetIncludeOnBoard( parseBool() );
198  NeedRIGHT();
199  break;
200 
201  case T_property:
202  parseProperty( symbol );
203  break;
204 
205  case T_extends:
206  {
207  token = NextTok();
208 
209  if( !IsSymbol( token ) )
210  {
211  error.Printf(
212  _( "Invalid symbol extends name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
213  CurSource().c_str(), CurLineNumber(), CurOffset() );
214  THROW_IO_ERROR( error );
215  }
216 
217  name = FromUTF8();
218  auto it = aSymbolLibMap.find( name );
219 
220  if( it == aSymbolLibMap.end() )
221  {
222  error.Printf(
223  _( "No parent for extended symbol %s in\nfile: \"%s\"\nline: %d\noffset: %d" ),
224  name.c_str(), CurSource().c_str(), CurLineNumber(), CurOffset() );
225  THROW_IO_ERROR( error );
226  }
227 
228  symbol->SetParent( it->second );
229  NeedRIGHT();
230  break;
231  }
232 
233  case T_symbol:
234  {
235  token = NextTok();
236 
237  if( !IsSymbol( token ) )
238  {
239  error.Printf(
240  _( "Invalid symbol unit name in\nfile: \"%s\"\nline: %d\noffset: %d" ),
241  CurSource().c_str(), CurLineNumber(), CurOffset() );
242  THROW_IO_ERROR( error );
243  }
244 
245  name = FromUTF8();
246 
247  if( !name.StartsWith( m_symbolName ) )
248  {
249  error.Printf(
250  _( "Invalid symbol unit name prefix %s in\nfile: \"%s\"\n"
251  "line: %d\noffset: %d" ),
252  name.c_str(), CurSource().c_str(), CurLineNumber(), CurOffset() );
253  THROW_IO_ERROR( error );
254  }
255 
256  name = name.Right( name.Length() - m_symbolName.Length() - 1 );
257 
258  wxStringTokenizer tokenizer( name, "_" );
259 
260  if( tokenizer.CountTokens() != 2 )
261  {
262  error.Printf(
263  _( "Invalid symbol unit name suffix %s in\nfile: \"%s\"\n"
264  "line: %d\noffset: %d" ),
265  name.c_str(), CurSource().c_str(), CurLineNumber(), CurOffset() );
266  THROW_IO_ERROR( error );
267  }
268 
269  if( !tokenizer.GetNextToken().ToLong( &tmp ) )
270  {
271  error.Printf(
272  _( "Invalid symbol unit number %s in\nfile: \"%s\"\nline: %d\noffset: %d" ),
273  name.c_str(), CurSource().c_str(), CurLineNumber(), CurOffset() );
274  THROW_IO_ERROR( error );
275  }
276 
277  m_unit = static_cast<int>( tmp );
278 
279  if( !tokenizer.GetNextToken().ToLong( &tmp ) )
280  {
281  error.Printf(
282  _( "Invalid symbol convert number %s in\nfile: \"%s\"\nline: %d\noffset: %d" ),
283  name.c_str(), CurSource().c_str(), CurLineNumber(), CurOffset() );
284  THROW_IO_ERROR( error );
285  }
286 
287  m_convert = static_cast<int>( tmp );
288 
289  if( m_convert > 1 )
290  symbol->SetConversion( true, false );
291 
292  if( m_unit > symbol->GetUnitCount() )
293  symbol->SetUnitCount( m_unit, false );
294 
295  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
296  {
297  if( token != T_LEFT )
298  Expecting( T_LEFT );
299 
300  token = NextTok();
301 
302  switch( token )
303  {
304  case T_arc:
305  case T_bezier:
306  case T_circle:
307  case T_pin:
308  case T_polyline:
309  case T_rectangle:
310  case T_text:
311  item = ParseDrawItem();
312 
313  wxCHECK_MSG( item, nullptr, "Invalid draw item pointer." );
314 
315  item->SetParent( symbol.get() );
316  symbol->AddDrawItem( item );
317  break;
318 
319  default:
320  Expecting( "arc, bezier, circle, pin, polyline, rectangle, or text" );
321  };
322  }
323 
324  m_unit = 1;
325  m_convert = 1;
326  break;
327  }
328 
329  case T_arc:
330  case T_bezier:
331  case T_circle:
332  case T_pin:
333  case T_polyline:
334  case T_rectangle:
335  case T_text:
336  item = ParseDrawItem();
337 
338  wxCHECK_MSG( item, nullptr, "Invalid draw item pointer." );
339 
340  item->SetParent( symbol.get() );
341  symbol->AddDrawItem( item );
342  break;
343 
344  default:
345  Expecting( "pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
346  "rectangle, or text" );
347  }
348  }
349 
350  m_symbolName.clear();
351 
352  return symbol.release();
353 }
int m_fieldId
The current field ID.
void parseProperty(std::unique_ptr< LIB_PART > &aSymbol)
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
int m_unit
The current unit being parsed.
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
virtual void SetParent(EDA_ITEM *aParent)
Definition: base_struct.h:196
The base class for drawable items used by schematic library components.
Definition: lib_item.h:61
wxString m_symbolName
The current symbol name.
int m_convert
The current body style being parsed.
Define a library symbol object.
LIB_ITEM * ParseDrawItem()
int m_requiredVersion
Set to the symbol library file version required.
const char * name
Definition: DXF_plotter.cpp:60
#define _(s)
Definition: 3d_actions.cpp:33
void parsePinNames(std::unique_ptr< LIB_PART > &aSymbol)
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, LIB_ID::ID_SCH, m_convert, m_fieldId, m_requiredVersion, m_symbolName, m_unit, MANDATORY_FIELDS, name, parseBool(), ParseDrawItem(), parsePinNames(), parseProperty(), EDA_ITEM::SetParent(), and THROW_IO_ERROR.

Referenced by ParseLib(), SCH_SEXPR_PLUGIN::ParsePart(), and ParseSchematic().

◆ parseText()

LIB_TEXT * SCH_SEXPR_PARSER::parseText ( )
private

Definition at line 1427 of file sch_sexpr_parser.cpp.

1428 {
1429  wxCHECK_MSG( CurTok() == T_text, nullptr,
1430  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a text token." ) );
1431 
1432  T token;
1433  wxString tmp;
1434  wxString error;
1435  std::unique_ptr<LIB_TEXT> text( new LIB_TEXT( nullptr ) );
1436 
1437  text->SetUnit( m_unit );
1438  text->SetConvert( m_convert );
1439  token = NextTok();
1440 
1441  if( !IsSymbol( token ) )
1442  {
1443  error.Printf( _( "Invalid text string in\nfile: \"%s\"\nline: %d\noffset: %d" ),
1444  CurSource().c_str(), CurLineNumber(), CurOffset() );
1445  THROW_IO_ERROR( error );
1446  }
1447 
1448  text->SetText( FromUTF8() );
1449 
1450  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1451  {
1452  if( token != T_LEFT )
1453  Expecting( T_LEFT );
1454 
1455  token = NextTok();
1456 
1457  switch( token )
1458  {
1459  case T_at:
1460  text->SetPosition( parseXY() );
1461  text->SetTextAngle( parseDouble( "text angle" ) );
1462  NeedRIGHT();
1463  break;
1464 
1465  case T_effects:
1466  parseEDA_TEXT( static_cast<EDA_TEXT*>( text.get() ) );
1467  break;
1468 
1469  default:
1470  Expecting( "at or effects" );
1471  }
1472  }
1473 
1474  return text.release();
1475 }
void parseEDA_TEXT(EDA_TEXT *aText)
Define a symbol library graphical text item.
Definition: lib_text.h:40
int m_unit
The current unit being parsed.
int m_convert
The current body style being parsed.
#define _(s)
Definition: 3d_actions.cpp:33
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38

References _, m_convert, m_unit, parseDouble(), parseEDA_TEXT(), parseXY(), and THROW_IO_ERROR.

Referenced by ParseDrawItem().

◆ parseTITLE_BLOCK()

void SCH_SEXPR_PARSER::parseTITLE_BLOCK ( TITLE_BLOCK aTitleBlock)
private

Definition at line 1531 of file sch_sexpr_parser.cpp.

1532 {
1533  wxCHECK_RET( CurTok() == T_title_block,
1534  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1535  wxT( " as TITLE_BLOCK." ) );
1536 
1537  T token;
1538 
1539  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1540  {
1541  if( token != T_LEFT )
1542  Expecting( T_LEFT );
1543 
1544  token = NextTok();
1545 
1546  switch( token )
1547  {
1548  case T_title:
1549  NextTok();
1550  aTitleBlock.SetTitle( FromUTF8() );
1551  break;
1552 
1553  case T_date:
1554  NextTok();
1555  aTitleBlock.SetDate( FromUTF8() );
1556  break;
1557 
1558  case T_rev:
1559  NextTok();
1560  aTitleBlock.SetRevision( FromUTF8() );
1561  break;
1562 
1563  case T_company:
1564  NextTok();
1565  aTitleBlock.SetCompany( FromUTF8() );
1566  break;
1567 
1568  case T_comment:
1569  {
1570  int commentNumber = parseInt( "comment" );
1571 
1572  switch( commentNumber )
1573  {
1574  case 1:
1575  NextTok();
1576  aTitleBlock.SetComment( 0, FromUTF8() );
1577  break;
1578 
1579  case 2:
1580  NextTok();
1581  aTitleBlock.SetComment( 1, FromUTF8() );
1582  break;
1583 
1584  case 3:
1585  NextTok();
1586  aTitleBlock.SetComment( 2, FromUTF8() );
1587  break;
1588 
1589  case 4:
1590  NextTok();
1591  aTitleBlock.SetComment( 3, FromUTF8() );
1592  break;
1593 
1594  case 5:
1595  NextTok();
1596  aTitleBlock.SetComment( 4, FromUTF8() );
1597  break;
1598 
1599  case 6:
1600  NextTok();
1601  aTitleBlock.SetComment( 5, FromUTF8() );
1602  break;
1603 
1604  case 7:
1605  NextTok();
1606  aTitleBlock.SetComment( 6, FromUTF8() );
1607  break;
1608 
1609  case 8:
1610  NextTok();
1611  aTitleBlock.SetComment( 7, FromUTF8() );
1612  break;
1613 
1614  case 9:
1615  NextTok();
1616  aTitleBlock.SetComment( 8, FromUTF8() );
1617  break;
1618 
1619  default:
1620  wxString err;
1621  err.Printf( wxT( "%d is not a valid title block comment number" ), commentNumber );
1622  THROW_PARSE_ERROR( err, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
1623  }
1624 
1625  break;
1626  }
1627 
1628  default:
1629  Expecting( "title, date, rev, company, or comment" );
1630  }
1631 
1632  NeedRIGHT();
1633  }
1634 }
void SetRevision(const wxString &aRevision)
Definition: title_block.h:84
void SetDate(const wxString &aDate)
Function SetDate sets the date field, and defaults to the current time and date.
Definition: title_block.h:74
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:162
void SetComment(int aIdx, const wxString &aComment)
Definition: title_block.h:104
void SetCompany(const wxString &aCompany)
Definition: title_block.h:94
void SetTitle(const wxString &aTitle)
Definition: title_block.h:60

References parseInt(), TITLE_BLOCK::SetComment(), TITLE_BLOCK::SetCompany(), TITLE_BLOCK::SetDate(), TITLE_BLOCK::SetRevision(), TITLE_BLOCK::SetTitle(), and THROW_PARSE_ERROR.

Referenced by ParseSchematic().

◆ parseXY()

Member Data Documentation

◆ m_convert

int SCH_SEXPR_PARSER::m_convert
private

The current body style being parsed.

Definition at line 84 of file sch_sexpr_parser.h.

Referenced by parseArc(), parseBezier(), parseCircle(), ParseLib(), parsePin(), parsePolyLine(), parseRectangle(), ParseSymbol(), and parseText().

◆ m_fieldId

int SCH_SEXPR_PARSER::m_fieldId
private

The current field ID.

Definition at line 82 of file sch_sexpr_parser.h.

Referenced by parseSchematicSymbol(), and ParseSymbol().

◆ m_requiredVersion

int SCH_SEXPR_PARSER::m_requiredVersion
private

Set to the symbol library file version required.

Definition at line 81 of file sch_sexpr_parser.h.

Referenced by IsTooRecent(), parseHeader(), ParseLib(), parsePAGE_INFO(), ParseSchematic(), parseSheet(), and ParseSymbol().

◆ m_symbolName

wxString SCH_SEXPR_PARSER::m_symbolName
private

The current symbol name.

Definition at line 85 of file sch_sexpr_parser.h.

Referenced by ParseSymbol().

◆ m_unit

int SCH_SEXPR_PARSER::m_unit
private

The current unit being parsed.

Definition at line 83 of file sch_sexpr_parser.h.

Referenced by parseArc(), parseBezier(), parseCircle(), ParseLib(), parsePin(), parsePolyLine(), parseRectangle(), ParseSymbol(), and parseText().


The documentation for this class was generated from the following files: