Commit 39194ef6 authored by Dick Hollenbeck's avatar Dick Hollenbeck

more free software, Format()ing works now, only a few more items to Parse()

parent 16e9ddc2
...@@ -10,7 +10,7 @@ REVS="rev1 rev5 rev10" ...@@ -10,7 +10,7 @@ REVS="rev1 rev5 rev10"
REFERENCE=" REFERENCE="
(reference U (reference U?
(effects (at 12 13 180)(font (size .7 1))(visible yes)) (effects (at 12 13 180)(font (size .7 1))(visible yes))
)" )"
...@@ -71,7 +71,7 @@ for C in ${CATEGORIES}; do ...@@ -71,7 +71,7 @@ for C in ${CATEGORIES}; do
for P in ${PARTS}; do for P in ${PARTS}; do
for R in ${REVS}; do for R in ${REVS}; do
echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane) echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane)(datasheet http://favorite.pdf)
$REFERENCE $REFERENCE
$LINE $LINE
$RECT $RECT
...@@ -86,7 +86,7 @@ for C in ${CATEGORIES}; do ...@@ -86,7 +86,7 @@ for C in ${CATEGORIES}; do
)" > $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:
echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane) echo "(part $C/$P (value 22)(footprint SM0805)(model Airplane)(datasheet http://favorite.pdf)
$REFERENCE $REFERENCE
$LINE $LINE
$RECT $RECT
......
...@@ -28,6 +28,7 @@ ...@@ -28,6 +28,7 @@
#include <sch_sweet_parser.h> #include <sch_sweet_parser.h>
#include <sch_lpid.h> #include <sch_lpid.h>
#include <sch_lib_table.h> #include <sch_lib_table.h>
#include <macros.h>
//#include <richio.h> //#include <richio.h>
using namespace SCH; using namespace SCH;
...@@ -38,16 +39,21 @@ PART::PART( LIB* aOwner, const STRING& aPartNameAndRev ) : ...@@ -38,16 +39,21 @@ PART::PART( LIB* aOwner, const STRING& aPartNameAndRev ) :
contains( 0 ), contains( 0 ),
partNameAndRev( aPartNameAndRev ), partNameAndRev( aPartNameAndRev ),
extends( 0 ), extends( 0 ),
base( 0 ), base( 0 )
/*
reference( this, wxT( "reference " ) ), reference( this, wxT( "reference " ) ),
value( this, wxT( "value" ) ), value( this, wxT( "value" ) ),
footprint( this, wxT( "footprint" ) ), footprint( this, wxT( "footprint" ) ),
model( this, wxT( "model" ) ), model( this, wxT( "model" ) ),
datasheet( this, wxT( "datasheet" ) ) datasheet( this, wxT( "datasheet" ) )
*/
{ {
// Our goal is to have class LIB only instantiate what is needed, so print here // Our goal is to have class LIB only instantiate what is needed, so print here
// what it is doing. It is the only class where PART can be instantiated. // what it is doing. It is the only class where PART can be instantiated.
D(printf("PART::PART(%s)\n", aPartNameAndRev.c_str() );) D(printf("PART::PART(%s)\n", aPartNameAndRev.c_str() );)
for( int i=REFERENCE; i<END; ++i )
mandatory[i] = 0;
} }
...@@ -69,7 +75,7 @@ void PART::clear() ...@@ -69,7 +75,7 @@ void PART::clear()
delete *it; delete *it;
pins.clear(); pins.clear();
// delete non-mandatory properties I own, since their container will not destroy them: // delete properties I own, since their container will not destroy them:
for( PROPERTIES::iterator it = properties.begin(); it != properties.end(); ++it ) for( PROPERTIES::iterator it = properties.begin(); it != properties.end(); ++it )
delete *it; delete *it;
properties.clear(); properties.clear();
...@@ -78,7 +84,54 @@ void PART::clear() ...@@ -78,7 +84,54 @@ void PART::clear()
contains = 0; contains = 0;
// @todo clear the mandatory fields // clear the mandatory fields
for( int ndx = REFERENCE; ndx < END; ++ndx )
{
delete mandatory[ndx];
mandatory[ndx] = 0;
}
}
PROPERTY* PART::FieldLookup( PROP_ID aPropertyId )
{
wxASSERT( unsigned(aPropertyId) < unsigned(END) );
PROPERTY* p = mandatory[aPropertyId];
if( !p )
{
switch( aPropertyId )
{
case REFERENCE:
p = new PROPERTY( this, wxT( "reference" ) );
p->text = wxT( "U?" );
break;
case VALUE:
p = new PROPERTY( this, wxT( "value" ) );
break;
case FOOTPRINT:
p = new PROPERTY( this, wxT( "footprint" ) );
break;
case DATASHEET:
p = new PROPERTY( this, wxT( "datasheet" ) );
break;
case MODEL:
p = new PROPERTY( this, wxT( "model" ) );
break;
default:
;
}
mandatory[aPropertyId] = p;
}
return p;
} }
...@@ -119,7 +172,7 @@ PART& PART::operator=( const PART& other ) ...@@ -119,7 +172,7 @@ PART& PART::operator=( const PART& other )
} }
void PART::Parse( SWEET_PARSER* aParser, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_ERROR ) void PART::Parse( SWEET_PARSER* aParser , LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_ERROR )
{ {
aParser->Parse( this, aTable ); aParser->Parse( this, aTable );
} }
...@@ -151,7 +204,8 @@ PROPERTIES::iterator PART::propertyFind( const wxString& aPropertyName ) ...@@ -151,7 +204,8 @@ PROPERTIES::iterator PART::propertyFind( const wxString& aPropertyName )
} }
void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_ERROR ) void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const
throw( IO_ERROR )
{ {
out->Print( indent, "(part %s", partNameAndRev.c_str() ); out->Print( indent, "(part %s", partNameAndRev.c_str() );
...@@ -160,12 +214,13 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_E ...@@ -160,12 +214,13 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_E
out->Print( 0, "\n" ); out->Print( 0, "\n" );
/* for( int i = REFERENCE; i < END; ++i )
@todo
for( int i=0; i<MANDATORY_FIELDS; ++i )
{ {
PROPERTY* prop = Field( PROP_ID( i ) );
if( prop )
prop->Format( out, indent+1, ctl );
} }
*/
for( PROPERTIES::const_iterator it = properties.begin(); it != properties.end(); ++it ) for( PROPERTIES::const_iterator it = properties.begin(); it != properties.end(); ++it )
{ {
(*it)->Format( out, indent+1, ctl ); (*it)->Format( out, indent+1, ctl );
...@@ -178,6 +233,14 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_E ...@@ -178,6 +233,14 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_E
InternalToLogical( anchor.y ) ); InternalToLogical( anchor.y ) );
} }
if( keywords.size() )
{
out->Print( indent+1, "(keywords" );
for( KEYWORDS::iterator it = keywords.begin(); it != keywords.end(); ++it )
out->Print( 0, " %s", out->Quotew( *it ).c_str() );
out->Print( 0, ")\n" );
}
for( GRAPHICS::const_iterator it = graphics.begin(); it != graphics.end(); ++it ) for( GRAPHICS::const_iterator it = graphics.begin(); it != graphics.end(); ++it )
{ {
(*it)->Format( out, indent+1, ctl ); (*it)->Format( out, indent+1, ctl );
...@@ -187,6 +250,274 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_E ...@@ -187,6 +250,274 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_E
{ {
(*it)->Format( out, indent+1, ctl ); (*it)->Format( out, indent+1, ctl );
} }
out->Print( indent, ")\n" );
} }
//-----< PART objects >------------------------------------------------------
void PROPERTY::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const
throw( IO_ERROR )
{
wxASSERT( owner ); // all PROPERTYs should have an owner.
int i;
for( i = PART::REFERENCE; i < PART::END; ++i )
{
if( owner->Field( PART::PROP_ID(i) ) == this )
break;
}
if( i < PART::END ) // is a field not a property
out->Print( indent, "(%s", TO_UTF8( name ) );
else
out->Print( indent, "(property %s", out->Quotew( name ).c_str() );
if( effects )
{
out->Print( 0, " %s\n", out->Quotew( text ).c_str() );
effects->Format( out, indent+1, ctl | CTL_OMIT_NL );
out->Print( 0, ")\n" );
}
else
{
out->Print( 0, " %s)\n", out->Quotew( text ).c_str() );
}
}
TEXT_EFFECTS* PROPERTY::EffectsLookup()
{
if( !effects )
{
effects = new TEXT_EFFECTS();
}
return effects;
}
void TEXT_EFFECTS::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const
throw( IO_ERROR )
{
if( propName.IsEmpty() )
out->Print( indent, "(effects " );
else
out->Print( indent, "(effects %s ", out->Quotew( propName ).c_str() );
out->Print( 0, "(at %.6g %.6g", InternalToLogical( pos.x ), InternalToLogical( pos.y ) );
if( angle )
out->Print( 0, " %.6g)", double( angle ) );
else
out->Print( 0, ")" );
font.Format( out, 0, ctl | CTL_OMIT_NL );
out->Print( 0, "(visible %s))%s",
isVisible ? "yes" : "no",
ctl & CTL_OMIT_NL ? "" : "\n" );
}
void FONT::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const
throw( IO_ERROR )
{
if( name.IsEmpty() )
out->Print( indent, "(font " );
else
out->Print( indent, "(font %s ", out->Quotew( name ).c_str() );
out->Print( 0, "(size %.6g %.6g)",
InternalToLogical( size.GetHeight() ),
InternalToLogical( size.GetWidth() ) );
if( italic )
out->Print( 0, " italic" );
if( bold )
out->Print( 0, " bold" );
out->Print( 0, ")%s", (ctl & CTL_OMIT_NL) ? "" : "\n" );
}
void PIN::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const
throw( IO_ERROR )
{
out->Print( indent, "(pin %s %s ", ShowType(), ShowShape() );
if( angle )
out->Print( 0, "(at %.6g %.6g %.6g)", InternalToLogical( pos.x ), InternalToLogical( pos.y ), double(angle) );
else
out->Print( 0, "(at %.6g %.6g)", InternalToLogical( pos.x ), InternalToLogical( pos.y ) );
out->Print( 0, "(length %.6g)", InternalToLogical( length ) );
out->Print( 0, "(visible %s)\n", isVisible ? "yes" : "no" );
signal.Format( out, "signal", indent+1, 0 );
padname.Format( out, "padname", indent+1, CTL_OMIT_NL );
out->Print( 0, ")\n" );
}
void PINTEXT::Format( OUTPUTFORMATTER* out, const char* aElement, int indent, int ctl ) const
throw( IO_ERROR )
{
out->Print( indent, "(%s %s ", aElement, out->Quotew( text ).c_str() );
font.Format( out, 0, CTL_OMIT_NL );
out->Print( 0, "(visible %s))%s",
isVisible ? "yes" : "no",
ctl & CTL_OMIT_NL ? "" : "\n" );
}
void POLY_LINE::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const
throw( IO_ERROR )
{
out->Print( indent, "(%s ", pts.size() == 2 ? "line" : "polyline" );
formatContents( out, indent, ctl );
}
void POLY_LINE::formatContents( OUTPUTFORMATTER* out, int indent, int ctl ) const
throw( IO_ERROR )
{
out->Print( 0, "(line_width %.6g)", lineWidth ); // @todo use logical units?
if( fillType != PR::T_none )
out->Print( 0, "(fill %s)", ShowFill( fillType ) );
out->Print( 0, "\n" );
if( pts.size() )
{
const int maxLength = 75;
int len = 10;
len += out->Print( indent+1, "(pts " );
for( POINTS::const_iterator it = pts.begin(); it != pts.end(); ++it )
{
if( len > maxLength )
{
len = 10;
out->Print( 0, "\n" );
out->Print( indent+2, "(xy %.6g %.6g)",
InternalToLogical( it->x ), InternalToLogical( it->y ) );
}
else
out->Print( 0, "(xy %.6g %.6g)",
InternalToLogical( it->x ), InternalToLogical( it->y ) );
}
out->Print( 0, ")" );
}
out->Print( 0, ")\n" );
}
void BEZIER::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const
throw( IO_ERROR )
{
out->Print( indent, "(bezier " );
formatContents( out, indent, ctl ); // inherited from POLY_LINE
}
void RECTANGLE::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const
throw( IO_ERROR )
{
// (rectangle (start X Y) (end X Y) (line_width WIDTH) (fill FILL_TYPE))
out->Print( indent, "(rectangle (start %.6g %.6g)(end %.6g %.6g)(line_width %.6g)",
InternalToLogical( start.x ), InternalToLogical( start.y ),
InternalToLogical( end.x ), InternalToLogical( end.y ),
lineWidth );
if( fillType != PR::T_none )
out->Print( 0, "(fill %s)", ShowFill( fillType ) );
out->Print( 0, ")\n" );
}
void CIRCLE::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const
throw( IO_ERROR )
{
/*
(circle (center X Y)(radius LENGTH)(line_width WIDTH)(fill FILL_TYPE))
*/
out->Print( indent, "(circle (center %.6g %.6g)(radius %.6g)(line_width %.6g)",
InternalToLogical( center.x ), InternalToLogical( center.y ),
InternalToLogical( radius),
lineWidth );
if( fillType != PR::T_none )
out->Print( 0, "(fill %s)", ShowFill( fillType ) );
out->Print( 0, ")\n" );
}
void ARC::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const
throw( IO_ERROR )
{
/*
(arc (pos X Y)(radius RADIUS)(start X Y)(end X Y)(line_width WIDTH)(fill FILL_TYPE))
*/
out->Print( indent, "(arc (pos %.6g %.6g)(radius %.6g)(start %.6g %.6g)(end %.6g %.6g)(line_width %.6g)",
InternalToLogical( pos.x ), InternalToLogical( pos.y ),
InternalToLogical( radius),
InternalToLogical( start.x ), InternalToLogical( start.y ),
InternalToLogical( end.x ), InternalToLogical( end.y ),
lineWidth );
if( fillType != PR::T_none )
out->Print( 0, "(fill %s)", ShowFill( fillType ) );
out->Print( 0, ")\n" );
}
void GR_TEXT::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const
throw( IO_ERROR )
{
/*
(text "This is the text that gets drawn."
(at X Y [ANGLE])
# Valid horizontal justification values are center, right, and left. Valid
# vertical justification values are center, top, bottom.
(justify HORIZONTAL_JUSTIFY VERTICAL_JUSTIFY)
(font [FONT] (size HEIGHT WIDTH) [italic] [bold])
(visible YES)
(fill FILL_TYPE)
)
*/
out->Print( indent, "(text %s\n", out->Quotew( text ).c_str() );
if( angle )
out->Print( indent+1, "(at %.6g %.6g %.6g)", InternalToLogical( pos.x ), InternalToLogical( pos.y ), double( angle ) );
else
out->Print( indent+1, "(at %.6g %.6g)", InternalToLogical( pos.x ), InternalToLogical( pos.y ) );
out->Print( 0, "(justify %s %s)(visible %s)",
ShowJustify( hjustify ), ShowJustify( vjustify ),
isVisible ? "yes" : "no" );
if( fillType != PR::T_none )
out->Print( 0, "(fill %s)", ShowFill( fillType ) );
out->Print( 0, "\n" );
font.Format( out, indent+1, CTL_OMIT_NL );
out->Print( 0, ")\n" );
}
...@@ -29,6 +29,32 @@ ...@@ -29,6 +29,32 @@
#include <sch_lib.h> #include <sch_lib.h>
#define INTERNAL_PER_LOGICAL 10000 ///< no. internal units per logical unit
/**
* Function InternalToLogical
* converts an internal coordinate to a logical coordinate. Logical coordinates
* are defined as the standard distance between pins being equal to one.
* Internal coordinates are currently INTERNAL_PER_LOGICAL times that.
*/
static inline double InternalToLogical( int aCoord )
{
return double( aCoord ) / INTERNAL_PER_LOGICAL;
}
/**
* Function LogicalToInternal
* converts a logical coordinate to an internal coordinate. Logical coordinates
* are defined as the standard distance between pins being equal to one.
* Internal coordinates are currently INTERNAL_PER_LOGICAL times that.
*/
static inline int LogicalToInternal( double aCoord )
{
return int( aCoord * INTERNAL_PER_LOGICAL );
}
//-----<temporary home for PART sub objects, move after stable>------------------ //-----<temporary home for PART sub objects, move after stable>------------------
#include <wx/gdicmn.h> #include <wx/gdicmn.h>
...@@ -39,6 +65,9 @@ ...@@ -39,6 +65,9 @@
class OUTPUTFORMATTER; class OUTPUTFORMATTER;
/// Control Bits for Format() functions
#define CTL_OMIT_NL (1<<0) ///< omit new line in Format()s.
namespace SCH { namespace SCH {
class PART; class PART;
...@@ -81,6 +110,9 @@ public: ...@@ -81,6 +110,9 @@ public:
italic( false ), italic( false ),
bold( false ) bold( false )
{} {}
void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR );
}; };
...@@ -99,6 +131,9 @@ struct TEXT_EFFECTS ...@@ -99,6 +131,9 @@ struct TEXT_EFFECTS
isVisible( false ), isVisible( false ),
property( 0 ) property( 0 )
{} {}
void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR );
}; };
...@@ -117,7 +152,16 @@ public: ...@@ -117,7 +152,16 @@ public:
virtual ~BASE_GRAPHIC() {} virtual ~BASE_GRAPHIC() {}
virtual void Format( OUTPUTFORMATTER* aOutputFormatter, int aNestLevel, int aControlBits ) const static const char* ShowFill( int aFillType )
{
return SWEET_LEXER::TokenName( PR::T( aFillType ) );
}
/**
* Function Format
* outputs this object to @a aFormatter in s-expression form.
*/
virtual void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR ) throw( IO_ERROR )
{} {}
}; };
...@@ -134,10 +178,19 @@ protected: ...@@ -134,10 +178,19 @@ protected:
int fillType; // T_none, T_filled, or T_transparent int fillType; // T_none, T_filled, or T_transparent
POINTS pts; POINTS pts;
void formatContents( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR );
public: public:
POLY_LINE( PART* aOwner ) : POLY_LINE( PART* aOwner ) :
BASE_GRAPHIC( aOwner ) BASE_GRAPHIC( aOwner ),
{} lineWidth( 1 ),
fillType( PR::T_none )
{
}
void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR );
}; };
class BEZIER : public POLY_LINE class BEZIER : public POLY_LINE
...@@ -148,7 +201,13 @@ class BEZIER : public POLY_LINE ...@@ -148,7 +201,13 @@ class BEZIER : public POLY_LINE
public: public:
BEZIER( PART* aOwner ) : BEZIER( PART* aOwner ) :
POLY_LINE( aOwner ) POLY_LINE( aOwner )
{} {
lineWidth = 1;
fillType = PR::T_none;
}
void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR );
}; };
class RECTANGLE : public BASE_GRAPHIC class RECTANGLE : public BASE_GRAPHIC
...@@ -164,8 +223,14 @@ protected: ...@@ -164,8 +223,14 @@ protected:
public: public:
RECTANGLE( PART* aOwner ) : RECTANGLE( PART* aOwner ) :
BASE_GRAPHIC( aOwner ) BASE_GRAPHIC( aOwner ),
{} lineWidth( 1 ),
fillType( PR::T_none )
{
}
void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR );
}; };
...@@ -182,8 +247,15 @@ protected: ...@@ -182,8 +247,15 @@ protected:
public: public:
CIRCLE( PART* aOwner ) : CIRCLE( PART* aOwner ) :
BASE_GRAPHIC( aOwner ) BASE_GRAPHIC( aOwner ),
{} radius( LogicalToInternal( 0.5 ) ),
lineWidth( 1 ),
fillType( PR::T_none )
{
}
void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR );
}; };
...@@ -202,8 +274,15 @@ protected: ...@@ -202,8 +274,15 @@ protected:
public: public:
ARC( PART* aOwner ) : ARC( PART* aOwner ) :
BASE_GRAPHIC( aOwner ) BASE_GRAPHIC( aOwner ),
{} lineWidth( 1 ),
fillType( PR::T_none ),
radius( LogicalToInternal( 0.5 ) )
{
}
void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR );
}; };
...@@ -233,6 +312,14 @@ public: ...@@ -233,6 +312,14 @@ public:
vjustify( PR::T_bottom ), vjustify( PR::T_bottom ),
isVisible( true ) isVisible( true )
{} {}
static const char* ShowJustify( int aJustify )
{
return SWEET_LEXER::TokenName( PR::T( aJustify ) );
}
void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR );
}; };
...@@ -245,14 +332,45 @@ protected: ...@@ -245,14 +332,45 @@ protected:
PART* birthplace; ///< at which PART in inheritance chain was this PROPERTY added 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;
void clear()
{
delete effects;
effects = 0;
name = wxEmptyString;
text = wxEmptyString;
}
public: public:
PROPERTY( PART* aOwner, const wxChar* aName = wxT( "" ) ) : PROPERTY( PART* aOwner, const wxChar* aName = wxT( "" ) ) :
BASE_GRAPHIC( aOwner ), BASE_GRAPHIC( aOwner ),
birthplace( aOwner ), birthplace( aOwner ),
name( aName ) name( aName ),
effects( 0 )
{} {}
~PROPERTY()
{
clear();
}
/**
* Function Effects
* returns a pointer to the TEXT_EFFECTS object for this PROPERTY, and optionally
* will lazily allocate one if it did not exist previously.
* @param doAlloc if true, means do an allocation of a new TEXT_EFFECTS if one
* currently does not exist, otherwise return NULL if non-existent.
*/
TEXT_EFFECTS* EffectsLookup();
TEXT_EFFECTS* Effects() const
{
return effects;
}
void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR );
}; };
...@@ -265,6 +383,9 @@ struct PINTEXT ...@@ -265,6 +383,9 @@ struct PINTEXT
PINTEXT() : PINTEXT() :
isVisible( true ) isVisible( true )
{} {}
void Format( OUTPUTFORMATTER* aFormatter, const char* aElement, int aNestLevel, int aControlBits ) const
throw( IO_ERROR );
}; };
...@@ -284,10 +405,18 @@ public: ...@@ -284,10 +405,18 @@ public:
isVisible( true ) isVisible( true )
{} {}
/* const char* ShowType() const
void Format( OUTPUTFORMATTER* aOutputFormatter, int aNestLevel, int aControlBits ) const {
return SWEET_LEXER::TokenName( PR::T( connectionType ) );
}
const char* ShowShape() const
{
return SWEET_LEXER::TokenName( PR::T( shape ) );
}
void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR ); throw( IO_ERROR );
*/
protected: protected:
PART* birthplace; ///< at which PART in inheritance chain was this PIN added PART* birthplace; ///< at which PART in inheritance chain was this PIN added
...@@ -340,86 +469,22 @@ class PART ...@@ -340,86 +469,22 @@ class PART
friend class LIB; // is the owner of all PARTS, afterall friend class LIB; // is the owner of all PARTS, afterall
friend class SWEET_PARSER; friend class SWEET_PARSER;
protected: // not likely to have C++ descendants, but protected none-the-less. public:
/// a protected constructor, only a LIB can instantiate a PART.
PART( LIB* aOwner, const STRING& aPartNameAndRev );
/**
* Function destroy
* clears out this object, deleting all graphics, all fields, all properties,
* etc.
*/
void clear();
/**
* Function inherit
* is a specialized assignment function that copies a specific subset, enough
* to fulfill the requirements of the Sweet s-expression language.
*/
void inherit( const PART& aBasePart );
/**
* Function propertyFind
* searches for aPropertyName and returns a PROPERTIES::iterator which
* is the found item or properties.end() if not found.
*/
PROPERTIES::iterator propertyFind( const wxString& aPropertyName );
POINT anchor;
//PART( LIB* aOwner );
LIB* owner; ///< which LIB am I a part of (pun if you want)
int contains; ///< has bits from Enum PartParts
STRING partNameAndRev; ///< example "passives/R[/revN..]", immutable.
LPID* extends; ///< of base part, NULL if none, otherwise I own it.
PART* base; ///< which PART am I extending, if any. no ownership.
/// encapsulate the old version deletion, take ownership of @a aLPID
void setExtends( LPID* aLPID );
/// s-expression text for the part, initially empty, and read in as this part
/// actually becomes cached in RAM.
STRING body;
// mandatory properties
PROPERTY reference; ///< prefix only, only components have full references
PROPERTY value;
PROPERTY footprint;
PROPERTY model;
PROPERTY datasheet;
// separate lists for speed:
/**
* Member properties
* holds the non-mandatory properties.
*/
PROPERTIES properties;
/** /**
* Member graphics * Enum PROP_ID
* owns : POLY_LINE, RECTANGLE, CIRCLE, ARC, BEZIER, and GR_TEXT objects. * is the set of "mandatory" properties within a PART. These are used by
* class PART as array indices into PART::mandatory[].
*/ */
GRAPHICS graphics; enum PROP_ID
{
/** REFERENCE, ///< reference prefix, a template for instantiation at COMPONENT level
* Member pins VALUE, ///< value, e.g. "3.3K"
* owns all the PINs in pins. FOOTPRINT, ///< name of PCB module, e.g. "16DIP300"
*/ DATASHEET, ///< URI of datasheet
PINS pins; MODEL, ///< spice model name
END ///< array sentinel, not a valid index
/// Alternate body forms. };
//ALTERNATES alternates;
KEYWORDS keywords;
public:
virtual ~PART(); virtual ~PART();
...@@ -457,6 +522,24 @@ public: ...@@ -457,6 +522,24 @@ public:
void PropertyDelete( const wxString& aPropertyName ) throw( IO_ERROR ); void PropertyDelete( const wxString& aPropertyName ) throw( IO_ERROR );
/**
* Function Field
* returns a pointer to one of the mandatory properties, or NULL
* if non-existent. Use FieldLookup() to potentially allocate it.
*/
PROPERTY* Field( PROP_ID aPropertyId ) const
{
wxASSERT( unsigned(aPropertyId) < unsigned(END) );
return mandatory[aPropertyId];
}
/**
* Function FieldLookup
* returns a pointer to one of the mandatory properties, which is lazily
* constructed by this function if need be.
* @param aPropertyId tells which field.
*/
PROPERTY* FieldLookup( PROP_ID aPropertyId );
/* /*
...@@ -494,6 +577,89 @@ public: ...@@ -494,6 +577,89 @@ public:
body = aSExpression; body = aSExpression;
} }
*/ */
protected: // not likely to have C++ descendants, but protected none-the-less.
/// a protected constructor, only a LIB can instantiate a PART.
PART( LIB* aOwner, const STRING& aPartNameAndRev );
/**
* Function destroy
* clears out this object, deleting everything that this PART owns and
* initializing values back to a state as if the object was just constructed
* empty.
*/
void clear();
/**
* Function inherit
* is a specialized assignment function that copies a specific subset, enough
* to fulfill the requirements of the Sweet s-expression language.
*/
void inherit( const PART& aBasePart );
/**
* Function propertyFind
* searches for aPropertyName and returns a PROPERTIES::iterator which
* is the found item or properties.end() if not found.
*/
PROPERTIES::iterator propertyFind( const wxString& aPropertyName );
POINT anchor;
//PART( LIB* aOwner );
LIB* owner; ///< which LIB am I a part of (pun if you want)
int contains; ///< has bits from Enum PartParts
STRING partNameAndRev; ///< example "passives/R[/revN..]", immutable.
LPID* extends; ///< of base part, NULL if none, otherwise I own it.
PART* base; ///< which PART am I extending, if any. no ownership.
/// encapsulate the old version deletion, take ownership of @a aLPID
void setExtends( LPID* aLPID );
/// s-expression text for the part, initially empty, and read in as this part
/// actually becomes cached in RAM.
STRING body;
// mandatory properties
PROPERTY* mandatory[END];
/*
PROPERTY value;
PROPERTY footprint;
PROPERTY model;
PROPERTY datasheet;
*/
// separate lists for speed:
/**
* Member properties
* holds the non-mandatory properties.
*/
PROPERTIES properties;
/**
* Member graphics
* owns : POLY_LINE, RECTANGLE, CIRCLE, ARC, BEZIER, and GR_TEXT objects.
*/
GRAPHICS graphics;
/**
* Member pins
* owns all the PINs in pins.
*/
PINS pins;
/// Alternate body forms.
//ALTERNATES alternates;
KEYWORDS keywords;
}; };
} // namespace PART } // namespace PART
......
...@@ -36,20 +36,9 @@ using namespace PR; ...@@ -36,20 +36,9 @@ using namespace PR;
#define MAX_INHERITANCE_NESTING 6 ///< max depth of inheritance, no problem going larger #define MAX_INHERITANCE_NESTING 6 ///< max depth of inheritance, no problem going larger
/**
* Function log2int
* converts a logical coordinate to an internal coordinate. Logical coordinates
* are defined as the standard distance between pins being equal to one.
* Internal coordinates are currently INTERNAL_PER_LOGICAL times that.
*/
static inline int log2int( double aCoord )
{
return int( aCoord * INTERNAL_PER_LOGICAL );
}
static inline int internal( const STRING& aCoord ) static inline int internal( const STRING& aCoord )
{ {
return log2int( strtod( aCoord.c_str(), NULL ) ); return LogicalToInternal( strtod( aCoord.c_str(), NULL ) );
} }
...@@ -61,15 +50,15 @@ static inline int internal( const STRING& aCoord ) ...@@ -61,15 +50,15 @@ static inline int internal( const STRING& aCoord )
*/ */
enum PartBit enum PartBit
{ {
PARSED, ///< have parsed this part already, otherwise 'body' text must be parsed parsed, ///< have parsed this part already, otherwise 'body' text must be parsed
EXTENDS, ///< saw "extends" keyword, inheriting from another PART extends, ///< saw "extends" keyword, inheriting from another PART
VALUE, value,
ANCHOR, anchor,
REFERENCE, reference,
FOOTPRINT, footprint,
DATASHEET, datasheet,
MODEL, model,
KEYWORDS, keywords,
}; };
...@@ -86,7 +75,7 @@ void SWEET_PARSER::parseExtends( PART* me ) ...@@ -86,7 +75,7 @@ void SWEET_PARSER::parseExtends( PART* me )
PART* base; PART* base;
int offset; int offset;
if( contains & PB(EXTENDS) ) if( contains & PB(extends) )
Duplicate( T_extends ); Duplicate( T_extends );
NeedSYMBOLorNUMBER(); NeedSYMBOLorNUMBER();
...@@ -129,7 +118,7 @@ void SWEET_PARSER::parseExtends( PART* me ) ...@@ -129,7 +118,7 @@ void SWEET_PARSER::parseExtends( PART* me )
me->inherit( *base ); me->inherit( *base );
me->base = base; me->base = base;
contains |= PB(EXTENDS); contains |= PB(extends);
} }
...@@ -175,6 +164,8 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E ...@@ -175,6 +164,8 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
{ {
if( tok == T_LEFT ) if( tok == T_LEFT )
{ {
PROPERTY* prop;
tok = NextTok(); tok = NextTok();
// because exceptions are thrown, any 'new' allocation has to be stored // because exceptions are thrown, any 'new' allocation has to be stored
...@@ -195,13 +186,13 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E ...@@ -195,13 +186,13 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
break; break;
case T_anchor: case T_anchor:
if( contains & PB(ANCHOR) ) if( contains & PB(anchor) )
Duplicate( tok ); Duplicate( tok );
NeedNUMBER( "anchor x" ); NeedNUMBER( "anchor x" );
me->anchor.x = internal( CurText() ); me->anchor.x = internal( CurText() );
NeedNUMBER( "anchor y" ); NeedNUMBER( "anchor y" );
me->anchor.y = internal( CurText() ); me->anchor.y = internal( CurText() );
contains |= PB(ANCHOR); contains |= PB(anchor);
break; break;
case T_line: case T_line:
...@@ -247,130 +238,71 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E ...@@ -247,130 +238,71 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
parseText( text ); parseText( text );
break; break;
// reference in a PART is incomplete, it is just the prefix of an case T_property:
// unannotated reference. Only components have full reference designators. prop = new PROPERTY( me );
case T_reference: // @todo check for uniqueness
if( contains & PB(REFERENCE) ) me->properties.push_back( prop );
Duplicate( tok );
contains |= PB(REFERENCE);
NeedSYMBOLorNUMBER(); NeedSYMBOLorNUMBER();
me->reference.text = FromUTF8(); prop->name = FromUTF8();
L_prop:
NeedSYMBOLorNUMBER();
prop->text = FromUTF8();
tok = NextTok(); tok = NextTok();
if( tok == T_LEFT ) if( tok == T_LEFT )
{ {
tok = NextTok(); tok = NextTok();
if( tok != T_effects ) if( tok != T_effects )
Expecting( T_effects ); Expecting( T_effects );
parseTextEffects( &me->reference.effects ); parseTextEffects( prop->EffectsLookup() );
NeedRIGHT(); NeedRIGHT();
} }
else if( tok != T_RIGHT ) else if( tok != T_RIGHT )
Expecting( ") | effects" ); Expecting( ") | effects" );
break; break;
case T_value: case T_property_del:
if( contains & PB(VALUE) )
Duplicate( tok );
contains |= PB(VALUE);
NeedSYMBOLorNUMBER(); NeedSYMBOLorNUMBER();
me->value.text = FromUTF8(); me->PropertyDelete( FromUTF8() );
tok = NextTok(); NeedRIGHT();
if( tok == T_LEFT )
{
tok = NextTok();
if( tok != T_effects )
Expecting( T_effects );
parseTextEffects( &me->value.effects );
NeedRIGHT();
}
else if( tok != T_RIGHT )
Expecting( ") | effects" );
break; break;
// reference in a PART is incomplete, it is just the prefix of an
// unannotated reference. Only components have full reference designators.
case T_reference:
if( contains & PB(reference) )
Duplicate( tok );
contains |= PB(reference);
prop = me->FieldLookup( PART::REFERENCE );
goto L_prop;
case T_value:
if( contains & PB(value) )
Duplicate( tok );
contains |= PB(value);
prop = me->FieldLookup( PART::VALUE );
goto L_prop;
case T_footprint: case T_footprint:
if( contains & PB(FOOTPRINT) ) if( contains & PB(footprint) )
Duplicate( tok ); Duplicate( tok );
contains |= PB(FOOTPRINT); contains |= PB(footprint);
NeedSYMBOLorNUMBER(); prop = me->FieldLookup( PART::FOOTPRINT );
me->footprint.text = FromUTF8(); goto L_prop;
tok = NextTok();
if( tok == T_LEFT )
{
tok = NextTok();
if( tok != T_effects )
Expecting( T_effects );
parseTextEffects( &me->footprint.effects );
NeedRIGHT();
}
else if( tok != T_RIGHT )
Expecting( ") | effects" );
break;
case T_datasheet: case T_datasheet:
if( contains & PB(MODEL) ) if( contains & PB(datasheet) )
Duplicate( tok ); Duplicate( tok );
contains |= PB(MODEL); contains |= PB(datasheet);
NeedSYMBOLorNUMBER(); prop = me->FieldLookup( PART::DATASHEET );
me->datasheet.text = FromUTF8(); goto L_prop;
tok = NextTok();
if( tok == T_LEFT )
{
tok = NextTok();
if( tok != T_effects )
Expecting( T_effects );
parseTextEffects( &me->datasheet.effects );
NeedRIGHT();
}
else if( tok != T_RIGHT )
Expecting( ") | effects" );
break;
case T_model: case T_model:
if( contains & PB(MODEL) ) if( contains & PB(model) )
Duplicate( tok ); Duplicate( tok );
contains |= PB(MODEL); contains |= PB(model);
NeedSYMBOLorNUMBER(); prop = me->FieldLookup( PART::MODEL );
me->model.text = FromUTF8(); goto L_prop;
tok = NextTok();
if( tok == T_LEFT )
{
tok = NextTok();
if( tok != T_effects )
Expecting( T_effects );
parseTextEffects( &me->model.effects );
NeedRIGHT();
}
else if( tok != T_RIGHT )
Expecting( ") | effects" );
break;
case T_property:
PROPERTY* property;
property = new PROPERTY( me );
// @todo check for uniqueness
me->properties.push_back( property );
NeedSYMBOLorNUMBER();
property->name = FromUTF8();
NeedSYMBOLorNUMBER();
property->text = FromUTF8();
tok = NextTok();
if( tok == T_LEFT )
{
tok = NextTok();
if( tok != T_effects )
Expecting( T_effects );
parseTextEffects( &property->effects );
NeedRIGHT();
}
else if( tok != T_RIGHT )
Expecting( ") | effects" );
break;
case T_property_del:
NeedSYMBOLorNUMBER();
me->PropertyDelete( FromUTF8() );
NeedRIGHT();
break;
case T_pin: case T_pin:
PIN* pin; PIN* pin;
...@@ -404,7 +336,6 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E ...@@ -404,7 +336,6 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
case T_route_pin_swap: case T_route_pin_swap:
break; break;
*/ */
} }
} }
...@@ -419,7 +350,7 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E ...@@ -419,7 +350,7 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
} }
} }
contains |= PB(PARSED); contains |= PB(parsed);
me->contains |= contains; me->contains |= contains;
} }
...@@ -804,6 +735,7 @@ void SWEET_PARSER::parsePolyLine( POLY_LINE* me ) ...@@ -804,6 +735,7 @@ void SWEET_PARSER::parsePolyLine( POLY_LINE* me )
if( sawWidth ) if( sawWidth )
Duplicate( tok ); Duplicate( tok );
NeedNUMBER( "line_width" ); NeedNUMBER( "line_width" );
// @todo Use logical units?
me->lineWidth = strtod( CurText(), NULL ); me->lineWidth = strtod( CurText(), NULL );
NeedRIGHT(); NeedRIGHT();
sawWidth = true; sawWidth = true;
......
...@@ -29,15 +29,6 @@ ...@@ -29,15 +29,6 @@
#include <sweet_lexer.h> #include <sweet_lexer.h>
#define INTERNAL_PER_LOGICAL 10000 ///< no. internal units per logical unit
static inline double InternalToLogical( int aCoord )
{
return double( aCoord ) / INTERNAL_PER_LOGICAL;
}
class POINT; class POINT;
namespace SCH { namespace SCH {
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#include <sch_lib_table.h> #include <sch_lib_table.h>
#include <sch_lib_table_lexer.h> #include <sch_lib_table_lexer.h>
#include <sch_lpid.h> #include <sch_lpid.h>
#include <sch_part.h>
using namespace SCH; using namespace SCH;
...@@ -86,7 +87,12 @@ void LIB_TABLE::Test() ...@@ -86,7 +87,12 @@ void LIB_TABLE::Test()
// find a part // find a part
LPID lpid( "meparts:tigers/ears" ); LPID lpid( "meparts:tigers/ears" );
LookupPart( lpid ); PART* part = LookupPart( lpid );
sf.Clear();
part->Format( &sf, 0, 0 );
printf( "%s", sf.GetString().c_str() );
} }
......
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