Gerbview: fix a subtle issue when reading parameter values in Gerber files.
In Gerber files the char 'X' is used as separator. But when reading parameter values, the sequence "0xnnn" is a number in hexadecimal format, and the 'X' char is not seen as separator by usual strtod or strtol C functions. This is now fixed.
This commit is contained in:
parent
675eb37163
commit
ba517db96c
|
@ -75,6 +75,7 @@ double AM_PARAM::GetValue( const D_CODE* aDcode ) const
|
||||||
for( unsigned ii = 0; ii < m_paramStack.size(); ii++ )
|
for( unsigned ii = 0; ii < m_paramStack.size(); ii++ )
|
||||||
{
|
{
|
||||||
AM_PARAM_ITEM item = m_paramStack[ii];
|
AM_PARAM_ITEM item = m_paramStack[ii];
|
||||||
|
|
||||||
switch( item.GetType() )
|
switch( item.GetType() )
|
||||||
{
|
{
|
||||||
case ADD:
|
case ADD:
|
||||||
|
@ -89,7 +90,9 @@ double AM_PARAM::GetValue( const D_CODE* aDcode ) const
|
||||||
if( aDcode ) // should be always true here
|
if( aDcode ) // should be always true here
|
||||||
{
|
{
|
||||||
if( item.GetIndex() <= aDcode->GetParamCount() )
|
if( item.GetIndex() <= aDcode->GetParamCount() )
|
||||||
|
{
|
||||||
curr_value = aDcode->GetParam( item.GetIndex() );
|
curr_value = aDcode->GetParam( item.GetIndex() );
|
||||||
|
}
|
||||||
else // Get parameter from local param definition
|
else // Get parameter from local param definition
|
||||||
{
|
{
|
||||||
const APERTURE_MACRO * am_parent = aDcode->GetMacro();
|
const APERTURE_MACRO * am_parent = aDcode->GetMacro();
|
||||||
|
@ -104,6 +107,7 @@ double AM_PARAM::GetValue( const D_CODE* aDcode ) const
|
||||||
case PUSHVALUE: // a value is on the stack:
|
case PUSHVALUE: // a value is on the stack:
|
||||||
if( item.GetType() == PUSHVALUE )
|
if( item.GetType() == PUSHVALUE )
|
||||||
curr_value = item.GetValue();
|
curr_value = item.GetValue();
|
||||||
|
|
||||||
switch( state )
|
switch( state )
|
||||||
{
|
{
|
||||||
case POPVALUE:
|
case POPVALUE:
|
||||||
|
@ -137,6 +141,7 @@ double AM_PARAM::GetValue( const D_CODE* aDcode ) const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return paramvalue;
|
return paramvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -162,6 +162,7 @@ public:
|
||||||
m_dvalue = aValue;
|
m_dvalue = aValue;
|
||||||
m_ivalue = 0;
|
m_ivalue = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
AM_PARAM_ITEM( parm_item_type aType, int aValue )
|
AM_PARAM_ITEM( parm_item_type aType, int aValue )
|
||||||
{
|
{
|
||||||
m_type = aType;
|
m_type = aType;
|
||||||
|
@ -173,18 +174,22 @@ public:
|
||||||
{
|
{
|
||||||
m_dvalue = aValue;
|
m_dvalue = aValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
double GetValue( ) const
|
double GetValue( ) const
|
||||||
{
|
{
|
||||||
return m_dvalue;
|
return m_dvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
parm_item_type GetType() const
|
parm_item_type GetType() const
|
||||||
{
|
{
|
||||||
return m_type;
|
return m_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned GetIndex() const
|
unsigned GetIndex() const
|
||||||
{
|
{
|
||||||
return (unsigned) m_ivalue;
|
return (unsigned) m_ivalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsOperator() const
|
bool IsOperator() const
|
||||||
{
|
{
|
||||||
return m_type == ADD || m_type == SUB || m_type == MUL || m_type == DIV;
|
return m_type == ADD || m_type == SUB || m_type == MUL || m_type == DIV;
|
||||||
|
@ -193,6 +198,7 @@ public:
|
||||||
{
|
{
|
||||||
return m_type == PUSHVALUE || m_type == PUSHPARM;
|
return m_type == PUSHVALUE || m_type == PUSHPARM;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsDefered() const
|
bool IsDefered() const
|
||||||
{
|
{
|
||||||
return m_type == PUSHPARM;
|
return m_type == PUSHPARM;
|
||||||
|
|
|
@ -143,6 +143,7 @@ void AM_PRIMITIVE::DrawBasicShape( GERBER_DRAW_ITEM* aParent,
|
||||||
|
|
||||||
// shape rotation:
|
// shape rotation:
|
||||||
rotation = params[6].GetValue( tool ) * 10.0;
|
rotation = params[6].GetValue( tool ) * 10.0;
|
||||||
|
|
||||||
if( rotation != 0)
|
if( rotation != 0)
|
||||||
{
|
{
|
||||||
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
|
for( unsigned ii = 0; ii < polybuffer.size(); ii++ )
|
||||||
|
@ -454,7 +455,7 @@ void AM_PRIMITIVE::ConvertShapeToPolygon( GERBER_DRAW_ITEM* aParent,
|
||||||
aBuffer[ii] += start;
|
aBuffer[ii] += start;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AMP_LINE_CENTER:
|
case AMP_LINE_CENTER:
|
||||||
{
|
{
|
||||||
|
@ -793,6 +794,7 @@ double APERTURE_MACRO::GetLocalParam( const D_CODE* aDcode, unsigned aParamId )
|
||||||
{
|
{
|
||||||
// find parameter descr.
|
// find parameter descr.
|
||||||
const AM_PARAM * param = NULL;
|
const AM_PARAM * param = NULL;
|
||||||
|
|
||||||
for( unsigned ii = 0; ii < m_localparamStack.size(); ii ++ )
|
for( unsigned ii = 0; ii < m_localparamStack.size(); ii ++ )
|
||||||
{
|
{
|
||||||
if( m_localparamStack[ii].GetIndex() == aParamId )
|
if( m_localparamStack[ii].GetIndex() == aParamId )
|
||||||
|
@ -801,9 +803,12 @@ double APERTURE_MACRO::GetLocalParam( const D_CODE* aDcode, unsigned aParamId )
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( param == NULL ) // not found
|
if ( param == NULL ) // not found
|
||||||
return 0.0;
|
return 0.0;
|
||||||
|
|
||||||
// Evaluate parameter
|
// Evaluate parameter
|
||||||
double value = param->GetValue( aDcode );
|
double value = param->GetValue( aDcode );
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ G04 Handcoded by Stefan Petersen *
|
||||||
%OFA0.0000B0.0000*%
|
%OFA0.0000B0.0000*%
|
||||||
G90*
|
G90*
|
||||||
%AMCIRCLE*
|
%AMCIRCLE*
|
||||||
|
0 this is a comment*
|
||||||
1,1,$1,0,0*
|
1,1,$1,0,0*
|
||||||
%
|
%
|
||||||
%AMVECTOR*
|
%AMVECTOR*
|
||||||
|
|
|
@ -173,6 +173,7 @@ bool GERBER_FILE_IMAGE::LoadGerberFile( const wxString& aFullFileName )
|
||||||
case 'I':
|
case 'I':
|
||||||
case 'J': /* Auxiliary Move command */
|
case 'J': /* Auxiliary Move command */
|
||||||
m_IJPos = ReadIJCoord( text );
|
m_IJPos = ReadIJCoord( text );
|
||||||
|
|
||||||
if( *text == '*' ) // command like X35142Y15945J504*
|
if( *text == '*' ) // command like X35142Y15945J504*
|
||||||
{
|
{
|
||||||
Execute_DCODE_Command( text,
|
Execute_DCODE_Command( text,
|
||||||
|
|
|
@ -267,7 +267,18 @@ wxPoint GERBER_FILE_IMAGE::ReadIJCoord( char*& Text )
|
||||||
*/
|
*/
|
||||||
int ReadInt( char*& text, bool aSkipSeparator = true )
|
int ReadInt( char*& text, bool aSkipSeparator = true )
|
||||||
{
|
{
|
||||||
int ret = (int) strtol( text, &text, 10 );
|
int ret;
|
||||||
|
|
||||||
|
// For strtol, a string starting by 0X or 0x is a valid number in hexadecimal or octal.
|
||||||
|
// However, 'X' is a separator in Gerber strings with numbers.
|
||||||
|
// We need to detect that
|
||||||
|
if( strnicmp( text, "0X", 2 ) == 0 )
|
||||||
|
{
|
||||||
|
text++;
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = (int) strtol( text, &text, 10 );
|
||||||
|
|
||||||
if( *text == ',' || isspace( *text ) )
|
if( *text == ',' || isspace( *text ) )
|
||||||
{
|
{
|
||||||
|
@ -290,7 +301,18 @@ int ReadInt( char*& text, bool aSkipSeparator = true )
|
||||||
*/
|
*/
|
||||||
double ReadDouble( char*& text, bool aSkipSeparator = true )
|
double ReadDouble( char*& text, bool aSkipSeparator = true )
|
||||||
{
|
{
|
||||||
double ret = strtod( text, &text );
|
double ret;
|
||||||
|
|
||||||
|
// For strtod, a string starting by 0X or 0x is a valid number in hexadecimal or octal.
|
||||||
|
// However, 'X' is a separator in Gerber strings with numbers.
|
||||||
|
// We need to detect that
|
||||||
|
if( strnicmp( text, "0X", 2 ) == 0 )
|
||||||
|
{
|
||||||
|
text++;
|
||||||
|
ret = 0.0;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
ret = strtod( text, &text );
|
||||||
|
|
||||||
if( *text == ',' || isspace( *text ) )
|
if( *text == ',' || isspace( *text ) )
|
||||||
{
|
{
|
||||||
|
|
|
@ -733,7 +733,6 @@ bool GERBER_FILE_IMAGE::ExecuteRS274XCommand( int command, char* buff, char*& te
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AP_DEFINITION:
|
case AP_DEFINITION:
|
||||||
|
|
||||||
/* input example: %ADD30R,0.081800X0.101500*%
|
/* input example: %ADD30R,0.081800X0.101500*%
|
||||||
* Aperture definition has 4 options: C, R, O, P
|
* Aperture definition has 4 options: C, R, O, P
|
||||||
* (Circle, Rect, Oval, regular Polygon)
|
* (Circle, Rect, Oval, regular Polygon)
|
||||||
|
@ -898,18 +897,24 @@ bool GERBER_FILE_IMAGE::ExecuteRS274XCommand( int command, char* buff, char*& te
|
||||||
if( *text == ',' )
|
if( *text == ',' )
|
||||||
{ // Read aperture macro parameters and store them
|
{ // Read aperture macro parameters and store them
|
||||||
text++; // text points the first parameter
|
text++; // text points the first parameter
|
||||||
|
|
||||||
while( *text && *text != '*' )
|
while( *text && *text != '*' )
|
||||||
{
|
{
|
||||||
double param = ReadDouble( text );
|
double param = ReadDouble( text );
|
||||||
dcode->AppendParam( param );
|
dcode->AppendParam( param );
|
||||||
while( isspace( *text ) ) text++;
|
|
||||||
if( *text == 'X' )
|
while( isspace( *text ) )
|
||||||
++text;
|
text++;
|
||||||
|
|
||||||
|
// Skip 'X' separator:
|
||||||
|
if( *text == 'X' || *text == 'x' )
|
||||||
|
text++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// lookup the aperture macro here.
|
// lookup the aperture macro here.
|
||||||
APERTURE_MACRO* pam = FindApertureMacro( am_lookup );
|
APERTURE_MACRO* pam = FindApertureMacro( am_lookup );
|
||||||
|
|
||||||
if( !pam )
|
if( !pam )
|
||||||
{
|
{
|
||||||
msg.Printf( wxT( "RS274X: aperture macro %s not found\n" ),
|
msg.Printf( wxT( "RS274X: aperture macro %s not found\n" ),
|
||||||
|
@ -922,6 +927,7 @@ bool GERBER_FILE_IMAGE::ExecuteRS274XCommand( int command, char* buff, char*& te
|
||||||
dcode->m_Shape = APT_MACRO;
|
dcode->m_Shape = APT_MACRO;
|
||||||
dcode->SetMacro( pam );
|
dcode->SetMacro( pam );
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1024,7 +1030,8 @@ bool GERBER_FILE_IMAGE::ReadApertureMacro( char *buff,
|
||||||
if( *text == '*' )
|
if( *text == '*' )
|
||||||
++text;
|
++text;
|
||||||
|
|
||||||
text = GetNextLine( buff, text, gerber_file ); // Get next line
|
text = GetNextLine( buff, text, gerber_file );
|
||||||
|
|
||||||
if( text == NULL ) // End of File
|
if( text == NULL ) // End of File
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
@ -1034,6 +1041,7 @@ bool GERBER_FILE_IMAGE::ReadApertureMacro( char *buff,
|
||||||
// last line is % or *% sometime found.
|
// last line is % or *% sometime found.
|
||||||
if( *text == '*' )
|
if( *text == '*' )
|
||||||
++text;
|
++text;
|
||||||
|
|
||||||
if( *text == '%' )
|
if( *text == '%' )
|
||||||
break; // exit with text still pointing at %
|
break; // exit with text still pointing at %
|
||||||
|
|
||||||
|
@ -1063,12 +1071,15 @@ bool GERBER_FILE_IMAGE::ReadApertureMacro( char *buff,
|
||||||
else
|
else
|
||||||
primitive_type = ReadInt( text );
|
primitive_type = ReadInt( text );
|
||||||
|
|
||||||
|
bool is_comment = false;
|
||||||
|
|
||||||
switch( primitive_type )
|
switch( primitive_type )
|
||||||
{
|
{
|
||||||
case AMP_COMMENT: // lines starting by 0 are a comment
|
case AMP_COMMENT: // lines starting by 0 are a comment
|
||||||
paramCount = 0;
|
paramCount = 0;
|
||||||
|
is_comment = true;
|
||||||
// Skip comment
|
// Skip comment
|
||||||
while( *text && (*text != '*') )
|
while( *text && ( *text != '*' ) )
|
||||||
text++;
|
text++;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1114,6 +1125,9 @@ bool GERBER_FILE_IMAGE::ReadApertureMacro( char *buff,
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if( is_comment )
|
||||||
|
continue;
|
||||||
|
|
||||||
AM_PRIMITIVE prim( m_GerbMetric );
|
AM_PRIMITIVE prim( m_GerbMetric );
|
||||||
prim.primitive_id = (AM_PRIMITIVE_ID) primitive_type;
|
prim.primitive_id = (AM_PRIMITIVE_ID) primitive_type;
|
||||||
int ii;
|
int ii;
|
||||||
|
|
Loading…
Reference in New Issue