This patch adds a mechanism to suppress ERC errors and warnings that are caused by pins incompatibilities. It works by loading a file with ERC exceptions each time an ERC is performed and then looking for an entry before issuing a warning or error. The file has the same path and name as the .sch file, but ends in .erx (Electric Rule eXceptions). Each line contains the following four whitespace-separated fields: - component reference of the first component - pin number of the first component - component reference of the second component - pin number of the second component # is used as a comment character. Note that the file is reloaded each time ERC is invoked, so one can edit it in parallel to running eeschema. Known bug: ERC dialog window needs reformatting for displaying the exception count. The patch needs to be applied on top of the TestOthersItems streamlining patch. - Werner Updated to rev 1923 - Nathael --- Index: kicad/eeschema/erc.cpp =================================================================== --- kicad.orig/eeschema/erc.cpp 2010-04-28 05:40:38.000000000 -0300 +++ kicad/eeschema/erc.cpp 2010-04-28 05:49:35.000000000 -0300 @@ -4,6 +4,7 @@ #include "fctsys.h" #include "common.h" +#include "confirm.h" #include "class_drawpanel.h" #include "kicad_string.h" #include "gestfich.h" @@ -230,6 +231,173 @@ } +static struct exception +{ + char* a_ref; + char* a_pin; + char* b_ref; + char* b_pin; + char* line; /* pointer to the memory object we've allocated */ + struct exception* next; +}* exceptions; + + + +static void FreeExceptions( void ) +{ + struct exception* next; + + while( exceptions ) + { + next = exceptions->next; + MyFree( exceptions->line ); + MyFree( exceptions ); + exceptions = next; + } +} + + +static bool ParseField( char **s, char **field ) +{ + *field = *s; + if( ! **s ) + return FALSE; + while( **s && ! isspace( **s ) ) + (*s)++; + if( ! **s ) + return TRUE; + *(*s)++ = 0; + while( **s && isspace( **s ) ) + (*s)++; + return TRUE; +} + + +static bool ParseException( char *s ) +{ + struct exception tmp; + struct exception* e; + + tmp.line = s; + + if( ! ParseField( &s, &tmp.a_ref)) + return FALSE; + if( ! ParseField( &s, &tmp.a_pin )) + return FALSE; + if( ! ParseField( &s, &tmp.b_ref)) + return FALSE; + if( ! ParseField( &s, &tmp.b_pin )) + return FALSE; + + e = (struct exception*) MyMalloc( sizeof( *e )); + *e = tmp; + e->next = exceptions; + exceptions = e; + + return TRUE; +} + + +static bool LoadExceptionsByName( const wxString &file_name ) +{ + FILE* file; + char buf[200]; /* enough room for chatty comments */ + char* s; + char* tmp; + char* hash; + int n = 0; + + FreeExceptions(); + file = wxFopen( file_name, wxT( "r" ) ); + if( ! file ) + return FALSE; + + while( 1 ) + { + s = fgets( buf, sizeof( buf ), file ); + if( ! s ) + break; + + n++; + + // remove comments + hash = strchr( s, '#' ); + if( hash ) + *hash = 0; + + // skip leading whitespace + while( *s && isspace( *s ) ) + s++; + if( ! *s ) + continue; + + tmp = (char*) MyMalloc( strlen( s ) + 1 ); + strcpy( tmp, s ); + + if( ! ParseException( tmp ) ) + { + wxString msg; + + msg.Printf( wxT( "Parse error at %s:%d" ), CONV_TO_UTF8(file_name), n ); + DisplayError( NULL, msg ); + MyFree( tmp ); + break; + } + } + + fclose( file ); + + return TRUE; +} + + +static void LoadExceptions( void ) +{ + wxFileName fn; + + fn = g_RootSheet->m_AssociatedScreen->m_FileName; + fn.SetExt( wxT( "erx" ) ); + if ( LoadExceptionsByName( fn.GetFullPath() ) ) + g_EESchemaVar.NbExceptionErc = 0; +} + + +static bool FindException( NETLIST_OBJECT* a, NETLIST_OBJECT* b ) +{ + SCH_COMPONENT* a_comp = (SCH_COMPONENT*) a->m_Link; + SCH_COMPONENT* b_comp = (SCH_COMPONENT*) b->m_Link; + const char* a_ref = CONV_TO_UTF8( a_comp->GetRef( &a->m_SheetList ) ); + const char* b_ref = CONV_TO_UTF8( b_comp->GetRef( &b->m_SheetList ) ); + const char* a_pin = (char *) &a->m_PinNum; + const char* b_pin = (char *) &b->m_PinNum; + struct exception* e = exceptions; + + for( e = exceptions; e; e = e->next ) + { +#if 0 +fprintf(stderr, "a) %s %4.4s =? %s %4.4s\n", e->a_ref, e->a_pin, a_ref, a_pin); +fprintf(stderr, "b) %s %4.4s =? %s %4.4s\n", e->b_ref, e->b_pin, b_ref, b_pin); +#endif + if( strcmp( e->a_ref, a_ref ) ) + continue; + if( strncmp( e->a_pin, a_pin, 4 ) ) + continue; + if( strcmp( e->b_ref, b_ref ) ) + continue; + if( strncmp( e->b_pin, b_pin, 4 ) ) + continue; + return TRUE; + } + return FALSE; +} + + +static bool IsException( NETLIST_OBJECT* a, NETLIST_OBJECT* b ) +{ + return FindException( a, b ) || FindException( b, a); +} + + void DIALOG_ERC::TestErc( wxArrayString* aMessagesList ) { wxFileName fn; @@ -264,6 +432,7 @@ g_EESchemaVar.NbErrorErc = 0; g_EESchemaVar.NbWarningErc = 0; + g_EESchemaVar.NbExceptionErc = -1; /* -1 means "no file" */ /* Cleanup the entire hierarchy */ EDA_ScreenList ScreenList; @@ -290,6 +459,8 @@ m_Parent->BuildNetListBase(); + LoadExceptions(); + /* Reset the flag m_FlagOfConnection, that will be used next, in * calculations */ for( unsigned ii = 0; ii < g_NetObjectslist.size(); ii++ ) @@ -358,7 +529,13 @@ // Displays global results: wxString num; - num.Printf( wxT( "%d" ), g_EESchemaVar.NbErrorErc ); + + if( g_EESchemaVar.NbExceptionErc >= 0) + num.Printf( wxT( "%d (%d exception%s)" ), g_EESchemaVar.NbErrorErc, + g_EESchemaVar.NbExceptionErc, + g_EESchemaVar.NbExceptionErc == 1 ? wxT( "" ) : wxT( "s" ) ); + else + num.Printf( wxT( "%d" ), g_EESchemaVar.NbErrorErc ); m_TotalErrCount->SetLabel( num ); num.Printf( wxT( @@ -662,6 +839,12 @@ if( g_NetObjectslist[NetItemTst]->m_FlagOfConnection != 0 ) break; + if( IsException( g_NetObjectslist[NetItemRef], g_NetObjectslist[NetItemTst] ) ) + { + g_EESchemaVar.NbExceptionErc++; + break; + } + Diagnose( panel, g_NetObjectslist[NetItemRef], g_NetObjectslist[NetItemTst], Index: kicad/eeschema/general.h =================================================================== --- kicad.orig/eeschema/general.h 2010-04-28 04:34:54.000000000 -0300 +++ kicad/eeschema/general.h 2010-04-28 05:42:13.000000000 -0300 @@ -118,6 +118,7 @@ { int NbErrorErc; int NbWarningErc; + int NbExceptionErc; }; extern struct EESchemaVariables g_EESchemaVar;