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, PROGRESS_REPORTER *aProgressReporter=nullptr, unsigned aLineCount=0)
 
void ParseLib (LIB_SYMBOL_MAP &aSymbolLibMap)
 
LIB_SYMBOLParseSymbol (LIB_SYMBOL_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...
 

Private Member Functions

void checkpoint ()
 
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, bool aConvertOverbarSyntax)
 
void parsePinNames (std::unique_ptr< LIB_SYMBOL > &aSymbol)
 
LIB_FIELDparseProperty (std::unique_ptr< LIB_SYMBOL > &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)
 
void parseSchSheetInstances (SCH_SHEET *aRootSheet, SCH_SCREEN *aScreen)
 
SCH_SHEET_PINparseSchSheetPin (SCH_SHEET *aSheet)
 
SCH_FIELDparseSchField (SCH_ITEM *aParent)
 
SCH_SYMBOLparseSchematicSymbol ()
 
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...
 
PROGRESS_REPORTERm_progressReporter
 
const LINE_READERm_lineReader
 
unsigned m_lastProgressLine
 
unsigned m_lineCount
 

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,
PROGRESS_REPORTER aProgressReporter = nullptr,
unsigned  aLineCount = 0 
)

Definition at line 64 of file sch_sexpr_parser.cpp.

65  :
66  SCHEMATIC_LEXER( aLineReader ),
67  m_requiredVersion( 0 ),
68  m_fieldId( 0 ),
69  m_unit( 1 ),
70  m_convert( 1 ),
71  m_progressReporter( aProgressReporter ),
72  m_lineReader( aLineReader ),
73  m_lastProgressLine( 0 ),
74  m_lineCount( aLineCount )
75 {
76 }
int m_fieldId
The current field ID.
unsigned m_lastProgressLine
int m_unit
The current unit being parsed.
int m_convert
The current body style being parsed.
const LINE_READER * m_lineReader
int m_requiredVersion
Set to the symbol library file version required.
PROGRESS_REPORTER * m_progressReporter

Member Function Documentation

◆ checkpoint()

void SCH_SEXPR_PARSER::checkpoint ( )
private

Definition at line 79 of file sch_sexpr_parser.cpp.

80 {
81  const unsigned PROGRESS_DELTA = 250;
82 
83  if( m_progressReporter )
84  {
85  unsigned curLine = m_lineReader->LineNumber();
86 
87  if( curLine > m_lastProgressLine + PROGRESS_DELTA )
88  {
89  m_progressReporter->SetCurrentProgress( ( (double) curLine )
90  / std::max( 1U, m_lineCount ) );
91 
93  THROW_IO_ERROR( ( "Open cancelled by user." ) );
94 
95  m_lastProgressLine = curLine;
96  }
97  }
98 }
unsigned m_lastProgressLine
virtual unsigned LineNumber() const
Return the line number of the last line read from this LINE_READER.
Definition: richio.h:135
const LINE_READER * m_lineReader
virtual bool KeepRefreshing(bool aWait=false)=0
Update the UI (if any).
#define THROW_IO_ERROR(msg)
Definition: ki_exception.h:38
PROGRESS_REPORTER * m_progressReporter
virtual void SetCurrentProgress(double aProgress)=0
Set the progress value to aProgress (0..1).

References PROGRESS_REPORTER::KeepRefreshing(), LINE_READER::LineNumber(), m_lastProgressLine, m_lineCount, m_lineReader, m_progressReporter, PROGRESS_REPORTER::SetCurrentProgress(), and THROW_IO_ERROR.

Referenced by ParseSchematic().

◆ parseArc()

LIB_ARC * SCH_SEXPR_PARSER::parseArc ( )
private

Definition at line 909 of file sch_sexpr_parser.cpp.

910 {
911  wxCHECK_MSG( CurTok() == T_arc, nullptr,
912  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as an arc token." ) );
913 
914  T token;
915  wxPoint startPoint;
916  wxPoint midPoint;
917  wxPoint endPoint;
918  wxPoint pos;
919  FILL_PARAMS fill;
920  bool hasMidPoint = false;
921  std::unique_ptr<LIB_ARC> arc = std::make_unique<LIB_ARC>( nullptr );
922 
923  arc->SetUnit( m_unit );
924  arc->SetConvert( m_convert );
925 
926  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
927  {
928  if( token != T_LEFT )
929  Expecting( T_LEFT );
930 
931  token = NextTok();
932 
933  switch( token )
934  {
935  case T_start:
936  startPoint = parseXY();
937  NeedRIGHT();
938  break;
939 
940  case T_mid:
941  midPoint = parseXY();
942  NeedRIGHT();
943  hasMidPoint = true;
944  break;
945 
946  case T_end:
947  endPoint = parseXY();
948  NeedRIGHT();
949  break;
950 
951  case T_radius:
952  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
953  {
954  if( token != T_LEFT )
955  Expecting( T_LEFT );
956 
957  token = NextTok();
958 
959  switch( token )
960  {
961  case T_at:
962  pos = parseXY();
963  NeedRIGHT();
964  break;
965 
966  case T_length:
967  arc->SetRadius( parseInternalUnits( "radius length" ) );
968  NeedRIGHT();
969  break;
970 
971  case T_angles:
972  {
973  int angle1 = KiROUND( parseDouble( "start radius angle" ) * 10.0 );
974  int angle2 = KiROUND( parseDouble( "end radius angle" ) * 10.0 );
975 
976  NORMALIZE_ANGLE_POS( angle1 );
977  NORMALIZE_ANGLE_POS( angle2 );
978  arc->SetFirstRadiusAngle( angle1 );
979  arc->SetSecondRadiusAngle( angle2 );
980  NeedRIGHT();
981  break;
982  }
983 
984  default:
985  Expecting( "at, length, or angle" );
986  }
987  }
988 
989  break;
990 
991  case T_stroke:
992  NeedLEFT();
993  token = NextTok();
994 
995  if( token != T_width )
996  Expecting( "width" );
997 
998  arc->SetWidth( parseInternalUnits( "stroke width" ) );
999  NeedRIGHT(); // Closes width token;
1000  NeedRIGHT(); // Closes stroke token;
1001  break;
1002 
1003  case T_fill:
1004  parseFill( fill );
1005  arc->SetFillMode( fill.m_FillType );
1006  break;
1007 
1008  default:
1009  Expecting( "start, end, radius, stroke, or fill" );
1010  }
1011  }
1012 
1013  arc->SetPosition( pos );
1014  arc->SetStart( startPoint );
1015  arc->SetEnd( endPoint );
1016 
1017  if( hasMidPoint )
1018  {
1019  VECTOR2I center = GetArcCenter( arc->GetStart(), midPoint, arc->GetEnd() );
1020 
1021  arc->SetPosition( wxPoint( center.x, center.y ) );
1022 
1023  // @todo Calculate the radius.
1024 
1025  arc->CalcRadiusAngles();
1026  }
1027 
1028  return arc.release();
1029 }
int m_unit
The current unit being parsed.
void NORMALIZE_ANGLE_POS(T &Angle)
Definition: trigo.h:290
FILL_TYPE m_FillType
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:73
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:454

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 1032 of file sch_sexpr_parser.cpp.

1033 {
1034  wxCHECK_MSG( CurTok() == T_bezier, nullptr,
1035  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bezier." ) );
1036 
1037  T token;
1038  FILL_PARAMS fill;
1039  std::unique_ptr<LIB_BEZIER> bezier = std::make_unique<LIB_BEZIER>( nullptr );
1040 
1041  bezier->SetUnit( m_unit );
1042  bezier->SetConvert( m_convert );
1043 
1044  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1045  {
1046  if( token != T_LEFT )
1047  Expecting( T_LEFT );
1048 
1049  token = NextTok();
1050 
1051  switch( token )
1052  {
1053  case T_pts:
1054  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1055  {
1056  if( token != T_LEFT )
1057  Expecting( T_LEFT );
1058 
1059  token = NextTok();
1060 
1061  if( token != T_xy )
1062  Expecting( "xy" );
1063 
1064  bezier->AddPoint( parseXY() );
1065 
1066  NeedRIGHT();
1067  }
1068 
1069  break;
1070 
1071  case T_stroke:
1072  NeedLEFT();
1073  token = NextTok();
1074 
1075  if( token != T_width )
1076  Expecting( "width" );
1077 
1078  bezier->SetWidth( parseInternalUnits( "stroke width" ) );
1079  NeedRIGHT(); // Closes width token;
1080  NeedRIGHT(); // Closes stroke token;
1081  break;
1082 
1083  case T_fill:
1084  parseFill( fill );
1085  bezier->SetFillMode( fill.m_FillType );
1086  break;
1087 
1088  default:
1089  Expecting( "pts, stroke, or fill" );
1090  }
1091  }
1092 
1093  return bezier.release();
1094 }
int m_unit
The current unit being parsed.
FILL_TYPE m_FillType
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().

◆ parseBool()

bool SCH_SEXPR_PARSER::parseBool ( )
private

Definition at line 101 of file sch_sexpr_parser.cpp.

102 {
103  T token = NextTok();
104 
105  if( token == T_yes )
106  return true;
107  else if( token == T_no )
108  return false;
109  else
110  Expecting( "yes or no" );
111 
112  return false;
113 }

Referenced by parseSchematicSymbol(), and ParseSymbol().

◆ parseBusAlias()

void SCH_SEXPR_PARSER::parseBusAlias ( SCH_SCREEN aScreen)
private

Definition at line 2980 of file sch_sexpr_parser.cpp.

2981 {
2982  wxCHECK_RET( CurTok() == T_bus_alias,
2983  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bus alias." ) );
2984  wxCHECK( aScreen, /* void */ );
2985 
2986  T token;
2987  std::shared_ptr<BUS_ALIAS> busAlias = std::make_shared<BUS_ALIAS>( aScreen );
2988  wxString alias;
2989  wxString member;
2990 
2991  NeedSYMBOL();
2992 
2993  alias = FromUTF8();
2994 
2995  if( m_requiredVersion < 20210621 )
2996  alias = ConvertToNewOverbarNotation( alias );
2997 
2998  busAlias->SetName( alias );
2999 
3000  NeedLEFT();
3001  token = NextTok();
3002 
3003  if( token != T_members )
3004  Expecting( "members" );
3005 
3006  token = NextTok();
3007 
3008  while( token != T_RIGHT )
3009  {
3010  if( !IsSymbol( token ) )
3011  Expecting( "quoted string" );
3012 
3013  member = FromUTF8();
3014 
3015  if( m_requiredVersion < 20210621 )
3016  member = ConvertToNewOverbarNotation( member );
3017 
3018  busAlias->AddMember( member );
3019 
3020  token = NextTok();
3021  }
3022 
3023  NeedRIGHT();
3024 
3025  aScreen->AddBusAlias( busAlias );
3026 }
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
int m_requiredVersion
Set to the symbol library file version required.
void AddBusAlias(std::shared_ptr< BUS_ALIAS > aAlias)
Add a bus alias definition (and transfers ownership of the pointer).

References SCH_SCREEN::AddBusAlias(), ConvertToNewOverbarNotation(), and m_requiredVersion.

Referenced by ParseSchematic().

◆ parseBusEntry()

SCH_BUS_WIRE_ENTRY * SCH_SEXPR_PARSER::parseBusEntry ( )
private

Definition at line 2722 of file sch_sexpr_parser.cpp.

2723 {
2724  wxCHECK_MSG( CurTok() == T_bus_entry, nullptr,
2725  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a bus entry." ) );
2726 
2727  T token;
2728  STROKE_PARAMS stroke;
2729  std::unique_ptr<SCH_BUS_WIRE_ENTRY> busEntry = std::make_unique<SCH_BUS_WIRE_ENTRY>();
2730 
2731  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2732  {
2733  if( token != T_LEFT )
2734  Expecting( T_LEFT );
2735 
2736  token = NextTok();
2737 
2738  switch( token )
2739  {
2740  case T_at:
2741  busEntry->SetPosition( parseXY() );
2742  NeedRIGHT();
2743  break;
2744 
2745  case T_size:
2746  {
2747  wxSize size;
2748 
2749  size.SetWidth( parseInternalUnits( "bus entry height" ) );
2750  size.SetHeight( parseInternalUnits( "bus entry width" ) );
2751  busEntry->SetSize( size );
2752  NeedRIGHT();
2753  break;
2754  }
2755 
2756  case T_stroke:
2757  parseStroke( stroke );
2758  busEntry->SetStroke( stroke );
2759  break;
2760 
2761  case T_uuid:
2762  NeedSYMBOL();
2763  const_cast<KIID&>( busEntry->m_Uuid ) = KIID( FromUTF8() );
2764  NeedRIGHT();
2765  break;
2766 
2767  default:
2768  Expecting( "at, size, uuid or stroke" );
2769  }
2770  }
2771 
2772  return busEntry.release();
2773 }
Definition: kiid.h:44
Simple container to manage line stroke parameters.
Definition: sch_item.h:151
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 1097 of file sch_sexpr_parser.cpp.

1098 {
1099  wxCHECK_MSG( CurTok() == T_circle, nullptr,
1100  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1101  wxT( " as a circle token." ) );
1102 
1103  T token;
1104  FILL_PARAMS fill;
1105  std::unique_ptr<LIB_CIRCLE> circle = std::make_unique<LIB_CIRCLE>( nullptr );
1106 
1107  circle->SetUnit( m_unit );
1108  circle->SetConvert( m_convert );
1109 
1110  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1111  {
1112  if( token != T_LEFT )
1113  Expecting( T_LEFT );
1114 
1115  token = NextTok();
1116 
1117  switch( token )
1118  {
1119  case T_center:
1120  circle->SetPosition( parseXY() );
1121  NeedRIGHT();
1122  break;
1123 
1124  case T_radius:
1125  circle->SetRadius( parseInternalUnits( "radius length" ) );
1126  NeedRIGHT();
1127  break;
1128 
1129  case T_stroke:
1130  NeedLEFT();
1131  token = NextTok();
1132 
1133  if( token != T_width )
1134  Expecting( "width" );
1135 
1136  circle->SetWidth( parseInternalUnits( "stroke width" ) );
1137  NeedRIGHT(); // Closes width token;
1138  NeedRIGHT(); // Closes stroke token;
1139  break;
1140 
1141  case T_fill:
1142  parseFill( fill );
1143  circle->SetFillMode( fill.m_FillType );
1144  break;
1145 
1146  default:
1147  Expecting( "start, end, radius, stroke, or fill" );
1148  }
1149  }
1150 
1151  return circle.release();
1152 }
int m_unit
The current unit being parsed.
FILL_TYPE m_FillType
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 421 of file sch_sexpr_parser.cpp.

422 {
423  char* tmp;
424 
425  // In case the file got saved with the wrong locale.
426  if( strchr( CurText(), ',' ) != nullptr )
427  {
428  THROW_PARSE_ERROR( _( "Floating point number with incorrect locale" ), CurSource(),
429  CurLine(), CurLineNumber(), CurOffset() );
430  }
431 
432  errno = 0;
433 
434  double fval = strtod( CurText(), &tmp );
435 
436  if( errno )
437  {
438  THROW_PARSE_ERROR( _( "Invalid floating point number" ), CurSource(), CurLine(),
439  CurLineNumber(), CurOffset() );
440  }
441 
442  if( CurText() == tmp )
443  {
444  THROW_PARSE_ERROR( _( "Missing floating point number" ), CurSource(), CurLine(),
445  CurLineNumber(), CurOffset() );
446  }
447 
448  return fval;
449 }
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
#define _(s)

References _, and THROW_PARSE_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 122 of file sch_sexpr_parser.h.

123  {
124  NeedNUMBER( aExpected );
125  return parseDouble();
126  }
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 128 of file sch_sexpr_parser.h.

129  {
130  return parseDouble( GetTokenText( aToken ) );
131  }
const char * GetTokenText(T aTok)
The DSN namespace and returns the C string representing a SPECCTRA_DB::keyword.
Definition: specctra.cpp:70
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 381 of file sch_sexpr_parser.cpp.

382 {
383  switch( CurTok() )
384  {
385  case T_arc:
386  return static_cast<LIB_ITEM*>( parseArc() );
387  break;
388 
389  case T_bezier:
390  return static_cast<LIB_ITEM*>( parseBezier() );
391  break;
392 
393  case T_circle:
394  return static_cast<LIB_ITEM*>( parseCircle() );
395  break;
396 
397  case T_pin:
398  return static_cast<LIB_ITEM*>( parsePin() );
399  break;
400 
401  case T_polyline:
402  return static_cast<LIB_ITEM*>( parsePolyLine() );
403  break;
404 
405  case T_rectangle:
406  return static_cast<LIB_ITEM*>( parseRectangle() );
407  break;
408 
409  case T_text:
410  return static_cast<LIB_TEXT*>( parseText() );
411  break;
412 
413  default:
414  Expecting( "arc, bezier, circle, pin, polyline, rectangle, or text" );
415  }
416 
417  return nullptr;
418 }
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,
bool  aConvertOverbarSyntax 
)
private

Definition at line 596 of file sch_sexpr_parser.cpp.

597 {
598  wxCHECK_RET( aText && CurTok() == T_effects,
599  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as EDA_TEXT." ) );
600 
601  // In version 20210606 the notation for overbars was changed from `~...~` to `~{...}`.
602  // We need to convert the old syntax to the new one.
603  if( aConvertOverbarSyntax && m_requiredVersion < 20210606 )
604  aText->SetText( ConvertToNewOverbarNotation( aText->GetText() ) );
605 
606  T token;
607 
608  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
609  {
610  if( token == T_LEFT )
611  token = NextTok();
612 
613  switch( token )
614  {
615  case T_font:
616  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
617  {
618  if( token == T_LEFT )
619  token = NextTok();
620 
621  switch( token )
622  {
623  case T_size:
624  {
625  wxSize sz;
626  sz.SetHeight( parseInternalUnits( "text height" ) );
627  sz.SetWidth( parseInternalUnits( "text width" ) );
628  aText->SetTextSize( sz );
629  NeedRIGHT();
630  break;
631  }
632 
633  case T_thickness:
634  aText->SetTextThickness( parseInternalUnits( "text thickness" ) );
635  NeedRIGHT();
636  break;
637 
638  case T_bold:
639  aText->SetBold( true );
640  break;
641 
642  case T_italic:
643  aText->SetItalic( true );
644  break;
645 
646  default:
647  Expecting( "size, bold, or italic" );
648  }
649  }
650 
651  break;
652 
653  case T_justify:
654  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
655  {
656  switch( token )
657  {
658  case T_left: aText->SetHorizJustify( GR_TEXT_HJUSTIFY_LEFT ); break;
659  case T_right: aText->SetHorizJustify( GR_TEXT_HJUSTIFY_RIGHT ); break;
660  case T_top: aText->SetVertJustify( GR_TEXT_VJUSTIFY_TOP ); break;
661  case T_bottom: aText->SetVertJustify( GR_TEXT_VJUSTIFY_BOTTOM ); break;
662  case T_mirror: aText->SetMirrored( true ); break;
663  default: Expecting( "left, right, top, bottom, or mirror" );
664  }
665  }
666 
667  break;
668 
669  case T_hide:
670  aText->SetVisible( false );
671  break;
672 
673  default:
674  Expecting( "font, justify, or hide" );
675  }
676  }
677 }
void SetMirrored(bool isMirrored)
Definition: eda_text.h:188
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
void SetItalic(bool isItalic)
Definition: eda_text.h:179
void SetTextSize(const wxSize &aNewSize)
Definition: eda_text.h:237
virtual void SetVisible(bool aVisible)
Definition: eda_text.h:185
virtual void SetText(const wxString &aText)
Definition: eda_text.cpp:114
void SetVertJustify(EDA_TEXT_VJUSTIFY_T aType)
Definition: eda_text.h:202
int m_requiredVersion
Set to the symbol library file version required.
void SetHorizJustify(EDA_TEXT_HJUSTIFY_T aType)
Definition: eda_text.h:201
void SetTextThickness(int aWidth)
The TextThickness is that set by the user.
Definition: eda_text.h:159
void SetBold(bool aBold)
Definition: eda_text.h:182
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:133

References ConvertToNewOverbarNotation(), EDA_TEXT::GetText(), GR_TEXT_HJUSTIFY_LEFT, GR_TEXT_HJUSTIFY_RIGHT, GR_TEXT_VJUSTIFY_BOTTOM, GR_TEXT_VJUSTIFY_TOP, m_requiredVersion, parseInternalUnits(), EDA_TEXT::SetBold(), EDA_TEXT::SetHorizJustify(), EDA_TEXT::SetItalic(), EDA_TEXT::SetMirrored(), EDA_TEXT::SetText(), 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 541 of file sch_sexpr_parser.cpp.

542 {
543  wxCHECK_RET( CurTok() == T_fill,
544  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as fill." ) );
545 
547  aFill.m_Color = COLOR4D::UNSPECIFIED;
548 
549  T token;
550 
551  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
552  {
553  if( token != T_LEFT )
554  Expecting( T_LEFT );
555 
556  token = NextTok();
557 
558  switch( token )
559  {
560  case T_type:
561  {
562  token = NextTok();
563 
564  switch( token )
565  {
566  case T_none: aFill.m_FillType = FILL_TYPE::NO_FILL; break;
567  case T_outline: aFill.m_FillType = FILL_TYPE::FILLED_SHAPE; break;
568  case T_background: aFill.m_FillType = FILL_TYPE::FILLED_WITH_BG_BODYCOLOR; break;
569  default: Expecting( "none, outline, or background" );
570  }
571 
572  NeedRIGHT();
573  break;
574  }
575 
576  case T_color:
577  {
578  COLOR4D color;
579 
580  color.r = parseInt( "red" ) / 255.0;
581  color.g = parseInt( "green" ) / 255.0;
582  color.b = parseInt( "blue" ) / 255.0;
583  color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
584  aFill.m_Color = color;
585  NeedRIGHT();
586  break;
587  }
588 
589  default:
590  Expecting( "type or color" );
591  }
592  }
593 }
int color
Definition: DXF_plotter.cpp:57
FILL_TYPE m_FillType
const T & Clamp(const T &lower, const T &value, const T &upper)
Limit value within the range lower <= value <= upper.
Definition: util.h:52
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103

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 680 of file sch_sexpr_parser.cpp.

681 {
682  wxCHECK_RET( CurTok() == aHeaderType,
683  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a header." ) );
684 
685  NeedLEFT();
686 
687  T tok = NextTok();
688 
689  if( tok == T_version )
690  {
691  m_requiredVersion = parseInt( FromUTF8().mb_str( wxConvUTF8 ) );
692 
693  if( m_requiredVersion > aFileVersion )
694  throw FUTURE_FORMAT_ERROR( FromUTF8() );
695 
696  NeedRIGHT();
697 
698  // Skip the host name and host build version information.
699  NeedLEFT();
700  NeedSYMBOL();
701  NeedSYMBOL();
702 
703  if( m_requiredVersion < 20200827 )
704  NeedSYMBOL();
705 
706  NeedRIGHT();
707  }
708  else
709  {
710  m_requiredVersion = aFileVersion;
711 
712  // Skip the host name and host build version information.
713  NeedSYMBOL();
714  NeedSYMBOL();
715  NeedRIGHT();
716  }
717 }
int m_requiredVersion
Set to the symbol library file version required.
Variant of PARSE_ERROR indicating that a syntax or related error was likely caused by a file generate...
Definition: ki_exception.h:174

References m_requiredVersion, and parseInt().

Referenced by ParseLib(), and ParseSchematic().

◆ parseHex()

long SCH_SEXPR_PARSER::parseHex ( )
inlineprivate

Definition at line 96 of file sch_sexpr_parser.h.

97  {
98  NextTok();
99  return strtol( CurText(), nullptr, 16 );
100  }

◆ parseImage()

SCH_BITMAP * SCH_SEXPR_PARSER::parseImage ( )
private

Definition at line 2453 of file sch_sexpr_parser.cpp.

2454 {
2455  wxCHECK_MSG( CurTok() == T_image, nullptr,
2456  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as an image." ) );
2457 
2458  T token;
2459  std::unique_ptr<SCH_BITMAP> bitmap = std::make_unique<SCH_BITMAP>();
2460 
2461  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2462  {
2463  if( token != T_LEFT )
2464  Expecting( T_LEFT );
2465 
2466  token = NextTok();
2467 
2468  switch( token )
2469  {
2470  case T_at:
2471  bitmap->SetPosition( parseXY() );
2472  NeedRIGHT();
2473  break;
2474 
2475  case T_scale:
2476  bitmap->GetImage()->SetScale( parseDouble( "image scale factor" ) );
2477 
2478  if( !std::isnormal( bitmap->GetImage()->GetScale() ) )
2479  bitmap->GetImage()->SetScale( 1.0 );
2480 
2481  NeedRIGHT();
2482  break;
2483 
2484  case T_uuid:
2485  NeedSYMBOL();
2486  const_cast<KIID&>( bitmap->m_Uuid ) = KIID( FromUTF8() );
2487  NeedRIGHT();
2488  break;
2489 
2490  case T_data:
2491  {
2492  token = NextTok();
2493 
2494  wxString data;
2495 
2496  // Reserve 128K because most image files are going to be larger than the default
2497  // 1K that wxString reserves.
2498  data.reserve( 1 << 17 );
2499 
2500  while( token != T_RIGHT )
2501  {
2502  if( !IsSymbol( token ) )
2503  Expecting( "base64 image data" );
2504 
2505  data += FromUTF8();
2506  token = NextTok();
2507  }
2508 
2509  wxMemoryBuffer buffer = wxBase64Decode( data );
2510  wxMemoryOutputStream stream( buffer.GetData(), buffer.GetBufSize() );
2511  wxImage* image = new wxImage();
2512  wxMemoryInputStream istream( stream );
2513  image->LoadFile( istream, wxBITMAP_TYPE_PNG );
2514  bitmap->GetImage()->SetImage( image );
2515  bitmap->GetImage()->SetBitmap( new wxBitmap( *image ) );
2516  break;
2517  }
2518 
2519  default:
2520  Expecting( "at, scale, uuid or data" );
2521  }
2522  }
2523 
2524  return bitmap.release();
2525 }
Definition: kiid.h:44
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

References image, parseDouble(), and parseXY().

Referenced by ParseSchematic().

◆ parseInt() [1/2]

int SCH_SEXPR_PARSER::parseInt ( )
inlineprivate

Definition at line 102 of file sch_sexpr_parser.h.

103  {
104  return (int)strtol( CurText(), nullptr, 10 );
105  }

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 107 of file sch_sexpr_parser.h.

108  {
109  NeedNUMBER( aExpected );
110  return parseInt();
111  }

References parseInt().

◆ parseInternalUnits() [1/3]

int SCH_SEXPR_PARSER::parseInternalUnits ( )
private

Definition at line 452 of file sch_sexpr_parser.cpp.

453 {
454  auto retval = parseDouble() * IU_PER_MM;
455 
456  // Schematic internal units are represented as integers. Any values that are
457  // larger or smaller than the schematic units represent undefined behavior for
458  // the system. Limit values to the largest that can be displayed on the screen.
459  double int_limit = std::numeric_limits<int>::max() * 0.7071; // 0.7071 = roughly 1/sqrt(2)
460 
461  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
462 }
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:73
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)
private

Definition at line 465 of file sch_sexpr_parser.cpp.

466 {
467  auto retval = parseDouble( aExpected ) * IU_PER_MM;
468 
469  double int_limit = std::numeric_limits<int>::max() * 0.7071;
470 
471  return KiROUND( Clamp<double>( -int_limit, retval, int_limit ) );
472 }
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:73
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 137 of file sch_sexpr_parser.h.

138  {
139  return parseInternalUnits( GetTokenText( aToken ) );
140  }
const char * GetTokenText(T aTok)
The DSN namespace and returns the C string representing a SPECCTRA_DB::keyword.
Definition: specctra.cpp:70

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

◆ parseJunction()

SCH_JUNCTION * SCH_SEXPR_PARSER::parseJunction ( )
private

Definition at line 2635 of file sch_sexpr_parser.cpp.

2636 {
2637  wxCHECK_MSG( CurTok() == T_junction, nullptr,
2638  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a junction." ) );
2639 
2640  T token;
2641  std::unique_ptr<SCH_JUNCTION> junction = std::make_unique<SCH_JUNCTION>();
2642 
2643  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2644  {
2645  if( token != T_LEFT )
2646  Expecting( T_LEFT );
2647 
2648  token = NextTok();
2649 
2650  switch( token )
2651  {
2652  case T_at:
2653  junction->SetPosition( parseXY() );
2654  NeedRIGHT();
2655  break;
2656 
2657  case T_diameter:
2658  junction->SetDiameter( parseInternalUnits( "junction diameter" ) );
2659  NeedRIGHT();
2660  break;
2661 
2662  case T_color:
2663  {
2664  COLOR4D color;
2665 
2666  color.r = parseInt( "red" ) / 255.0;
2667  color.g = parseInt( "green" ) / 255.0;
2668  color.b = parseInt( "blue" ) / 255.0;
2669  color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
2670 
2671  junction->SetColor( color );
2672  NeedRIGHT();
2673  break;
2674  }
2675 
2676  default:
2677  Expecting( "at" );
2678  }
2679  }
2680 
2681  return junction.release();
2682 }
int color
Definition: DXF_plotter.cpp:57
const T & Clamp(const T &lower, const T &value, const T &upper)
Limit value within the range lower <= value <= upper.
Definition: util.h:52
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103

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

Referenced by ParseSchematic().

◆ ParseLib()

void SCH_SEXPR_PARSER::ParseLib ( LIB_SYMBOL_MAP aSymbolLibMap)

Definition at line 116 of file sch_sexpr_parser.cpp.

117 {
118  T token;
119 
120  NeedLEFT();
121  NextTok();
122  parseHeader( T_kicad_symbol_lib, SEXPR_SYMBOL_LIB_FILE_VERSION );
123 
124  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
125  {
126  if( token != T_LEFT )
127  Expecting( T_LEFT );
128 
129  token = NextTok();
130 
131  if( token == T_symbol )
132  {
133  m_unit = 1;
134  m_convert = 1;
135  LIB_SYMBOL* symbol = ParseSymbol( aSymbolLibMap, m_requiredVersion );
136  aSymbolLibMap[symbol->GetName()] = symbol;
137  }
138  else
139  {
140  Expecting( "symbol" );
141  }
142  }
143 }
wxString GetName() const override
Definition: lib_symbol.h:133
LIB_SYMBOL * ParseSymbol(LIB_SYMBOL_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
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...
Define a library symbol object.
Definition: lib_symbol.h:96
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
int m_convert
The current body style being parsed.
int m_requiredVersion
Set to the symbol library file version required.

References LIB_SYMBOL::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 2776 of file sch_sexpr_parser.cpp.

2777 {
2778  T token;
2779  STROKE_PARAMS stroke;
2780  std::unique_ptr<SCH_LINE> line = std::make_unique<SCH_LINE>();
2781 
2782  switch( CurTok() )
2783  {
2784  case T_polyline: line->SetLayer( LAYER_NOTES ); break;
2785  case T_wire: line->SetLayer( LAYER_WIRE ); break;
2786  case T_bus: line->SetLayer( LAYER_BUS ); break;
2787  default:
2788  wxCHECK_MSG( false, nullptr,
2789  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a line." ) );
2790  }
2791 
2792  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2793  {
2794  if( token != T_LEFT )
2795  Expecting( T_LEFT );
2796 
2797  token = NextTok();
2798 
2799  switch( token )
2800  {
2801  case T_pts:
2802  NeedLEFT();
2803  token = NextTok();
2804 
2805  if( token != T_xy )
2806  Expecting( "xy" );
2807 
2808  line->SetStartPoint( parseXY() );
2809  NeedRIGHT();
2810  NeedLEFT();
2811  token = NextTok();
2812 
2813  if( token != T_xy )
2814  Expecting( "xy" );
2815 
2816  line->SetEndPoint( parseXY() );
2817  NeedRIGHT();
2818  NeedRIGHT();
2819  break;
2820 
2821  case T_stroke:
2822  parseStroke( stroke );
2823  line->SetStroke( stroke );
2824  break;
2825 
2826  case T_uuid:
2827  NeedSYMBOL();
2828  const_cast<KIID&>( line->m_Uuid ) = KIID( FromUTF8() );
2829  NeedRIGHT();
2830  break;
2831 
2832  default:
2833  Expecting( "at, uuid or stroke" );
2834  }
2835  }
2836 
2837  return line.release();
2838 }
Definition: kiid.h:44
Simple container to manage line stroke parameters.
Definition: sch_item.h:151
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 2685 of file sch_sexpr_parser.cpp.

2686 {
2687  wxCHECK_MSG( CurTok() == T_no_connect, nullptr,
2688  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a no connect." ) );
2689 
2690  T token;
2691  std::unique_ptr<SCH_NO_CONNECT> no_connect = std::make_unique<SCH_NO_CONNECT>();
2692 
2693  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2694  {
2695  if( token != T_LEFT )
2696  Expecting( T_LEFT );
2697 
2698  token = NextTok();
2699 
2700  switch( token )
2701  {
2702  case T_at:
2703  no_connect->SetPosition( parseXY() );
2704  NeedRIGHT();
2705  break;
2706 
2707  case T_uuid:
2708  NeedSYMBOL();
2709  const_cast<KIID&>( no_connect->m_Uuid ) = KIID( FromUTF8() );
2710  NeedRIGHT();
2711  break;
2712 
2713  default:
2714  Expecting( "at or uuid" );
2715  }
2716  }
2717 
2718  return no_connect.release();
2719 }
Definition: kiid.h:44

References parseXY().

Referenced by ParseSchematic().

◆ parsePAGE_INFO()

void SCH_SEXPR_PARSER::parsePAGE_INFO ( PAGE_INFO aPageInfo)
private

Definition at line 1550 of file sch_sexpr_parser.cpp.

1551 {
1552  wxCHECK_RET( ( CurTok() == T_page && m_requiredVersion <= 20200506 ) || CurTok() == T_paper,
1553  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a PAGE_INFO." ) );
1554 
1555  T token;
1556 
1557  NeedSYMBOL();
1558 
1559  wxString pageType = FromUTF8();
1560 
1561  if( !aPageInfo.SetType( pageType ) )
1562  {
1563  THROW_PARSE_ERROR( _( "Invalid page type" ), CurSource(), CurLine(), CurLineNumber(),
1564  CurOffset() );
1565  }
1566 
1567  if( pageType == PAGE_INFO::Custom )
1568  {
1569  double width = parseDouble( "width" ); // width in mm
1570 
1571  // Perform some controls to avoid crashes if the size is edited by hands
1572  if( width < 100.0 )
1573  width = 100.0;
1574  else if( width > 1200.0 )
1575  width = 1200.0;
1576 
1577  double height = parseDouble( "height" ); // height in mm
1578 
1579  if( height < 100.0 )
1580  height = 100.0;
1581  else if( height > 1200.0 )
1582  height = 1200.0;
1583 
1584  aPageInfo.SetWidthMils( Mm2mils( width ) );
1585  aPageInfo.SetHeightMils( Mm2mils( height ) );
1586  }
1587 
1588  token = NextTok();
1589 
1590  if( token == T_portrait )
1591  {
1592  aPageInfo.SetPortrait( true );
1593  NeedRIGHT();
1594  }
1595  else if( token != T_RIGHT )
1596  {
1597  Expecting( "portrait" );
1598  }
1599 }
bool SetType(const wxString &aStandardPageDescriptionName, bool aIsPortrait=false)
Set the name of the page type and also the sizes and margins commonly associated with that type name.
Definition: page_info.cpp:119
static const wxChar Custom[]
"User" defined page type
Definition: page_info.h:77
int Mm2mils(double x)
Convert mm to mils.
Definition: base_units.cpp:56
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
#define _(s)
void SetHeightMils(int aHeightInMils)
Definition: page_info.cpp:257
int m_requiredVersion
Set to the symbol library file version required.
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)
Rotate the paper page 90 degrees.
Definition: page_info.cpp:186

References _, PAGE_INFO::Custom, 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 1155 of file sch_sexpr_parser.cpp.

1156 {
1157  auto parseType = [&]( T token ) -> ELECTRICAL_PINTYPE
1158  {
1159  switch( token )
1160  {
1161  case T_input: return ELECTRICAL_PINTYPE::PT_INPUT;
1162  case T_output: return ELECTRICAL_PINTYPE::PT_OUTPUT;
1163  case T_bidirectional: return ELECTRICAL_PINTYPE::PT_BIDI;
1164  case T_tri_state: return ELECTRICAL_PINTYPE::PT_TRISTATE;
1165  case T_passive: return ELECTRICAL_PINTYPE::PT_PASSIVE;
1166  case T_unspecified: return ELECTRICAL_PINTYPE::PT_UNSPECIFIED;
1167  case T_power_in: return ELECTRICAL_PINTYPE::PT_POWER_IN;
1168  case T_power_out: return ELECTRICAL_PINTYPE::PT_POWER_OUT;
1169  case T_open_collector: return ELECTRICAL_PINTYPE::PT_OPENCOLLECTOR;
1170  case T_open_emitter: return ELECTRICAL_PINTYPE::PT_OPENEMITTER;
1171  case T_unconnected:
1172  case T_no_connect: return ELECTRICAL_PINTYPE::PT_NC;
1173  case T_free: return ELECTRICAL_PINTYPE::PT_NIC;
1174 
1175  default:
1176  Expecting( "input, output, bidirectional, tri_state, passive, "
1177  "unspecified, power_in, power_out, open_collector, "
1178  "open_emitter, free or no_connect" );
1180  }
1181  };
1182 
1183  auto parseShape = [&]( T token ) -> GRAPHIC_PINSHAPE
1184  {
1185  switch( token )
1186  {
1187  case T_line: return GRAPHIC_PINSHAPE::LINE;
1188  case T_inverted: return GRAPHIC_PINSHAPE::INVERTED;
1189  case T_clock: return GRAPHIC_PINSHAPE::CLOCK;
1190  case T_inverted_clock: return GRAPHIC_PINSHAPE::INVERTED_CLOCK;
1191  case T_input_low: return GRAPHIC_PINSHAPE::INPUT_LOW;
1192  case T_clock_low: return GRAPHIC_PINSHAPE::CLOCK_LOW;
1193  case T_output_low: return GRAPHIC_PINSHAPE::OUTPUT_LOW;
1194  case T_edge_clock_high: return GRAPHIC_PINSHAPE::FALLING_EDGE_CLOCK;
1195  case T_non_logic: return GRAPHIC_PINSHAPE::NONLOGIC;
1196 
1197  default:
1198  Expecting( "line, inverted, clock, inverted_clock, input_low, "
1199  "clock_low, output_low, edge_clock_high, non_logic" );
1200  return GRAPHIC_PINSHAPE::LINE;
1201  }
1202  };
1203 
1204  wxCHECK_MSG( CurTok() == T_pin, nullptr,
1205  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a pin token." ) );
1206 
1207  T token;
1208  wxString tmp;
1209  wxString error;
1210  std::unique_ptr<LIB_PIN> pin = std::make_unique<LIB_PIN>( nullptr );
1211 
1212  pin->SetUnit( m_unit );
1213  pin->SetConvert( m_convert );
1214 
1215  // Pin electrical type.
1216  token = NextTok();
1217  pin->SetType( parseType( token ) );
1218 
1219  // Pin shape.
1220  token = NextTok();
1221  pin->SetShape( parseShape( token ) );
1222 
1223  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1224  {
1225  if( token == T_hide )
1226  {
1227  pin->SetVisible( false );
1228  continue;
1229  }
1230 
1231  if( token != T_LEFT )
1232  Expecting( T_LEFT );
1233 
1234  token = NextTok();
1235 
1236  switch( token )
1237  {
1238  case T_at:
1239  pin->SetPosition( parseXY() );
1240 
1241  switch( parseInt( "pin orientation" ) )
1242  {
1243  case 0:
1244  pin->SetOrientation( PIN_RIGHT );
1245  break;
1246 
1247  case 90:
1248  pin->SetOrientation( PIN_UP );
1249  break;
1250 
1251  case 180:
1252  pin->SetOrientation( PIN_LEFT );
1253  break;
1254 
1255  case 270:
1256  pin->SetOrientation( PIN_DOWN );
1257  break;
1258 
1259  default:
1260  Expecting( "0, 90, 180, or 270" );
1261  }
1262 
1263  NeedRIGHT();
1264  break;
1265 
1266  case T_length:
1267  pin->SetLength( parseInternalUnits( "pin length" ) );
1268  NeedRIGHT();
1269  break;
1270 
1271  case T_name:
1272  token = NextTok();
1273 
1274  if( !IsSymbol( token ) )
1275  {
1276  THROW_PARSE_ERROR( _( "Invalid pin name" ), CurSource(), CurLine(), CurLineNumber(),
1277  CurOffset() );
1278  }
1279 
1280  if( m_requiredVersion < 20210606 )
1281  pin->SetName( ConvertToNewOverbarNotation( FromUTF8() ) );
1282  else
1283  pin->SetName( FromUTF8() );
1284 
1285  token = NextTok();
1286 
1287  if( token != T_RIGHT )
1288  {
1289  token = NextTok();
1290 
1291  if( token == T_effects )
1292  {
1293  // The EDA_TEXT font effects formatting is used so use and EDA_TEXT object
1294  // so duplicate parsing is not required.
1295  EDA_TEXT text;
1296 
1297  parseEDA_TEXT( &text, true );
1298  pin->SetNameTextSize( text.GetTextHeight() );
1299  NeedRIGHT();
1300  }
1301  else
1302  {
1303  Expecting( "effects" );
1304  }
1305  }
1306 
1307  break;
1308 
1309  case T_number:
1310  token = NextTok();
1311 
1312  if( !IsSymbol( token ) )
1313  {
1314  THROW_PARSE_ERROR( _( "Invalid pin number" ), CurSource(), CurLine(),
1315  CurLineNumber(), CurOffset() );
1316  }
1317 
1318  pin->SetNumber( FromUTF8() );
1319  token = NextTok();
1320 
1321  if( token != T_RIGHT )
1322  {
1323  token = NextTok();
1324 
1325  if( token == T_effects )
1326  {
1327  // The EDA_TEXT font effects formatting is used so use and EDA_TEXT object
1328  // so duplicate parsing is not required.
1329  EDA_TEXT text;
1330 
1331  parseEDA_TEXT( &text, false );
1332  pin->SetNumberTextSize( text.GetTextHeight() );
1333  NeedRIGHT();
1334  }
1335  else
1336  {
1337  Expecting( "effects" );
1338  }
1339  }
1340 
1341  break;
1342 
1343  case T_alternate:
1344  {
1345  LIB_PIN::ALT alt;
1346 
1347  token = NextTok();
1348 
1349  if( !IsSymbol( token ) )
1350  {
1351  THROW_PARSE_ERROR( _( "Invalid alternate pin name" ), CurSource(), CurLine(),
1352  CurLineNumber(), CurOffset() );
1353  }
1354 
1355  alt.m_Name = FromUTF8();
1356 
1357  token = NextTok();
1358  alt.m_Type = parseType( token );
1359 
1360  token = NextTok();
1361  alt.m_Shape = parseShape( token );
1362 
1363  pin->GetAlternates()[ alt.m_Name ] = alt;
1364 
1365  NeedRIGHT();
1366  }
1367  break;
1368 
1369  default:
1370  Expecting( "at, name, number, length, or alternate" );
1371  }
1372  }
1373 
1374  return pin.release();
1375 }
wxString ConvertToNewOverbarNotation(const wxString &aOldStr)
Convert the old ~...~ overbar notation to the new ~{...} one.
power input (GND, VCC for ICs). Must be connected to a power output.
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax)
pin for passive symbols: 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:48
GRAPHIC_PINSHAPE
Definition: pin_type.h:55
ELECTRICAL_PINTYPE m_Type
Definition: lib_pin.h:60
A mix-in class (via multiple inheritance) that handles texts such as labels, parts,...
Definition: eda_text.h:119
not internally connected (may be connected to anything)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
int m_convert
The current body style being parsed.
wxString m_Name
Definition: lib_pin.h:58
#define _(s)
int m_requiredVersion
Set to the symbol library file version required.
ELECTRICAL_PINTYPE
The symbol library pin object electrical types used in ERC tests.
Definition: pin_type.h:35
usual pin input: must be connected
input or output (like port for a microprocessor)
not connected (must be left open)
output of a regulator: intended to be connected to power input pins
GRAPHIC_PINSHAPE m_Shape
Definition: lib_pin.h:59

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

Referenced by ParseDrawItem().

◆ parsePinNames()

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

Definition at line 720 of file sch_sexpr_parser.cpp.

721 {
722  wxCHECK_RET( CurTok() == T_pin_names,
723  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
724  wxT( " as a pin_name token." ) );
725 
726  wxString error;
727 
728  T token = NextTok();
729 
730  if( token == T_LEFT )
731  {
732  token = NextTok();
733 
734  if( token != T_offset )
735  Expecting( "offset" );
736 
737  aSymbol->SetPinNameOffset( parseInternalUnits( "pin name offset" ) );
738  NeedRIGHT();
739  token = NextTok(); // Either ) or hide
740  }
741 
742  if( token == T_hide )
743  {
744  aSymbol->SetShowPinNames( false );
745  NeedRIGHT();
746  }
747  else if( token != T_RIGHT )
748  {
749  THROW_PARSE_ERROR( _( "Invalid pin names definition" ), CurSource(), CurLine(),
750  CurLineNumber(), CurOffset() );
751  }
752 }
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
#define _(s)

References _, parseInternalUnits(), and THROW_PARSE_ERROR.

Referenced by ParseSymbol().

◆ parsePolyLine()

LIB_POLYLINE * SCH_SEXPR_PARSER::parsePolyLine ( )
private

Definition at line 1378 of file sch_sexpr_parser.cpp.

1379 {
1380  wxCHECK_MSG( CurTok() == T_polyline, nullptr,
1381  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a polyline." ) );
1382 
1383  T token;
1384  FILL_PARAMS fill;
1385  std::unique_ptr<LIB_POLYLINE> polyLine = std::make_unique<LIB_POLYLINE>( nullptr );
1386 
1387  polyLine->SetUnit( m_unit );
1388  polyLine->SetConvert( m_convert );
1389 
1390  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1391  {
1392  if( token != T_LEFT )
1393  Expecting( T_LEFT );
1394 
1395  token = NextTok();
1396 
1397  switch( token )
1398  {
1399  case T_pts:
1400  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1401  {
1402  if( token != T_LEFT )
1403  Expecting( T_LEFT );
1404 
1405  token = NextTok();
1406 
1407  if( token != T_xy )
1408  Expecting( "xy" );
1409 
1410  polyLine->AddPoint( parseXY() );
1411 
1412  NeedRIGHT();
1413  }
1414 
1415  break;
1416 
1417  case T_stroke:
1418  NeedLEFT();
1419  token = NextTok();
1420 
1421  if( token != T_width )
1422  Expecting( "width" );
1423 
1424  polyLine->SetWidth( parseInternalUnits( "stroke width" ) );
1425  NeedRIGHT(); // Closes width token;
1426  NeedRIGHT(); // Closes stroke token;
1427  break;
1428 
1429  case T_fill:
1430  parseFill( fill );
1431  polyLine->SetFillMode( fill.m_FillType );
1432  break;
1433 
1434  default:
1435  Expecting( "pts, stroke, or fill" );
1436  }
1437  }
1438 
1439  return polyLine.release();
1440 }
int m_unit
The current unit being parsed.
FILL_TYPE m_FillType
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()

LIB_FIELD * SCH_SEXPR_PARSER::parseProperty ( std::unique_ptr< LIB_SYMBOL > &  aSymbol)
private

Definition at line 755 of file sch_sexpr_parser.cpp.

756 {
757  wxCHECK_MSG( CurTok() == T_property, nullptr,
758  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a property." ) );
759  wxCHECK( aSymbol, nullptr );
760 
761  wxString error;
762  wxString name;
763  wxString value;
764  std::unique_ptr<LIB_FIELD> field = std::make_unique<LIB_FIELD>( aSymbol.get(),
766 
767  T token = NextTok();
768 
769  if( !IsSymbol( token ) )
770  {
771  THROW_PARSE_ERROR( _( "Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
772  CurOffset() );
773  }
774 
775  name = FromUTF8();
776 
777  if( name.IsEmpty() )
778  {
779  THROW_PARSE_ERROR( _( "Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
780  CurOffset() );
781  }
782 
783  field->SetName( name );
784  token = NextTok();
785 
786  if( !IsSymbol( token ) )
787  {
788  THROW_PARSE_ERROR( _( "Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
789  CurOffset() );
790  }
791 
792  // Empty property values are valid.
793  value = FromUTF8();
794 
795  field->SetText( value );
796 
797  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
798  {
799  if( token != T_LEFT )
800  Expecting( T_LEFT );
801 
802  token = NextTok();
803 
804  switch( token )
805  {
806  case T_id:
807  field->SetId( parseInt( "field ID" ) );
808  NeedRIGHT();
809  break;
810 
811  case T_at:
812  field->SetPosition( parseXY() );
813  field->SetTextAngle( static_cast<int>( parseDouble( "text angle" ) * 10.0 ) );
814  NeedRIGHT();
815  break;
816 
817  case T_effects:
818  parseEDA_TEXT( static_cast<EDA_TEXT*>( field.get() ), field->GetId() == VALUE_FIELD );
819  break;
820 
821  default:
822  Expecting( "id, at or effects" );
823  }
824  }
825 
826  LIB_FIELD* existingField;
827 
828  if( field->GetId() < MANDATORY_FIELDS )
829  {
830  existingField = aSymbol->GetFieldById( field->GetId() );
831 
832  *existingField = *field;
833  return existingField;
834  }
835  else if( name == "ki_keywords" )
836  {
837  // Not a LIB_FIELD object yet.
838  aSymbol->SetKeyWords( value );
839  return nullptr;
840  }
841  else if( name == "ki_description" )
842  {
843  // Not a LIB_FIELD object yet.
844  aSymbol->SetDescription( value );
845  return nullptr;
846  }
847  else if( name == "ki_fp_filters" )
848  {
849  // Not a LIB_FIELD object yet.
850  wxArrayString filters;
851  wxStringTokenizer tokenizer( value );
852 
853  while( tokenizer.HasMoreTokens() )
854  {
855  wxString curr_token = UnescapeString( tokenizer.GetNextToken() );
856  filters.Add( curr_token );
857  }
858 
859  aSymbol->SetFPFilters( filters );
860  return nullptr;
861  }
862  else if( name == "ki_locked" )
863  {
864  // This is a temporary LIB_FIELD object until interchangeable units are determined on
865  // the fly.
866  aSymbol->LockUnits( true );
867  return nullptr;
868  }
869  else
870  {
871  // At this point, a user field is read.
872  existingField = aSymbol->FindField( field->GetCanonicalName() );
873 
874 #if 1 // Enable it to modify the name of the field to add if already existing
875  // Disable it to skip the field having the same name as previous field
876  if( existingField )
877  {
878  // We cannot handle 2 fields with the same name, so because the field name
879  // is already in use, try to build a new name (oldname_x)
880  wxString base_name = field->GetCanonicalName();
881 
882  // Arbitrary limit 10 attempts to find a new name
883  for( int ii = 1; ii < 10 && existingField ; ii++ )
884  {
885  wxString newname = base_name;
886  newname << '_' << ii;
887 
888  existingField = aSymbol->FindField( newname );
889 
890  if( !existingField ) // the modified name is not found, use it
891  field->SetName( newname );
892  }
893  }
894 #endif
895  if( !existingField )
896  {
897  aSymbol->AddDrawItem( field.get(), false );
898  return field.release();
899  }
900  else
901  {
902  // We cannot handle 2 fields with the same name, so skip this one
903  return nullptr;
904  }
905  }
906 }
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax)
Field object used in symbol libraries.
Definition: lib_field.h:59
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
Field Value of part, i.e. "3.3K".
wxString GetCanonicalName() const
Get a non-language-specific name for a field which can be used for storage, variable look-up,...
Definition: lib_field.cpp:371
#define _(s)
wxString UnescapeString(const wxString &aSource)
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
const char * name
Definition: DXF_plotter.cpp:56
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

References _, LIB_FIELD::GetCanonicalName(), MANDATORY_FIELDS, name, parseDouble(), parseEDA_TEXT(), parseInt(), parseXY(), THROW_PARSE_ERROR, UnescapeString(), and VALUE_FIELD.

Referenced by ParseSymbol().

◆ parseRectangle()

LIB_RECTANGLE * SCH_SEXPR_PARSER::parseRectangle ( )
private

Definition at line 1443 of file sch_sexpr_parser.cpp.

1444 {
1445  wxCHECK_MSG( CurTok() == T_rectangle, nullptr,
1446  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1447  wxT( " as a rectangle token." ) );
1448 
1449  T token;
1450  FILL_PARAMS fill;
1451  std::unique_ptr<LIB_RECTANGLE> rectangle = std::make_unique<LIB_RECTANGLE>( nullptr );
1452 
1453  rectangle->SetUnit( m_unit );
1454  rectangle->SetConvert( m_convert );
1455 
1456  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1457  {
1458  if( token != T_LEFT )
1459  Expecting( T_LEFT );
1460 
1461  token = NextTok();
1462 
1463  switch( token )
1464  {
1465  case T_start:
1466  rectangle->SetPosition( parseXY() );
1467  NeedRIGHT();
1468  break;
1469 
1470  case T_end:
1471  rectangle->SetEnd( parseXY() );
1472  NeedRIGHT();
1473  break;
1474 
1475  case T_stroke:
1476  NeedLEFT();
1477  token = NextTok();
1478 
1479  if( token != T_width )
1480  Expecting( "width" );
1481 
1482  rectangle->SetWidth( parseInternalUnits( "stroke width" ) );
1483  NeedRIGHT(); // Closes width token;
1484  NeedRIGHT(); // Closes stroke token;
1485  break;
1486 
1487  case T_fill:
1488  parseFill( fill );
1489  rectangle->SetFillMode( fill.m_FillType );
1490  break;
1491 
1492  default:
1493  Expecting( "start, end, stroke, or fill" );
1494  }
1495  }
1496 
1497  return rectangle.release();
1498 }
int m_unit
The current unit being parsed.
FILL_TYPE m_FillType
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 2031 of file sch_sexpr_parser.cpp.

2032 {
2033  wxCHECK( aSheet != nullptr, /* void */ );
2034 
2035  SCH_SCREEN* screen = aSheet->GetScreen();
2036 
2037  wxCHECK( screen != nullptr, /* void */ );
2038 
2039  if( aIsCopyableOnly )
2040  m_requiredVersion = aFileVersion;
2041 
2042  T token;
2043 
2044  if( !aIsCopyableOnly )
2045  {
2046  NeedLEFT();
2047  NextTok();
2048 
2049  if( CurTok() != T_kicad_sch )
2050  Expecting( "kicad_sch" );
2051 
2052  parseHeader( T_kicad_sch, SEXPR_SCHEMATIC_FILE_VERSION );
2053  }
2054 
2056 
2057  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2058  {
2059  if( aIsCopyableOnly && token == T_EOF )
2060  break;
2061 
2062  if( token != T_LEFT )
2063  Expecting( T_LEFT );
2064 
2065  token = NextTok();
2066 
2067  checkpoint();
2068 
2069  if( !aIsCopyableOnly && token == T_page && m_requiredVersion <= 20200506 )
2070  token = T_paper;
2071 
2072  switch( token )
2073  {
2074  case T_uuid:
2075  NeedSYMBOL();
2076  screen->m_uuid = KIID( FromUTF8() );
2077  NeedRIGHT();
2078  break;
2079 
2080  case T_paper:
2081  {
2082  if( aIsCopyableOnly )
2083  Unexpected( T_paper );
2084 
2085  PAGE_INFO pageInfo;
2086  parsePAGE_INFO( pageInfo );
2087  screen->SetPageSettings( pageInfo );
2088  break;
2089  }
2090 
2091  case T_page:
2092  {
2093  if( aIsCopyableOnly )
2094  Unexpected( T_page );
2095 
2096  // Only saved for top-level sniffing in Kicad Manager frame and other external
2097  // tool usage with flat hierarchies
2098  NeedSYMBOLorNUMBER();
2099  NeedSYMBOLorNUMBER();
2100  NeedRIGHT();
2101  break;
2102  }
2103 
2104  case T_title_block:
2105  {
2106  if( aIsCopyableOnly )
2107  Unexpected( T_title_block );
2108 
2109  TITLE_BLOCK tb;
2110  parseTITLE_BLOCK( tb );
2111  screen->SetTitleBlock( tb );
2112  break;
2113  }
2114 
2115  case T_lib_symbols:
2116  {
2117  // Dummy map. No derived symbols are allowed in the library cache.
2118  LIB_SYMBOL_MAP symbolLibMap;
2119 
2120  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2121  {
2122  if( token != T_LEFT )
2123  Expecting( T_LEFT );
2124 
2125  token = NextTok();
2126 
2127  switch( token )
2128  {
2129  case T_symbol:
2130  screen->AddLibSymbol( ParseSymbol( symbolLibMap, m_requiredVersion ) );
2131  break;
2132 
2133  default:
2134  Expecting( "symbol" );
2135  }
2136  }
2137 
2138  break;
2139  }
2140 
2141  case T_symbol:
2142  screen->Append( static_cast<SCH_ITEM*>( parseSchematicSymbol() ) );
2143  break;
2144 
2145  case T_image:
2146  screen->Append( static_cast<SCH_ITEM*>( parseImage() ) );
2147  break;
2148 
2149  case T_sheet:
2150  {
2151  SCH_SHEET* sheet = parseSheet();
2152 
2153  // Set the parent to aSheet. This effectively creates a method to find
2154  // the root sheet from any sheet so a pointer to the root sheet does not
2155  // need to be stored globally. Note: this is not the same as a hierarchy.
2156  // Complex hierarchies can have multiple copies of a sheet. This only
2157  // provides a simple tree to find the root sheet.
2158  sheet->SetParent( aSheet );
2159  screen->Append( static_cast<SCH_ITEM*>( sheet ) );
2160  break;
2161  }
2162 
2163  case T_junction:
2164  screen->Append( static_cast<SCH_ITEM*>( parseJunction() ) );
2165  break;
2166 
2167  case T_no_connect:
2168  screen->Append( static_cast<SCH_ITEM*>( parseNoConnect() ) );
2169  break;
2170 
2171  case T_bus_entry:
2172  screen->Append( static_cast<SCH_ITEM*>( parseBusEntry() ) );
2173  break;
2174 
2175  case T_polyline:
2176  case T_bus:
2177  case T_wire:
2178  screen->Append( static_cast<SCH_ITEM*>( parseLine() ) );
2179  break;
2180 
2181  case T_text:
2182  case T_label:
2183  case T_global_label:
2184  case T_hierarchical_label:
2185  screen->Append( static_cast<SCH_ITEM*>( parseSchText() ) );
2186  break;
2187 
2188  case T_sheet_instances:
2189  parseSchSheetInstances( aSheet, screen );
2190  break;
2191 
2192  case T_symbol_instances:
2193  parseSchSymbolInstances( screen );
2194  break;
2195 
2196  case T_bus_alias:
2197  if( aIsCopyableOnly )
2198  Unexpected( T_bus_alias );
2199 
2200  parseBusAlias( screen );
2201  break;
2202 
2203  default:
2204  Expecting( "symbol, paper, page, title_block, bitmap, sheet, junction, no_connect, "
2205  "bus_entry, line, bus, text, label, global_label, hierarchical_label, "
2206  "symbol_instances, or bus_alias" );
2207  }
2208  }
2209 
2210  screen->UpdateLocalLibSymbolLinks();
2211 }
std::map< wxString, LIB_SYMBOL *, LibSymbolMapSort > LIB_SYMBOL_MAP
Symbol map used by symbol library object.
void parseBusAlias(SCH_SCREEN *aScreen)
LIB_SYMBOL * ParseSymbol(LIB_SYMBOL_MAP &aSymbolLibMap, int aFileVersion=SEXPR_SYMBOL_LIB_FILE_VERSION)
void parseTITLE_BLOCK(TITLE_BLOCK &aTitleBlock)
void SetPageSettings(const PAGE_INFO &aPageSettings)
Definition: sch_screen.h:133
SCH_SYMBOL * parseSchematicSymbol()
SCH_SCREEN * GetScreen() const
Definition: sch_sheet.h:103
Hold the information shown in the lower right corner of a plot, printout, or editing view.
Definition: title_block.h:40
void parseSchSheetInstances(SCH_SHEET *aRootSheet, SCH_SCREEN *aScreen)
void parseSchSymbolInstances(SCH_SCREEN *aScreen)
virtual void SetParent(EDA_ITEM *aParent)
Definition: eda_item.h:116
SCH_BUS_WIRE_ENTRY * parseBusEntry()
Definition: kiid.h:44
void UpdateLocalLibSymbolLinks()
Initialize the LIB_SYMBOL reference for each SCH_SYMBOL found in this schematic with the local projec...
Definition: sch_screen.cpp:703
void parseHeader(TSCHEMATIC_T::T aHeaderType, int aFileVersion)
SCH_JUNCTION * parseJunction()
Describe the page size and margins of a paper page on which to eventually print or plot.
Definition: page_info.h:53
SCH_NO_CONNECT * parseNoConnect()
void SetFileFormatVersionAtLoad(int aVersion)
Definition: sch_screen.h:129
void SetTitleBlock(const TITLE_BLOCK &aTitleBlock)
Definition: sch_screen.h:152
Sheet symbol placed in a schematic, and is the entry point for a sub schematic.
Definition: sch_sheet.h:54
void AddLibSymbol(LIB_SYMBOL *aLibSymbol)
Add aLibSymbol to the library symbol map.
void parsePAGE_INFO(PAGE_INFO &aPageInfo)
int m_requiredVersion
Set to the symbol library file version required.
void Append(SCH_ITEM *aItem)
Definition: sch_screen.cpp:144
SCH_BITMAP * parseImage()
KIID m_uuid
A unique identifier for each schematic file.
Definition: sch_screen.h:544
SCH_TEXT * parseSchText()
#define SEXPR_SCHEMATIC_FILE_VERSION
Schematic file version.
SCH_SHEET * parseSheet()

References SCH_SCREEN::AddLibSymbol(), SCH_SCREEN::Append(), checkpoint(), SCH_SHEET::GetScreen(), m_requiredVersion, SCH_SCREEN::m_uuid, parseBusAlias(), parseBusEntry(), parseHeader(), parseImage(), parseJunction(), parseLine(), parseNoConnect(), parsePAGE_INFO(), parseSchematicSymbol(), parseSchSheetInstances(), parseSchSymbolInstances(), parseSchText(), parseSheet(), ParseSymbol(), parseTITLE_BLOCK(), SCH_SCREEN::SetFileFormatVersionAtLoad(), 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_SYMBOL * SCH_SEXPR_PARSER::parseSchematicSymbol ( )
private

Definition at line 2214 of file sch_sexpr_parser.cpp.

2215 {
2216  wxCHECK_MSG( CurTok() == T_symbol, nullptr,
2217  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a symbol." ) );
2218 
2219  T token;
2220  wxString tmp;
2221  wxString libName;
2222  SCH_FIELD* field;
2223  std::unique_ptr<SCH_SYMBOL> symbol = std::make_unique<SCH_SYMBOL>();
2224  TRANSFORM transform;
2225  std::set<int> fieldIDsRead;
2226 
2227  // We'll reset this if we find a fields_autoplaced token
2228  symbol->ClearFieldsAutoplaced();
2229 
2231 
2232  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2233  {
2234  if( token != T_LEFT )
2235  Expecting( T_LEFT );
2236 
2237  token = NextTok();
2238 
2239  switch( token )
2240  {
2241  case T_lib_name:
2242  {
2243  LIB_ID libId;
2244 
2245  token = NextTok();
2246 
2247  if( !IsSymbol( token ) )
2248  {
2249  THROW_PARSE_ERROR( _( "Invalid symbol library name" ), CurSource(), CurLine(),
2250  CurLineNumber(), CurOffset() );
2251  }
2252 
2253  libName = FromUTF8();
2254  NeedRIGHT();
2255  break;
2256  }
2257 
2258  case T_lib_id:
2259  {
2260  token = NextTok();
2261 
2262  if( !IsSymbol( token ) && token != T_NUMBER )
2263  Expecting( "symbol|number" );
2264 
2265  LIB_ID libId;
2266 
2267  if( libId.Parse( FromUTF8() ) >= 0 )
2268  {
2269  THROW_PARSE_ERROR( _( "Invalid symbol library ID" ), CurSource(), CurLine(),
2270  CurLineNumber(), CurOffset() );
2271  }
2272 
2273  symbol->SetLibId( libId );
2274  NeedRIGHT();
2275  break;
2276  }
2277 
2278  case T_at:
2279  symbol->SetPosition( parseXY() );
2280 
2281  switch( static_cast<int>( parseDouble( "symbol orientation" ) ) )
2282  {
2283  case 0: transform = TRANSFORM(); break;
2284  case 90: transform = TRANSFORM( 0, -1, -1, 0 ); break;
2285  case 180: transform = TRANSFORM( -1, 0, 0, 1 ); break;
2286  case 270: transform = TRANSFORM( 0, 1, 1, 0 ); break;
2287  default: Expecting( "0, 90, 180, or 270" );
2288  }
2289 
2290  symbol->SetTransform( transform );
2291  NeedRIGHT();
2292  break;
2293 
2294  case T_mirror:
2295  token = NextTok();
2296 
2297  if( token == T_x )
2298  symbol->SetOrientation( SYM_MIRROR_X );
2299  else if( token == T_y )
2300  symbol->SetOrientation( SYM_MIRROR_Y );
2301  else
2302  Expecting( "x or y" );
2303 
2304  NeedRIGHT();
2305  break;
2306 
2307  case T_unit:
2308  symbol->SetUnit( parseInt( "symbol unit" ) );
2309  NeedRIGHT();
2310  break;
2311 
2312  case T_convert:
2313  symbol->SetConvert( parseInt( "symbol convert" ) );
2314  NeedRIGHT();
2315  break;
2316 
2317  case T_in_bom:
2318  symbol->SetIncludeInBom( parseBool() );
2319  NeedRIGHT();
2320  break;
2321 
2322  case T_on_board:
2323  symbol->SetIncludeOnBoard( parseBool() );
2324  NeedRIGHT();
2325  break;
2326 
2327  case T_fields_autoplaced:
2328  symbol->SetFieldsAutoplaced();
2329  NeedRIGHT();
2330  break;
2331 
2332  case T_uuid:
2333  NeedSYMBOL();
2334  const_cast<KIID&>( symbol->m_Uuid ) = KIID( FromUTF8() );
2335  NeedRIGHT();
2336  break;
2337 
2338  case T_property:
2339  // The field parent symbol must be set and its orientation must be set before
2340  // the field positions are set.
2341  field = parseSchField( symbol.get() );
2342 
2343  // It would appear that at some point we allowed duplicate ids to slip through
2344  // when writing files. The easiest (and most complete) solution is to disallow
2345  // multiple instances of the same id (for all files since the source of the error
2346  // *might* in fact be hand-edited files).
2347  //
2348  // While no longer used, -1 is still a valid id for user field. It gets converted
2349  // to the next unused number on save.
2350  if( fieldIDsRead.count( field->GetId() ) )
2351  field->SetId( -1 );
2352  else
2353  fieldIDsRead.insert( field->GetId() );
2354 
2355  // Set the default symbol reference prefix.
2356  if( field->GetId() == REFERENCE_FIELD )
2357  {
2358  wxString refDesignator = field->GetText();
2359 
2360  refDesignator.Replace( "~", " " );
2361 
2362  wxString prefix = refDesignator;
2363 
2364  while( prefix.Length() )
2365  {
2366  if( ( prefix.Last() < '0' || prefix.Last() > '9') && prefix.Last() != '?' )
2367  break;
2368 
2369  prefix.RemoveLast();
2370  }
2371 
2372  // Avoid a prefix containing trailing/leading spaces
2373  prefix.Trim( true );
2374  prefix.Trim( false );
2375 
2376  if( prefix.IsEmpty() )
2377  symbol->SetPrefix( wxString( "U" ) );
2378  else
2379  symbol->SetPrefix( prefix );
2380  }
2381 
2382  if( symbol->GetFieldById( field->GetId() ) )
2383  *symbol->GetFieldById( field->GetId() ) = *field;
2384  else
2385  symbol->AddField( *field );
2386 
2387  delete field;
2388  break;
2389 
2390  case T_pin:
2391  {
2392  // Read an alternate pin designation
2393  wxString number;
2394  KIID uuid;
2395  wxString alt;
2396 
2397  NeedSYMBOL();
2398  number = FromUTF8();
2399 
2400  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2401  {
2402  if( token != T_LEFT )
2403  Expecting( T_LEFT );
2404 
2405  token = NextTok();
2406 
2407  switch( token )
2408  {
2409  case T_alternate:
2410  NeedSYMBOL();
2411  alt = FromUTF8();
2412  NeedRIGHT();
2413  break;
2414 
2415  case T_uuid:
2416  NeedSYMBOL();
2417 
2418  // First version to write out pin uuids accidentally wrote out the symbol's
2419  // uuid for each pin, so ignore uuids coming from that version.
2420  if( m_requiredVersion >= 20210126 )
2421  uuid = KIID( FromUTF8() );
2422 
2423  NeedRIGHT();
2424  break;
2425 
2426  default:
2427  Expecting( "alternate or uuid" );
2428  }
2429  }
2430 
2431  symbol->GetRawPins().emplace_back( std::make_unique<SCH_PIN>( symbol.get(),
2432  number, alt ) );
2433 
2434  const_cast<KIID&>( symbol->GetRawPins().back()->m_Uuid ) = uuid;
2435  }
2436  break;
2437 
2438  default:
2439  Expecting( "lib_id, lib_name, at, mirror, uuid, property, pin, or instances" );
2440  }
2441  }
2442 
2443  if( !libName.IsEmpty() && ( symbol->GetLibId().Format().wx_str() != libName ) )
2444  symbol->SetSchSymbolLibraryName( libName );
2445 
2446  // Ensure edit/status flags are cleared after these initializations:
2447  symbol->ClearFlags();
2448 
2449  return symbol.release();
2450 }
Field Reference of part, i.e. "IC21".
int m_fieldId
The current field ID.
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:49
int GetId() const
Definition: sch_field.h:113
A logical library item identifier and consists of various portions much like a URI.
Definition: lib_id.h:51
Definition: kiid.h:44
for transforming drawing coordinates for a wxDC device context.
Definition: transform.h:45
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
#define _(s)
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
int Parse(const UTF8 &aId, bool aFix=false)
Parse LIB_ID with the information from aId.
Definition: lib_id.cpp:49
int m_requiredVersion
Set to the symbol library file version required.
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
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:80
virtual const wxString & GetText() const
Return the string associated with the text object.
Definition: eda_text.h:133

References _, SCH_FIELD::GetId(), EDA_TEXT::GetText(), m_fieldId, m_requiredVersion, MANDATORY_FIELDS, LIB_ID::Parse(), parseBool(), parseDouble(), parseInt(), parseSchField(), parseXY(), REFERENCE_FIELD, SCH_FIELD::SetId(), SYM_MIRROR_X, SYM_MIRROR_Y, and THROW_PARSE_ERROR.

Referenced by ParseSchematic().

◆ parseSchField()

SCH_FIELD * SCH_SEXPR_PARSER::parseSchField ( SCH_ITEM aParent)
private

Definition at line 1707 of file sch_sexpr_parser.cpp.

1708 {
1709  wxCHECK_MSG( CurTok() == T_property, nullptr,
1710  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1711  wxT( " as a property token." ) );
1712 
1713  T token = NextTok();
1714 
1715  if( !IsSymbol( token ) )
1716  {
1717  THROW_PARSE_ERROR( _( "Invalid property name" ), CurSource(), CurLine(), CurLineNumber(),
1718  CurOffset() );
1719  }
1720 
1721  wxString name = FromUTF8();
1722 
1723  if( name.IsEmpty() )
1724  {
1725  THROW_PARSE_ERROR( _( "Empty property name" ), CurSource(), CurLine(), CurLineNumber(),
1726  CurOffset() );
1727  }
1728 
1729  token = NextTok();
1730 
1731  if( !IsSymbol( token ) )
1732  {
1733  THROW_PARSE_ERROR( _( "Invalid property value" ), CurSource(), CurLine(), CurLineNumber(),
1734  CurOffset() );
1735  }
1736 
1737  // Empty property values are valid.
1738  wxString value = FromUTF8();
1739 
1740  std::unique_ptr<SCH_FIELD> field = std::make_unique<SCH_FIELD>( wxDefaultPosition, -1,
1741  aParent, name );
1742 
1743  field->SetText( value );
1744  field->SetVisible( true );
1745 
1746  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1747  {
1748  if( token != T_LEFT )
1749  Expecting( T_LEFT );
1750 
1751  token = NextTok();
1752 
1753  switch( token )
1754  {
1755  case T_id:
1756  field->SetId( parseInt( "field ID" ) );
1757  NeedRIGHT();
1758  break;
1759 
1760  case T_at:
1761  field->SetPosition( parseXY() );
1762  field->SetTextAngle( static_cast<int>( parseDouble( "text angle" ) * 10.0 ) );
1763  NeedRIGHT();
1764  break;
1765 
1766  case T_effects:
1767  parseEDA_TEXT( static_cast<EDA_TEXT*>( field.get() ), field->GetId() == VALUE_FIELD );
1768  break;
1769 
1770  default:
1771  Expecting( "at or effects" );
1772  }
1773  }
1774 
1775  return field.release();
1776 }
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax)
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
Field Value of part, i.e. "3.3K".
#define _(s)
const char * name
Definition: DXF_plotter.cpp:56
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

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

Referenced by parseSchematicSymbol(), parseSchText(), and parseSheet().

◆ parseSchSheetInstances()

void SCH_SEXPR_PARSER::parseSchSheetInstances ( SCH_SHEET aRootSheet,
SCH_SCREEN aScreen 
)
private

Definition at line 1866 of file sch_sexpr_parser.cpp.

1867 {
1868  wxCHECK_RET( CurTok() == T_sheet_instances,
1869  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1870  wxT( " as a instances token." ) );
1871  wxCHECK( aScreen, /* void */ );
1872 
1873  T token;
1874 
1875  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1876  {
1877  if( token != T_LEFT )
1878  Expecting( T_LEFT );
1879 
1880  token = NextTok();
1881 
1882  switch( token )
1883  {
1884  case T_path:
1885  {
1886  NeedSYMBOL();
1887 
1888  SCH_SHEET_INSTANCE instance;
1889 
1890  instance.m_Path = KIID_PATH( FromUTF8() );
1891 
1892  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1893  {
1894  if( token != T_LEFT )
1895  Expecting( T_LEFT );
1896 
1897  token = NextTok();
1898 
1899  std::vector<wxString> whitespaces = { wxT( "\r" ), wxT( "\n" ), wxT( "\t" ),
1900  wxT( " " ) };
1901 
1902  size_t numReplacements = 0;
1903 
1904  switch( token )
1905  {
1906  case T_page:
1907  NeedSYMBOL();
1908  instance.m_PageNumber = FromUTF8();
1909 
1910  // Whitespaces are not permitted
1911  for( wxString ch : whitespaces )
1912  numReplacements += instance.m_PageNumber.Replace( ch, wxEmptyString );
1913 
1914 
1915  // Empty page numbers are not permitted
1916  if( instance.m_PageNumber.IsEmpty() )
1917  {
1918  // Use hash character instead
1919  instance.m_PageNumber = wxT( "#" );
1920  numReplacements++;
1921  }
1922 
1923  // Set the file as modified so the user can be warned.
1924  if( numReplacements > 0 )
1925  aScreen->SetContentModified();
1926 
1927  NeedRIGHT();
1928  break;
1929 
1930  default:
1931  Expecting( "path or page" );
1932  }
1933  }
1934 
1935  aScreen->m_sheetInstances.emplace_back( instance );
1936  break;
1937  }
1938 
1939  default:
1940  Expecting( "path" );
1941  }
1942  }
1943 
1944  // We don't store the root sheet's KIID, so pick it up from any sheet instance paths so
1945  // that it doesn't change on every round-trip.
1946  for( const SCH_SHEET_INSTANCE& instance : aScreen->m_sheetInstances )
1947  {
1948  if( instance.m_Path.size() > 0 )
1949  {
1950  const_cast<KIID&>( aRootSheet->m_Uuid ) = instance.m_Path[0];
1951  break;
1952  }
1953  }
1954 }
std::vector< SCH_SHEET_INSTANCE > m_sheetInstances
Definition: sch_screen.h:536
const KIID m_Uuid
Definition: eda_item.h:475
void SetContentModified(bool aModified=true)
Definition: base_screen.h:59
A simple container for sheet instance information.

References SCH_SHEET_INSTANCE::m_PageNumber, SCH_SHEET_INSTANCE::m_Path, SCH_SCREEN::m_sheetInstances, EDA_ITEM::m_Uuid, and BASE_SCREEN::SetContentModified().

Referenced by ParseSchematic().

◆ parseSchSheetPin()

SCH_SHEET_PIN * SCH_SEXPR_PARSER::parseSchSheetPin ( SCH_SHEET aSheet)
private

Definition at line 1779 of file sch_sexpr_parser.cpp.

1780 {
1781  wxCHECK_MSG( aSheet != nullptr, nullptr, "" );
1782  wxCHECK_MSG( CurTok() == T_pin, nullptr,
1783  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1784  wxT( " as a sheet pin token." ) );
1785 
1786  T token = NextTok();
1787 
1788  if( !IsSymbol( token ) )
1789  {
1790  THROW_PARSE_ERROR( _( "Invalid sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
1791  CurOffset() );
1792  }
1793 
1794  wxString name = FromUTF8();
1795 
1796  if( name.IsEmpty() )
1797  {
1798  THROW_PARSE_ERROR( _( "Empty sheet pin name" ), CurSource(), CurLine(), CurLineNumber(),
1799  CurOffset() );
1800  }
1801 
1802  auto sheetPin = std::make_unique<SCH_SHEET_PIN>( aSheet, wxPoint( 0, 0 ), name );
1803 
1804  token = NextTok();
1805 
1806  switch( token )
1807  {
1808  case T_input: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_INPUT ); break;
1809  case T_output: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_OUTPUT ); break;
1810  case T_bidirectional: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_BIDI ); break;
1811  case T_tri_state: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_TRISTATE ); break;
1812  case T_passive: sheetPin->SetShape( PINSHEETLABEL_SHAPE::PS_UNSPECIFIED ); break;
1813  default:
1814  Expecting( "input, output, bidirectional, tri_state, or passive" );
1815  }
1816 
1817  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1818  {
1819  if( token != T_LEFT )
1820  Expecting( T_LEFT );
1821 
1822  token = NextTok();
1823 
1824  switch( token )
1825  {
1826  case T_at:
1827  {
1828  sheetPin->SetPosition( parseXY() );
1829 
1830  double angle = parseDouble( "sheet pin angle (side)" );
1831 
1832  if( angle == 0.0 )
1833  sheetPin->SetEdge( SHEET_SIDE::RIGHT );
1834  else if( angle == 90.0 )
1835  sheetPin->SetEdge( SHEET_SIDE::TOP );
1836  else if( angle == 180.0 )
1837  sheetPin->SetEdge( SHEET_SIDE::LEFT );
1838  else if( angle == 270.0 )
1839  sheetPin->SetEdge( SHEET_SIDE::BOTTOM );
1840  else
1841  Expecting( "0, 90, 180, or 270" );
1842 
1843  NeedRIGHT();
1844  break;
1845  }
1846 
1847  case T_effects:
1848  parseEDA_TEXT( static_cast<EDA_TEXT*>( sheetPin.get() ), true );
1849  break;
1850 
1851  case T_uuid:
1852  NeedSYMBOL();
1853  const_cast<KIID&>( sheetPin->m_Uuid ) = KIID( FromUTF8() );
1854  NeedRIGHT();
1855  break;
1856 
1857  default:
1858  Expecting( "at, uuid or effects" );
1859  }
1860  }
1861 
1862  return sheetPin.release();
1863 }
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax)
Definition: kiid.h:44
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
#define _(s)
const char * name
Definition: DXF_plotter.cpp:56
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...

References _, PNS::angle(), BOTTOM, LEFT, name, parseDouble(), parseEDA_TEXT(), parseXY(), PS_BIDI, PS_INPUT, PS_OUTPUT, PS_TRISTATE, PS_UNSPECIFIED, RIGHT, THROW_PARSE_ERROR, and TOP.

Referenced by parseSheet().

◆ parseSchSymbolInstances()

void SCH_SEXPR_PARSER::parseSchSymbolInstances ( SCH_SCREEN aScreen)
private

Definition at line 1957 of file sch_sexpr_parser.cpp.

1958 {
1959  wxCHECK_RET( CurTok() == T_symbol_instances,
1960  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1961  wxT( " as a instances token." ) );
1962  wxCHECK( aScreen, /* void */ );
1963 
1964  T token;
1965 
1966  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1967  {
1968  if( token != T_LEFT )
1969  Expecting( T_LEFT );
1970 
1971  token = NextTok();
1972 
1973  switch( token )
1974  {
1975  case T_path:
1976  {
1977  NeedSYMBOL();
1978 
1979  SYMBOL_INSTANCE_REFERENCE instance;
1980 
1981  instance.m_Path = KIID_PATH( FromUTF8() );
1982 
1983  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1984  {
1985  if( token != T_LEFT )
1986  Expecting( T_LEFT );
1987 
1988  token = NextTok();
1989 
1990  switch( token )
1991  {
1992  case T_reference:
1993  NeedSYMBOL();
1994  instance.m_Reference = FromUTF8();
1995  NeedRIGHT();
1996  break;
1997 
1998  case T_unit:
1999  instance.m_Unit = parseInt( "symbol unit" );
2000  NeedRIGHT();
2001  break;
2002 
2003  case T_value:
2004  NeedSYMBOL();
2005  instance.m_Value = FromUTF8();
2006  NeedRIGHT();
2007  break;
2008 
2009  case T_footprint:
2010  NeedSYMBOL();
2011  instance.m_Footprint = FromUTF8();
2012  NeedRIGHT();
2013  break;
2014 
2015  default:
2016  Expecting( "path, unit, value or footprint" );
2017  }
2018  }
2019 
2020  aScreen->m_symbolInstances.emplace_back( instance );
2021  break;
2022  }
2023 
2024  default:
2025  Expecting( "path" );
2026  }
2027  }
2028 }
std::vector< SYMBOL_INSTANCE_REFERENCE > m_symbolInstances
The list of symbol instances loaded from the schematic file.
Definition: sch_screen.h:535
A simple container for schematic symbol instance information.

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

Referenced by ParseSchematic().

◆ parseSchText()

SCH_TEXT * SCH_SEXPR_PARSER::parseSchText ( )
private

Definition at line 2841 of file sch_sexpr_parser.cpp.

2842 {
2843  T token;
2844  std::unique_ptr<SCH_TEXT> text;
2845 
2846  switch( CurTok() )
2847  {
2848  case T_text: text = std::make_unique<SCH_TEXT>(); break;
2849  case T_label: text = std::make_unique<SCH_LABEL>(); break;
2850  case T_global_label: text = std::make_unique<SCH_GLOBALLABEL>(); break;
2851  case T_hierarchical_label: text = std::make_unique<SCH_HIERLABEL>(); break;
2852  default:
2853  wxCHECK_MSG( false, nullptr, "Cannot parse " + GetTokenString( CurTok() ) + " as text." );
2854  }
2855 
2856  // We'll reset this if we find a fields_autoplaced token
2857  text->ClearFieldsAutoplaced();
2858 
2859  NeedSYMBOL();
2860 
2861  text->SetText( FromUTF8() );
2862 
2863  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2864  {
2865  if( token != T_LEFT )
2866  Expecting( T_LEFT );
2867 
2868  token = NextTok();
2869 
2870  switch( token )
2871  {
2872  case T_at:
2873  text->SetPosition( parseXY() );
2874 
2875  switch( static_cast<int>( parseDouble( "text angle" ) ) )
2876  {
2877  case 0: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::RIGHT ); break;
2878  case 90: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::UP ); break;
2879  case 180: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::LEFT ); break;
2880  case 270: text->SetLabelSpinStyle( LABEL_SPIN_STYLE::BOTTOM ); break;
2881  default:
2882  wxFAIL;
2883  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::RIGHT );
2884  break;
2885  }
2886 
2887  NeedRIGHT();
2888  break;
2889 
2890  case T_shape:
2891  if( text->Type() == SCH_TEXT_T || text->Type() == SCH_LABEL_T )
2892  Unexpected( T_shape );
2893 
2894  token = NextTok();
2895 
2896  switch( token )
2897  {
2898  case T_input: text->SetShape( PINSHEETLABEL_SHAPE::PS_INPUT ); break;
2899  case T_output: text->SetShape( PINSHEETLABEL_SHAPE::PS_OUTPUT ); break;
2900  case T_bidirectional: text->SetShape( PINSHEETLABEL_SHAPE::PS_BIDI ); break;
2901  case T_tri_state: text->SetShape( PINSHEETLABEL_SHAPE::PS_TRISTATE ); break;
2902  case T_passive: text->SetShape( PINSHEETLABEL_SHAPE::PS_UNSPECIFIED ); break;
2903  default:
2904  Expecting( "input, output, bidirectional, tri_state, or passive" );
2905  }
2906 
2907  NeedRIGHT();
2908  break;
2909 
2910  case T_fields_autoplaced:
2911  text->SetFieldsAutoplaced();
2912  NeedRIGHT();
2913  break;
2914 
2915  case T_effects:
2916  parseEDA_TEXT( static_cast<EDA_TEXT*>( text.get() ), true );
2917 
2918  // Spin style is defined differently for graphical text (#SCH_TEXT) objects.
2919  if( text->Type() == SCH_TEXT_T )
2920  {
2921  if( text->GetHorizJustify() == GR_TEXT_HJUSTIFY_RIGHT
2922  && text->GetTextAngle() == TEXT_ANGLE_VERT )
2923  {
2924  // The vertically aligned text angle is always 90 (labels use 270 for the
2925  // down direction) combined with the text justification flags.
2926  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::BOTTOM );
2927  }
2928  else if( text->GetHorizJustify() == GR_TEXT_HJUSTIFY_RIGHT
2929  && text->GetTextAngle() == TEXT_ANGLE_HORIZ )
2930  {
2931  // The horizontally aligned text angle is always 0 (labels use 180 for the
2932  // left direction) combined with the text justification flags.
2933  text->SetLabelSpinStyle( LABEL_SPIN_STYLE::LEFT );
2934  }
2935  }
2936 
2937  break;
2938 
2939  case T_iref: // legacy format; current is a T_property (aka SCH_FIELD)
2940  if( text->Type() == SCH_GLOBAL_LABEL_T )
2941  {
2942  SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( text.get() );
2943  SCH_FIELD* field = label->GetIntersheetRefs();
2944 
2945  field->SetTextPos( parseXY() );
2946  NeedRIGHT();
2947 
2948  field->SetVisible( true );
2949  }
2950  break;
2951 
2952  case T_uuid:
2953  NeedSYMBOL();
2954  const_cast<KIID&>( text->m_Uuid ) = KIID( FromUTF8() );
2955  NeedRIGHT();
2956  break;
2957 
2958  case T_property:
2959  if( text->Type() == SCH_GLOBAL_LABEL_T )
2960  {
2961  SCH_GLOBALLABEL* label = static_cast<SCH_GLOBALLABEL*>( text.get() );
2962  SCH_FIELD* field = parseSchField( label );
2963 
2964  field->SetLayer( LAYER_GLOBLABEL );
2965  label->SetIntersheetRefs( *field );
2966 
2967  delete field;
2968  }
2969  break;
2970 
2971  default:
2972  Expecting( "at, shape, iref, uuid or effects" );
2973  }
2974  }
2975 
2976  return text.release();
2977 }
#define TEXT_ANGLE_HORIZ
Frequent text rotations, used with {Set,Get}TextAngle(), in 0.1 degrees for now, hoping to migrate to...
Definition: eda_text.h:50
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:49
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax)
void SetTextPos(const wxPoint &aPoint)
Definition: eda_text.h:246
Definition: kiid.h:44
void SetIntersheetRefs(const SCH_FIELD &aField)
Definition: sch_text.h:414
SCH_FIELD * GetIntersheetRefs()
Definition: sch_text.h:413
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
#define TEXT_ANGLE_VERT
Definition: eda_text.h:51

References LABEL_SPIN_STYLE::BOTTOM, SCH_GLOBALLABEL::GetIntersheetRefs(), GR_TEXT_HJUSTIFY_RIGHT, LAYER_GLOBLABEL, LABEL_SPIN_STYLE::LEFT, parseDouble(), parseEDA_TEXT(), parseSchField(), parseXY(), PS_BIDI, PS_INPUT, PS_OUTPUT, PS_TRISTATE, PS_UNSPECIFIED, LABEL_SPIN_STYLE::RIGHT, SCH_GLOBAL_LABEL_T, SCH_LABEL_T, SCH_TEXT_T, SCH_GLOBALLABEL::SetIntersheetRefs(), EDA_TEXT::SetTextPos(), text, TEXT_ANGLE_HORIZ, TEXT_ANGLE_VERT, and LABEL_SPIN_STYLE::UP.

Referenced by ParseSchematic().

◆ parseSheet()

SCH_SHEET * SCH_SEXPR_PARSER::parseSheet ( )
private

Definition at line 2528 of file sch_sexpr_parser.cpp.

2529 {
2530  wxCHECK_MSG( CurTok() == T_sheet, nullptr,
2531  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a sheet." ) );
2532 
2533  T token;
2534  STROKE_PARAMS stroke;
2535  FILL_PARAMS fill;
2536  SCH_FIELD* field;
2537  std::vector<SCH_FIELD> fields;
2538  std::unique_ptr<SCH_SHEET> sheet = std::make_unique<SCH_SHEET>();
2539  std::set<int> fieldIDsRead;
2540 
2541  // We'll reset this if we find a fields_autoplaced token
2542  sheet->ClearFieldsAutoplaced();
2543 
2544  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
2545  {
2546  if( token != T_LEFT )
2547  Expecting( T_LEFT );
2548 
2549  token = NextTok();
2550 
2551  switch( token )
2552  {
2553  case T_at:
2554  sheet->SetPosition( parseXY() );
2555  NeedRIGHT();
2556  break;
2557 
2558  case T_size:
2559  {
2560  wxSize size;
2561  size.SetWidth( parseInternalUnits( "sheet width" ) );
2562  size.SetHeight( parseInternalUnits( "sheet height" ) );
2563  sheet->SetSize( size );
2564  NeedRIGHT();
2565  break;
2566  }
2567 
2568  case T_fields_autoplaced:
2569  sheet->SetFieldsAutoplaced();
2570  NeedRIGHT();
2571  break;
2572 
2573  case T_stroke:
2574  parseStroke( stroke );
2575  sheet->SetBorderWidth( stroke.GetWidth() );
2576  sheet->SetBorderColor( stroke.GetColor() );
2577  break;
2578 
2579  case T_fill:
2580  parseFill( fill );
2581  sheet->SetBackgroundColor( fill.m_Color );
2582  break;
2583 
2584  case T_uuid:
2585  NeedSYMBOL();
2586  const_cast<KIID&>( sheet->m_Uuid ) = KIID( FromUTF8() );
2587  NeedRIGHT();
2588  break;
2589 
2590  case T_property:
2591  field = parseSchField( sheet.get() );
2592 
2593  if( m_requiredVersion <= 20200310 )
2594  {
2595  // Earlier versions had the wrong ids (and names) saved for sheet fields.
2596  // Fortunately they only saved the sheetname and sheetfilepath (and always
2597  // in that order), so we can hack in a recovery.
2598  if( fields.empty() )
2599  field->SetId( SHEETNAME );
2600  else
2601  field->SetId( SHEETFILENAME );
2602  }
2603 
2604  // It would appear the problem persists past 20200310, but this time with the
2605  // earlier ids being re-used for later (user) fields. The easiest (and most
2606  // complete) solution is to disallow multiple instances of the same id (for all
2607  // files since the source of the error *might* in fact be hand-edited files).
2608  //
2609  // While no longer used, -1 is still a valid id for user field. It gets converted
2610  // to the next unused number on save.
2611  if( fieldIDsRead.count( field->GetId() ) )
2612  field->SetId( -1 );
2613  else
2614  fieldIDsRead.insert( field->GetId() );
2615 
2616  fields.emplace_back( *field );
2617  delete field;
2618  break;
2619 
2620  case T_pin:
2621  sheet->AddPin( parseSchSheetPin( sheet.get() ) );
2622  break;
2623 
2624  default:
2625  Expecting( "at, size, stroke, background, uuid, property, or pin" );
2626  }
2627  }
2628 
2629  sheet->SetFields( fields );
2630 
2631  return sheet.release();
2632 }
Instances are attached to a symbol or sheet and provide a place for the symbol's value,...
Definition: sch_field.h:49
SCH_SHEET_PIN * parseSchSheetPin(SCH_SHEET *aSheet)
int GetId() const
Definition: sch_field.h:113
Definition: kiid.h:44
Simple container to manage fill parameters.
int GetWidth() const
Definition: sch_item.h:163
COLOR4D GetColor() const
Definition: sch_item.h:169
int m_requiredVersion
Set to the symbol library file version required.
Simple container to manage line stroke parameters.
Definition: sch_item.h:151
SCH_FIELD * parseSchField(SCH_ITEM *aParent)
void parseFill(FILL_PARAMS &aFill)
void SetId(int aId)
Definition: sch_field.cpp:80
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 475 of file sch_sexpr_parser.cpp.

476 {
477  wxCHECK_RET( CurTok() == T_stroke,
478  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a stroke." ) );
479 
480  aStroke.SetWidth( Mils2iu( DEFAULT_LINE_WIDTH_MILS ) );
482  aStroke.SetColor( COLOR4D::UNSPECIFIED );
483 
484  T token;
485 
486  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
487  {
488  if( token != T_LEFT )
489  Expecting( T_LEFT );
490 
491  token = NextTok();
492 
493  switch( token )
494  {
495  case T_width:
496  aStroke.SetWidth( parseInternalUnits( "stroke width" ) );
497  NeedRIGHT();
498  break;
499 
500  case T_type:
501  {
502  token = NextTok();
503 
504  switch( token )
505  {
506  case T_dash: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DASH ); break;
507  case T_dot: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DOT ); break;
508  case T_dash_dot: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DASHDOT ); break;
509  case T_solid: aStroke.SetPlotStyle( PLOT_DASH_TYPE::SOLID ); break;
510  case T_default: aStroke.SetPlotStyle( PLOT_DASH_TYPE::DEFAULT ); break;
511  default:
512  Expecting( "solid, dash, dash_dot, dot or default" );
513  }
514 
515  NeedRIGHT();
516  break;
517  }
518 
519  case T_color:
520  {
521  COLOR4D color;
522 
523  color.r = parseInt( "red" ) / 255.0;
524  color.g = parseInt( "green" ) / 255.0;
525  color.b = parseInt( "blue" ) / 255.0;
526  color.a = Clamp( parseDouble( "alpha" ), 0.0, 1.0 );
527 
528  aStroke.SetColor( color );
529  NeedRIGHT();
530  break;
531  }
532 
533  default:
534  Expecting( "width, type, or color" );
535  }
536 
537  }
538 }
void SetWidth(int aWidth)
Definition: sch_item.h:164
#define DEFAULT_LINE_WIDTH_MILS
The default wire width in mils. (can be changed in preference menu)
int color
Definition: DXF_plotter.cpp:57
void SetPlotStyle(PLOT_DASH_TYPE aPlotStyle)
Definition: sch_item.h:167
const T & Clamp(const T &lower, const T &value, const T &upper)
Limit value within the range lower <= value <= upper.
Definition: util.h:52
void SetColor(const COLOR4D &aColor)
Definition: sch_item.h:170
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...
A color representation with 4 components: red, green, blue, alpha.
Definition: color4d.h:103

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

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

◆ ParseSymbol()

LIB_SYMBOL * SCH_SEXPR_PARSER::ParseSymbol ( LIB_SYMBOL_MAP aSymbolLibMap,
int  aFileVersion = SEXPR_SYMBOL_LIB_FILE_VERSION 
)

Definition at line 146 of file sch_sexpr_parser.cpp.

147 {
148  wxCHECK_MSG( CurTok() == T_symbol, nullptr,
149  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a symbol." ) );
150 
151  T token;
152  long tmp;
153  wxString name;
154  wxString error;
155  LIB_ITEM* item;
156  LIB_FIELD* field;
157  std::unique_ptr<LIB_SYMBOL> symbol = std::make_unique<LIB_SYMBOL>( wxEmptyString );
158  std::set<int> fieldIDsRead;
159 
160  m_requiredVersion = aFileVersion;
161  symbol->SetUnitCount( 1 );
162 
164 
165  token = NextTok();
166 
167  if( !IsSymbol( token ) )
168  {
169  THROW_PARSE_ERROR( _( "Invalid symbol name" ), CurSource(), CurLine(), CurLineNumber(),
170  CurOffset() );
171  }
172 
173  name = FromUTF8();
174 
175  LIB_ID id;
176 
177  if( id.Parse( name ) >= 0 )
178  {
179  THROW_PARSE_ERROR( _( "Invalid library identifier" ), CurSource(), CurLine(),
180  CurLineNumber(), CurOffset() );
181  }
182 
183  m_symbolName = id.GetLibItemName().wx_str();
184  symbol->SetName( m_symbolName );
185  symbol->SetLibId( id );
186 
187  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
188  {
189  if( token != T_LEFT )
190  Expecting( T_LEFT );
191 
192  token = NextTok();
193 
194  switch( token )
195  {
196  case T_power:
197  symbol->SetPower();
198  NeedRIGHT();
199  break;
200 
201  case T_pin_names:
202  parsePinNames( symbol );
203  break;
204 
205  case T_pin_numbers:
206  token = NextTok();
207 
208  if( token != T_hide )
209  Expecting( "hide" );
210 
211  symbol->SetShowPinNumbers( false );
212  NeedRIGHT();
213  break;
214 
215  case T_in_bom:
216  symbol->SetIncludeInBom( parseBool() );
217  NeedRIGHT();
218  break;
219 
220  case T_on_board:
221  symbol->SetIncludeOnBoard( parseBool() );
222  NeedRIGHT();
223  break;
224 
225  case T_property:
226  field = parseProperty( symbol );
227 
228  if( field )
229  {
230  // It would appear that at some point we allowed duplicate ids to slip through
231  // when writing files. The easiest (and most complete) solution is to disallow
232  // multiple instances of the same id (for all files since the source of the error
233  // *might* in fact be hand-edited files).
234  //
235  // While no longer used, -1 is still a valid id for user field. It gets converted
236  // to the next unused number on save.
237  if( fieldIDsRead.count( field->GetId() ) )
238  field->SetId( -1 );
239  else if( field )
240  fieldIDsRead.insert( field->GetId() );
241  }
242 
243  break;
244 
245  case T_extends:
246  {
247  token = NextTok();
248 
249  if( !IsSymbol( token ) )
250  {
251  THROW_PARSE_ERROR( _( "Invalid parent symbol name" ), CurSource(), CurLine(),
252  CurLineNumber(), CurOffset() );
253  }
254 
255  name = FromUTF8();
256  auto it = aSymbolLibMap.find( name );
257 
258  if( it == aSymbolLibMap.end() )
259  {
260  error.Printf( _( "No parent for extended symbol %s" ), name.c_str() );
261  THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
262  }
263 
264  symbol->SetParent( it->second );
265  NeedRIGHT();
266  break;
267  }
268 
269  case T_symbol:
270  {
271  token = NextTok();
272 
273  if( !IsSymbol( token ) )
274  {
275  THROW_PARSE_ERROR( _( "Invalid symbol unit name" ), CurSource(), CurLine(),
276  CurLineNumber(), CurOffset() );
277  }
278 
279  name = FromUTF8();
280 
281  if( !name.StartsWith( m_symbolName ) )
282  {
283  error.Printf( _( "Invalid symbol unit name prefix %s" ), name.c_str() );
284  THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
285  }
286 
287  name = name.Right( name.Length() - m_symbolName.Length() - 1 );
288 
289  wxStringTokenizer tokenizer( name, "_" );
290 
291  if( tokenizer.CountTokens() != 2 )
292  {
293  error.Printf( _( "Invalid symbol unit name suffix %s" ), name.c_str() );
294  THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
295  }
296 
297  if( !tokenizer.GetNextToken().ToLong( &tmp ) )
298  {
299  error.Printf( _( "Invalid symbol unit number %s" ), name.c_str() );
300  THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
301  }
302 
303  m_unit = static_cast<int>( tmp );
304 
305  if( !tokenizer.GetNextToken().ToLong( &tmp ) )
306  {
307  error.Printf( _( "Invalid symbol convert number %s" ), name.c_str() );
308  THROW_PARSE_ERROR( error, CurSource(), CurLine(), CurLineNumber(), CurOffset() );
309  }
310 
311  m_convert = static_cast<int>( tmp );
312 
313  if( m_convert > 1 )
314  symbol->SetConversion( true, false );
315 
316  if( m_unit > symbol->GetUnitCount() )
317  symbol->SetUnitCount( m_unit, false );
318 
319  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
320  {
321  if( token != T_LEFT )
322  Expecting( T_LEFT );
323 
324  token = NextTok();
325 
326  switch( token )
327  {
328  case T_arc:
329  case T_bezier:
330  case T_circle:
331  case T_pin:
332  case T_polyline:
333  case T_rectangle:
334  case T_text:
335  item = ParseDrawItem();
336 
337  wxCHECK_MSG( item, nullptr, "Invalid draw item pointer." );
338 
339  item->SetParent( symbol.get() );
340  symbol->AddDrawItem( item, false );
341  break;
342 
343  default:
344  Expecting( "arc, bezier, circle, pin, polyline, rectangle, or text" );
345  };
346  }
347 
348  m_unit = 1;
349  m_convert = 1;
350  break;
351  }
352 
353  case T_arc:
354  case T_bezier:
355  case T_circle:
356  case T_pin:
357  case T_polyline:
358  case T_rectangle:
359  case T_text:
360  item = ParseDrawItem();
361 
362  wxCHECK_MSG( item, nullptr, "Invalid draw item pointer." );
363 
364  item->SetParent( symbol.get() );
365  symbol->AddDrawItem( item, false );
366  break;
367 
368  default:
369  Expecting( "pin_names, pin_numbers, arc, bezier, circle, pin, polyline, "
370  "rectangle, or text" );
371  }
372  }
373 
374  symbol->GetDrawItems().sort();
375  m_symbolName.clear();
376 
377  return symbol.release();
378 }
int m_fieldId
The current field ID.
LIB_FIELD * parseProperty(std::unique_ptr< LIB_SYMBOL > &aSymbol)
Field object used in symbol libraries.
Definition: lib_field.h:59
int m_unit
The current unit being parsed.
int GetId() const
Definition: lib_field.h:115
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: eda_item.h:116
The base class for drawable items used by schematic library symbols.
Definition: lib_item.h:61
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
wxString m_symbolName
The current symbol name.
int m_convert
The current body style being parsed.
#define _(s)
The first 4 are mandatory, and must be instantiated in SCH_COMPONENT and LIB_PART constructors.
LIB_ITEM * ParseDrawItem()
int m_requiredVersion
Set to the symbol library file version required.
const char * name
Definition: DXF_plotter.cpp:56
void parsePinNames(std::unique_ptr< LIB_SYMBOL > &aSymbol)
void SetId(int aId)
Definition: lib_field.h:116

References _, LIB_FIELD::GetId(), m_convert, m_fieldId, m_requiredVersion, m_symbolName, m_unit, MANDATORY_FIELDS, name, parseBool(), ParseDrawItem(), parsePinNames(), parseProperty(), LIB_FIELD::SetId(), EDA_ITEM::SetParent(), and THROW_PARSE_ERROR.

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

◆ parseText()

LIB_TEXT * SCH_SEXPR_PARSER::parseText ( )
private

Definition at line 1501 of file sch_sexpr_parser.cpp.

1502 {
1503  wxCHECK_MSG( CurTok() == T_text, nullptr,
1504  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as a text token." ) );
1505 
1506  T token;
1507  wxString tmp;
1508  std::unique_ptr<LIB_TEXT> text = std::make_unique<LIB_TEXT>( nullptr );
1509 
1510  text->SetUnit( m_unit );
1511  text->SetConvert( m_convert );
1512  token = NextTok();
1513 
1514  if( !IsSymbol( token ) )
1515  {
1516  THROW_PARSE_ERROR( _( "Invalid text string" ), CurSource(), CurLine(), CurLineNumber(),
1517  CurOffset() );
1518  }
1519 
1520  text->SetText( FromUTF8() );
1521 
1522  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1523  {
1524  if( token != T_LEFT )
1525  Expecting( T_LEFT );
1526 
1527  token = NextTok();
1528 
1529  switch( token )
1530  {
1531  case T_at:
1532  text->SetPosition( parseXY() );
1533  text->SetTextAngle( parseDouble( "text angle" ) );
1534  NeedRIGHT();
1535  break;
1536 
1537  case T_effects:
1538  parseEDA_TEXT( static_cast<EDA_TEXT*>( text.get() ), true );
1539  break;
1540 
1541  default:
1542  Expecting( "at or effects" );
1543  }
1544  }
1545 
1546  return text.release();
1547 }
void parseEDA_TEXT(EDA_TEXT *aText, bool aConvertOverbarSyntax)
int m_unit
The current unit being parsed.
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
int m_convert
The current body style being parsed.
#define _(s)
double parseDouble()
Parse the current token as an ASCII numeric string with possible leading whitespace into a double pre...

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

Referenced by ParseDrawItem().

◆ parseTITLE_BLOCK()

void SCH_SEXPR_PARSER::parseTITLE_BLOCK ( TITLE_BLOCK aTitleBlock)
private

Definition at line 1602 of file sch_sexpr_parser.cpp.

1603 {
1604  wxCHECK_RET( CurTok() == T_title_block,
1605  wxT( "Cannot parse " ) + GetTokenString( CurTok() ) +
1606  wxT( " as TITLE_BLOCK." ) );
1607 
1608  T token;
1609 
1610  for( token = NextTok(); token != T_RIGHT; token = NextTok() )
1611  {
1612  if( token != T_LEFT )
1613  Expecting( T_LEFT );
1614 
1615  token = NextTok();
1616 
1617  switch( token )
1618  {
1619  case T_title:
1620  NextTok();
1621  aTitleBlock.SetTitle( FromUTF8() );
1622  break;
1623 
1624  case T_date:
1625  NextTok();
1626  aTitleBlock.SetDate( FromUTF8() );
1627  break;
1628 
1629  case T_rev:
1630  NextTok();
1631  aTitleBlock.SetRevision( FromUTF8() );
1632  break;
1633 
1634  case T_company:
1635  NextTok();
1636  aTitleBlock.SetCompany( FromUTF8() );
1637  break;
1638 
1639  case T_comment:
1640  {
1641  int commentNumber = parseInt( "comment" );
1642 
1643  switch( commentNumber )
1644  {
1645  case 1:
1646  NextTok();
1647  aTitleBlock.SetComment( 0, FromUTF8() );
1648  break;
1649 
1650  case 2:
1651  NextTok();
1652  aTitleBlock.SetComment( 1, FromUTF8() );
1653  break;
1654 
1655  case 3:
1656  NextTok();
1657  aTitleBlock.SetComment( 2, FromUTF8() );
1658  break;
1659 
1660  case 4:
1661  NextTok();
1662  aTitleBlock.SetComment( 3, FromUTF8() );
1663  break;
1664 
1665  case 5:
1666  NextTok();
1667  aTitleBlock.SetComment( 4, FromUTF8() );
1668  break;
1669 
1670  case 6:
1671  NextTok();
1672  aTitleBlock.SetComment( 5, FromUTF8() );
1673  break;
1674 
1675  case 7:
1676  NextTok();
1677  aTitleBlock.SetComment( 6, FromUTF8() );
1678  break;
1679 
1680  case 8:
1681  NextTok();
1682  aTitleBlock.SetComment( 7, FromUTF8() );
1683  break;
1684 
1685  case 9:
1686  NextTok();
1687  aTitleBlock.SetComment( 8, FromUTF8() );
1688  break;
1689 
1690  default:
1691  THROW_PARSE_ERROR( _( "Invalid title block comment number" ), CurSource(),
1692  CurLine(), CurLineNumber(), CurOffset() );
1693  }
1694 
1695  break;
1696  }
1697 
1698  default:
1699  Expecting( "title, date, rev, company, or comment" );
1700  }
1701 
1702  NeedRIGHT();
1703  }
1704 }
void SetRevision(const wxString &aRevision)
Definition: title_block.h:81
void SetDate(const wxString &aDate)
Set the date field, and defaults to the current time and date.
Definition: title_block.h:71
#define THROW_PARSE_ERROR(aProblem, aSource, aInputLine, aLineNumber, aByteIndex)
Definition: ki_exception.h:164
void SetComment(int aIdx, const wxString &aComment)
Definition: title_block.h:101
void SetCompany(const wxString &aCompany)
Definition: title_block.h:91
#define _(s)
void SetTitle(const wxString &aTitle)
Definition: title_block.h:58

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()

wxPoint SCH_SEXPR_PARSER::parseXY ( )
inlineprivate

Definition at line 142 of file sch_sexpr_parser.h.

143  {
144  wxPoint xy;
145 
146  xy.x = parseInternalUnits( "X coordinate" );
147  xy.y = parseInternalUnits( "Y coordinate" );
148 
149  return xy;
150  }

References parseInternalUnits().

Referenced by parseArc(), parseBezier(), parseBusEntry(), parseCircle(), parseImage(), parseJunction(), parseLine(), parseNoConnect(), parsePin(), parsePolyLine(), parseProperty(), parseRectangle(), parseSchematicSymbol(), parseSchField(), parseSchSheetPin(), parseSchText(), parseSheet(), and parseText().

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_lastProgressLine

unsigned SCH_SEXPR_PARSER::m_lastProgressLine
private

Definition at line 89 of file sch_sexpr_parser.h.

Referenced by checkpoint().

◆ m_lineCount

unsigned SCH_SEXPR_PARSER::m_lineCount
private

Definition at line 90 of file sch_sexpr_parser.h.

Referenced by checkpoint().

◆ m_lineReader

const LINE_READER* SCH_SEXPR_PARSER::m_lineReader
private

Definition at line 88 of file sch_sexpr_parser.h.

Referenced by checkpoint().

◆ m_progressReporter

PROGRESS_REPORTER* SCH_SEXPR_PARSER::m_progressReporter
private

Definition at line 87 of file sch_sexpr_parser.h.

Referenced by checkpoint().

◆ 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 parseBusAlias(), parseEDA_TEXT(), parseHeader(), ParseLib(), parsePAGE_INFO(), parsePin(), ParseSchematic(), parseSchematicSymbol(), 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: