Commit babc73e7 authored by dickelbeck's avatar dickelbeck

first version after splitting out specctra.h

parent b67f7983
......@@ -41,7 +41,8 @@
Wide use is made of boost::ptr_vector<> and std::vector<> template classes.
If the contained object is small, then std::vector tends to be used.
If the contained object is large, or variable size, then boost::ptr_vector
If the contained object is large, variable size, or would require writing
an assignment operator() or copy constructore, then boost::ptr_vector
cannot be beat.
*/
......@@ -49,3053 +50,21 @@
#include <cstdarg>
#include <cstdio>
#include <boost/ptr_container/ptr_vector.hpp>
#include "specctra.h"
#include <wx/ffile.h>
#include "fctsys.h"
#include "pcbstruct.h"
#include "dsn.h"
//#include <time.h>
#define EDA_BASE // build_version.h behavior
#undef COMMON_GLOBL
#define COMMON_GLOBL // build_version.h behavior
#include "build_version.h"
namespace DSN {
#define NESTWIDTH 4 ///< how many spaces per nestLevel
class SPECCTRA_DB;
class PCB;
/**
* Class OUTPUTFORMATTER
* is an interface (abstract class) used to output ASCII text. The destination
* of the ASCII text is up to the implementer.
*/
class OUTPUTFORMATTER
{
// When used on a C++ function, we must account for the "this" pointer,
// so increase the STRING-INDEX and FIRST-TO_CHECK by one.
// See http://docs.freebsd.org/info/gcc/gcc.info.Function_Attributes.html
// Then to get format checking during the compile, compile with -Wall or -Wformat
#define PRINTF_FUNC __attribute__ ((format (printf, 3, 4)))
public:
/**
* Function print
* formats and writes text to the output stream.
*
* @param nestLevel The multiple of spaces to preceed the output with.
* @param fmt A printf() style format string.
* @param ... a variable list of parameters that will get blended into
* the output under control of the format string.
* @return int - the number of characters output.
* @throw IOError, if there is a problem outputting, such as a full disk.
*/
virtual int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError ) = 0;
/**
* Function GetQuoteChar
* returns the quote character as a single character string for a given
* input wrapee string. Often the return value is "" the null string if
* there are no delimiters in the input string. If you want the quote_char
* to be assuredly not "", then pass in "(" as the wrappee.
* @param wrapee A string that might need wrapping on each end.
* @return const char* - the quote_char as a single character string, or ""
* if the wrapee does not need to be wrapped.
*/
virtual const char* GetQuoteChar( const char* wrapee ) = 0;
};
struct POINT
{
float x;
float y;
POINT() { x=0.0; y=0.0; }
/**
* Function Format
* writes this object as ASCII out to an OUTPUTFORMATTER according to the
* SPECCTRA DSN format.
* @param out The formatter to write to.
* @param nestLevel A multiple of the number of spaces to preceed the output with.
* @throw IOError if a system error writing the output, such as a full disk.
*/
void Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IOError )
{
out->Print( nestLevel, " %f %f", x, y );
}
};
typedef std::vector<std::string> STRINGS;
typedef std::vector<POINT> POINTS;
struct PROPERTY
{
std::string name;
std::string value;
/**
* Function Format
* writes this object as ASCII out to an OUTPUTFORMATTER according to the
* SPECCTRA DSN format.
* @param out The formatter to write to.
* @param nestLevel A multiple of the number of spaces to preceed the output with.
* @throw IOError if a system error writing the output, such as a full disk.
*/
void Format( OUTPUTFORMATTER* out, int nestLevel ) const throw( IOError )
{
const char* quoteName = out->GetQuoteChar( name.c_str() );
const char* quoteValue = out->GetQuoteChar( value.c_str() );
out->Print( nestLevel, "(%s%s%s %s%s%s)\n",
quoteName, name.c_str(), quoteName,
quoteValue, value.c_str(), quoteValue );
}
};
typedef std::vector<PROPERTY> PROPERTIES;
/**
* Class ELEM
* is a base class for any DSN element class.
* See class ELEM_HOLDER also.
*/
class ELEM
{
protected:
DSN_T type;
ELEM* parent;
public:
ELEM( DSN_T aType, ELEM* aParent = 0 );
virtual ~ELEM();
DSN_T Type() { return type; }
/**
* Function GetUnits
* returns the units for this section. Derived classes may override this
* to check for section specific overrides.
* @return DSN_T - one of the allowed values to &lt;unit_descriptor&gt;
*/
virtual DSN_T GetUnits()
{
if( parent )
return parent->GetUnits();
return T_inch;
}
/**
* Function Format
* writes this object as ASCII out to an OUTPUTFORMATTER according to the
* SPECCTRA DSN format.
* @param out The formatter to write to.
* @param nestLevel A multiple of the number of spaces to preceed the output with.
* @throw IOError if a system error writing the output, such as a full disk.
*/
virtual void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError );
/**
* Function FormatContents
* writes the contents as ASCII out to an OUTPUTFORMATTER according to the
* SPECCTRA DSN format. This is the same as Format() except that the outer
* wrapper is not included.
* @param out The formatter to write to.
* @param nestLevel A multiple of the number of spaces to preceed the output with.
* @throw IOError if a system error writing the output, such as a full disk.
*/
virtual void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
// overridden in ELEM_HOLDER
}
};
/**
* Class ELEM_HOLDER
* is a holder for any DSN class. It can contain other
* class instances, including classes derived from this class.
*/
class ELEM_HOLDER : public ELEM
{
// see http://www.boost.org/libs/ptr_container/doc/ptr_sequence_adapter.html
typedef boost::ptr_vector<ELEM> ELEM_ARRAY;
ELEM_ARRAY kids; ///< ELEM pointers
public:
ELEM_HOLDER( DSN_T aType, ELEM* aParent = 0 ) :
ELEM( aType, aParent )
{
}
virtual void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError );
//-----< list operations >--------------------------------------------
/**
* Function FindElem
* finds a particular instance number of a given type of ELEM.
* @param aType The type of ELEM to find
* @param instanceNum The instance number of to find: 0 for first, 1 for second, etc.
* @return int - The index into the kids array or -1 if not found.
*/
int FindElem( DSN_T aType, int instanceNum = 0 );
/**
* Function Length
* returns the number of ELEMs in this ELEM.
* @return int - the count of children
*/
int Length() const
{
return kids.size();
}
void Append( ELEM* aElem )
{
kids.push_back( aElem );
}
ELEM* Replace( int aIndex, ELEM* aElem )
{
ELEM_ARRAY::auto_type ret = kids.replace( aIndex, aElem );
return ret.release();
}
ELEM* Remove( int aIndex )
{
ELEM_ARRAY::auto_type ret = kids.release( kids.begin()+aIndex );
return ret.release();
}
void Insert( int aIndex, ELEM* aElem )
{
kids.insert( kids.begin()+aIndex, aElem );
}
ELEM* At( int aIndex )
{
// we have varying sized objects and are using polymorphism, so we
// must return a pointer not a reference.
return &kids[aIndex];
}
ELEM* operator[]( int aIndex )
{
return At( aIndex );
}
void Delete( int aIndex )
{
kids.erase( kids.begin()+aIndex );
}
};
/**
* Class PARSER
* is simply a configuration record per the SPECCTRA DSN file spec.
* It is not actually a parser, but rather corresponds to &lt;parser_descriptor&gt;
*/
class PARSER : public ELEM
{
friend class SPECCTRA_DB;
char string_quote;
bool space_in_quoted_tokens;
bool case_sensitive;
bool wires_include_testpoint;
bool routes_include_testpoint;
bool routes_include_guides;
bool routes_include_image_conductor;
bool via_rotate_first;
bool generated_by_freeroute;
std::string const_id1;
std::string const_id2;
std::string host_cad;
std::string host_version;
public:
PARSER( ELEM* aParent ) :
ELEM( T_parser, aParent )
{
string_quote = '"';
space_in_quoted_tokens = false;
case_sensitive = false;
wires_include_testpoint = false;
routes_include_testpoint = false;
routes_include_guides = false;
routes_include_image_conductor = false;
via_rotate_first = true;
generated_by_freeroute = false;
host_cad = "Kicad's PCBNEW";
host_version = CONV_TO_UTF8(g_BuildVersion);
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError );
};
/**
* Class UNIT_RES
* is a holder for either a T_unit or T_resolution object which are usually
* mutually exclusive in the dsn grammar, except within the T_pcb level.
*/
class UNIT_RES : public ELEM
{
friend class SPECCTRA_DB;
DSN_T units;
int value;
public:
UNIT_RES( ELEM* aParent, DSN_T aType ) :
ELEM( aType, aParent )
{
units = T_inch;
value = 2540000;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
if( type == T_unit )
out->Print( nestLevel, "(%s %s)\n", LEXER::GetTokenText( Type() ),
LEXER::GetTokenText(units) );
else // T_resolution
out->Print( nestLevel, "(%s %s %d)\n", LEXER::GetTokenText( Type() ),
LEXER::GetTokenText(units), value );
}
DSN_T GetUnits()
{
return units;
}
};
class RECTANGLE : public ELEM
{
friend class SPECCTRA_DB;
std::string layer_id;
POINT point0;
POINT point1;
public:
RECTANGLE( ELEM* aParent ) :
ELEM( T_rect, aParent )
{
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( layer_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s %f %f %f %f)\n",
LEXER::GetTokenText( Type() ),
quote, layer_id.c_str(), quote,
point0.x, point0.y,
point1.x, point1.y );
}
};
/**
* Class RULE
* corresponds to the &lt;rule_descriptor&gt; in the specctra dsn spec.
*/
class RULE : public ELEM
{
friend class SPECCTRA_DB;
STRINGS rules; ///< rules are saved in std::string form.
public:
RULE( ELEM* aParent, DSN_T aType ) :
ELEM( aType, aParent )
{
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
out->Print( nestLevel, "(%s ", LEXER::GetTokenText( Type() ) );
bool singleLine;
if( rules.size() == 1 )
{
singleLine = true;
out->Print( 0, "%s)", rules.begin()->c_str() );
}
else
{
singleLine = false;
for( STRINGS::const_iterator i = rules.begin(); i!=rules.end(); ++i )
out->Print( nestLevel, "%s\n", i->c_str() );
out->Print( nestLevel, ")" );
}
if( nestLevel || !singleLine )
out->Print( 0, "\n" );
}
};
#if 0
class PLACE_RULE : public RULE
{
friend class SPECCTRA_DB;
DSN_T object_type;
DSN_T image_type;
/* T_spacing, T_permit_orient, T_permit_side & T_opposite_side are
all stored in the kids list.
*/
public:
PLACE_RULE( ELEM* aParent ) :
RULE( aParent, T_place_rule )
{
object_type = T_NONE;
image_type = T_NONE;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
if( object_type != T_NONE )
{
if( object_type == T_pcb )
out->Print( nestLevel, "(object_type %s",
LEXER::GetTokenText( object_type ) );
else
out->Print( nestLevel, "(object_type image_set %s",
LEXER::GetTokenText( object_type ) );
if( image_type != T_NONE )
out->Print( 0, " (image_type %s)", LEXER::GetTokenText( image_type ) );
out->Print( 0, ")\n" );
}
RULE::FormatContents( out, nestLevel );
}
};
#endif
class LAYER_RULE : public ELEM
{
friend class SPECCTRA_DB;
STRINGS layer_ids;
RULE* rule;
public:
LAYER_RULE( ELEM* aParent ) :
ELEM( T_layer_rule, aParent )
{
rule = 0;
}
~LAYER_RULE()
{
delete rule;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
out->Print( nestLevel, "(%s", LEXER::GetTokenText( Type() ) );
for( STRINGS::const_iterator i=layer_ids.begin(); i!=layer_ids.end(); ++i )
{
const char* quote = out->GetQuoteChar( i->c_str() );
out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
}
out->Print( 0 , "\n" );
if( rule )
rule->Format( out, nestLevel+1 );
out->Print( nestLevel, ")\n" );
}
};
typedef boost::ptr_vector<LAYER_RULE> LAYER_RULES;
/**
* Class PATH
* supports both the &lt;path_descriptor&gt; and the &lt;polygon_descriptor&gt; per
* the specctra dsn spec.
*/
class PATH : public ELEM
{
friend class SPECCTRA_DB;
std::string layer_id;
double aperture_width;
POINTS points;
DSN_T aperture_type;
public:
PATH( ELEM* aParent, DSN_T aType ) :
ELEM( aType, aParent )
{
aperture_width = 0.0;
aperture_type = T_round;
}
~PATH()
{
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( layer_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s %f\n", LEXER::GetTokenText( Type() ),
quote, layer_id.c_str(), quote,
aperture_width );
for( unsigned i=0; i<points.size(); ++i )
{
out->Print( nestLevel+1, "%f %f\n", points[i].x, points[i].y );
}
if( aperture_type == T_square )
out->Print( nestLevel+1, "(aperture_type square)\n" );
out->Print( nestLevel, ")\n" );
}
};
/// see http://www.boost.org/libs/ptr_container/doc/ptr_sequence_adapter.html
typedef boost::ptr_vector<PATH> PATHS;
class BOUNDARY : public ELEM
{
friend class SPECCTRA_DB;
// only one or the other of these two is used, not both
PATHS paths;
RECTANGLE* rectangle;
public:
BOUNDARY( ELEM* aParent, DSN_T aType = T_boundary ) :
ELEM( aType, aParent )
{
rectangle = 0;
}
~BOUNDARY()
{
delete rectangle;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) );
if( rectangle )
rectangle->Format( out, nestLevel+1 );
else
{
for( PATHS::iterator i=paths.begin(); i!=paths.end(); ++i )
i->Format( out, nestLevel+1 );
}
out->Print( nestLevel, ")\n" );
}
};
class CIRCLE : public ELEM
{
friend class SPECCTRA_DB;
std::string layer_id;
double diameter;
POINT vertex;
public:
CIRCLE( ELEM* aParent ) :
ELEM( T_circle, aParent )
{
diameter = 0.0;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( layer_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s %f %f %f)\n", LEXER::GetTokenText( Type() ) ,
quote, layer_id.c_str(), quote,
diameter, vertex.x, vertex.y );
}
};
class QARC : public ELEM
{
friend class SPECCTRA_DB;
std::string layer_id;
double aperture_width;
POINT vertex[3];
public:
QARC( ELEM* aParent ) :
ELEM( T_qarc, aParent )
{
aperture_width = 0.0;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( layer_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s %f\n", LEXER::GetTokenText( Type() ) ,
quote, layer_id.c_str(), quote,
aperture_width);
for( int i=0; i<3; ++i )
out->Print( nestLevel+1, "%f %f\n", vertex[i].x, vertex[i].y );
out->Print( nestLevel, ")\n" );
}
};
class WINDOW : public ELEM
{
friend class SPECCTRA_DB;
//----- only one of these is used, like a union -----
PATH* path; ///< used for both path and polygon
RECTANGLE* rectangle;
CIRCLE* circle;
QARC* qarc;
//---------------------------------------------------
public:
WINDOW( ELEM* aParent ) :
ELEM( T_window, aParent )
{
path = 0;
rectangle = 0;
circle = 0;
qarc = 0;
}
~WINDOW()
{
delete path;
delete rectangle;
delete circle;
delete qarc;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
// these are mutually exclusive
if( rectangle )
rectangle->Format( out, nestLevel );
else if( path )
path->Format( out, nestLevel );
else if( circle )
circle->Format( out, nestLevel );
else if( qarc )
qarc->Format( out, nestLevel );
}
};
typedef boost::ptr_vector<WINDOW> WINDOWS;
/**
* Class KEEPOUT
* is used for <keepout_descriptor> and <plane_descriptor>.
*/
class KEEPOUT : public ELEM
{
friend class SPECCTRA_DB;
protected:
std::string name;
int sequence_number;
RULE* rules;
RULE* place_rules;
WINDOWS windows;
//----- only one of these is used, like a union -----
PATH* path; ///< used for both path and polygon
RECTANGLE* rectangle;
CIRCLE* circle;
QARC* qarc;
//---------------------------------------------------
public:
/**
* Constructor KEEPOUT
* requires a DSN_T because this class is used for T_place_keepout, T_via_keepout,
* T_wire_keepout, T_bend_keepout, and T_elongate_keepout as well as T_keepout.
*/
KEEPOUT( ELEM* aParent, DSN_T aType ) :
ELEM( aType, aParent )
{
rules = 0;
place_rules = 0;
path = 0;
rectangle = 0;
circle = 0;
qarc = 0;
sequence_number = -1;
}
~KEEPOUT()
{
delete rules;
delete place_rules;
delete path;
delete rectangle;
delete circle;
delete qarc;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) );
if( name.size() )
{
const char* quote = out->GetQuoteChar( name.c_str() );
out->Print( nestLevel+1, "%s%s%s\n", quote, name.c_str(), quote );
}
if( sequence_number != -1 )
out->Print( nestLevel+1, "(sequence_number %d)\n", sequence_number );
// these are mutually exclusive
if( rectangle )
rectangle->Format( out, nestLevel+1 );
else if( path )
path->Format( out, nestLevel+1 );
else if( circle )
circle->Format( out, nestLevel+1 );
else if( qarc )
qarc->Format( out, nestLevel+1 );
if( rules )
rules->Format( out, nestLevel+1 );
if( place_rules )
place_rules->Format( out, nestLevel+1 );
for( WINDOWS::iterator i=windows.begin(); i!=windows.end(); ++i )
i->Format( out, nestLevel+1 );
out->Print( nestLevel, ")\n" );
}
};
class VIA : public ELEM
{
friend class SPECCTRA_DB;
STRINGS padstacks;
STRINGS spares;
public:
VIA( ELEM* aParent ) :
ELEM( T_via, aParent )
{
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) );
for( STRINGS::iterator i=padstacks.begin(); i!=padstacks.end(); ++i )
{
const char* quote = out->GetQuoteChar( i->c_str() );
out->Print( nestLevel+1, "%s%s%s\n", quote, i->c_str(), quote );
}
if( spares.size() )
{
out->Print( nestLevel+1, "(spare\n" );
for( STRINGS::iterator i=spares.begin(); i!=spares.end(); ++i )
{
const char* quote = out->GetQuoteChar( i->c_str() );
out->Print( nestLevel+2, "%s%s%s\n", quote, i->c_str(), quote );
}
out->Print( nestLevel+1, ")\n" );
}
out->Print( nestLevel, ")\n" );
}
};
class CLASSES : public ELEM
{
friend class SPECCTRA_DB;
STRINGS class_ids;
public:
CLASSES( ELEM* aParent ) :
ELEM( T_classes, aParent )
{
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
for( STRINGS::iterator i=class_ids.begin(); i!=class_ids.end(); ++i )
{
const char* quote = out->GetQuoteChar( i->c_str() );
out->Print( nestLevel, "%s%s%s\n", quote, i->c_str(), quote );
}
}
};
class CLASS_CLASS : public ELEM_HOLDER
{
friend class SPECCTRA_DB;
CLASSES* classes;
/* rule | layer_rule are put into the kids container.
*/
public:
/**
* Constructor CLASS_CLASS
* @param aType May be either T_class_class or T_region_class_class
*/
CLASS_CLASS( ELEM* aParent, DSN_T aType ) :
ELEM_HOLDER( aType, aParent )
{
classes = 0;
}
~CLASS_CLASS()
{
delete classes;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
if( classes )
classes->Format( out, nestLevel );
// format the kids
ELEM_HOLDER::FormatContents( out, nestLevel );
}
};
class CONTROL : public ELEM_HOLDER
{
friend class SPECCTRA_DB;
bool via_at_smd;
bool via_at_smd_grid_on;
public:
CONTROL( ELEM* aParent ) :
ELEM_HOLDER( T_control, aParent )
{
via_at_smd = false;
via_at_smd_grid_on = false;
}
~CONTROL()
{
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) );
//if( via_at_smd )
{
out->Print( nestLevel+1, "(via_at_smd %s", via_at_smd ? "on" : "off" );
if( via_at_smd_grid_on )
out->Print( 0, " grid %s", via_at_smd_grid_on ? "on" : "off" );
out->Print( 0, ")\n" );
}
for( int i=0; i<Length(); ++i )
{
At(i)->Format( out, nestLevel+1 );
}
out->Print( nestLevel, ")\n" );
}
};
class LAYER : public ELEM
{
friend class SPECCTRA_DB;
std::string name;
DSN_T layer_type; ///< one of: T_signal, T_power, T_mixed, T_jumper
int direction;
int cost; ///< [forbidden | high | medium | low | free | <positive_integer > | -1]
int cost_type; ///< T_length | T_way
RULE* rules;
STRINGS use_net;
PROPERTIES properties;
public:
LAYER( ELEM* aParent ) :
ELEM( T_layer, aParent )
{
layer_type = T_signal;
direction = -1;
cost = -1;
cost_type = -1;
rules = 0;
}
~LAYER()
{
delete rules;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( name.c_str() );
out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ),
quote, name.c_str(), quote );
out->Print( nestLevel+1, "(type %s)\n", LEXER::GetTokenText( layer_type ) );
if( properties.size() )
{
out->Print( nestLevel+1, "(property \n" );
for( PROPERTIES::iterator i = properties.begin(); i != properties.end(); ++i )
{
i->Format( out, nestLevel+2 );
}
out->Print( nestLevel+1, ")\n" );
}
if( direction != -1 )
out->Print( nestLevel+1, "(direction %s)\n",
LEXER::GetTokenText( (DSN_T)direction ) );
if( rules )
rules->Format( out, nestLevel+1 );
if( cost != -1 )
{
if( cost < 0 )
out->Print( nestLevel+1, "(cost %d", -cost ); // positive integer, stored as negative
else
out->Print( nestLevel+1, "(cost %s", LEXER::GetTokenText( (DSN_T)cost ) );
if( cost_type != -1 )
out->Print( 0, " (type %s)", LEXER::GetTokenText( (DSN_T)cost_type ) );
out->Print( 0, ")\n" );
}
if( use_net.size() )
{
out->Print( nestLevel+1, "(use_net" );
for( STRINGS::const_iterator i = use_net.begin(); i!=use_net.end(); ++i )
{
const char* quote = out->GetQuoteChar( i->c_str() );
out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
}
out->Print( 0, ")\n" );
}
out->Print( nestLevel, ")\n" );
}
};
class LAYER_PAIR : public ELEM
{
friend class SPECCTRA_DB;
std::string layer_id0;
std::string layer_id1;
double layer_weight;
public:
LAYER_PAIR( ELEM* aParent ) :
ELEM( T_layer_pair, aParent )
{
layer_weight = 0.0;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote0 = out->GetQuoteChar( layer_id0.c_str() );
const char* quote1 = out->GetQuoteChar( layer_id1.c_str() );
out->Print( nestLevel, "(%s %s%s%s %s%s%s %f)\n", LEXER::GetTokenText( Type() ),
quote0, layer_id0.c_str(), quote0,
quote1, layer_id1.c_str(), quote1,
layer_weight );
}
};
class LAYER_NOISE_WEIGHT : public ELEM
{
friend class SPECCTRA_DB;
typedef boost::ptr_vector<LAYER_PAIR> LAYER_PAIRS;
LAYER_PAIRS layer_pairs;
public:
LAYER_NOISE_WEIGHT( ELEM* aParent ) :
ELEM( T_layer_noise_weight, aParent )
{
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) );
for( LAYER_PAIRS::iterator i=layer_pairs.begin(); i!=layer_pairs.end(); ++i )
i->Format( out, nestLevel+1 );
out->Print( nestLevel, ")\n" );
}
};
class PLANE : public KEEPOUT
{
friend class SPECCTRA_DB;
public:
PLANE( ELEM* aParent ) :
KEEPOUT( aParent, T_plane )
{}
};
/**
* Class TOKPROP
* is a container for a single property whose value is another DSN_T token.
* The name of the property is obtained from the DSN_T Type().
*/
class TOKPROP : public ELEM
{
friend class SPECCTRA_DB;
DSN_T value;
public:
TOKPROP( ELEM* aParent, DSN_T aType ) :
ELEM( aType, aParent )
{
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
out->Print( nestLevel, "(%s %s)\n", LEXER::GetTokenText( Type() ),
LEXER::GetTokenText( value ) );
}
};
/**
* Class STRINGPROP
* is a container for a single property whose value is a string.
* The name of the property is obtained from the DSN_T.
*/
class STRINGPROP : public ELEM
{
friend class SPECCTRA_DB;
std::string value;
public:
STRINGPROP( ELEM* aParent, DSN_T aType ) :
ELEM( aType, aParent )
{
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( value.c_str() );
out->Print( nestLevel, "(%s %s%s%s)\n", LEXER::GetTokenText( Type() ),
quote, value.c_str(), quote );
}
};
class REGION : public ELEM_HOLDER
{
friend class SPECCTRA_DB;
std::string region_id;
//-----<mutually exclusive>--------------------------------------
RECTANGLE* rectangle;
PATH* polygon;
//-----</mutually exclusive>-------------------------------------
/* region_net | region_class | region_class_class are all mutually
exclusive and are put into the kids container.
*/
RULE* rules;
public:
REGION( ELEM* aParent ) :
ELEM_HOLDER( T_region, aParent )
{
rectangle = 0;
polygon = 0;
rules = 0;
}
~REGION()
{
delete rectangle;
delete polygon;
delete rules;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
if( region_id.size() )
{
const char* quote = out->GetQuoteChar( region_id.c_str() );
out->Print( nestLevel, "%s%s%s\n", quote, region_id.c_str(), quote );
}
if( rectangle )
rectangle->Format( out, nestLevel );
if( polygon )
polygon->Format( out, nestLevel );
ELEM_HOLDER::FormatContents( out, nestLevel );
if( rules )
rules->Format( out, nestLevel );
}
};
class GRID : public ELEM
{
friend class SPECCTRA_DB;
DSN_T grid_type; ///< T_via | T_wire | T_via_keepout | T_place | T_snap
float dimension;
DSN_T direction; ///< T_x | T_y | -1 for both
float offset;
DSN_T image_type;
public:
GRID( ELEM* aParent ) :
ELEM( T_grid, aParent )
{
grid_type = T_via;
direction = T_NONE;
dimension = 0.0;
offset = 0.0;
image_type= T_NONE;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
out->Print( nestLevel, "(%s %s %f",
LEXER::GetTokenText( Type() ),
LEXER::GetTokenText( grid_type ), dimension );
if( grid_type == T_place )
{
if( image_type==T_smd || image_type==T_pin )
out->Print( 0, " (image_type %s)", LEXER::GetTokenText( image_type ) );
}
else
{
if( direction==T_x || direction==T_y )
out->Print( 0, " (direction %s)", LEXER::GetTokenText( direction ) );
}
if( offset != 0.0 )
out->Print( 0, " (offset %f)", offset );
out->Print( 0, ")\n");
}
};
class STRUCTURE : public ELEM_HOLDER
{
friend class SPECCTRA_DB;
UNIT_RES* unit;
typedef boost::ptr_vector<LAYER> LAYERS;
LAYERS layers;
LAYER_NOISE_WEIGHT* layer_noise_weight;
BOUNDARY* boundary;
BOUNDARY* place_boundary;
VIA* via;
CONTROL* control;
RULE* rules;
typedef boost::ptr_vector<KEEPOUT> KEEPOUTS;
KEEPOUTS keepouts;
typedef boost::ptr_vector<PLANE> PLANES;
PLANES planes;
typedef boost::ptr_vector<REGION> REGIONS;
REGIONS regions;
RULE* place_rules;
typedef boost::ptr_vector<GRID> GRIDS;
GRIDS grids;
public:
STRUCTURE( ELEM* aParent ) :
ELEM_HOLDER( T_structure, aParent )
{
unit = 0;
layer_noise_weight = 0;
boundary = 0;
place_boundary = 0;
via = 0;
control = 0;
rules = 0;
place_rules = 0;
}
~STRUCTURE()
{
delete unit;
delete layer_noise_weight;
delete boundary;
delete place_boundary;
delete via;
delete control;
delete rules;
delete place_rules;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
if( unit )
unit->Format( out, nestLevel );
for( LAYERS::iterator i=layers.begin(); i!=layers.end(); ++i )
i->Format( out, nestLevel );
if( layer_noise_weight )
layer_noise_weight->Format( out, nestLevel );
if( boundary )
boundary->Format( out, nestLevel );
if( place_boundary )
place_boundary->Format( out, nestLevel );
for( PLANES::iterator i=planes.begin(); i!=planes.end(); ++i )
i->Format( out, nestLevel );
for( REGIONS::iterator i=regions.begin(); i!=regions.end(); ++i )
i->Format( out, nestLevel );
for( KEEPOUTS::iterator i=keepouts.begin(); i!=keepouts.end(); ++i )
i->Format( out, nestLevel );
if( via )
via->Format( out, nestLevel );
if( control )
control->Format( out, nestLevel );
for( int i=0; i<Length(); ++i )
{
At(i)->Format( out, nestLevel );
}
if( rules )
rules->Format( out, nestLevel );
if( place_rules )
place_rules->Format( out, nestLevel );
for( GRIDS::iterator i=grids.begin(); i!=grids.end(); ++i )
i->Format( out, nestLevel );
}
DSN_T GetUnits()
{
if( unit )
return unit->GetUnits();
return ELEM::GetUnits();
}
};
class PLACE : public ELEM
{
friend class SPECCTRA_DB;
std::string component_id; ///< reference designator
DSN_T side;
bool isRotated;
float rotation;
bool hasVertex;
POINT vertex;
DSN_T mirror;
DSN_T status;
std::string logical_part;
RULE* place_rules;
PROPERTIES properties;
DSN_T lock_type;
//-----<mutually exclusive>--------------
RULE* rules;
REGION* region;
//-----</mutually exclusive>-------------
std::string part_number;
public:
PLACE( ELEM* aParent ) :
ELEM( T_place, aParent )
{
side = T_NONE;
isRotated = false;
hasVertex = false;
mirror = T_NONE;
status = T_NONE;
place_rules = 0;
lock_type = T_NONE;
rules = 0;
region = 0;
}
~PLACE()
{
delete place_rules;
delete rules;
delete region;
}
void SetVertex( const POINT& aVertex )
{
vertex = aVertex;
hasVertex = true;
}
void SetRotation( double aRotation )
{
rotation = (float) aRotation;
isRotated = (aRotation != 0.0);
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError );
};
class COMPONENT : public ELEM
{
friend class SPECCTRA_DB;
std::string image_id;
typedef boost::ptr_vector<PLACE> PLACES;
PLACES places;
public:
COMPONENT( ELEM* aParent ) :
ELEM( T_component, aParent )
{
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( image_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ),
quote, image_id.c_str(), quote );
for( PLACES::iterator i=places.begin(); i!=places.end(); ++i )
i->Format( out, nestLevel+1 );
out->Print( nestLevel, ")\n" );
}
};
class PLACEMENT : public ELEM
{
friend class SPECCTRA_DB;
UNIT_RES* unit;
DSN_T flip_style;
typedef boost::ptr_vector<COMPONENT> COMPONENTS;
COMPONENTS components;
public:
PLACEMENT( ELEM* aParent ) :
ELEM( T_placement, aParent )
{
unit = 0;
flip_style = T_NONE;
}
~PLACEMENT()
{
delete unit;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
if( unit )
unit->Format( out, nestLevel );
if( flip_style != T_NONE )
{
out->Print( nestLevel, "(place_control (flip_style %s))\n",
LEXER::GetTokenText( flip_style ) );
}
for( COMPONENTS::iterator i=components.begin(); i!=components.end(); ++i )
i->Format( out, nestLevel );
}
DSN_T GetUnits()
{
if( unit )
return unit->GetUnits();
return ELEM::GetUnits();
}
};
class SHAPE : public ELEM
{
friend class SPECCTRA_DB;
DSN_T connect;
//----- only one of these is used, like a union -----
PATH* path; ///< used for both path and polygon
RECTANGLE* rectangle;
CIRCLE* circle;
QARC* qarc;
//---------------------------------------------------
WINDOWS windows;
public:
SHAPE( ELEM* aParent, DSN_T aType = T_shape ) :
ELEM( aType, aParent )
{
connect = T_on;
path = 0;
rectangle = 0;
circle = 0;
qarc = 0;
}
~SHAPE()
{
delete path;
delete rectangle;
delete circle;
delete qarc;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
if( path )
path->Format( out, nestLevel );
else if( rectangle )
rectangle->Format( out, nestLevel );
else if( circle )
circle->Format( out, nestLevel );
else if( qarc )
qarc->Format( out, nestLevel );
if( connect == T_off )
out->Print( nestLevel, "(connect %s)\n", LEXER::GetTokenText( connect ) );
for( WINDOWS::iterator i=windows.begin(); i!=windows.end(); ++i )
i->Format( out, nestLevel );
}
};
class PIN : public ELEM
{
friend class SPECCTRA_DB;
std::string padstack_id;
float rotation;
bool isRotated;
std::string pin_id;
POINT vertex;
public:
PIN( ELEM* aParent ) :
ELEM( T_pin, aParent )
{
rotation = 0.0;
isRotated = false;
}
void SetRotation( double aRotation )
{
rotation = (float) aRotation;
isRotated = (aRotation != 0.0);
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( padstack_id.c_str() );
if( isRotated )
out->Print( nestLevel, "(pin %s%s%s (rotate %1.2f)",
quote, padstack_id.c_str(), quote,
rotation
);
else
out->Print( nestLevel, "(pin %s%s%s", quote, padstack_id.c_str(), quote );
quote = out->GetQuoteChar( pin_id.c_str() );
out->Print( 0, " %s%s%s %f %f)\n", quote, pin_id.c_str(), quote,
vertex.x, vertex.y );
}
};
class IMAGE : public ELEM_HOLDER
{
friend class SPECCTRA_DB;
std::string image_id;
DSN_T side;
UNIT_RES* unit;
/* The grammar spec says only one outline is supported, but I am seeing
*.dsn examples with multiple outlines. So the outlines will go into
the kids list.
*/
typedef boost::ptr_vector<PIN> PINS;
PINS pins;
RULE* rules;
RULE* place_rules;
public:
IMAGE( ELEM* aParent ) :
ELEM_HOLDER( T_image, aParent )
{
side = T_both;
unit = 0;
rules = 0;
place_rules = 0;
}
~IMAGE()
{
delete unit;
delete rules;
delete place_rules;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( image_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s", LEXER::GetTokenText( Type() ),
quote, image_id.c_str(), quote );
if( side != T_both )
out->Print( 0, " (side %s)", LEXER::GetTokenText( side ) );
out->Print( 0, "\n");
if( unit )
unit->Format( out, nestLevel+1 );
// format the kids, which in this class are the shapes
ELEM_HOLDER::FormatContents( out, nestLevel+1 );
for( PINS::iterator i=pins.begin(); i!=pins.end(); ++i )
i->Format( out, nestLevel+1 );
if( rules )
rules->Format( out, nestLevel+1 );
if( place_rules )
place_rules->Format( out, nestLevel+1 );
out->Print( nestLevel, ")\n" );
}
DSN_T GetUnits()
{
if( unit )
return unit->GetUnits();
return ELEM::GetUnits();
}
};
class PADSTACK : public ELEM_HOLDER
{
friend class SPECCTRA_DB;
std::string padstack_id;
UNIT_RES* unit;
/* The shapes are stored in the kids list */
DSN_T rotate;
DSN_T absolute;
DSN_T attach;
std::string via_id;
RULE* rules;
public:
PADSTACK( ELEM* aParent ) :
ELEM_HOLDER( T_padstack, aParent )
{
unit = 0;
rotate = T_on;
absolute = T_off;
rules = 0;
attach = T_off;
}
~PADSTACK()
{
delete unit;
delete rules;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( padstack_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ),
quote, padstack_id.c_str(), quote );
if( unit )
unit->Format( out, nestLevel+1 );
// format the kids, which in this class are the shapes
ELEM_HOLDER::FormatContents( out, nestLevel+1 );
out->Print( nestLevel+1, "%s", "" );
// spec for <attach_descriptor> says default is on, so
// print the off condition to override this.
if( attach == T_off )
out->Print( 0, "(attach off)" );
else if( attach == T_on )
{
const char* quote = out->GetQuoteChar( via_id.c_str() );
out->Print( 0, "(attach on (use_via %s%s%s))",
quote, via_id.c_str(), quote );
}
if( rotate == T_off ) // print the non-default
out->Print( 0, "(rotate %s)", LEXER::GetTokenText( rotate ) );
if( absolute == T_on ) // print the non-default
out->Print( 0, "(absolute %s)", LEXER::GetTokenText( absolute ) );
out->Print( 0, "\n" );
if( rules )
rules->Format( out, nestLevel+1 );
out->Print( nestLevel, ")\n" );
}
DSN_T GetUnits()
{
if( unit )
return unit->GetUnits();
return ELEM::GetUnits();
}
};
/**
* Class LIBRARY
* corresponds to the &lt;library_descriptor&gt; in the specctra dsn specification.
* Only unit_descriptor, image_descriptors, and padstack_descriptors are
* included as children at this time.
*/
class LIBRARY : public ELEM
{
friend class SPECCTRA_DB;
UNIT_RES* unit;
typedef boost::ptr_vector<IMAGE> IMAGES;
IMAGES images;
typedef boost::ptr_vector<PADSTACK> PADSTACKS;
PADSTACKS padstacks;
public:
LIBRARY( ELEM* aParent ) :
ELEM( T_library, aParent )
{
unit = 0;
}
~LIBRARY()
{
delete unit;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
if( unit )
unit->Format( out, nestLevel );
for( IMAGES::iterator i=images.begin(); i!=images.end(); ++i )
i->Format( out, nestLevel );
for( PADSTACKS::iterator i=padstacks.begin(); i!=padstacks.end(); ++i )
i->Format( out, nestLevel );
}
DSN_T GetUnits()
{
if( unit )
return unit->GetUnits();
return ELEM::GetUnits();
}
};
/**
* Class PIN_REF
* corresponds to the &lt;pin_reference&gt; definition in the specctra dsn spec.
*/
class PIN_REF : public ELEM
{
friend class SPECCTRA_DB;
std::string component_id;
std::string pin_id;
public:
PIN_REF( ELEM* aParent ) :
ELEM( T_pin, aParent )
{
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
// only print the newline if there is a nest level, and make
// the quotes unconditional on this one.
const char* newline = nestLevel ? "\n" : "";
out->Print( nestLevel, "\"%s\"-\"%s\"%s",
component_id.c_str(), pin_id.c_str(), newline );
}
};
typedef std::vector<PIN_REF> PIN_REFS;
class FROMTO : public ELEM
{
friend class SPECCTRA_DB;
std::string fromText;
std::string toText;
DSN_T fromto_type;
std::string net_id;
RULE* rules;
// std::string circuit;
LAYER_RULES layer_rules;
public:
FROMTO( ELEM* aParent ) :
ELEM( T_fromto, aParent )
{
rules = 0;
fromto_type = T_NONE;
}
~FROMTO()
{
delete rules;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
// no quoting on these two, the lexer preserved the quotes on input
out->Print( nestLevel, "(%s %s %s ",
LEXER::GetTokenText( Type() ), fromText.c_str(), toText.c_str() );
if( type != T_NONE )
out->Print( 0, "(type %s)", LEXER::GetTokenText( fromto_type ) );
if( net_id.size() )
{
const char* quote = out->GetQuoteChar( net_id.c_str() );
out->Print( 0, "(net %s%s%s)", quote, net_id.c_str(), quote );
}
bool singleLine = true;
if( rules || layer_rules.size() )
{
out->Print( 0, "\n" );
singleLine = false;
}
if( rules )
rules->Format( out, nestLevel+1 );
/*
if( circuit.size() )
out->Print( nestLevel, "%s\n", circuit.c_str() );
*/
for( LAYER_RULES::iterator i=layer_rules.begin(); i!=layer_rules.end(); ++i )
i->Format( out, nestLevel+1 );
out->Print( singleLine ? 0 : nestLevel, ")" );
if( nestLevel || !singleLine )
out->Print( 0, "\n" );
}
};
/**
* Class COMP_ORDER
* corresponds to the &lt;component_order_descriptor&gt;
*/
class COMP_ORDER : public ELEM
{
friend class SPECCTRA_DB;
STRINGS placement_ids;
public:
COMP_ORDER( ELEM* aParent ) :
ELEM( T_comp_order, aParent )
{
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
out->Print( nestLevel, "(%s", LEXER::GetTokenText( Type() ) );
for( STRINGS::iterator i=placement_ids.begin(); i!=placement_ids.end(); ++i )
{
const char* quote = out->GetQuoteChar( i->c_str() );
out->Print( 0, " %s%s%s", quote, i->c_str(), quote );
}
out->Print( 0, ")" );
if( nestLevel )
out->Print( 0, "\n" );
}
};
class NET : public ELEM
{
friend class SPECCTRA_DB;
std::string net_id;
bool unassigned;
int net_number;
DSN_T pins_type; ///< T_pins | T_order
PIN_REFS pins;
DSN_T type; ///< T_fix | T_normal
DSN_T supply; ///< T_power | T_ground
RULE* rules;
LAYER_RULES layer_rules;
FROMTO* fromto;
COMP_ORDER* comp_order;
public:
NET( ELEM* aParent ) :
ELEM( T_net, aParent )
{
unassigned = false;
net_number = T_NONE;
pins_type = T_pins;
type = T_NONE;
supply = T_NONE;
rules = 0;
fromto = 0;
comp_order = 0;
}
~NET()
{
delete rules;
delete fromto;
delete comp_order;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( net_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s ", LEXER::GetTokenText( Type() ),
quote, net_id.c_str(), quote );
if( unassigned )
out->Print( 0, "(unassigned)" );
if( net_number != T_NONE )
out->Print( 0, "(net_number %d)", net_number );
out->Print( 0, "\n" );
out->Print( nestLevel+1, "(%s\n", LEXER::GetTokenText( pins_type ) );
for( PIN_REFS::iterator i=pins.begin(); i!=pins.end(); ++i )
i->Format( out, nestLevel+2 );
out->Print( nestLevel+1, ")\n" );
if( comp_order )
comp_order->Format( out, nestLevel+1 );
if( type != T_NONE )
out->Print( nestLevel+1, "(type %s)\n", LEXER::GetTokenText( type ) );
if( rules )
rules->Format( out, nestLevel+1 );
for( LAYER_RULES::iterator i=layer_rules.begin(); i!=layer_rules.end(); ++i )
i->Format( out, nestLevel+1 );
if( fromto )
fromto->Format( out, nestLevel+1 );
out->Print( nestLevel, ")\n" );
}
};
class TOPOLOGY : public ELEM
{
friend class SPECCTRA_DB;
typedef boost::ptr_vector<FROMTO> FROMTOS;
FROMTOS fromtos;
typedef boost::ptr_vector<COMP_ORDER> COMP_ORDERS;
COMP_ORDERS comp_orders;
public:
TOPOLOGY( ELEM* aParent ) :
ELEM( T_topology, aParent )
{
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
for( FROMTOS::iterator i=fromtos.begin(); i!=fromtos.end(); ++i )
i->Format( out, nestLevel );
for( COMP_ORDERS::iterator i=comp_orders.begin(); i!=comp_orders.end(); ++i )
i->Format( out, nestLevel );
}
};
class CLASS : public ELEM
{
friend class SPECCTRA_DB;
std::string class_id;
STRINGS net_ids;
/// <circuit_descriptor> list
STRINGS circuit;
RULE* rules;
LAYER_RULES layer_rules;
TOPOLOGY* topology;
public:
CLASS( ELEM* aParent ) :
ELEM( T_class, aParent )
{
rules = 0;
topology = 0;
}
~CLASS()
{
delete rules;
delete topology;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( class_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s", LEXER::GetTokenText( Type() ),
quote, class_id.c_str(), quote );
const int NETGAP = 2;
const int RIGHTMARGIN = 92;
int perRow=RIGHTMARGIN;
for( STRINGS::iterator i=net_ids.begin(); i!=net_ids.end(); ++i )
{
quote = out->GetQuoteChar( i->c_str() );
int slength = strlen( i->c_str() );
if( *quote!='\0' )
slength += 2;
if( perRow + slength + NETGAP > RIGHTMARGIN )
{
out->Print( 0, "\n" );
perRow = 0;
perRow += out->Print( nestLevel+1, "%s%s%s",
quote, i->c_str(), quote );
}
else
{
perRow += out->Print( 0, "%*c%s%s%s", NETGAP, ' ',
quote, i->c_str(), quote );
}
}
out->Print( 0, "\n" );
for( STRINGS::iterator i=circuit.begin(); i!=circuit.end(); ++i )
out->Print( nestLevel+1, "%s\n", i->c_str() );
for( LAYER_RULES::iterator i=layer_rules.begin(); i!=layer_rules.end(); ++i )
i->Format( out, nestLevel+1 );
if( topology )
topology->Format( out, nestLevel+1 );
out->Print( nestLevel, ")\n" );
}
};
class NETWORK : public ELEM
{
friend class SPECCTRA_DB;
typedef boost::ptr_vector<NET> NETS;
NETS nets;
typedef boost::ptr_vector<CLASS> CLASSLIST;
CLASSLIST classes;
public:
NETWORK( ELEM* aParent ) :
ELEM( T_network, aParent )
{
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
for( NETS::iterator i=nets.begin(); i!=nets.end(); ++i )
i->Format( out, nestLevel );
for( CLASSLIST::iterator i=classes.begin(); i!=classes.end(); ++i )
i->Format( out, nestLevel );
}
};
class CONNECT : public ELEM
{
};
/**
* Class WIRE
* corresponds to &lt;wire_shape_descriptor&gt; in the specctra dsn spec.
*/
class WIRE : public ELEM
{
friend class SPECCTRA_DB;
//----- only one of these is used, like a union -----
PATH* path; ///< used for both path and polygon
RECTANGLE* rectangle;
CIRCLE* circle;
QARC* qarc;
//---------------------------------------------------
std::string net_id;
int turret;
DSN_T type;
DSN_T attr;
std::string shield;
WINDOWS windows;
CONNECT* connect;
bool supply;
public:
WIRE( ELEM* aParent ) :
ELEM( T_wire, aParent )
{
path = 0;
rectangle = 0;
circle = 0;
qarc = 0;
connect = 0;
turret = -1;
type = T_NONE;
attr = T_NONE;
supply = false;
}
~WIRE()
{
delete path;
delete rectangle;
delete circle;
delete qarc;
delete connect;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
// these are mutually exclusive
if( rectangle )
rectangle->Format( out, nestLevel );
else if( path )
path->Format( out, nestLevel );
else if( circle )
circle->Format( out, nestLevel );
else if( qarc )
qarc->Format( out, nestLevel );
if( net_id.size() )
{
const char* quote = out->GetQuoteChar( net_id.c_str() );
out->Print( nestLevel, "(net %s%s%s)\n",
quote, net_id.c_str(), quote );
}
if( turret >= 0 )
out->Print( nestLevel, "(turrent %d)\n", turret );
if( type != T_NONE )
out->Print( nestLevel, "(type %s)\n", LEXER::GetTokenText( type ) );
if( attr != T_NONE )
out->Print( nestLevel, "(attr %s)\n", LEXER::GetTokenText( attr ) );
if( shield.size() )
{
const char* quote = out->GetQuoteChar( shield.c_str() );
out->Print( nestLevel, "(shield %s%s%s)\n",
quote, shield.c_str(), quote );
}
for( WINDOWS::iterator i=windows.begin(); i!=windows.end(); ++i )
i->Format( out, nestLevel );
if( connect )
connect->Format( out, nestLevel );
if( supply )
out->Print( nestLevel, "(supply)\n" );
}
};
typedef boost::ptr_vector<WIRE> WIRES;
/**
* Class WIRE_VIA
* corresponds to &lt;wire_via_descriptor&gt; in the specctra dsn spec.
*/
class WIRE_VIA : public ELEM
{
friend class SPECCTRA_DB;
std::string padstack_id;
POINTS vertexes;
std::string net_id;
int via_number;
DSN_T type;
DSN_T attr;
std::string virtual_pin_name;
STRINGS contact_layers;
bool supply;
public:
WIRE_VIA( ELEM* aParent ) :
ELEM( T_via, aParent )
{
via_number = -1;
type = T_NONE;
attr = T_NONE;
supply = false;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( padstack_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s", LEXER::GetTokenText( Type() ),
quote, padstack_id.c_str(), quote );
const int RIGHTMARGIN = 80;
int perLine=RIGHTMARGIN;
for( POINTS::iterator i=vertexes.begin(); i!=vertexes.end(); ++i )
{
if( perLine >= RIGHTMARGIN )
{
out->Print( 0, "\n" );
perLine = 0;
perLine += out->Print( nestLevel+1, "%f %f", i->x, i->y );
}
else
{
perLine += out->Print( 0, " %f %f", i->x, i->y );
}
}
out->Print( 0, "\n" );
if( net_id.size() )
{
const char* quote = out->GetQuoteChar( net_id.c_str() );
out->Print( nestLevel+1, "(net %s%s%s)\n", quote, net_id.c_str(), quote );
}
if( type != T_NONE )
out->Print( nestLevel+1, "(type %s)\n", LEXER::GetTokenText( type ) );
if( attr != T_NONE )
{
if( attr == T_virtual_pin )
{
const char* quote = out->GetQuoteChar( virtual_pin_name.c_str() );
out->Print( nestLevel+1, "(attr virtual_pin %s%s%s)\n",
quote, virtual_pin_name.c_str(), quote );
}
else
out->Print( nestLevel+1, "(attr %s)\n", LEXER::GetTokenText( attr ) );
}
if( contact_layers.size() )
{
out->Print( nestLevel+1, "(contact\n" );
for( STRINGS::iterator i=contact_layers.begin(); i!=contact_layers.end(); ++i )
{
const char* quote = out->GetQuoteChar( i->c_str() );
out->Print( nestLevel+2, "%s%s%s\n", quote, i->c_str(), quote );
}
out->Print( nestLevel+1, ")\n" );
}
if( supply )
out->Print( nestLevel+1, "(supply)\n" );
out->Print( nestLevel, ")\n" );
}
};
typedef boost::ptr_vector<WIRE_VIA> WIRE_VIAS;
/**
* Class WIRING
* corresponds to &lt;wiring_descriptor&gt; in the specctra dsn spec.
*/
class WIRING : public ELEM
{
friend class SPECCTRA_DB;
UNIT_RES* unit;
WIRES wires;
WIRE_VIAS wire_vias;
public:
WIRING( ELEM* aParent ) :
ELEM( T_wiring, aParent )
{
unit = 0;
}
~WIRING()
{
delete unit;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
if( unit )
unit->Format( out, nestLevel );
for( WIRES::iterator i=wires.begin(); i!=wires.end(); ++i )
i->Format( out, nestLevel );
for( WIRE_VIAS::iterator i=wire_vias.begin(); i!=wire_vias.end(); ++i )
i->Format( out, nestLevel );
}
DSN_T GetUnits()
{
if( unit )
return unit->GetUnits();
return ELEM::GetUnits();
}
};
class PCB : public ELEM
{
friend class SPECCTRA_DB;
std::string pcbname;
PARSER* parser;
UNIT_RES* resolution;
UNIT_RES* unit;
STRUCTURE* structure;
PLACEMENT* placement;
LIBRARY* library;
NETWORK* network;
WIRING* wiring;
public:
PCB( ELEM* aParent = 0 ) :
ELEM( T_pcb, aParent )
{
parser = 0;
resolution = 0;
unit = 0;
structure = 0;
placement = 0;
library = 0;
network = 0;
wiring = 0;
}
~PCB()
{
delete parser;
delete resolution;
delete unit;
delete structure;
delete placement;
delete library;
delete network;
delete wiring;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( pcbname.c_str() );
out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ),
quote, pcbname.c_str(), quote );
if( parser )
parser->Format( out, nestLevel+1 );
if( resolution )
resolution->Format( out, nestLevel+1 );
if( unit )
unit->Format( out, nestLevel+1 );
if( structure )
structure->Format( out, nestLevel+1 );
if( placement )
placement->Format( out, nestLevel+1 );
if( library )
library->Format( out, nestLevel+1 );
if( network )
network->Format( out, nestLevel+1 );
if( wiring )
wiring->Format( out, nestLevel+1 );
out->Print( nestLevel, ")\n" );
}
DSN_T GetUnits()
{
if( unit )
return unit->GetUnits();
if( resolution )
return resolution->GetUnits();
return ELEM::GetUnits();
}
};
class ANCESTOR : public ELEM
{
friend class SPECCTRA_DB;
std::string filename;
std::string comment;
time_t time_stamp;
public:
ANCESTOR( ELEM* aParent ) :
ELEM( T_ancestor, aParent )
{
time_stamp = time(NULL);
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
char temp[80];
struct tm* tmp;
tmp = localtime( &time_stamp );
strftime( temp, sizeof(temp), "%b %d %H : %M : %S %Y", tmp );
// format the time first to temp
// filename may be empty, so quote it just in case.
out->Print( nestLevel, "(%s \"%s\" (created_time %s)\n",
LEXER::GetTokenText( Type() ),
filename.c_str(),
temp );
if( comment.size() )
{
const char* quote = out->GetQuoteChar( comment.c_str() );
out->Print( nestLevel+1, "(comment %s%s%s)\n",
quote, comment.c_str(), quote );
}
out->Print( nestLevel, ")\n" );
}
};
typedef boost::ptr_vector<ANCESTOR> ANCESTORS;
class HISTORY : public ELEM
{
friend class SPECCTRA_DB;
ANCESTORS ancestors;
time_t time_stamp;
STRINGS comments;
public:
HISTORY( ELEM* aParent ) :
ELEM( T_history, aParent )
{
time_stamp = time(NULL);
}
~HISTORY()
{
;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
for( ANCESTORS::iterator i=ancestors.begin(); i!=ancestors.end(); ++i )
i->Format( out, nestLevel );
char temp[80];
struct tm* tmp;
tmp = localtime( &time_stamp );
strftime( temp, sizeof(temp), "%b %d %H : %M : %S %Y", tmp );
// format the time first to temp
out->Print( nestLevel, "(self (created_time %s)\n", temp );
for( STRINGS::iterator i=comments.begin(); i!=comments.end(); ++i )
{
const char* quote = out->GetQuoteChar( i->c_str() );
out->Print( nestLevel+1, "(comment %s%s%s)\n",
quote, i->c_str(), quote );
}
out->Print( nestLevel, ")\n" );
}
};
class ROUTE : public ELEM
{
friend class SPECCTRA_DB;
UNIT_RES* resolution;
PARSER* parser;
STRUCTURE* structure;
LIBRARY* library;
NETWORK* network;
// TEST_POINTS* test_points;
public:
ROUTE( ELEM* aParent ) :
ELEM( T_route, aParent )
{
resolution = 0;
parser = 0;
structure = 0;
library = 0;
network = 0;
}
~ROUTE()
{
delete resolution;
delete parser;
delete structure;
delete library;
delete network;
// delete test_points;
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
if( resolution )
resolution->Format( out, nestLevel );
if( parser )
parser->Format( out, nestLevel );
if( structure )
structure->Format( out, nestLevel );
if( library )
library->Format( out, nestLevel );
if( network )
library->Format( out, nestLevel );
// if( test_poinst )
// test_points->Format( out, nestLevel );
}
};
/**
* Struct PIN_PAIR
* is used within the WAS_IS class below to hold a pair of PIN_REFs and
* corresponds to the (pins was is) construct within the specctra dsn spec.
*/
struct PIN_PAIR
{
PIN_PAIR( ELEM* aParent = 0 ) :
was( aParent ),
is( aParent )
{
}
PIN_REF was;
PIN_REF is;
};
typedef std::vector<PIN_PAIR> PIN_PAIRS;
/**
* Class WAS_IS
* corresponds to the &lt;was_is_descriptor&gt; in the specctra dsn spec.
*/
class WAS_IS : public ELEM
{
friend class SPECCTRA_DB;
PIN_PAIRS pin_pairs;
public:
WAS_IS( ELEM* aParent ) :
ELEM( T_was_is, aParent )
{
}
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
for( PIN_PAIRS::iterator i=pin_pairs.begin(); i!=pin_pairs.end(); ++i )
{
out->Print( nestLevel, "(pins " );
i->was.Format( out, 0 );
out->Print( 0, " " );
i->is.Format( out, 0 );
out->Print( 0, ")\n" );
}
}
};
/**
* Class SESSION
* corresponds to the &lt;session_file_descriptor&gt; in the specctra dsn spec.
*/
class SESSION : public ELEM
{
friend class SPECCTRA_DB;
std::string session_id;
std::string base_design;
HISTORY* history;
STRUCTURE* structure;
PLACEMENT* placement;
WAS_IS* was_is;
ROUTE* route;
/* not supported:
FLOOR_PLAN* floor_plan;
NET_PIN_CHANGES* net_pin_changes;
SWAP_HISTORY* swap_history;
*/
public:
SESSION( ELEM* aParent = 0 ) :
ELEM( T_pcb, aParent )
{
history = 0;
structure = 0;
placement = 0;
was_is = 0;
route = 0;
}
~SESSION()
{
delete history;
delete structure;
delete placement;
delete was_is;
delete route;
}
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
const char* quote = out->GetQuoteChar( session_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ),
quote, session_id.c_str(), quote );
out->Print( nestLevel+1, "(base_design \"%s\")\n", base_design.c_str() );
if( history )
history->Format( out, nestLevel+1 );
if( structure )
structure->Format( out, nestLevel+1 );
if( placement )
placement->Format( out, nestLevel+1 );
if( was_is )
was_is->Format( out, nestLevel+1 );
if( route )
route->Format( out, nestLevel+1 );
out->Print( nestLevel, ")\n" );
}
};
/**
* Class SPECCTRA_DB
* holds a DSN data tree, usually coming from a DSN file.
*/
class SPECCTRA_DB : public OUTPUTFORMATTER
{
LEXER* lexer;
PCB* pcb;
SESSION* session;
FILE* fp;
wxString filename;
std::string quote_char;
/**
* Function nextTok
* returns the next token from the lexer.
*/
DSN_T nextTok();
static bool isSymbol( DSN_T aTok )
{
// if aTok is >= 0, then it might be a coincidental match to a keyword.
return aTok==T_SYMBOL || aTok==T_STRING || aTok>=0;
}
/**
* Function needLEFT
* calls nextTok() and then verifies that the token read in is a T_LEFT.
* If it is not, an IOError is thrown.
* @throw IOError, if the next token is not a T_LEFT
*/
void needLEFT() throw( IOError );
/**
* Function needRIGHT
* calls nextTok() and then verifies that the token read in is a T_RIGHT.
* If it is not, an IOError is thrown.
* @throw IOError, if the next token is not a T_RIGHT
*/
void needRIGHT() throw( IOError );
/**
* Function needSYMBOL
* calls nextTok() and then verifies that the token read in
* satisfies bool isSymbol().
* If not, an IOError is thrown.
* @throw IOError, if the next token does not satisfy isSymbol()
*/
void needSYMBOL() throw( IOError );
/**
* Function readCOMPnPIN
* reads a &lt;pin_reference&gt; and splits it into the two parts which are
* on either side of the hyphen. This function is specialized because
* pin_reference may or may not be using double quotes. Both of these
* are legal: U2-14 or "U2"-"14". The lexer treats the first one as a
* single T_SYMBOL, so in that case we have to split it into two here.
* <p>
* The caller should have already read in the first token comprizing the
* pin_reference and it will be tested through lexer->CurTok().
*
* @param component_id Where to put the text preceeding the '-' hyphen.
* @param pin_d Where to put the text which trails the '-'.
* @throw IOError, if the next token or two do no make up a pin_reference,
* or there is an error reading from the input stream.
*/
void readCOMPnPIN( std::string* component_id, std::string* pid_id ) throw( IOError );
/**
* Function readTIME
* reads a &lt;time_stamp&gt; which consists of 8 lexer tokens:
* "month date hour : minute : second year".
* This function is specialized because time_stamps occur more than
* once in a session file.
* <p>
* The caller should not have already read in the first token comprizing the
* time stamp.
*
* @param time_stamp Where to put the parsed time value.
* @throw IOError, if the next token or 8 do no make up a time stamp,
* or there is an error reading from the input stream.
*/
void readTIME( time_t* time_stamp ) throw( IOError );
/**
* Function expecting
* throws an IOError exception with an input file specific error message.
* @param DSN_T The token type which was expected at the current input location.
* @throw IOError with the location within the input file of the problem.
*/
void expecting( DSN_T ) throw( IOError );
void expecting( const char* text ) throw( IOError );
void unexpected( DSN_T aTok ) throw( IOError );
void unexpected( const char* text ) throw( IOError );
void doPCB( PCB* growth ) throw(IOError);
void doPARSER( PARSER* growth ) throw(IOError);
void doRESOLUTION( UNIT_RES* growth ) throw(IOError);
void doUNIT( UNIT_RES* growth ) throw( IOError );
void doSTRUCTURE( STRUCTURE* growth ) throw( IOError );
void doLAYER_NOISE_WEIGHT( LAYER_NOISE_WEIGHT* growth ) throw( IOError );
void doLAYER_PAIR( LAYER_PAIR* growth ) throw( IOError );
void doBOUNDARY( BOUNDARY* growth ) throw( IOError );
void doRECTANGLE( RECTANGLE* growth ) throw( IOError );
void doPATH( PATH* growth ) throw( IOError );
void doSTRINGPROP( STRINGPROP* growth ) throw( IOError );
void doTOKPROP( TOKPROP* growth ) throw( IOError );
void doVIA( VIA* growth ) throw( IOError );
void doCONTROL( CONTROL* growth ) throw( IOError );
void doLAYER( LAYER* growth ) throw( IOError );
void doRULE( RULE* growth ) throw( IOError );
void doKEEPOUT( KEEPOUT* growth ) throw( IOError );
void doCIRCLE( CIRCLE* growth ) throw( IOError );
void doQARC( QARC* growth ) throw( IOError );
void doWINDOW( WINDOW* growth ) throw( IOError );
void doREGION( REGION* growth ) throw( IOError );
void doCLASS_CLASS( CLASS_CLASS* growth ) throw( IOError );
void doLAYER_RULE( LAYER_RULE* growth ) throw( IOError );
void doCLASSES( CLASSES* growth ) throw( IOError );
void doGRID( GRID* growth ) throw( IOError );
void doPLACE( PLACE* growth ) throw( IOError );
void doCOMPONENT( COMPONENT* growth ) throw( IOError );
void doPLACEMENT( PLACEMENT* growth ) throw( IOError );
void doPROPERTIES( PROPERTIES* growth ) throw( IOError );
void doPADSTACK( PADSTACK* growth ) throw( IOError );
void doSHAPE( SHAPE* growth ) throw( IOError );
void doIMAGE( IMAGE* growth ) throw( IOError );
void doLIBRARY( LIBRARY* growth ) throw( IOError );
void doPIN( PIN* growth ) throw( IOError );
void doNET( NET* growth ) throw( IOError );
void doNETWORK( NETWORK* growth ) throw( IOError );
void doCLASS( CLASS* growth ) throw( IOError );
void doTOPOLOGY( TOPOLOGY* growth ) throw( IOError );
void doFROMTO( FROMTO* growth ) throw( IOError );
void doCOMP_ORDER( COMP_ORDER* growth ) throw( IOError );
void doWIRE( WIRE* growth ) throw( IOError );
void doWIRE_VIA( WIRE_VIA* growth ) throw( IOError );
void doWIRING( WIRING* growth ) throw( IOError );
void doSESSION( SESSION* growth ) throw( IOError );
void doANCESTOR( ANCESTOR* growth ) throw( IOError );
void doHISTORY( HISTORY* growth ) throw( IOError );
void doROUTE( ROUTE* growth ) throw( IOError );
void doWAS_IS( WAS_IS* growth ) throw( IOError );
public:
SPECCTRA_DB()
{
lexer = 0;
pcb = 0;
session = 0;
fp = 0;
quote_char += '"';
}
~SPECCTRA_DB()
{
delete lexer;
delete pcb;
delete session;
if( fp )
fclose( fp );
}
//-----<OUTPUTFORMATTER>-------------------------------------------------
int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError );
const char* GetQuoteChar( const char* wrapee );
//-----</OUTPUTFORMATTER>------------------------------------------------
/**
* Function MakePCB
* makes a PCB with all the default ELEMs and parts on the heap.
*/
static PCB* MakePCB();
/**
* Function SetPCB
* deletes any existing PCB and replaces it with the given one.
*/
void SetPCB( PCB* aPcb )
{
delete pcb;
pcb = aPcb;
}
#define EDA_BASE // build_version.h behavior
#undef COMMON_GLOBL
#define COMMON_GLOBL // build_version.h behavior
#include "build_version.h"
/**
* Function SetSESSION
* deletes any existing SESSION and replaces it with the given one.
*/
void SetSESSION( SESSION* aSession )
{
delete session;
session = aSession;
}
/**
* Function LoadPCB
* is a recursive descent parser for a SPECCTRA DSN "design" file.
* A design file is nearly a full description of a PCB (seems to be
* missing only the silkscreen stuff).
*
* @param filename The name of the dsn file to load.
* @throw IOError if there is a lexer or parser error.
*/
void LoadPCB( const wxString& filename ) throw( IOError );
/**
* Function LoadSESSION
* is a recursive descent parser for a SPECCTRA DSN "session" file.
* A session file is file that is fed back from the router to the layout
* tool (PCBNEW) and should be used to update a BOARD object with the new
* tracks, vias, and component locations.
*
* @param filename The name of the dsn file to load.
* @throw IOError if there is a lexer or parser error.
*/
void LoadSESSION( const wxString& filename ) throw( IOError );
namespace DSN {
void ThrowIOError( const wxChar* fmt, ... ) throw( IOError );
/**
* Function ExportPCB
* writes the given BOARD out as a SPECTRA DSN format file.
*
* @param aFilename The file to save to.
* @param aBoard The BOARD to save.
*/
void ExportPCB( wxString aFilename, BOARD* aBoard );
#define NESTWIDTH 4 ///< how many spaces per nestLevel
/**
* Function ExportSESSION
* writes the internal session out as a SPECTRA DSN format file.
*
* @param aFilename The file to save to.
*/
void ExportSESSION( wxString aFilename );
};
//-----<SPECCTRA_DB>-------------------------------------------------
......@@ -3148,6 +117,14 @@ DSN_T SPECCTRA_DB::nextTok()
return ret;
}
bool SPECCTRA_DB::isSymbol( DSN_T aTok )
{
// if aTok is >= 0, then it might be a coincidental match to a keyword.
return aTok==T_SYMBOL || aTok==T_STRING || aTok>=0;
}
void SPECCTRA_DB::needLEFT() throw( IOError )
{
DSN_T tok = nextTok();
......@@ -3449,6 +426,22 @@ void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError )
{
DSN_T tok;
/* <parser_descriptor >::=
(parser
[(string_quote <quote_char >)]
(space_in_quoted_tokens [on | off])
[(host_cad <id >)]
[(host_version <id >)]
[{(constant <id > <id >)}]
[(write_resolution] {<character> <positive_integer >})]
[(routes_include {[testpoint | guides |
image_conductor]})]
[(wires_include testpoint)]
[(case_sensitive [on | off])]
[(via_rotate_first [on | off])]
)
*/
while( (tok = nextTok()) != T_RIGHT )
{
if( tok != T_LEFT )
......@@ -3464,6 +457,7 @@ void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError )
lexer->SetStringDelimiter( (unsigned char) *lexer->CurText() );
growth->string_quote = *lexer->CurText();
quote_char = lexer->CurText();
needRIGHT();
break;
case T_space_in_quoted_tokens:
......@@ -3472,16 +466,19 @@ void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError )
expecting( "on|off" );
lexer->SetSpaceInQuotedTokens( tok==T_on );
growth->space_in_quoted_tokens = (tok==T_on);
needRIGHT();
break;
case T_host_cad:
needSYMBOL();
growth->host_cad = lexer->CurText();
needRIGHT();
break;
case T_host_version:
needSYMBOL();
growth->host_version = lexer->CurText();
needRIGHT();
break;
case T_constant:
......@@ -3489,6 +486,7 @@ void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError )
growth->const_id1 = lexer->CurText();
needSYMBOL();
growth->const_id2 = lexer->CurText();
needRIGHT();
break;
case T_write_resolution: // [(writee_resolution {<character> <positive_integer >})]
......@@ -3501,7 +499,7 @@ void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError )
expecting( T_NUMBER );
// @todo
}
continue; // we ate the T_RIGHT
break;
case T_routes_include: // [(routes_include {[testpoint | guides | image_conductor]})]
while( (tok = nextTok()) != T_RIGHT )
......@@ -3521,13 +519,14 @@ void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError )
expecting( "testpoint|guides|image_conductor" );
}
}
continue; // we ate the T_RIGHT
break;
case T_wires_include: // [(wires_include testpoint)]
tok = nextTok();
if( tok != T_testpoint )
expecting( T_testpoint );
growth->routes_include_testpoint = true;
needRIGHT();
break;
case T_case_sensitive:
......@@ -3535,6 +534,7 @@ void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError )
if( tok!=T_on && tok!=T_off )
expecting( "on|off" );
growth->case_sensitive = (tok==T_on);
needRIGHT();
break;
case T_via_rotate_first: // [(via_rotate_first [on | off])]
......@@ -3542,17 +542,17 @@ void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError )
if( tok!=T_on && tok!=T_off )
expecting( "on|off" );
growth->via_rotate_first = (tok==T_on);
needRIGHT();
break;
case T_generated_by_freeroute:
growth->generated_by_freeroute = true;
needRIGHT();
break;
default:
unexpected( lexer->CurText() );
}
needRIGHT();
}
}
......@@ -6124,18 +3124,97 @@ void SPECCTRA_DB::doROUTE( ROUTE* growth ) throw( IOError )
doSTRUCTURE( growth->structure );
break;
case T_library:
case T_library_out:
if( growth->library )
unexpected( tok );
growth->library = new LIBRARY( growth );
doLIBRARY( growth->library );
break;
case T_network:
if( growth->network )
case T_network_out:
while( (tok = nextTok()) != T_RIGHT )
{
if( tok != T_LEFT )
expecting( T_LEFT );
tok = nextTok();
if( tok != T_net ) // it is class NET_OUT, but token T_net
unexpected( lexer->CurText() );
NET_OUT* net_out;
net_out = new NET_OUT( growth );
growth->net_outs.push_back( net_out );
doNET_OUT( net_out );
}
break;
default:
unexpected( lexer->CurText() );
}
}
}
void SPECCTRA_DB::doNET_OUT( NET_OUT* growth ) throw( IOError )
{
DSN_T tok;
/* <net_out_descriptor >::=
(net <net_id >
[(net_number <integer >)]
[<rule_descriptor> ]
{[<wire_shape_descriptor> | <wire_guide_descriptor> |
<wire_via_descriptor> | <bond_shape_descriptor> ]}
{[<supply_pin_descriptor> ]}
)
*/
needSYMBOL();
growth->net_id = lexer->CurText();
while( (tok = nextTok()) != T_RIGHT )
{
if( tok != T_LEFT )
expecting( T_LEFT );
tok = nextTok();
switch( tok )
{
case T_net_number:
tok = nextTok();
if( tok!= T_NUMBER )
expecting( T_NUMBER );
growth->net_number = atoi( lexer->CurText() );
needRIGHT();
break;
case T_rule:
if( growth->rules )
unexpected( tok );
growth->network = new NETWORK( growth );
doNETWORK( growth->network );
growth->rules = new RULE( growth, tok );
doRULE( growth->rules );
break;
case T_wire:
WIRE* wire;
wire = new WIRE( growth );
growth->wires.push_back( wire );
doWIRE( wire );
break;
case T_via:
WIRE_VIA* wire_via;
wire_via = new WIRE_VIA( growth );
growth->wire_vias.push_back( wire_via );
doWIRE_VIA( wire_via );
break;
case T_supply_pin:
SUPPLY_PIN* supply_pin;
supply_pin = new SUPPLY_PIN( growth );
growth->supply_pins.push_back( supply_pin );
doSUPPLY_PIN( supply_pin );
break;
default:
......@@ -6145,6 +3224,42 @@ void SPECCTRA_DB::doROUTE( ROUTE* growth ) throw( IOError )
}
void SPECCTRA_DB::doSUPPLY_PIN( SUPPLY_PIN* growth ) throw( IOError )
{
DSN_T tok;
PIN_REF empty(growth);
/* <supply_pin_descriptor >::=
(supply_pin {<pin_reference> } [(net <net_id >)])
*/
needSYMBOL();
growth->net_id = lexer->CurText();
while( (tok = nextTok()) != T_RIGHT )
{
if( isSymbol(tok) )
{
growth->pin_refs.push_back( empty );
PIN_REF* pin_ref = &growth->pin_refs.back();
readCOMPnPIN( &pin_ref->component_id, &pin_ref->pin_id );
}
else if( tok == T_LEFT )
{
tok = nextTok();
if( tok != T_net )
expecting( T_net );
growth->net_id = lexer->CurText();
needRIGHT();
}
else
unexpected( lexer->CurText() );
}
}
int SPECCTRA_DB::Print( int nestLevel, const char* fmt, ... ) throw( IOError )
{
va_list args;
......@@ -6182,6 +3297,9 @@ const char* SPECCTRA_DB::GetQuoteChar( const char* wrapee )
if( *wrapee == '#' )
return quote_char.c_str();
if( strlen(wrapee)==0 )
return quote_char.c_str();
bool isNumber = true;
for( ; *wrapee; ++wrapee )
......@@ -6299,6 +3417,26 @@ int ELEM_HOLDER::FindElem( DSN_T aType, int instanceNum )
//-----<PARSER>-----------------------------------------------------------
PARSER::PARSER( ELEM* aParent ) :
ELEM( T_parser, aParent )
{
string_quote = '"';
space_in_quoted_tokens = false;
case_sensitive = false;
wires_include_testpoint = false;
routes_include_testpoint = false;
routes_include_guides = false;
routes_include_image_conductor = false;
via_rotate_first = true;
generated_by_freeroute = false;
host_cad = "Kicad's PCBNEW";
host_version = CONV_TO_UTF8(g_BuildVersion);
}
void PARSER::FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{
out->Print( nestLevel, "(string_quote %c)\n", string_quote );
......@@ -6416,9 +3554,12 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
} // namespace DSN
// unit test this source file
#if 1
using namespace DSN;
// unit test this source file
int main( int argc, char** argv )
{
......@@ -6452,5 +3593,8 @@ int main( int argc, char** argv )
}
#endif
//EOF
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