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"
REFERENCE="
(reference U
(reference U?
(effects (at 12 13 180)(font (size .7 1))(visible yes))
)"
......@@ -71,7 +71,7 @@ for C in ${CATEGORIES}; do
for P in ${PARTS}; 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
$LINE
$RECT
......@@ -86,7 +86,7 @@ for C in ${CATEGORIES}; do
)" > $BASEDIR/$C/$P.part.$R
done
# 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
$LINE
$RECT
......
......@@ -28,6 +28,7 @@
#include <sch_sweet_parser.h>
#include <sch_lpid.h>
#include <sch_lib_table.h>
#include <macros.h>
//#include <richio.h>
using namespace SCH;
......@@ -38,16 +39,21 @@ PART::PART( LIB* aOwner, const STRING& aPartNameAndRev ) :
contains( 0 ),
partNameAndRev( aPartNameAndRev ),
extends( 0 ),
base( 0 ),
base( 0 )
/*
reference( this, wxT( "reference " ) ),
value( this, wxT( "value" ) ),
footprint( this, wxT( "footprint" ) ),
model( this, wxT( "model" ) ),
datasheet( this, wxT( "datasheet" ) )
*/
{
// 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.
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()
delete *it;
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 )
delete *it;
properties.clear();
......@@ -78,7 +84,54 @@ void PART::clear()
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 )
}
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 );
}
......@@ -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() );
......@@ -160,12 +214,13 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_E
out->Print( 0, "\n" );
/*
@todo
for( int i=0; i<MANDATORY_FIELDS; ++i )
for( int i = REFERENCE; i < END; ++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 )
{
(*it)->Format( out, indent+1, ctl );
......@@ -178,6 +233,14 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_E
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 )
{
(*it)->Format( out, indent+1, ctl );
......@@ -187,6 +250,274 @@ void PART::Format( OUTPUTFORMATTER* out, int indent, int ctl ) const throw( IO_E
{
(*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 @@
#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>------------------
#include <wx/gdicmn.h>
......@@ -39,6 +65,9 @@
class OUTPUTFORMATTER;
/// Control Bits for Format() functions
#define CTL_OMIT_NL (1<<0) ///< omit new line in Format()s.
namespace SCH {
class PART;
......@@ -81,6 +110,9 @@ public:
italic( false ),
bold( false )
{}
void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR );
};
......@@ -99,6 +131,9 @@ struct TEXT_EFFECTS
isVisible( false ),
property( 0 )
{}
void Format( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR );
};
......@@ -117,7 +152,16 @@ public:
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 )
{}
};
......@@ -134,10 +178,19 @@ protected:
int fillType; // T_none, T_filled, or T_transparent
POINTS pts;
void formatContents( OUTPUTFORMATTER* aFormatter, int aNestLevel, int aControlBits ) const
throw( IO_ERROR );
public:
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
......@@ -148,7 +201,13 @@ class BEZIER : public POLY_LINE
public:
BEZIER( PART* 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
......@@ -164,8 +223,14 @@ protected:
public:
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:
public:
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:
public:
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:
vjustify( PR::T_bottom ),
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:
PART* birthplace; ///< at which PART in inheritance chain was this PROPERTY added
wxString name;
wxString text;
TEXT_EFFECTS effects;
TEXT_EFFECTS* effects;
void clear()
{
delete effects;
effects = 0;
name = wxEmptyString;
text = wxEmptyString;
}
public:
PROPERTY( PART* aOwner, const wxChar* aName = wxT( "" ) ) :
BASE_GRAPHIC( 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
PINTEXT() :
isVisible( true )
{}
void Format( OUTPUTFORMATTER* aFormatter, const char* aElement, int aNestLevel, int aControlBits ) const
throw( IO_ERROR );
};
......@@ -284,10 +405,18 @@ public:
isVisible( true )
{}
/*
void Format( OUTPUTFORMATTER* aOutputFormatter, int aNestLevel, int aControlBits ) const
const char* ShowType() 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 );
*/
protected:
PART* birthplace; ///< at which PART in inheritance chain was this PIN added
......@@ -340,86 +469,22 @@ class PART
friend class LIB; // is the owner of all PARTS, afterall
friend class SWEET_PARSER;
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 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;
public:
/**
* Member graphics
* owns : POLY_LINE, RECTANGLE, CIRCLE, ARC, BEZIER, and GR_TEXT objects.
* Enum PROP_ID
* is the set of "mandatory" properties within a PART. These are used by
* class PART as array indices into PART::mandatory[].
*/
GRAPHICS graphics;
/**
* Member pins
* owns all the PINs in pins.
*/
PINS pins;
/// Alternate body forms.
//ALTERNATES alternates;
KEYWORDS keywords;
public:
enum PROP_ID
{
REFERENCE, ///< reference prefix, a template for instantiation at COMPONENT level
VALUE, ///< value, e.g. "3.3K"
FOOTPRINT, ///< name of PCB module, e.g. "16DIP300"
DATASHEET, ///< URI of datasheet
MODEL, ///< spice model name
END ///< array sentinel, not a valid index
};
virtual ~PART();
......@@ -457,6 +522,24 @@ public:
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:
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
......
......@@ -36,20 +36,9 @@ using namespace PR;
#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 )
{
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 )
*/
enum PartBit
{
PARSED, ///< have parsed this part already, otherwise 'body' text must be parsed
EXTENDS, ///< saw "extends" keyword, inheriting from another PART
VALUE,
ANCHOR,
REFERENCE,
FOOTPRINT,
DATASHEET,
MODEL,
KEYWORDS,
parsed, ///< have parsed this part already, otherwise 'body' text must be parsed
extends, ///< saw "extends" keyword, inheriting from another PART
value,
anchor,
reference,
footprint,
datasheet,
model,
keywords,
};
......@@ -86,7 +75,7 @@ void SWEET_PARSER::parseExtends( PART* me )
PART* base;
int offset;
if( contains & PB(EXTENDS) )
if( contains & PB(extends) )
Duplicate( T_extends );
NeedSYMBOLorNUMBER();
......@@ -129,7 +118,7 @@ void SWEET_PARSER::parseExtends( PART* me )
me->inherit( *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
{
if( tok == T_LEFT )
{
PROPERTY* prop;
tok = NextTok();
// 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
break;
case T_anchor:
if( contains & PB(ANCHOR) )
if( contains & PB(anchor) )
Duplicate( tok );
NeedNUMBER( "anchor x" );
me->anchor.x = internal( CurText() );
NeedNUMBER( "anchor y" );
me->anchor.y = internal( CurText() );
contains |= PB(ANCHOR);
contains |= PB(anchor);
break;
case T_line:
......@@ -247,130 +238,71 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
parseText( text );
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);
case T_property:
prop = new PROPERTY( me );
// @todo check for uniqueness
me->properties.push_back( prop );
NeedSYMBOLorNUMBER();
me->reference.text = FromUTF8();
prop->name = FromUTF8();
L_prop:
NeedSYMBOLorNUMBER();
prop->text = FromUTF8();
tok = NextTok();
if( tok == T_LEFT )
{
tok = NextTok();
if( tok != T_effects )
Expecting( T_effects );
parseTextEffects( &me->reference.effects );
parseTextEffects( prop->EffectsLookup() );
NeedRIGHT();
}
else if( tok != T_RIGHT )
Expecting( ") | effects" );
break;
case T_value:
if( contains & PB(VALUE) )
Duplicate( tok );
contains |= PB(VALUE);
case T_property_del:
NeedSYMBOLorNUMBER();
me->value.text = FromUTF8();
tok = NextTok();
if( tok == T_LEFT )
{
tok = NextTok();
if( tok != T_effects )
Expecting( T_effects );
parseTextEffects( &me->value.effects );
me->PropertyDelete( FromUTF8() );
NeedRIGHT();
}
else if( tok != T_RIGHT )
Expecting( ") | effects" );
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:
if( contains & PB(FOOTPRINT) )
if( contains & PB(footprint) )
Duplicate( tok );
contains |= PB(FOOTPRINT);
NeedSYMBOLorNUMBER();
me->footprint.text = FromUTF8();
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;
contains |= PB(footprint);
prop = me->FieldLookup( PART::FOOTPRINT );
goto L_prop;
case T_datasheet:
if( contains & PB(MODEL) )
if( contains & PB(datasheet) )
Duplicate( tok );
contains |= PB(MODEL);
NeedSYMBOLorNUMBER();
me->datasheet.text = FromUTF8();
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;
contains |= PB(datasheet);
prop = me->FieldLookup( PART::DATASHEET );
goto L_prop;
case T_model:
if( contains & PB(MODEL) )
if( contains & PB(model) )
Duplicate( tok );
contains |= PB(MODEL);
NeedSYMBOLorNUMBER();
me->model.text = FromUTF8();
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;
contains |= PB(model);
prop = me->FieldLookup( PART::MODEL );
goto L_prop;
case T_pin:
PIN* pin;
......@@ -404,7 +336,6 @@ void SWEET_PARSER::Parse( PART* me, LIB_TABLE* aTable ) throw( IO_ERROR, PARSE_E
case T_route_pin_swap:
break;
*/
}
}
......@@ -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;
}
......@@ -804,6 +735,7 @@ void SWEET_PARSER::parsePolyLine( POLY_LINE* me )
if( sawWidth )
Duplicate( tok );
NeedNUMBER( "line_width" );
// @todo Use logical units?
me->lineWidth = strtod( CurText(), NULL );
NeedRIGHT();
sawWidth = true;
......
......@@ -29,15 +29,6 @@
#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;
namespace SCH {
......
......@@ -25,6 +25,7 @@
#include <sch_lib_table.h>
#include <sch_lib_table_lexer.h>
#include <sch_lpid.h>
#include <sch_part.h>
using namespace SCH;
......@@ -86,7 +87,12 @@ void LIB_TABLE::Test()
// find a part
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