Eeschema: fix library symbol pin definition parsing bug.

Pin names are unquoted strings that can contain non-ascii characters
which breaks the parser.  Converting the line to uft-8 before breaking
the string into tokens resolves the issue.

(cherry picked from commit 742961119d)
This commit is contained in:
Wayne Stambaugh 2018-12-06 11:47:20 -05:00
parent 385eb49cb2
commit 9f1b6680a2
1 changed files with 123 additions and 104 deletions

View File

@ -3242,89 +3242,129 @@ LIB_PIN* SCH_LEGACY_PLUGIN_CACHE::loadPin( std::unique_ptr< LIB_PART >& aPart,
std::unique_ptr< LIB_PIN > pin( new LIB_PIN( aPart.get() ) );
wxString name, number;
size_t pos = 2; // "X" plus ' ' space character.
wxString tmp;
wxString utf8Line = wxString::FromUTF8( line );
wxStringTokenizer tokens( utf8Line, " \r\n\t" );
parseUnquotedString( name, aReader, line, &line );
parseUnquotedString( number, aReader, line, &line );
if( tokens.CountTokens() < 11 )
SCH_PARSE_ERROR( "invalid pin definition", aReader, line );
// Unlike most of the other LIB_ITEMs, the SetXXX() routines on LIB_PINs are at the UI
// level, performing additional pin checking, multi-pin editing, and setting the modified
// flag. So we must set the member fields directly.
pin->m_name = tokens.GetNextToken();
pos += pin->m_name.size() + 1;
pin->m_number = tokens.GetNextToken();
pos += pin->m_number.size() + 1;
pin->m_name = name;
pin->m_number = number;
long num;
wxPoint position;
wxPoint pos;
tmp = tokens.GetNextToken();
pos.x = parseInt( aReader, line, &line );
pos.y = parseInt( aReader, line, &line );
pin->m_position = pos;
pin->m_length = parseInt( aReader, line, &line );
pin->m_orientation = parseChar( aReader, line, &line );
pin->m_numTextSize = parseInt( aReader, line, &line );
pin->m_nameTextSize = parseInt( aReader, line, &line );
pin->m_Unit = parseInt( aReader, line, &line );
pin->m_Convert = parseInt( aReader, line, &line );
if( !tmp.ToLong( &num ) )
THROW_PARSE_ERROR( "invalid pin X coordinate", aReader.GetSource(), aReader.Line(),
aReader.LineNumber(), pos );
char type = parseChar( aReader, line, &line );
pos += tmp.size() + 1;
position.x = (int) num;
tmp = tokens.GetNextToken();
if( !tmp.ToLong( &num ) )
THROW_PARSE_ERROR( "invalid pin Y coordinate", aReader.GetSource(), aReader.Line(),
aReader.LineNumber(), pos );
pos += tmp.size() + 1;
position.y = (int) num;
pin->m_position = position;
tmp = tokens.GetNextToken();
if( !tmp.ToLong( &num ) )
THROW_PARSE_ERROR( "invalid pin length", aReader.GetSource(), aReader.Line(),
aReader.LineNumber(), pos );
pos += tmp.size() + 1;
pin->m_length = (int) num;
tmp = tokens.GetNextToken();
if( tmp.size() > 1 )
THROW_PARSE_ERROR( "invalid pin orientation", aReader.GetSource(), aReader.Line(),
aReader.LineNumber(), pos );
pos += tmp.size() + 1;
pin->m_orientation = tmp[0];
tmp = tokens.GetNextToken();
if( !tmp.ToLong( &num ) )
THROW_PARSE_ERROR( "invalid pin number text size", aReader.GetSource(), aReader.Line(),
aReader.LineNumber(), pos );
pos += tmp.size() + 1;
pin->m_numTextSize = (int) num;
tmp = tokens.GetNextToken();
if( !tmp.ToLong( &num ) )
THROW_PARSE_ERROR( "invalid pin name text size", aReader.GetSource(), aReader.Line(),
aReader.LineNumber(), pos );
pos += tmp.size() + 1;
pin->m_nameTextSize = (int) num;
tmp = tokens.GetNextToken();
if( !tmp.ToLong( &num ) )
THROW_PARSE_ERROR( "invalid pin unit", aReader.GetSource(), aReader.Line(),
aReader.LineNumber(), pos );
pos += tmp.size() + 1;
pin->m_Unit = (int) num;
tmp = tokens.GetNextToken();
if( !tmp.ToLong( &num ) )
THROW_PARSE_ERROR( "invalid pin alternate body type", aReader.GetSource(), aReader.Line(),
aReader.LineNumber(), pos );
pos += tmp.size() + 1;
pin->m_Convert = (int) num;
tmp = tokens.GetNextToken();
if( tmp.size() != 1 )
THROW_PARSE_ERROR( "invalid pin type", aReader.GetSource(), aReader.Line(),
aReader.LineNumber(), pos );
pos += tmp.size() + 1;
char type = tmp[0];
wxString attributes;
// Optional
parseUnquotedString( attributes, aReader, line, &line, true );
switch( type )
{
case 'I':
pin->m_type = PIN_INPUT;
break;
case 'O':
pin->m_type = PIN_OUTPUT;
break;
case 'B':
pin->m_type = PIN_BIDI;
break;
case 'T':
pin->m_type = PIN_TRISTATE;
break;
case 'P':
pin->m_type = PIN_PASSIVE;
break;
case 'U':
pin->m_type = PIN_UNSPECIFIED;
break;
case 'W':
pin->m_type = PIN_POWER_IN;
break;
case 'w':
pin->m_type = PIN_POWER_OUT;
break;
case 'C':
pin->m_type = PIN_OPENCOLLECTOR;
break;
case 'E':
pin->m_type = PIN_OPENEMITTER;
break;
case 'N':
pin->m_type = PIN_NC;
break;
default:
SCH_PARSE_ERROR( "unknown pin type", aReader, line );
case 'I': pin->m_type = PIN_INPUT; break;
case 'O': pin->m_type = PIN_OUTPUT; break;
case 'B': pin->m_type = PIN_BIDI; break;
case 'T': pin->m_type = PIN_TRISTATE; break;
case 'P': pin->m_type = PIN_PASSIVE; break;
case 'U': pin->m_type = PIN_UNSPECIFIED; break;
case 'W': pin->m_type = PIN_POWER_IN; break;
case 'w': pin->m_type = PIN_POWER_OUT; break;
case 'C': pin->m_type = PIN_OPENCOLLECTOR; break;
case 'E': pin->m_type = PIN_OPENEMITTER; break;
case 'N': pin->m_type = PIN_NC; break;
default: THROW_PARSE_ERROR( "unknown pin type", aReader.GetSource(),
aReader.Line(), aReader.LineNumber(), pos );
}
if( !attributes.IsEmpty() ) /* Special Symbol defined */
// Optional
if( tokens.HasMoreTokens() ) /* Special Symbol defined */
{
tmp = tokens.GetNextToken();
enum
{
INVERTED = 1 << 0,
@ -3337,44 +3377,23 @@ LIB_PIN* SCH_LEGACY_PLUGIN_CACHE::loadPin( std::unique_ptr< LIB_PART >& aPart,
int flags = 0;
for( int j = attributes.size(); j > 0; )
for( int j = tmp.size(); j > 0; )
{
switch( attributes[--j].GetValue() )
switch( tmp[--j].GetValue() )
{
case '~':
break;
case 'N':
pin->m_attributes |= PIN_INVISIBLE;
break;
case 'I':
flags |= INVERTED;
break;
case 'C':
flags |= CLOCK;
break;
case 'L':
flags |= LOWLEVEL_IN;
break;
case 'V':
flags |= LOWLEVEL_OUT;
break;
case 'F':
flags |= FALLING_EDGE;
break;
case 'X':
flags |= NONLOGIC;
break;
default:
SCH_PARSE_ERROR( "unknown pin attribute", aReader, line );
case '~': break;
case 'N': pin->m_attributes |= PIN_INVISIBLE; break;
case 'I': flags |= INVERTED; break;
case 'C': flags |= CLOCK; break;
case 'L': flags |= LOWLEVEL_IN; break;
case 'V': flags |= LOWLEVEL_OUT; break;
case 'F': flags |= FALLING_EDGE; break;
case 'X': flags |= NONLOGIC; break;
default: THROW_PARSE_ERROR( "invalid pin attribut", aReader.GetSource(),
aReader.Line(), aReader.LineNumber(), pos );
}
pos += 1;
}
switch( flags )