Commit b07fa2bf authored by Dick Hollenbeck's avatar Dick Hollenbeck

more free SWEET software

parent c2ff1d94
...@@ -56,6 +56,28 @@ PIN2=" ...@@ -56,6 +56,28 @@ PIN2="
(padname A24 (font (size 0.9 1.1) italic bold) (visible yes)) (padname A24 (font (size 0.9 1.1) italic bold) (visible yes))
)" )"
PIN3="
(pin (padname A25))"
PINS="
(pin (padname Z12))(pin (padname Y14))(pin (padname Z13))(pin (padname Y15))"
PIN_SWAP="
(pin_swap A23 A24)"
PIN_RENUM="
(pin_renum A24 B24)"
PIN_RENAME="
(pin_rename #WE LED)"
PIN_DELETE="
(pin_del B24)"
PIN_MERGE="(pin_merge A23 (hide Z12 Y14))(pin_merge A25 (hide Z13 Y15))"
PROP1=" PROP1="
(property mWatts 12 (property mWatts 12
(effects (at 1 34 270)(font (size .5 1) italic bold)(visible no)) (effects (at 1 34 270)(font (size .5 1) italic bold)(visible no))
...@@ -64,6 +86,10 @@ PROP1=" ...@@ -64,6 +86,10 @@ PROP1="
KEYWORDS=" KEYWORDS="
(keywords varistor batcave einstein)" (keywords varistor batcave einstein)"
ALTERNATES="
(alternates 7400/7400_b 7400/7400_c)"
for C in ${CATEGORIES}; do for C in ${CATEGORIES}; do
...@@ -81,8 +107,16 @@ for C in ${CATEGORIES}; do ...@@ -81,8 +107,16 @@ for C in ${CATEGORIES}; do
$TEXT $TEXT
$PIN1 $PIN1
$PIN2 $PIN2
$PIN3
$PINS
$PROP1 $PROP1
$KEYWORDS $KEYWORDS
$ALTERNATES
$PIN_SWAP
$PIN_RENUM
$PIN_RENAME
$PIN_DELETE
$PIN_MERGE
)" > $BASEDIR/$C/$P.part.$R )" > $BASEDIR/$C/$P.part.$R
done done
# also make the part without a rev: # also make the part without a rev:
...@@ -96,8 +130,16 @@ for C in ${CATEGORIES}; do ...@@ -96,8 +130,16 @@ for C in ${CATEGORIES}; do
$TEXT $TEXT
$PIN1 $PIN1
$PIN2 $PIN2
$PIN3
$PINS
$PROP1 $PROP1
$KEYWORDS $KEYWORDS
$ALTERNATES
$PIN_SWAP
$PIN_RENUM
$PIN_RENAME
$PIN_DELETE
$PIN_MERGE
)" > $BASEDIR/$C/$P.part )" > $BASEDIR/$C/$P.part
done done
done done
......
...@@ -123,13 +123,19 @@ static int okRevision( const STRING& aField ) ...@@ -123,13 +123,19 @@ static int okRevision( const STRING& aField )
//----</Policy and field test functions>------------------------------------- //----</Policy and field test functions>-------------------------------------
int LPID::Parse( const STRING& aLPID ) void LPID::clear()
{ {
logical.clear(); logical.clear();
category.clear(); category.clear();
baseName.clear(); baseName.clear();
partName.clear(); partName.clear();
revision.clear(); revision.clear();
}
int LPID::Parse( const STRING& aLPID )
{
clear();
const char* rev = EndsWithRev( aLPID ); const char* rev = EndsWithRev( aLPID );
size_t revNdx; size_t revNdx;
......
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
namespace SCH { namespace SCH {
/** /**
* Class LPID * Class LPID
* (aka GUID) is a Logical Part ID and consists of various portions much like a URI. * (aka GUID) is a Logical Part ID and consists of various portions much like a URI.
...@@ -196,6 +197,7 @@ public: ...@@ -196,6 +197,7 @@ public:
static STRING Format( const STRING& aLogicalLib, const STRING& aPartName, const STRING& aRevision="" ) static STRING Format( const STRING& aLogicalLib, const STRING& aPartName, const STRING& aRevision="" )
throw( PARSE_ERROR ); throw( PARSE_ERROR );
void clear();
#if defined(DEBUG) #if defined(DEBUG)
static void Test(); static void Test();
......
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
/** /**
* Function formatAt * Function formatAt
* returns a formatted "(at X Y [ANGLE])" s-expression * outputs a formatted "(at X Y [ANGLE])" s-expression
*/ */
static void formatAt( OUTPUTFORMATTER* out, const POINT& aPos, ANGLE aAngle, int indent=0 ) static void formatAt( OUTPUTFORMATTER* out, const POINT& aPos, ANGLE aAngle, int indent=0 )
throw( IO_ERROR ) throw( IO_ERROR )
...@@ -72,6 +72,18 @@ void PART::clear() ...@@ -72,6 +72,18 @@ void PART::clear()
extends = 0; extends = 0;
} }
// clear the mandatory fields
for( int ndx = REFERENCE; ndx < END; ++ndx )
{
delete mandatory[ndx];
mandatory[ndx] = 0;
}
// delete properties I own, since their container will not destroy them:
for( PROPERTIES::iterator it = properties.begin(); it != properties.end(); ++it )
delete *it;
properties.clear();
// delete graphics I own, since their container will not destroy them: // delete graphics I own, since their container will not destroy them:
for( GRAPHICS::iterator it = graphics.begin(); it != graphics.end(); ++it ) for( GRAPHICS::iterator it = graphics.begin(); it != graphics.end(); ++it )
delete *it; delete *it;
...@@ -82,21 +94,13 @@ void PART::clear() ...@@ -82,21 +94,13 @@ void PART::clear()
delete *it; delete *it;
pins.clear(); pins.clear();
// delete properties I own, since their container will not destroy them: alternates.clear();
for( PROPERTIES::iterator it = properties.begin(); it != properties.end(); ++it )
delete *it;
properties.clear();
keywords.clear(); keywords.clear();
contains = 0; pin_merges.clear();
// clear the mandatory fields contains = 0;
for( int ndx = REFERENCE; ndx < END; ++ndx )
{
delete mandatory[ndx];
mandatory[ndx] = 0;
}
} }
...@@ -141,6 +145,49 @@ PROPERTY* PART::FieldLookup( PROP_ID aPropertyId ) ...@@ -141,6 +145,49 @@ PROPERTY* PART::FieldLookup( PROP_ID aPropertyId )
return p; return p;
} }
PINS::iterator PART::pinFindByPadName( const wxString& aPadName )
{
PINS::iterator it;
for( it = pins.begin(); it != pins.end(); ++it )
{
if( (*it)->padname.text == aPadName )
break;
}
return it;
}
PINS::iterator PART::pinFindBySignal( const wxString& aSignal )
{
PINS::iterator it;
for( it = pins.begin(); it != pins.end(); ++it )
{
if( (*it)->signal.text == aSignal )
break;
}
return it;
}
bool PART::PinDelete( const wxString& aPadName )
{
PINS::iterator it = pinFindByPadName( aPadName );
if( it != pins.end() )
{
delete *it;
pins.erase( it );
return true;
}
// there is only one reason this can fail: not found:
return false;
}
PART::~PART() PART::~PART()
{ {
...@@ -185,19 +232,17 @@ void PART::Parse( SWEET_PARSER* aParser , LIB_TABLE* aTable ) throw( IO_ERROR, P ...@@ -185,19 +232,17 @@ void PART::Parse( SWEET_PARSER* aParser , LIB_TABLE* aTable ) throw( IO_ERROR, P
} }
void PART::PropertyDelete( const wxString& aPropertyName ) throw( IO_ERROR ) bool PART::PropertyDelete( const wxString& aPropertyName )
{ {
PROPERTIES::iterator it = propertyFind( aPropertyName ); PROPERTIES::iterator it = propertyFind( aPropertyName );
if( it == properties.end() ) if( it != properties.end() )
{ {
wxString msg;
msg.Printf( _( "Unable to find property: %s" ), aPropertyName.GetData() );
THROW_IO_ERROR( msg );
}
delete *it; delete *it;
properties.erase( it ); properties.erase( it );
return; return true;
}
return false;
} }
...@@ -258,6 +303,26 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const ...@@ -258,6 +303,26 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const
(*it)->Format( out, indent+1, ctl ); (*it)->Format( out, indent+1, ctl );
} }
if( alternates.size() )
{
out->Print( indent+1, "(alternates" );
for( PART_REFS::const_iterator it = alternates.begin(); it!=alternates.end(); ++it )
out->Print( 0, " %s", out->Quotes( it->Format() ).c_str() );
out->Print( 0, ")\n" );
}
for( MERGE_SETS::const_iterator mit = pin_merges.begin(); mit != pin_merges.end(); ++mit )
{
out->Print( indent+1, "(pin_merge %s (hide", out->Quotew( mit->first ).c_str() );
const MERGE_SET& mset = *mit->second;
for( MERGE_SET::const_iterator pit = mset.begin(); pit != mset.end(); ++pit )
{
out->Print( 0, " %s", out->Quotew( *pit ).c_str() );
}
out->Print( 0, "))\n" );
}
out->Print( indent, ")\n" ); out->Print( indent, ")\n" );
} }
...@@ -349,18 +414,30 @@ void FONT::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const ...@@ -349,18 +414,30 @@ void FONT::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const
void PIN::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const void PIN::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const
throw( IO_ERROR ) throw( IO_ERROR )
{ {
bool hasSignal = !signal.text.IsEmpty();
bool hasPadName = !padname.text.IsEmpty();
out->Print( indent, "(pin %s %s ", ShowType(), ShowShape() ); out->Print( indent, "(pin %s %s ", ShowType(), ShowShape() );
formatAt( out, pos, angle ); formatAt( out, pos, angle );
out->Print( 0, "(length %.6g)", InternalToLogical( length ) ); out->Print( 0, "(length %.6g)", InternalToLogical( length ) );
out->Print( 0, "(visible %s)\n", isVisible ? "yes" : "no" ); out->Print( 0, "(visible %s)\n", isVisible ? "yes" : "no" );
signal.Format( out, "signal", indent+1, 0 ); if( hasSignal )
signal.Format( out, "signal", indent+1, hasPadName ? 0 : CTL_OMIT_NL );
if( hasPadName )
padname.Format( out, "padname", indent+1, CTL_OMIT_NL ); padname.Format( out, "padname", indent+1, CTL_OMIT_NL );
out->Print( 0, ")\n" ); out->Print( 0, ")\n" );
} }
PIN::~PIN()
{
}
void PINTEXT::Format( OUTPUTFORMATTER* out, const char* aElement, int indent, int ctl ) const void PINTEXT::Format( OUTPUTFORMATTER* out, const char* aElement, int indent, int ctl ) const
throw( IO_ERROR ) throw( IO_ERROR )
{ {
......
...@@ -27,6 +27,10 @@ ...@@ -27,6 +27,10 @@
#define SCH_PART_H_ #define SCH_PART_H_
#include <sch_lib.h> #include <sch_lib.h>
#include <sch_lib_table.h>
#include <sch_lpid.h>
//#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/ptr_container/ptr_map.hpp>
#define INTERNAL_PER_LOGICAL 10000 ///< no. internal units per logical unit #define INTERNAL_PER_LOGICAL 10000 ///< no. internal units per logical unit
...@@ -89,6 +93,13 @@ class PROPERTY; ...@@ -89,6 +93,13 @@ class PROPERTY;
}; };
/// a set of pin padnames that are electrically equivalent for a PART.
typedef std::set< wxString > MERGE_SET;
/// The key is the VISIBLE_PIN from
/// (pin_merge VISIBLE_PIN (hide HIDDEN_PIN1 HIDDEN_PIN2...))
typedef boost::ptr_map< wxString, MERGE_SET > MERGE_SETS;
class POINT : public wxPoint class POINT : public wxPoint
{ {
...@@ -157,10 +168,12 @@ class BASE_GRAPHIC ...@@ -157,10 +168,12 @@ class BASE_GRAPHIC
protected: protected:
PART* owner; PART* owner;
PART* birthplace; ///< at which PART in inheritance chain was 'this' added
public: public:
BASE_GRAPHIC( PART* aOwner ) : BASE_GRAPHIC( PART* aOwner ) :
owner( aOwner ) owner( aOwner ),
birthplace( aOwner )
{} {}
virtual ~BASE_GRAPHIC() {} virtual ~BASE_GRAPHIC() {}
...@@ -342,7 +355,6 @@ class PROPERTY : public BASE_GRAPHIC ...@@ -342,7 +355,6 @@ class PROPERTY : public BASE_GRAPHIC
friend class SWEET_PARSER; friend class SWEET_PARSER;
protected: protected:
PART* birthplace; ///< at which PART in inheritance chain was this PROPERTY added
wxString name; wxString name;
wxString text; wxString text;
TEXT_EFFECTS* effects; TEXT_EFFECTS* effects;
...@@ -359,7 +371,6 @@ protected: ...@@ -359,7 +371,6 @@ protected:
public: public:
PROPERTY( PART* aOwner, const wxChar* aName = wxT( "" ) ) : PROPERTY( PART* aOwner, const wxChar* aName = wxT( "" ) ) :
BASE_GRAPHIC( aOwner ), BASE_GRAPHIC( aOwner ),
birthplace( aOwner ),
name( aName ), name( aName ),
effects( 0 ) effects( 0 )
{} {}
...@@ -410,7 +421,6 @@ class PIN : public BASE_GRAPHIC ...@@ -410,7 +421,6 @@ class PIN : public BASE_GRAPHIC
public: public:
PIN( PART* aOwner ) : PIN( PART* aOwner ) :
BASE_GRAPHIC( aOwner ), BASE_GRAPHIC( aOwner ),
birthplace( aOwner ),
angle( 0 ), angle( 0 ),
connectionType( PR::T_input ), connectionType( PR::T_input ),
shape( PR::T_line ), shape( PR::T_line ),
...@@ -418,6 +428,8 @@ public: ...@@ -418,6 +428,8 @@ public:
isVisible( true ) isVisible( true )
{} {}
~PIN();
const char* ShowType() const const char* ShowType() const
{ {
return SWEET_LEXER::TokenName( PR::T( connectionType ) ); return SWEET_LEXER::TokenName( PR::T( connectionType ) );
...@@ -432,7 +444,6 @@ public: ...@@ -432,7 +444,6 @@ public:
throw( IO_ERROR ); throw( IO_ERROR );
protected: protected:
PART* birthplace; ///< at which PART in inheritance chain was this PIN added
POINT pos; POINT pos;
ANGLE angle; ANGLE angle;
...@@ -448,21 +459,74 @@ protected: ...@@ -448,21 +459,74 @@ protected:
int length; ///< length of pin in internal units int length; ///< length of pin in internal units
bool isVisible; ///< pin is visible bool isVisible; ///< pin is visible
wxString pin_merge; ///< padname of (pin_merge ...) that I am a member of, else empty if none
}; };
/**
* Class PART_REF
* is an LPID with a pointer to the "looked up" PART, which is looked up lazily.
*/
class PART_REF : public LPID
{
public:
PART_REF() :
LPID(),
part(0)
{}
/**
* Constructor LPID
* takes aLPID string and parses it. A typical LPID string uses a logical
* library name followed by a part name.
* e.g.: "kicad:passives/R/rev2", or
* e.g.: "mylib:R33"
*/
PART_REF( const STRING& aLPID ) throw( PARSE_ERROR ) :
LPID( aLPID ),
part(0)
{
}
/**
* Function Lookup
* returns the PART that this LPID refers to. Never returns NULL, because
* instead an exception would be thrown.
* @throw IO_ERROR if any problem occurs or if the part cannot be found.
*/
PART* Lookup( LIB_TABLE* aLibTable, LIB* aFallBackLib ) throw( IO_ERROR )
{
if( !part )
{
part = aLibTable->LookupPart( *this, aFallBackLib );
}
return part;
}
protected:
PART* part; ///< The looked-up PART,
///< no ownership (duh, PARTs are always owned by a LIB)
};
typedef std::vector<PART_REF> PART_REFS;
} // namespace SCH } // namespace SCH
//-----</temporary home for PART sub objects, move after stable>----------------- //-----</temporary home for PART sub objects, move after stable>-----------------
typedef std::set< wxString > KEYWORDS;
namespace SCH { namespace SCH {
typedef std::vector< BASE_GRAPHIC* > GRAPHICS; typedef std::vector< BASE_GRAPHIC* > GRAPHICS;
typedef std::vector< PIN* > PINS;
typedef std::vector< PROPERTY* > PROPERTIES; typedef std::vector< PROPERTY* > PROPERTIES;
typedef std::set< wxString > KEYWORDS;
typedef std::vector< PIN* > PINS;
class LPID; class LPID;
class SWEET_PARSER; class SWEET_PARSER;
...@@ -533,7 +597,12 @@ public: ...@@ -533,7 +597,12 @@ public:
void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits = 0 ) const void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits = 0 ) const
throw( IO_ERROR ); throw( IO_ERROR );
void PropertyDelete( const wxString& aPropertyName ) throw( IO_ERROR ); /**
* Function PropertyDelete
* deletes the property with aPropertyName if found and returns true, else false
* if not found.
*/
bool PropertyDelete( const wxString& aPropertyName );
/** /**
* Function Field * Function Field
...@@ -554,6 +623,31 @@ public: ...@@ -554,6 +623,31 @@ public:
*/ */
PROPERTY* FieldLookup( PROP_ID aPropertyId ); PROPERTY* FieldLookup( PROP_ID aPropertyId );
/**
* Function PinFindByPadName
* finds a PIN based on aPadName or returns NULL if not found.
* @param aPadName is the pin to find
* @return PIN* - the found PIN or NULL if not found.
*/
PIN* PinFindByPadName( const wxString& aPadName )
{
PINS::iterator it = pinFindByPadName( aPadName );
return it != pins.end() ? *it : NULL;
}
PIN* PinFindBySignal( const wxString& aSignal )
{
PINS::iterator it = pinFindBySignal( aSignal );
return it != pins.end() ? *it : NULL;
}
/**
* Function PinDelete
* deletes the pin with aPadName if found and returns true, else false
* if not found.
*/
bool PinDelete( const wxString& aPadName );
/* /*
void SetValue( const wxString& aValue ) void SetValue( const wxString& aValue )
...@@ -619,6 +713,15 @@ protected: // not likely to have C++ descendants, but protected none-the-le ...@@ -619,6 +713,15 @@ protected: // not likely to have C++ descendants, but protected none-the-le
*/ */
PROPERTIES::iterator propertyFind( const wxString& aPropertyName ); PROPERTIES::iterator propertyFind( const wxString& aPropertyName );
/**
* Function pinFindByPadName
* searches for a PIN with aPadName and returns a PROPERTIES::iterator which
* is the found item or pins.end() if not found.
*/
PINS::iterator pinFindByPadName( const wxString& aPadName );
PINS::iterator pinFindBySignal( const wxString& aSignal );
POINT anchor; POINT anchor;
//PART( LIB* aOwner ); //PART( LIB* aOwner );
...@@ -638,18 +741,9 @@ protected: // not likely to have C++ descendants, but protected none-the-le ...@@ -638,18 +741,9 @@ protected: // not likely to have C++ descendants, but protected none-the-le
/// actually becomes cached in RAM. /// actually becomes cached in RAM.
STRING body; STRING body;
// mandatory properties /// mandatory properties, aka fields. Index into mandatory[] is PROP_ID.
PROPERTY* mandatory[END]; PROPERTY* mandatory[END];
/*
PROPERTY value;
PROPERTY footprint;
PROPERTY model;
PROPERTY datasheet;
*/
// separate lists for speed:
/** /**
* Member properties * Member properties
* holds the non-mandatory properties. * holds the non-mandatory properties.
...@@ -669,10 +763,17 @@ protected: // not likely to have C++ descendants, but protected none-the-le ...@@ -669,10 +763,17 @@ protected: // not likely to have C++ descendants, but protected none-the-le
PINS pins; PINS pins;
/// Alternate body forms. /// Alternate body forms.
//ALTERNATES alternates; PART_REFS alternates;
/// searching aids
KEYWORDS keywords; KEYWORDS keywords;
/**
* A pin_merge set is a set of pins that are all electrically equivalent
* and whose anchor pin is the only one visible. The visible pin is the
* key in the MERGE_SETS boost::ptr_map::map
*/
MERGE_SETS pin_merges;
}; };
} // namespace PART } // namespace PART
......
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
#include <sch_lib_table.h> #include <sch_lib_table.h>
#include <sch_lpid.h> #include <sch_lpid.h>
#include <macros.h>
using namespace SCH; using namespace SCH;
using namespace PR; using namespace PR;
...@@ -74,58 +75,6 @@ static inline const int PB( PartBit oneBitOnly ) ...@@ -74,58 +75,6 @@ static inline const int PB( PartBit oneBitOnly )
} }
void SWEET_PARSER::parseExtends( PART* me )
{
PART* base;
int offset;
if( contains & PB(extends) )
Duplicate( T_extends );
NeedSYMBOLorNUMBER();
me->setExtends( new LPID() );
offset = me->extends->Parse( CurText() );
if( offset > -1 ) // -1 is success
THROW_PARSE_ERROR( _("invalid extends LPID"),
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() + offset );
base = libs->LookupPart( *me->extends, me->Owner() );
// we could be going in circles here, recursively, or too deep, set limits
// and disallow extending from self (even indirectly)
int extendsDepth = 0;
for( PART* ancestor = base; ancestor && extendsDepth<MAX_INHERITANCE_NESTING;
++extendsDepth, ancestor = ancestor->base )
{
if( ancestor == me )
{
THROW_PARSE_ERROR( _("'extends' may not have self as any ancestor"),
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() );
}
}
if( extendsDepth == MAX_INHERITANCE_NESTING )
{
THROW_PARSE_ERROR( _("max allowed extends depth exceeded"),
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() );
}
me->inherit( *base );
me->base = base;
contains |= PB(extends);
}
void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_ERROR ) void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_ERROR )
{ {
T tok; T tok;
...@@ -266,9 +215,7 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E ...@@ -266,9 +215,7 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
break; break;
case T_property_del: case T_property_del:
NeedSYMBOLorNUMBER(); parsePropertyDel( me );
me->PropertyDelete( FromUTF8() );
NeedRIGHT();
break; break;
// reference in a PART is incomplete, it is just the prefix of an // reference in a PART is incomplete, it is just the prefix of an
...@@ -308,37 +255,45 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E ...@@ -308,37 +255,45 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
prop = me->FieldLookup( PART::MODEL ); prop = me->FieldLookup( PART::MODEL );
goto L_prop; goto L_prop;
case T_pin:
PIN* pin;
pin = new PIN( me );
me->pins.push_back( pin );
parsePin( pin );
break;
case T_keywords: case T_keywords:
parseKeywords( me ); parseKeywords( me );
break; break;
/*
@todo
case T_alternates: case T_alternates:
// @todo: do we want to inherit alternates?
parseAlternates( me );
break; break;
// do we want to inherit alternates? case T_pin:
case T_pin_merge: PIN* pin;
pin = new PIN( me );
me->pins.push_back( pin );
parsePin( pin );
break;
case T_pin_del:
parsePinDel( me );
break; break;
case T_pin_swap: case T_pin_swap:
parsePinSwap( me );
break; break;
case T_pin_renum: case T_pin_renum:
parsePinRenum( me );
break; break;
case T_pin_rename: case T_pin_rename:
parsePinRename( me );
break; break;
case T_pin_merge:
parsePinMerge( me );
break;
/*
@todo
case T_route_pin_swap: case T_route_pin_swap:
break; break;
*/ */
...@@ -361,6 +316,85 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E ...@@ -361,6 +316,85 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
} }
void SWEET_PARSER::parseExtends( PART* me )
{
PART* base;
int offset;
if( contains & PB(extends) )
Duplicate( T_extends );
NeedSYMBOLorNUMBER();
me->setExtends( new LPID() );
offset = me->extends->Parse( CurText() );
if( offset > -1 ) // -1 is success
THROW_PARSE_ERROR( _("invalid extends LPID"),
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() + offset );
base = libs->LookupPart( *me->extends, me->Owner() );
// we could be going in circles here, recursively, or too deep, set limits
// and disallow extending from self (even indirectly)
int extendsDepth = 0;
for( PART* ancestor = base; ancestor && extendsDepth<MAX_INHERITANCE_NESTING;
++extendsDepth, ancestor = ancestor->base )
{
if( ancestor == me )
{
THROW_PARSE_ERROR( _("'extends' may not have self as any ancestor"),
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() );
}
}
if( extendsDepth == MAX_INHERITANCE_NESTING )
{
THROW_PARSE_ERROR( _("max allowed extends depth exceeded"),
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() );
}
me->inherit( *base );
me->base = base;
contains |= PB(extends);
}
void SWEET_PARSER::parseAlternates( PART* me )
{
T tok;
PART_REF lpid;
int offset;
while( ( tok = NextTok() ) != T_RIGHT )
{
if( !IsSymbol( tok ) && tok != T_NUMBER )
Expecting( "lpid" );
// lpid.clear(); Parse does this
offset = lpid.Parse( CurText() );
if( offset > -1 )
THROW_PARSE_ERROR( _("invalid alternates LPID"),
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() + offset );
// PART_REF assignment should be OK, it contains no ownership
me->alternates.push_back( lpid );
}
}
void SWEET_PARSER::parseKeywords( PART* me ) void SWEET_PARSER::parseKeywords( PART* me )
{ {
T tok; T tok;
...@@ -637,6 +671,256 @@ void SWEET_PARSER::parsePin( PIN* me ) ...@@ -637,6 +671,256 @@ void SWEET_PARSER::parsePin( PIN* me )
} }
void SWEET_PARSER::parsePinDel( PART* me )
{
wxString padName;
// we do this somewhat unorthodoxically because we want to avoid doing two lookups,
// which would need to be done to 1) find pin, and 2) delete pin. Only one
// lookup is needed with this scheme.
NeedSYMBOLorNUMBER();
padName = FromUTF8();
// lookup now while CurOffset() is still meaningful.
PINS::iterator it = me->pinFindByPadName( padName );
if( it == me->pins.end() )
{
THROW_PARSE_ERROR( _("undefined pin"),
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() );
}
/* enable in future, but not now while testing
if( (*it)->birthplace == me )
{
THROW_PARSE_ERROR( _("pin_del allowed for inherited pins only"),
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() );
}
*/
NeedRIGHT();
delete *it; // good thing I'm a friend.
me->pins.erase( it );
}
void SWEET_PARSER::parsePinSwap( PART* me )
{
PIN* pin1;
PIN* pin2;
wxString padName;
NeedSYMBOLorNUMBER();
padName = FromUTF8();
// lookup now while CurOffset() is still meaningful.
pin1 = me->PinFindByPadName( padName );
if( !pin1 )
{
THROW_PARSE_ERROR( _("undefined pin"),
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() );
}
NeedSYMBOLorNUMBER();
padName = FromUTF8();
pin2 = me->PinFindByPadName( padName );
if( !pin2 )
{
THROW_PARSE_ERROR( _("undefined pin"),
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() );
}
NeedRIGHT();
// swap only the text, but might want to swap entire PIN_TEXTs
pin2->padname.text = pin1->padname.text;
pin1->padname.text = padName;
}
void SWEET_PARSER::parsePinRenum( PART* me )
{
PIN* pin;
wxString oldPadName;
wxString newPadName;
NeedSYMBOLorNUMBER();
oldPadName = FromUTF8();
// lookup now while CurOffset() is still meaningful.
pin = me->PinFindByPadName( oldPadName );
if( !pin )
{
THROW_PARSE_ERROR( _("undefined pin"),
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() );
}
NeedSYMBOLorNUMBER();
newPadName = FromUTF8();
NeedRIGHT();
// @todo: check for padname legalities
pin->padname.text = newPadName;
}
void SWEET_PARSER::parsePinRename( PART* me )
{
PIN* pin;
wxString oldSignal;
wxString newSignal;
NeedSYMBOLorNUMBER();
oldSignal = FromUTF8();
// lookup now while CurOffset() is still meaningful.
pin = me->PinFindBySignal( oldSignal );
if( !pin )
{
THROW_PARSE_ERROR( _("undefined pin"),
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() );
}
NeedSYMBOLorNUMBER();
newSignal = FromUTF8();
NeedRIGHT();
pin->signal.text = newSignal;
}
void SWEET_PARSER::parsePinMerge( PART* me )
{
T tok;
wxString padName;
wxString msg;
NeedSYMBOLorNUMBER();
wxString anchorPadName = FromUTF8();
// lookup now while CurOffset() is still good.
PINS::iterator pit = me->pinFindByPadName( anchorPadName );
if( pit == me->pins.end() )
{
msg.Printf( _( "undefined pin %s" ), anchorPadName.GetData() );
THROW_PARSE_ERROR( msg,
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() );
}
if( !(*pit)->pin_merge.IsEmpty() && anchorPadName != (*pit)->pin_merge )
{
msg.Printf( _( "pin %s already in pin_merge group %s" ),
anchorPadName.GetData(), (*pit)->pin_merge.GetData() );
THROW_PARSE_ERROR( msg,
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() );
}
NeedLEFT();
tok = NextTok();
if( tok != T_hide )
Expecting( T_hide );
(*pit)->isVisible = true;
(*pit)->pin_merge = anchorPadName;
// allocate or find a MERGE_SET;
MERGE_SET& ms = me->pin_merges[anchorPadName];
while( ( tok = NextTok() ) != T_RIGHT )
{
if( !IsSymbol( tok ) && tok != T_NUMBER )
Expecting( "padname" );
padName = FromUTF8();
D(printf("padName=%s\n", TO_UTF8( padName ) );)
// find the PIN and mark it as being in this MERGE_SET or throw
// error if already in another MERGET_SET.
pit = me->pinFindByPadName( padName );
if( pit == me->pins.end() )
{
msg.Printf( _( "undefined pin %s" ), padName.GetData() );
THROW_PARSE_ERROR( msg,
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() );
}
if( !(*pit)->pin_merge.IsEmpty() && anchorPadName != (*pit)->pin_merge )
{
msg.Printf( _( "pin %s already in pin_merge group %s" ),
padName.GetData(), (*pit)->pin_merge.GetData() );
THROW_PARSE_ERROR( msg,
CurSource(),
CurLine(),
CurLineNumber(),
CurOffset() );
}
(*pit)->isVisible = false;
(*pit)->pin_merge = anchorPadName;
ms.insert( padName );
}
NeedRIGHT();
}
void SWEET_PARSER::parsePropertyDel( PART* me )
{
NeedSYMBOLorNUMBER();
wxString propertyName = FromUTF8();
if( !me->PropertyDelete( propertyName ) )
{
wxString msg;
msg.Printf( _( "Unable to find property: %s" ), propertyName.GetData() );
THROW_IO_ERROR( msg );
}
NeedRIGHT();
}
void SWEET_PARSER::parseTextEffects( TEXT_EFFECTS* me ) void SWEET_PARSER::parseTextEffects( TEXT_EFFECTS* me )
{ {
/* /*
......
...@@ -75,14 +75,21 @@ class SWEET_PARSER : public SWEET_LEXER ...@@ -75,14 +75,21 @@ class SWEET_PARSER : public SWEET_LEXER
void parseCircle( CIRCLE* me ); void parseCircle( CIRCLE* me );
void parseArc( ARC* me ); void parseArc( ARC* me );
void parseText( GR_TEXT* me ); void parseText( GR_TEXT* me );
void parsePin( PIN* me );
void parseAt( POINT* pos, float* angle ); void parseAt( POINT* pos, float* angle );
void parseBool( bool* aBool ); void parseBool( bool* aBool );
void parseFont( FONT* me ); void parseFont( FONT* me );
void parsePinText( PINTEXT* me ); void parsePinText( PINTEXT* me );
void parseTextEffects( TEXT_EFFECTS* me ); void parseTextEffects( TEXT_EFFECTS* me );
void parseKeywords( PART* me ); void parseKeywords( PART* me );
void parseAlternates( PART* me );
void parsePropertyDel( PART* me );
void parsePin( PIN* me );
void parsePinDel( PART* me );
void parsePinSwap( PART* me );
void parsePinRenum( PART* me );
void parsePinRename( PART* me );
void parsePinMerge( PART* me );
public: public:
......
...@@ -20,6 +20,7 @@ fill ...@@ -20,6 +20,7 @@ fill
filled filled
font font
footprint footprint
hide
input input
input_low input_low
inverted inverted
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment