Commit ceb6ad1a authored by dickelbeck's avatar dickelbeck

* Factored out the DSNLEXER class so it can be re-used more generally. The

    constructor takes a keyword table, so it can be used for arbitrary DSN
    syntax files of your own chosing.  Simply create an enum {} with all your
    unique tokens in it.  Then create a KEYWORD table.  See SPECCTRA_DB::keywords[].
    The reason you want an enum is to give the C++ debugger better type information
    so it can show symbolic integer symbols.
  * Factored out common richio.cpp and richio.h
    which is what DSNLEXER uses.
  * Fixed some minor issues with reading circuit descriptor from a *.dsn file.
parent 0fc7d7c1
...@@ -4,6 +4,21 @@ KiCad ChangeLog 2009 ...@@ -4,6 +4,21 @@ KiCad ChangeLog 2009
Please add newer entries at the top, list the date and your name with Please add newer entries at the top, list the date and your name with
email address. email address.
2009-Dec-10 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================
++all
* Factored out the DSNLEXER class so it can be re-used more generally. The
constructor takes a keyword table, so it can be used for arbitrary DSN
syntax files of your own chosing. Simply create an enum {} with all your
unique tokens in it. Then create a KEYWORD table. See SPECCTRA_DB::keywords[].
The reason you want an enum is to give the C++ debugger better type information
so it can show symbolic integer symbols.
* Factored out common richio.cpp and richio.h
which is what DSNLEXER uses.
* Fixed some minor issues with reading circuit descriptor from a *.dsn file.
2009-Dec-6 UPDATE Dick Hollenbeck <dick@softplc.com> 2009-Dec-6 UPDATE Dick Hollenbeck <dick@softplc.com>
================================================================================ ================================================================================
++pcbnew & gerbview ++pcbnew & gerbview
......
...@@ -31,6 +31,7 @@ set(COMMON_SRCS ...@@ -31,6 +31,7 @@ set(COMMON_SRCS
drawframe.cpp drawframe.cpp
drawpanel.cpp drawpanel.cpp
drawtxt.cpp drawtxt.cpp
dsnlexer.cpp
edaappl.cpp edaappl.cpp
eda_dde.cpp eda_dde.cpp
eda_doc.cpp eda_doc.cpp
...@@ -41,6 +42,7 @@ set(COMMON_SRCS ...@@ -41,6 +42,7 @@ set(COMMON_SRCS
msgpanel.cpp msgpanel.cpp
projet_config.cpp projet_config.cpp
# pyhandler.cpp # pyhandler.cpp
richio.cpp
selcolor.cpp selcolor.cpp
string.cpp string.cpp
toolbars.cpp toolbars.cpp
......
...@@ -11,14 +11,6 @@ ...@@ -11,14 +11,6 @@
#define BUILD_VERSION "(2009-12-05-unstable)" #define BUILD_VERSION "(2009-12-05-unstable)"
#ifdef HAVE_SVN_VERSION
#include "version.h"
wxString g_BuildVersion( wxT( KICAD_SVN_VERSION ) );
#else
wxString g_BuildVersion( wxT( BUILD_VERSION ) );
#endif
#if defined(HAVE_SVN_VERSION) || defined(HAVE_SVN_REVISION) #if defined(HAVE_SVN_VERSION) || defined(HAVE_SVN_REVISION)
# include "version.h" # include "version.h"
#ifndef KICAD_ABOUT_VERSION #ifndef KICAD_ABOUT_VERSION
...@@ -30,6 +22,15 @@ wxString g_BuildAboutVersion( wxT( BUILD_VERSION ) ); ...@@ -30,6 +22,15 @@ wxString g_BuildAboutVersion( wxT( BUILD_VERSION ) );
#endif #endif
/** Function GetAboutBuildVersion()
* Return custom build date for about dialog
*/
wxString GetAboutBuildVersion()
{
return g_BuildAboutVersion;
}
/**********************************/ /**********************************/
wxString SetMsg( const wxString& msg ) wxString SetMsg( const wxString& msg )
/**********************************/ /**********************************/
......
...@@ -118,6 +118,17 @@ StructColors ColorRefs[NBCOLOR] = ...@@ -118,6 +118,17 @@ StructColors ColorRefs[NBCOLOR] =
}; };
#define BUILD_VERSION "(2009-12-05-unstable)"
#ifdef HAVE_SVN_VERSION
#include "version.h"
wxString g_BuildVersion( wxT( KICAD_SVN_VERSION ) );
#else
wxString g_BuildVersion( wxT( BUILD_VERSION ) );
#endif
/** Function GetBuildVersion() /** Function GetBuildVersion()
* Return the build date * Return the build date
*/ */
...@@ -127,15 +138,6 @@ wxString GetBuildVersion() ...@@ -127,15 +138,6 @@ wxString GetBuildVersion()
} }
/** Function GetAboutBuildVersion()
* Return custom build date for about dialog
*/
wxString GetAboutBuildVersion()
{
return g_BuildAboutVersion;
}
/** function SetLocaleTo_C_standard /** function SetLocaleTo_C_standard
* because kicad is internationalized, switch internalization to "C" standard * because kicad is internationalized, switch internalization to "C" standard
* i.e. uses the . (dot) as separator in print/read float numbers * i.e. uses the . (dot) as separator in print/read float numbers
......
...@@ -30,433 +30,12 @@ ...@@ -30,433 +30,12 @@
#include <cctype> #include <cctype>
#include "dsn.h" #include "dsnlexer.h"
#include "fctsys.h" #include "fctsys.h"
#include "pcbnew.h" #include "pcbnew.h"
/**
* Class LEXER
* implements a lexical analyzer for the SPECCTRA DSN file format. It
* reads lexical tokens from the current LINE_READER through the NextTok()
* function. The NextTok() function returns one of the DSN_T values.
*/
namespace DSN {
/**
* Struct KEYWORD
* holds a string and a DSN_T
*/
struct KEYWORD
{
const char* name;
// int token;
};
//#define TOKDEF(x) { #x, T_##x }
#define TOKDEF(x) { #x }
// This MUST be sorted alphabetically, and also so MUST enum DSN_T {} be alphabetized.
// These MUST all be lower case because of the conversion to lowercase in findToken().
const static KEYWORD tokens[] = {
TOKDEF(absolute),
TOKDEF(added),
TOKDEF(add_group),
TOKDEF(add_pins),
TOKDEF(allow_antenna),
TOKDEF(allow_redundant_wiring),
TOKDEF(amp),
TOKDEF(ancestor),
TOKDEF(antipad),
TOKDEF(aperture_type),
TOKDEF(array),
TOKDEF(attach),
TOKDEF(attr),
TOKDEF(average_pair_length),
TOKDEF(back),
TOKDEF(base_design),
TOKDEF(bbv_ctr2ctr),
TOKDEF(bend_keepout),
TOKDEF(bond),
TOKDEF(both),
TOKDEF(bottom),
TOKDEF(bottom_layer_sel),
TOKDEF(boundary),
TOKDEF(brickpat),
TOKDEF(bundle),
TOKDEF(bus),
TOKDEF(bypass),
TOKDEF(capacitance_resolution),
TOKDEF(capacitor),
TOKDEF(case_sensitive),
TOKDEF(cct1),
TOKDEF(cct1a),
TOKDEF(center_center),
TOKDEF(checking_trim_by_pin),
TOKDEF(circ),
TOKDEF(circle),
TOKDEF(circuit),
TOKDEF(class),
TOKDEF(class_class),
TOKDEF(classes),
TOKDEF(clear),
TOKDEF(clearance),
TOKDEF(cluster),
TOKDEF(cm),
TOKDEF(color),
TOKDEF(colors),
TOKDEF(comment),
TOKDEF(comp),
TOKDEF(comp_edge_center),
TOKDEF(comp_order),
TOKDEF(component),
TOKDEF(composite),
TOKDEF(conductance_resolution),
TOKDEF(conductor),
TOKDEF(conflict),
TOKDEF(connect),
TOKDEF(constant),
TOKDEF(contact),
TOKDEF(control),
TOKDEF(corner),
TOKDEF(corners),
TOKDEF(cost),
TOKDEF(created_time),
TOKDEF(cross),
TOKDEF(crosstalk_model),
TOKDEF(current_resolution),
TOKDEF(delete_pins),
TOKDEF(deleted),
TOKDEF(deleted_keepout),
TOKDEF(delta),
TOKDEF(diagonal),
TOKDEF(direction),
TOKDEF(directory),
TOKDEF(discrete),
TOKDEF(effective_via_length),
TOKDEF(elongate_keepout),
TOKDEF(exclude),
TOKDEF(expose),
TOKDEF(extra_image_directory),
TOKDEF(family),
TOKDEF(family_family),
TOKDEF(family_family_spacing),
TOKDEF(fanout),
TOKDEF(farad),
TOKDEF(file),
TOKDEF(fit),
TOKDEF(fix),
TOKDEF(flip_style),
TOKDEF(floor_plan),
TOKDEF(footprint),
TOKDEF(forbidden),
TOKDEF(force_to_terminal_point),
TOKDEF(forgotten),
TOKDEF(free),
TOKDEF(fromto),
TOKDEF(front),
TOKDEF(front_only),
TOKDEF(gap),
TOKDEF(gate),
TOKDEF(gates),
TOKDEF(generated_by_freeroute),
TOKDEF(global),
TOKDEF(grid),
TOKDEF(group),
TOKDEF(group_set),
TOKDEF(guide),
TOKDEF(hard),
TOKDEF(height),
TOKDEF(high),
TOKDEF(history),
TOKDEF(horizontal),
TOKDEF(host_cad),
TOKDEF(host_version),
TOKDEF(image),
TOKDEF(image_conductor),
TOKDEF(image_image),
TOKDEF(image_image_spacing),
TOKDEF(image_outline_clearance),
TOKDEF(image_set),
TOKDEF(image_type),
TOKDEF(inch),
TOKDEF(include),
TOKDEF(include_pins_in_crosstalk),
TOKDEF(inductance_resolution),
TOKDEF(insert),
TOKDEF(instcnfg),
TOKDEF(inter_layer_clearance),
TOKDEF(jumper),
TOKDEF(junction_type),
TOKDEF(keepout),
TOKDEF(kg),
TOKDEF(kohm),
TOKDEF(large),
TOKDEF(large_large),
TOKDEF(layer),
TOKDEF(layer_depth),
TOKDEF(layer_noise_weight),
TOKDEF(layer_pair),
TOKDEF(layer_rule),
TOKDEF(length),
TOKDEF(length_amplitude),
TOKDEF(length_factor),
TOKDEF(length_gap),
TOKDEF(library),
TOKDEF(library_out),
TOKDEF(limit),
TOKDEF(limit_bends),
TOKDEF(limit_crossing),
TOKDEF(limit_vias),
TOKDEF(limit_way),
TOKDEF(linear),
TOKDEF(linear_interpolation),
TOKDEF(load),
TOKDEF(lock_type),
TOKDEF(logical_part),
TOKDEF(logical_part_mapping),
TOKDEF(low),
TOKDEF(match_fromto_delay),
TOKDEF(match_fromto_length),
TOKDEF(match_group_delay),
TOKDEF(match_group_length),
TOKDEF(match_net_delay),
TOKDEF(match_net_length),
TOKDEF(max_delay),
TOKDEF(max_len),
TOKDEF(max_length),
TOKDEF(max_noise),
TOKDEF(max_restricted_layer_length),
TOKDEF(max_stagger),
TOKDEF(max_stub),
TOKDEF(max_total_delay),
TOKDEF(max_total_length),
TOKDEF(max_total_vias),
TOKDEF(medium),
TOKDEF(mhenry),
TOKDEF(mho),
TOKDEF(microvia),
TOKDEF(mid_driven),
TOKDEF(mil),
TOKDEF(min_gap),
TOKDEF(mirror),
TOKDEF(mirror_first),
TOKDEF(mixed),
TOKDEF(mm),
TOKDEF(negative_diagonal),
TOKDEF(net),
TOKDEF(net_number),
TOKDEF(net_out),
TOKDEF(net_pin_changes),
TOKDEF(nets),
TOKDEF(network),
TOKDEF(network_out),
TOKDEF(no),
TOKDEF(noexpose),
TOKDEF(noise_accumulation),
TOKDEF(noise_calculation),
TOKDEF(normal),
TOKDEF(object_type),
TOKDEF(off),
TOKDEF(off_grid),
TOKDEF(offset),
TOKDEF(on),
TOKDEF(open),
TOKDEF(opposite_side),
TOKDEF(order),
TOKDEF(orthogonal),
TOKDEF(outline),
TOKDEF(overlap),
TOKDEF(pad),
TOKDEF(pad_pad),
TOKDEF(padstack),
TOKDEF(pair),
TOKDEF(parallel),
TOKDEF(parallel_noise),
TOKDEF(parallel_segment),
TOKDEF(parser),
TOKDEF(part_library),
TOKDEF(path),
TOKDEF(pcb),
TOKDEF(permit_orient),
TOKDEF(permit_side),
TOKDEF(physical),
TOKDEF(physical_part_mapping),
TOKDEF(piggyback),
TOKDEF(pin),
TOKDEF(pin_allow),
TOKDEF(pin_cap_via),
TOKDEF(pin_via_cap),
TOKDEF(pin_width_taper),
TOKDEF(pins),
TOKDEF(pintype),
TOKDEF(place),
TOKDEF(place_boundary),
TOKDEF(place_control),
TOKDEF(place_keepout),
TOKDEF(place_rule),
TOKDEF(placement),
TOKDEF(plan),
TOKDEF(plane),
TOKDEF(pn),
TOKDEF(point),
TOKDEF(polyline_path), // used by freerouting.com
TOKDEF(polygon),
TOKDEF(position),
TOKDEF(positive_diagonal),
TOKDEF(power),
TOKDEF(power_dissipation),
TOKDEF(power_fanout),
TOKDEF(prefix),
TOKDEF(primary),
TOKDEF(priority),
TOKDEF(property),
TOKDEF(protect),
TOKDEF(qarc),
TOKDEF(quarter),
TOKDEF(radius),
TOKDEF(ratio),
TOKDEF(ratio_tolerance),
TOKDEF(rect),
TOKDEF(reduced),
TOKDEF(region),
TOKDEF(region_class),
TOKDEF(region_class_class),
TOKDEF(region_net),
TOKDEF(relative_delay),
TOKDEF(relative_group_delay),
TOKDEF(relative_group_length),
TOKDEF(relative_length),
TOKDEF(reorder),
TOKDEF(reroute_order_viols),
TOKDEF(resistance_resolution),
TOKDEF(resistor),
TOKDEF(resolution),
TOKDEF(restricted_layer_length_factor),
TOKDEF(room),
TOKDEF(rotate),
TOKDEF(rotate_first),
TOKDEF(round),
TOKDEF(roundoff_rotation),
TOKDEF(route),
TOKDEF(route_to_fanout_only),
TOKDEF(routes),
TOKDEF(routes_include),
TOKDEF(rule),
TOKDEF(same_net_checking),
TOKDEF(sample_window),
TOKDEF(saturation_length),
TOKDEF(sec),
TOKDEF(secondary),
TOKDEF(self),
TOKDEF(sequence_number),
TOKDEF(session),
TOKDEF(set_color),
TOKDEF(set_pattern),
TOKDEF(shape),
TOKDEF(shield),
TOKDEF(shield_gap),
TOKDEF(shield_loop),
TOKDEF(shield_tie_down_interval),
TOKDEF(shield_width),
TOKDEF(side),
TOKDEF(signal),
TOKDEF(site),
TOKDEF(small),
TOKDEF(smd),
TOKDEF(snap),
TOKDEF(snap_angle),
TOKDEF(soft),
TOKDEF(source),
TOKDEF(space_in_quoted_tokens),
TOKDEF(spacing),
TOKDEF(spare),
TOKDEF(spiral_via),
TOKDEF(square),
TOKDEF(stack_via),
TOKDEF(stack_via_depth),
TOKDEF(standard),
TOKDEF(starburst),
TOKDEF(status),
TOKDEF(string_quote),
TOKDEF(structure),
TOKDEF(structure_out),
TOKDEF(subgate),
TOKDEF(subgates),
TOKDEF(substituted),
TOKDEF(such),
TOKDEF(suffix),
TOKDEF(super_placement),
TOKDEF(supply),
TOKDEF(supply_pin),
TOKDEF(swapping),
TOKDEF(switch_window),
TOKDEF(system),
TOKDEF(tandem_noise),
TOKDEF(tandem_segment),
TOKDEF(tandem_shield_overhang),
TOKDEF(terminal),
TOKDEF(terminator),
TOKDEF(term_only),
TOKDEF(test),
TOKDEF(test_points),
TOKDEF(testpoint),
TOKDEF(threshold),
TOKDEF(time_length_factor),
TOKDEF(time_resolution),
TOKDEF(tjunction),
TOKDEF(tolerance),
TOKDEF(top),
TOKDEF(topology),
TOKDEF(total),
TOKDEF(track_id),
TOKDEF(turret),
TOKDEF(type),
TOKDEF(um),
TOKDEF(unassigned),
TOKDEF(unconnects),
TOKDEF(unit),
TOKDEF(up),
TOKDEF(use_array),
TOKDEF(use_layer),
TOKDEF(use_net),
TOKDEF(use_via),
TOKDEF(value),
TOKDEF(vertical),
TOKDEF(via),
TOKDEF(via_array_template),
TOKDEF(via_at_smd),
TOKDEF(via_keepout),
TOKDEF(via_number),
TOKDEF(via_rotate_first),
TOKDEF(via_site),
TOKDEF(via_size),
TOKDEF(virtual_pin),
TOKDEF(volt),
TOKDEF(voltage_resolution),
TOKDEF(was_is),
TOKDEF(way),
TOKDEF(weight),
TOKDEF(width),
TOKDEF(window),
TOKDEF(wire),
TOKDEF(wire_keepout),
TOKDEF(wires),
TOKDEF(wires_include),
TOKDEF(wiring),
TOKDEF(write_resolution),
TOKDEF(x),
TOKDEF(xy),
TOKDEF(y),
};
static int compare( const void* a1, const void* a2 ) static int compare( const void* a1, const void* a2 )
{ {
const KEYWORD* k1 = (const KEYWORD*) a1; const KEYWORD* k1 = (const KEYWORD*) a1;
...@@ -467,54 +46,17 @@ static int compare( const void* a1, const void* a2 ) ...@@ -467,54 +46,17 @@ static int compare( const void* a1, const void* a2 )
} }
//-----<LINE_READER>------------------------------------------------------ //-----<DSNLEXER>-------------------------------------------------------------
LINE_READER::LINE_READER( FILE* aFile, unsigned aMaxLineLength )
{
fp = aFile;
lineNum = 0;
maxLineLength = aMaxLineLength;
// the real capacity is 10 bytes larger than requested.
capacity = aMaxLineLength + 10;
line = new char[capacity];
line[0] = '\0';
length = 0;
}
DSNLEXER::DSNLEXER( FILE* aFile, const wxString& aFilename,
const KEYWORD* aKeywordTable, unsigned aKeywordCount ) :
reader( aFile, 4096 )
int LINE_READER::ReadLine() throw (IOError)
{ {
const char* p = fgets( line, capacity, fp ); keywords = aKeywordTable;
keywordCount = aKeywordCount;
if( !p ) curTok = DSN_NONE;
{
line[0] = 0;
length = 0;
}
else
{
length = strlen( line );
if( length > maxLineLength )
throw IOError( _("Line length exceeded") );
++lineNum;
}
return length;
}
//-----<LEXER>-------------------------------------------------------------
LEXER::LEXER( FILE* aFile, const wxString& aFilename ) :
reader( aFile, 4096 )
{
curTok = T_END;
stringDelimiter = '"'; stringDelimiter = '"';
filename = aFilename; filename = aFilename;
...@@ -530,7 +72,7 @@ LEXER::LEXER( FILE* aFile, const wxString& aFilename ) : ...@@ -530,7 +72,7 @@ LEXER::LEXER( FILE* aFile, const wxString& aFilename ) :
} }
int LEXER::findToken( const std::string& tok ) int DSNLEXER::findToken( const std::string& tok )
{ {
// convert to lower case once, this should be faster than using strcasecmp() // convert to lower case once, this should be faster than using strcasecmp()
// for each test in compare(). // for each test in compare().
...@@ -540,78 +82,83 @@ int LEXER::findToken( const std::string& tok ) ...@@ -540,78 +82,83 @@ int LEXER::findToken( const std::string& tok )
lowercase += (char) tolower( *iter ); lowercase += (char) tolower( *iter );
KEYWORD search; KEYWORD search;
search.name = lowercase.c_str(); search.name = lowercase.c_str();
// a boost hashtable might be a few percent faster, depending on
// hashtable size and quality of the hash function.
const KEYWORD* findings = (const KEYWORD*) bsearch( &search, const KEYWORD* findings = (const KEYWORD*) bsearch( &search,
tokens, sizeof(tokens)/sizeof(tokens[0]), keywords, keywordCount,
sizeof(KEYWORD), compare ); sizeof(KEYWORD), compare );
if( findings ) if( findings )
// return findings->token; return findings->token;
return findings - tokens;
else else
return -1; return -1;
} }
const char* LEXER::GetTokenText( DSN_T aTok ) const char* DSNLEXER::Syntax( int aTok )
{ {
const char* ret; const char* ret;
if( aTok < 0 )
{
switch( aTok ) switch( aTok )
{ {
case T_NONE: case DSN_NONE:
ret = "NONE"; ret = "NONE";
break; break;
case T_QUOTE_DEF: case DSN_QUOTE_DEF:
ret = "quoted text delimiter"; ret = "quoted text delimiter";
break; break;
case T_DASH: case DSN_DASH:
ret = "-"; ret = "-";
break; break;
case T_SYMBOL: case DSN_SYMBOL:
ret = "symbol"; ret = "symbol";
break; break;
case T_NUMBER: case DSN_NUMBER:
ret = "number"; ret = "number";
break; break;
case T_RIGHT: case DSN_RIGHT:
ret = ")"; ret = ")";
break; break;
case T_LEFT: case DSN_LEFT:
ret = "("; ret = "(";
break; break;
case T_STRING: case DSN_STRING:
ret = "quoted string"; ret = "quoted string";
break; break;
case T_EOF: case DSN_EOF:
ret = "end of file"; ret = "end of file";
break; break;
default: default:
ret = "???"; ret = "???";
} }
}
else
{
ret = tokens[aTok].name;
}
return ret; return ret;
} }
wxString LEXER::GetTokenString( DSN_T aTok ) const char* DSNLEXER::GetTokenText( int aTok )
{ {
wxString ret; const char* ret;
ret << wxT("'") << CONV_FROM_UTF8( GetTokenText(aTok) ) << wxT("'"); if( aTok < 0 )
{
return Syntax( aTok );
}
else if( (unsigned) aTok < keywordCount )
{
ret = keywords[aTok].name;
}
else
ret = "token too big";
return ret; return ret;
} }
void LEXER::ThrowIOError( wxString aText, int charOffset ) throw (IOError) void DSNLEXER::ThrowIOError( wxString aText, int charOffset ) throw (IOError)
{ {
aText << wxT(" ") << _("in file") << wxT(" \"") << filename aText << wxT(" ") << _("in file") << wxT(" \"") << filename
<< wxT("\" ") << _("on line") << wxT(" ") << reader.LineNumber() << wxT("\" ") << _("on line") << wxT(" ") << reader.LineNumber()
...@@ -633,14 +180,14 @@ static inline bool isSpace( int cc ) ...@@ -633,14 +180,14 @@ static inline bool isSpace( int cc )
} }
DSN_T LEXER::NextTok() throw (IOError) int DSNLEXER::NextTok() throw (IOError)
{ {
char* cur = next; char* cur = next;
char* head = cur; char* head = cur;
prevTok = curTok; prevTok = curTok;
if( curTok != T_EOF ) if( curTok != DSN_EOF )
{ {
if( cur >= limit ) if( cur >= limit )
{ {
...@@ -648,7 +195,7 @@ L_read: ...@@ -648,7 +195,7 @@ L_read:
int len = readLine(); int len = readLine();
if( len == 0 ) if( len == 0 )
{ {
curTok = T_EOF; curTok = DSN_EOF;
goto exit; goto exit;
} }
...@@ -673,7 +220,7 @@ L_read: ...@@ -673,7 +220,7 @@ L_read:
goto L_read; goto L_read;
// switching the string_quote character // switching the string_quote character
if( prevTok == T_string_quote ) if( prevTok == DSN_STRING_QUOTE )
{ {
static const wxString errtxt( _("String delimiter must be a single character of ', \", or $")); static const wxString errtxt( _("String delimiter must be a single character of ', \", or $"));
...@@ -698,7 +245,7 @@ L_read: ...@@ -698,7 +245,7 @@ L_read:
ThrowIOError( errtxt, CurOffset() ); ThrowIOError( errtxt, CurOffset() );
} }
curTok = T_QUOTE_DEF; curTok = DSN_QUOTE_DEF;
goto exit; goto exit;
} }
...@@ -707,7 +254,7 @@ L_read: ...@@ -707,7 +254,7 @@ L_read:
curText.clear(); curText.clear();
curText += *cur; curText += *cur;
curTok = T_LEFT; curTok = DSN_LEFT;
head = cur+1; head = cur+1;
goto exit; goto exit;
} }
...@@ -717,7 +264,7 @@ L_read: ...@@ -717,7 +264,7 @@ L_read:
curText.clear(); curText.clear();
curText += *cur; curText += *cur;
curTok = T_RIGHT; curTok = DSN_RIGHT;
head = cur+1; head = cur+1;
goto exit; goto exit;
} }
...@@ -731,11 +278,11 @@ L_read: ...@@ -731,11 +278,11 @@ L_read:
head = cur+1; head = cur+1;
curText.clear(); curText.clear();
curText += '-'; curText += '-';
curTok = T_DASH; curTok = DSN_DASH;
goto exit; goto exit;
} }
// handle T_NUMBER // handle DSN_NUMBER
if( strchr( "+-.0123456789", *cur ) ) if( strchr( "+-.0123456789", *cur ) )
{ {
head = cur+1; head = cur+1;
...@@ -746,7 +293,7 @@ L_read: ...@@ -746,7 +293,7 @@ L_read:
{ {
curText.clear(); curText.clear();
curText.append( cur, head ); curText.append( cur, head );
curTok = T_NUMBER; curTok = DSN_NUMBER;
goto exit; goto exit;
} }
...@@ -774,12 +321,12 @@ L_read: ...@@ -774,12 +321,12 @@ L_read:
++head; // skip over the trailing delimiter ++head; // skip over the trailing delimiter
curTok = T_STRING; curTok = DSN_STRING;
goto exit; goto exit;
} }
// a token we hope to find in the tokens[] array. If not, then // Maybe it is a token we will find in the token table.
// call it a T_SYMBOL. // If not, then call it a DSN_SYMBOL.
{ {
head = cur+1; head = cur+1;
while( head<limit && !isSpace( *head ) && *head!=')' && *head!='(' ) while( head<limit && !isSpace( *head ) && *head!=')' && *head!='(' )
...@@ -791,33 +338,33 @@ L_read: ...@@ -791,33 +338,33 @@ L_read:
int found = findToken( curText ); int found = findToken( curText );
if( found != -1 ) if( found != -1 )
curTok = (DSN_T) found; curTok = found;
else if( 0 == curText.compare( "string_quote" ) )
curTok = DSN_STRING_QUOTE;
else // unrecogized token, call it a symbol else // unrecogized token, call it a symbol
curTok = T_SYMBOL; curTok = DSN_SYMBOL;
} }
} }
exit: // single point of exit exit: // single point of exit, no returns elsewhere please.
curOffset = cur - start; curOffset = cur - start;
next = head; next = head;
// printf("tok:\"%s\"\n", curText.c_str() ); // printf("tok:\"%s\"\n", curText.c_str() );
return curTok; return curTok;
} }
} // namespace DSN
#if 0 && defined(STANDALONE) #if 0 && defined(STANDALONE)
// stand alone testing // stand alone testing
int main( int argc, char** argv ) int main( int argc, char** argv )
{ {
...@@ -833,17 +380,18 @@ int main( int argc, char** argv ) ...@@ -833,17 +380,18 @@ int main( int argc, char** argv )
exit(1); exit(1);
} }
DSN::LEXER lexer( fp, filename ); // this won't compile without a token table.
DSNLEXER lexer( fp, filename );
try try
{ {
int tok; int tok;
while( (tok = lexer.NextTok()) != DSN::T_EOF ) while( (tok = lexer.NextTok()) != DSN_EOF )
{ {
printf( "%-3d %s\n", tok, lexer.CurText() ); printf( "%-3d %s\n", tok, lexer.CurText() );
} }
} }
catch( DSN::IOError ioe ) catch( IOError ioe )
{ {
printf( "%s\n", (const char*) ioe.errorText.mb_str() ); printf( "%s\n", (const char*) ioe.errorText.mb_str() );
} }
......
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2007-2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <cstdarg>
#include "richio.h"
// This file defines 3 classes useful for working with DSN text files and is named
// "richio" after its author, Richard Hollenbeck, aka Dick Hollenbeck.
//-----<LINE_READER>------------------------------------------------------
LINE_READER::LINE_READER( FILE* aFile, unsigned aMaxLineLength )
{
fp = aFile;
lineNum = 0;
maxLineLength = aMaxLineLength;
// the real capacity is 10 bytes larger than requested.
capacity = aMaxLineLength + 10;
line = new char[capacity];
line[0] = '\0';
length = 0;
}
int LINE_READER::ReadLine() throw (IOError)
{
const char* p = fgets( line, capacity, fp );
if( !p )
{
line[0] = 0;
length = 0;
}
else
{
length = strlen( line );
if( length > maxLineLength )
throw IOError( _("Line length exceeded") );
++lineNum;
}
return length;
}
//-----<OUTPUTFORMATTER>----------------------------------------------------
// factor out a common GetQuoteChar
const char* OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, const char* quote_char )
{
// Include '#' so a symbol is not confused with a comment. We intend
// to wrap any symbol starting with a '#'.
// Our LEXER class handles comments, and comments appear to be an extension
// to the SPECCTRA DSN specification.
if( *wrapee == '#' )
return quote_char;
if( strlen(wrapee)==0 )
return quote_char;
bool isFirst = true;
for( ; *wrapee; ++wrapee, isFirst=false )
{
static const char quoteThese[] = "\t ()"
"%" // per Alfons of freerouting.net, he does not like this unquoted as of 1-Feb-2008
"{}" // guessing that these are problems too
;
// if the string to be wrapped (wrapee) has a delimiter in it,
// return the quote_char so caller wraps the wrapee.
if( strchr( quoteThese, *wrapee ) )
return quote_char;
if( !isFirst && '-' == *wrapee )
return quote_char;
}
return ""; // caller does not need to wrap, can use an unwrapped string.
}
//-----<STRINGFORMATTER>----------------------------------------------------
const char* STRINGFORMATTER::GetQuoteChar( const char* wrapee )
{
// for what we are using STRINGFORMATTER for at this time, we can return
// the nul string always.
return "";
// return OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, "\"" );
}
int STRINGFORMATTER::vprint( const char* fmt, va_list ap )
{
int ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
if( ret >= (int) buffer.size() )
{
buffer.reserve( ret+200 );
ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
}
if( ret > 0 )
mystring.append( (const char*) &buffer[0] );
return ret;
}
int STRINGFORMATTER::sprint( const char* fmt, ... )
{
va_list args;
va_start( args, fmt );
int ret = vprint( fmt, args);
va_end( args );
return ret;
}
int STRINGFORMATTER::Print( int nestLevel, const char* fmt, ... ) throw( IOError )
{
#define NESTWIDTH 2 ///< how many spaces per nestLevel
va_list args;
va_start( args, fmt );
int result = 0;
int total = 0;
for( int i=0; i<nestLevel; ++i )
{
result = sprint( "%*c", NESTWIDTH, ' ' );
if( result < 0 )
break;
total += result;
}
if( result<0 || (result=vprint( fmt, args ))<0 )
{
throw IOError( _("Error writing to STRINGFORMATTER") );
}
va_end( args );
total += result;
return total;
}
void STRINGFORMATTER::StripUseless()
{
std::string copy = mystring;
mystring.clear();
for( std::string::iterator i=copy.begin(); i!=copy.end(); ++i )
{
if( !isspace( *i ) && *i!=')' && *i!='(' && *i!='"' )
{
mystring += *i;
}
}
}
/* /*
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 2007-2008 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2007-2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors. * Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
...@@ -22,8 +22,8 @@ ...@@ -22,8 +22,8 @@
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/ */
#ifndef _DSN_H #ifndef _DSNLEXER_H
#define _DSN_H #define _DSNLEXER_H
#include <cstdio> #include <cstdio>
#include <string> #include <string>
...@@ -31,521 +31,51 @@ ...@@ -31,521 +31,51 @@
#include "fctsys.h" #include "fctsys.h"
#include "pcbnew.h" #include "pcbnew.h"
#include "richio.h"
namespace DSN {
/**
* Enum DSN_T
* lists all the DSN lexer's tokens that are supported in lexing. It is up
* to the parser if it wants also to support them.
*/
enum DSN_T {
// the first few are special (the uppercase ones)
T_NONE = -9,
T_QUOTE_DEF = -8,
T_DASH = -7,
T_SYMBOL = -6,
T_NUMBER = -5,
T_RIGHT = -4, // right bracket, ')'
T_LEFT = -3, // left bracket, '('
T_STRING = -2, // a quoted string, stripped of the quotes
T_EOF = -1, // special case for end of file
// from here down, this list segment should be coordinated with the
// const static KEYWORD tokens[] array in dsn.cpp, and must be sorted
// alphabetically. Remember that '_' is less than any alpha character
// according to ASCII.
T_absolute, // this one should be == zero
T_added,
T_add_group,
T_add_pins,
T_allow_antenna,
T_allow_redundant_wiring,
T_amp,
T_ancestor,
T_antipad,
T_aperture_type,
T_array,
T_attach,
T_attr,
T_average_pair_length,
T_back,
T_base_design,
T_bbv_ctr2ctr,
T_bend_keepout,
T_bond,
T_both,
T_bottom,
T_bottom_layer_sel,
T_boundary,
T_brickpat,
T_bundle,
T_bus,
T_bypass,
T_capacitance_resolution,
T_capacitor,
T_case_sensitive,
T_cct1,
T_cct1a,
T_center_center,
T_checking_trim_by_pin,
T_circ,
T_circle,
T_circuit,
T_class,
T_class_class,
T_classes,
T_clear,
T_clearance,
T_cluster,
T_cm,
T_color,
T_colors,
T_comment,
T_comp,
T_comp_edge_center,
T_comp_order,
T_component,
T_composite,
T_conductance_resolution,
T_conductor,
T_conflict,
T_connect,
T_constant,
T_contact,
T_control,
T_corner,
T_corners,
T_cost,
T_created_time,
T_cross,
T_crosstalk_model,
T_current_resolution,
T_delete_pins,
T_deleted,
T_deleted_keepout,
T_delta,
T_diagonal,
T_direction,
T_directory,
T_discrete,
T_effective_via_length,
T_elongate_keepout,
T_exclude,
T_expose,
T_extra_image_directory,
T_family,
T_family_family,
T_family_family_spacing,
T_fanout,
T_farad,
T_file,
T_fit,
T_fix,
T_flip_style,
T_floor_plan,
T_footprint,
T_forbidden,
T_force_to_terminal_point,
T_free,
T_forgotten,
T_fromto,
T_front,
T_front_only,
T_gap,
T_gate,
T_gates,
T_generated_by_freeroute,
T_global,
T_grid,
T_group,
T_group_set,
T_guide,
T_hard,
T_height,
T_high,
T_history,
T_horizontal,
T_host_cad,
T_host_version,
T_image,
T_image_conductor,
T_image_image,
T_image_image_spacing,
T_image_outline_clearance,
T_image_set,
T_image_type,
T_inch,
T_include,
T_include_pins_in_crosstalk,
T_inductance_resolution,
T_insert,
T_instcnfg,
T_inter_layer_clearance,
T_jumper,
T_junction_type,
T_keepout,
T_kg,
T_kohm,
T_large,
T_large_large,
T_layer,
T_layer_depth,
T_layer_noise_weight,
T_layer_pair,
T_layer_rule,
T_length,
T_length_amplitude,
T_length_factor,
T_length_gap,
T_library,
T_library_out,
T_limit,
T_limit_bends,
T_limit_crossing,
T_limit_vias,
T_limit_way,
T_linear,
T_linear_interpolation,
T_load,
T_lock_type,
T_logical_part,
T_logical_part_mapping,
T_low,
T_match_fromto_delay,
T_match_fromto_length,
T_match_group_delay,
T_match_group_length,
T_match_net_delay,
T_match_net_length,
T_max_delay,
T_max_len,
T_max_length,
T_max_noise,
T_max_restricted_layer_length,
T_max_stagger,
T_max_stub,
T_max_total_delay,
T_max_total_length,
T_max_total_vias,
T_medium,
T_mhenry,
T_mho,
T_microvia,
T_mid_driven,
T_mil,
T_min_gap,
T_mirror,
T_mirror_first,
T_mixed,
T_mm,
T_negative_diagonal,
T_net,
T_net_number,
T_net_out,
T_net_pin_changes,
T_nets,
T_network,
T_network_out,
T_no,
T_noexpose,
T_noise_accumulation,
T_noise_calculation,
T_normal,
T_object_type,
T_off,
T_off_grid,
T_offset,
T_on,
T_open,
T_opposite_side,
T_order,
T_orthogonal,
T_outline,
T_overlap,
T_pad,
T_pad_pad,
T_padstack,
T_pair,
T_parallel,
T_parallel_noise,
T_parallel_segment,
T_parser,
T_part_library,
T_path,
T_pcb,
T_permit_orient,
T_permit_side,
T_physical,
T_physical_part_mapping,
T_piggyback,
T_pin,
T_pin_allow,
T_pin_cap_via,
T_pin_via_cap,
T_pin_width_taper,
T_pins,
T_pintype,
T_place,
T_place_boundary,
T_place_control,
T_place_keepout,
T_place_rule,
T_placement,
T_plan,
T_plane,
T_pn,
T_point,
T_polyline_path,
T_polygon,
T_position,
T_positive_diagonal,
T_power,
T_power_dissipation,
T_power_fanout,
T_prefix,
T_primary,
T_priority,
T_property,
T_protect,
T_qarc,
T_quarter,
T_radius,
T_ratio,
T_ratio_tolerance,
T_rect,
T_reduced,
T_region,
T_region_class,
T_region_class_class,
T_region_net,
T_relative_delay,
T_relative_group_delay,
T_relative_group_length,
T_relative_length,
T_reorder,
T_reroute_order_viols,
T_resistance_resolution,
T_resistor,
T_resolution,
T_restricted_layer_length_factor,
T_room,
T_rotate,
T_rotate_first,
T_round,
T_roundoff_rotation,
T_route,
T_route_to_fanout_only,
T_routes,
T_routes_include,
T_rule,
T_same_net_checking,
T_sample_window,
T_saturation_length,
T_sec,
T_secondary,
T_self,
T_sequence_number,
T_session,
T_set_color,
T_set_pattern,
T_shape,
T_shield,
T_shield_gap,
T_shield_loop,
T_shield_tie_down_interval,
T_shield_width,
T_side,
T_signal,
T_site,
T_small,
T_smd,
T_snap,
T_snap_angle,
T_soft,
T_source,
T_space_in_quoted_tokens,
T_spacing,
T_spare,
T_spiral_via,
T_square,
T_stack_via,
T_stack_via_depth,
T_standard,
T_starburst,
T_status,
T_string_quote,
T_structure,
T_structure_out,
T_subgate,
T_subgates,
T_substituted,
T_such,
T_suffix,
T_super_placement,
T_supply,
T_supply_pin,
T_swapping,
T_switch_window,
T_system,
T_tandem_noise,
T_tandem_segment,
T_tandem_shield_overhang,
T_terminal,
T_terminator,
T_term_only,
T_test,
T_test_points,
T_testpoint,
T_threshold,
T_time_length_factor,
T_time_resolution,
T_tjunction,
T_tolerance,
T_top,
T_topology,
T_total,
T_track_id,
T_turret,
T_type,
T_um,
T_unassigned,
T_unconnects,
T_unit,
T_up,
T_use_array,
T_use_layer,
T_use_net,
T_use_via,
T_value,
T_vertical,
T_via,
T_via_array_template,
T_via_at_smd,
T_via_keepout,
T_via_number,
T_via_rotate_first,
T_via_site,
T_via_size,
T_virtual_pin,
T_volt,
T_voltage_resolution,
T_was_is,
T_way,
T_weight,
T_width,
T_window,
T_wire,
T_wire_keepout,
T_wires,
T_wires_include,
T_wiring,
T_write_resolution,
T_x,
T_xy,
T_y,
T_END // just a sentinel, not a token
};
/** /**
* Struct IOError * Struct KEYWORD
* is a class used to hold an error message and may be thrown from the LEXER. * holds a keyword string and its unique integer token.
*/ */
struct IOError struct KEYWORD
{ {
wxString errorText; const char* name; ///< unique keyword.
int token; ///< a zero based index into an array of KEYWORDs
IOError( const wxChar* aMsg ) :
errorText( aMsg )
{
}
IOError( const wxString& aMsg ) :
errorText( aMsg )
{
}
}; };
// something like this macro can be used to help initialize a KEYWORD table.
// see SPECCTRA_DB::keywords[] as an example.
/** //#define TOKDEF(x) { #x, T_##x }
* Class LINE_READER
* reads single lines of text into its buffer and increments a line number counter.
* It throws an exception if a line is too long.
*/
class LINE_READER
{
protected:
FILE* fp;
int lineNum;
unsigned maxLineLength;
unsigned length;
char* line;
unsigned capacity;
public:
/**
* Constructor LINE_READER
* takes an open FILE and the size of the desired line buffer.
* @param aFile An open file in "ascii" mode, not binary mode.
* @param aMaxLineLength The number of bytes to use in the line buffer.
*/
LINE_READER( FILE* aFile, unsigned aMaxLineLength );
~LINE_READER()
{
delete[] line;
}
/*
int CharAt( int aNdx )
{
if( (unsigned) aNdx < capacity )
return (char) (unsigned char) line[aNdx];
return -1;
}
*/
/** /**
* Function ReadLine * Enum DSN_SYNTAX_T
* reads a line of text into the buffer and increments the line number * lists all the DSN lexer's tokens that are supported in lexing. It is up
* counter. If the line is larger than the buffer size, then an exception * to the parser if it wants also to support them.
* is thrown.
* @return int - The number of bytes read, 0 at end of file.
* @throw IOError only when a line is too long.
*/ */
int ReadLine() throw (IOError); enum DSN_SYNTAX_T {
DSN_NONE = -10,
operator char* () DSN_STRING_QUOTE = -9,
{ DSN_QUOTE_DEF = -8,
return line; DSN_DASH = -7,
} DSN_SYMBOL = -6,
DSN_NUMBER = -5,
int LineNumber() DSN_RIGHT = -4, // right bracket, ')'
{ DSN_LEFT = -3, // left bracket, '('
return lineNum; DSN_STRING = -2, // a quoted string, stripped of the quotes
} DSN_EOF = -1, // special case for end of file
unsigned Length()
{
return length;
}
}; };
/** /**
* Class LEXER * Class DLEXER
* implements a lexical analyzer for the SPECCTRA DSN file format. It * implements a lexical analyzer for the SPECCTRA DSN file format. It
* reads lexical tokens from the current LINE_READER through the NextTok() * reads lexical tokens from the current LINE_READER through the NextTok()
* function. The NextTok() function returns one of the DSN_T values. * function. The NextTok() function returns one of the DSN_T values.
*/ */
class LEXER class DSNLEXER
{ {
char* next; char* next;
char* start; char* start;
...@@ -556,13 +86,16 @@ class LEXER ...@@ -556,13 +86,16 @@ class LEXER
bool space_in_quoted_tokens; ///< blank spaces within quoted strings bool space_in_quoted_tokens; ///< blank spaces within quoted strings
wxString filename; wxString filename;
DSN_T prevTok; ///< curTok from previous NextTok() call. int prevTok; ///< curTok from previous NextTok() call.
int curOffset; ///< offset within current line of the current token int curOffset; ///< offset within current line of the current token
DSN_T curTok; ///< the current token obtained on last NextTok() int curTok; ///< the current token obtained on last NextTok()
std::string curText; ///< the text of the current token std::string curText; ///< the text of the current token
std::string lowercase; ///< a scratch buf holding token in lowercase std::string lowercase; ///< a scratch buf holding token in lowercase
const KEYWORD* keywords;
unsigned keywordCount;
int readLine() throw (IOError) int readLine() throw (IOError)
{ {
...@@ -599,8 +132,18 @@ class LEXER ...@@ -599,8 +132,18 @@ class LEXER
public: public:
LEXER( FILE* aFile, const wxString& aFilename );
/**
* Constructor DSNLEXER
* intializes a DSN lexer and prepares to read from aFile which
* is already open and has aFilename.
*
* @param aKeywordTable is an array of KEYWORDS holding \a aKeywordCount. This
* token table need not contain the lexer separators such as '(' ')', etc.
* @param aKeywordTable is the count of tokens in aKeywordTable.
*/
DSNLEXER( FILE* aFile, const wxString& aFilename,
const KEYWORD* aKeywordTable, unsigned aKeywordCount );
/** /**
* Function SetStringDelimiter * Function SetStringDelimiter
...@@ -634,10 +177,10 @@ public: ...@@ -634,10 +177,10 @@ public:
* Function NextTok * Function NextTok
* returns the next token found in the input file or T_EOF when reaching * returns the next token found in the input file or T_EOF when reaching
* the end of file. * the end of file.
* @return DSN_T - the type of token found next. * @return int - the type of token found next.
* @throw IOError - only if the LINE_READER throws it. * @throw IOError - only if the LINE_READER throws it.
*/ */
DSN_T NextTok() throw (IOError); int NextTok() throw (IOError);
/** /**
...@@ -647,18 +190,13 @@ public: ...@@ -647,18 +190,13 @@ public:
*/ */
void ThrowIOError( wxString aText, int charOffset ) throw (IOError); void ThrowIOError( wxString aText, int charOffset ) throw (IOError);
/**
* Function GetTokenString
* returns the wxString representation of a DSN_T value.
*/
static wxString GetTokenString( DSN_T aTok );
/** /**
* Function GetTokenString * Function GetTokenString
* returns the C string representation of a DSN_T value. * returns the C string representation of a DSN_T value.
*/ */
static const char* GetTokenText( DSN_T aTok ); const char* GetTokenText( int aTok );
static const char* Syntax( int aTok );
/** /**
...@@ -674,7 +212,7 @@ public: ...@@ -674,7 +212,7 @@ public:
* Function CurTok * Function CurTok
* returns whatever NextTok() returned the last time it was called. * returns whatever NextTok() returned the last time it was called.
*/ */
DSN_T CurTok() int CurTok()
{ {
return curTok; return curTok;
} }
...@@ -702,7 +240,7 @@ public: ...@@ -702,7 +240,7 @@ public:
* Function PrevTok * Function PrevTok
* returns whatever NextTok() returned the 2nd to last time it was called. * returns whatever NextTok() returned the 2nd to last time it was called.
*/ */
DSN_T PrevTok() int PrevTok()
{ {
return prevTok; return prevTok;
} }
...@@ -716,10 +254,6 @@ public: ...@@ -716,10 +254,6 @@ public:
{ {
return curOffset + 1; return curOffset + 1;
} }
}; };
#endif // _DSNLEXER_H
} // namespace DSN
#endif // _DSN_H
/*
* This program source code file is part of KICAD, a free EDA CAD application.
*
* Copyright (C) 2007-2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, you may find one here:
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
* or you may search the http://www.gnu.org website for the version 2 license,
* or you may write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef RICHIO_H_
#define RICHIO_H_
// This file defines 3 classes useful for working with DSN text files and is named
// "richio" after its author, Richard Hollenbeck, aka Dick Hollenbeck.
#include <string>
#include <vector>
// I really did not want to be dependent on wxWidgets in richio
// but the errorText needs to be wide char so wxString rules.
#include <wx/wx.h>
#include <cstdio> // FILE
/**
* Struct IOError
* is a class used to hold an error message and may be used to throw exceptions
* containing meaningful error messages.
*/
struct IOError
{
wxString errorText;
IOError( const wxChar* aMsg ) :
errorText( aMsg )
{
}
IOError( const wxString& aMsg ) :
errorText( aMsg )
{
}
};
/**
* Class LINE_READER
* reads single lines of text into its buffer and increments a line number counter.
* It throws an exception if a line is too long.
*/
class LINE_READER
{
protected:
FILE* fp;
int lineNum;
unsigned maxLineLength;
unsigned length;
char* line;
unsigned capacity;
public:
/**
* Constructor LINE_READER
* takes an open FILE and the size of the desired line buffer.
* @param aFile An open file in "ascii" mode, not binary mode.
* @param aMaxLineLength The number of bytes to use in the line buffer.
*/
LINE_READER( FILE* aFile, unsigned aMaxLineLength );
~LINE_READER()
{
delete[] line;
}
/*
int CharAt( int aNdx )
{
if( (unsigned) aNdx < capacity )
return (char) (unsigned char) line[aNdx];
return -1;
}
*/
/**
* Function ReadLine
* reads a line of text into the buffer and increments the line number
* counter. If the line is larger than the buffer size, then an exception
* is thrown.
* @return int - The number of bytes read, 0 at end of file.
* @throw IOError only when a line is too long.
*/
int ReadLine() throw (IOError);
operator char* ()
{
return line;
}
int LineNumber()
{
return lineNum;
}
unsigned Length()
{
return length;
}
};
/**
* Class OUTPUTFORMATTER
* is an interface (abstract class) used to output ASCII text in a convenient
* way. The primary interface is printf() like but with support for indentation
* control. The destination of the 8 bit wide text is up to the implementer.
* If you want to output a wxString, then use CONV_TO_UTF8() on it before passing
* it as an argument to Print().
* <p>
* Since this is an abstract interface, only classes derived from this one
* will be the implementations.
*/
class OUTPUTFORMATTER
{
#if defined(__GNUG__) // The GNU C++ compiler defines this
// 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)))
#else
#define PRINTF_FUNC // nothing
#endif
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
* performs quote character need determination.
* It returns the quote character as a single character string for a given
* input wrapee string. If the wrappee does not need to be quoted,
* the return value is "" (the null string), such as when there are no
* delimiters in the input wrapee string. If you want the quote_char
* to be assuredly not "", then pass in "(" as the wrappee.
* <p>
* Implementations are free to override the default behavior, which is to
* call the static function of the same name.
* @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;
virtual ~OUTPUTFORMATTER() {}
/**
* Function GetQuoteChar
* performs quote character need determination according to the Specctra DSN
* specification.
* @param wrapee A string that might need wrapping on each end.
* @param quote_char A single character C string which provides the current
* quote character, should it be needed by the wrapee.
*
* @return const char* - the quote_char as a single character string, or ""
* if the wrapee does not need to be wrapped.
*/
static const char* GetQuoteChar( const char* wrapee, const char* quote_char );
};
/**
* Class STRINGFORMATTER
* implements OUTPUTFORMATTER to a memory buffer. After Print()ing the
* string is available through GetString()
*/
class STRINGFORMATTER : public OUTPUTFORMATTER
{
std::vector<char> buffer;
std::string mystring;
int sprint( const char* fmt, ... );
int vprint( const char* fmt, va_list ap );
public:
/**
* Constructor STRINGFORMATTER
* reserves space in the buffer
*/
STRINGFORMATTER( int aReserve = 300 ) :
buffer( aReserve, '\0' )
{
}
/**
* Function Clear
* clears the buffer and empties the internal string.
*/
void Clear()
{
mystring.clear();
}
/**
* Function StripUseless
* removes whitespace, '(', and ')' from the mystring.
*/
void StripUseless();
std::string GetString()
{
return mystring;
}
//-----<OUTPUTFORMATTER>------------------------------------------------
int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError );
const char* GetQuoteChar( const char* wrapee );
//-----</OUTPUTFORMATTER>-----------------------------------------------
};
#endif // RICHIO_H_
...@@ -78,7 +78,6 @@ set(PCBNEW_SRCS ...@@ -78,7 +78,6 @@ set(PCBNEW_SRCS
dist.cpp dist.cpp
dragsegm.cpp dragsegm.cpp
drc.cpp drc.cpp
dsn.cpp
edgemod.cpp edgemod.cpp
edit.cpp edit.cpp
editedge.cpp editedge.cpp
...@@ -222,9 +221,9 @@ install(TARGETS pcbnew ...@@ -222,9 +221,9 @@ install(TARGETS pcbnew
# This one gets made only when testing. # This one gets made only when testing.
add_executable(dsntest EXCLUDE_FROM_ALL dsn.cpp) #add_executable(dsntest EXCLUDE_FROM_ALL dsn.cpp)
target_link_libraries(dsntest common ${wxWidgets_LIBRARIES}) #target_link_libraries(dsntest common ${wxWidgets_LIBRARIES})
# This one gets made only when testing. # This one gets made only when testing.
add_executable(specctra_test EXCLUDE_FROM_ALL specctra.cpp dsn.cpp) add_executable(specctra_test EXCLUDE_FROM_ALL specctra.cpp)
target_link_libraries(specctra_test common ${wxWidgets_LIBRARIES}) target_link_libraries(specctra_test common ${wxWidgets_LIBRARIES})
...@@ -47,20 +47,21 @@ ...@@ -47,20 +47,21 @@
*/ */
#include <cstdarg> #include <cstdarg>
#include <cstdio> #include <cstdio>
#include "specctra.h" #include "specctra.h"
#include "common.h" // IsOK() & EDA_FileSelector()
#include <wx/ffile.h> #include <wx/ffile.h>
// To build the DSN beautifier and unit tester, simply uncomment this and then // To build the DSN beautifier and unit tester, simply uncomment this and then
// use CMake's makefile to build target "specctra_test". // use CMake's makefile to build target "specctra_test".
#define STANDALONE // define "stand alone, i.e. unit testing" //#define SPECCTRA_TEST // define for "stand alone, i.e. unit testing"
#if defined(STANDALONE) #if defined(SPECCTRA_TEST)
#define EDA_BASE // build_version.h behavior #define EDA_BASE // build_version.h behavior
#undef COMMON_GLOBL #undef COMMON_GLOBL
#define COMMON_GLOBL // build_version.h behavior #define COMMON_GLOBL // build_version.h behavior
...@@ -72,11 +73,445 @@ namespace DSN { ...@@ -72,11 +73,445 @@ namespace DSN {
#define NESTWIDTH 2 ///< how many spaces per nestLevel #define NESTWIDTH 2 ///< how many spaces per nestLevel
#define TOKDEF(x) { #x, T_##x }
// This MUST be sorted alphabetically, and the order of enum DSN_T {} be
// identially alphabetized. These MUST all be lower case because of the
// conversion to lowercase in findToken().
const KEYWORD SPECCTRA_DB::keywords[] = {
// Note that TOKDEF(string_quote) has been moved to the
// DSNLEXER, and DSN_SYNTAX_T enum, and the string for it is "string_quote".
TOKDEF(absolute),
TOKDEF(added),
TOKDEF(add_group),
TOKDEF(add_pins),
TOKDEF(allow_antenna),
TOKDEF(allow_redundant_wiring),
TOKDEF(amp),
TOKDEF(ancestor),
TOKDEF(antipad),
TOKDEF(aperture_type),
TOKDEF(array),
TOKDEF(attach),
TOKDEF(attr),
TOKDEF(average_pair_length),
TOKDEF(back),
TOKDEF(base_design),
TOKDEF(bbv_ctr2ctr),
TOKDEF(bend_keepout),
TOKDEF(bond),
TOKDEF(both),
TOKDEF(bottom),
TOKDEF(bottom_layer_sel),
TOKDEF(boundary),
TOKDEF(brickpat),
TOKDEF(bundle),
TOKDEF(bus),
TOKDEF(bypass),
TOKDEF(capacitance_resolution),
TOKDEF(capacitor),
TOKDEF(case_sensitive),
TOKDEF(cct1),
TOKDEF(cct1a),
TOKDEF(center_center),
TOKDEF(checking_trim_by_pin),
TOKDEF(circ),
TOKDEF(circle),
TOKDEF(circuit),
TOKDEF(class),
TOKDEF(class_class),
TOKDEF(classes),
TOKDEF(clear),
TOKDEF(clearance),
TOKDEF(cluster),
TOKDEF(cm),
TOKDEF(color),
TOKDEF(colors),
TOKDEF(comment),
TOKDEF(comp),
TOKDEF(comp_edge_center),
TOKDEF(comp_order),
TOKDEF(component),
TOKDEF(composite),
TOKDEF(conductance_resolution),
TOKDEF(conductor),
TOKDEF(conflict),
TOKDEF(connect),
TOKDEF(constant),
TOKDEF(contact),
TOKDEF(control),
TOKDEF(corner),
TOKDEF(corners),
TOKDEF(cost),
TOKDEF(created_time),
TOKDEF(cross),
TOKDEF(crosstalk_model),
TOKDEF(current_resolution),
TOKDEF(delete_pins),
TOKDEF(deleted),
TOKDEF(deleted_keepout),
TOKDEF(delta),
TOKDEF(diagonal),
TOKDEF(direction),
TOKDEF(directory),
TOKDEF(discrete),
TOKDEF(effective_via_length),
TOKDEF(elongate_keepout),
TOKDEF(exclude),
TOKDEF(expose),
TOKDEF(extra_image_directory),
TOKDEF(family),
TOKDEF(family_family),
TOKDEF(family_family_spacing),
TOKDEF(fanout),
TOKDEF(farad),
TOKDEF(file),
TOKDEF(fit),
TOKDEF(fix),
TOKDEF(flip_style),
TOKDEF(floor_plan),
TOKDEF(footprint),
TOKDEF(forbidden),
TOKDEF(force_to_terminal_point),
TOKDEF(forgotten),
TOKDEF(free),
TOKDEF(fromto),
TOKDEF(front),
TOKDEF(front_only),
TOKDEF(gap),
TOKDEF(gate),
TOKDEF(gates),
TOKDEF(generated_by_freeroute),
TOKDEF(global),
TOKDEF(grid),
TOKDEF(group),
TOKDEF(group_set),
TOKDEF(guide),
TOKDEF(hard),
TOKDEF(height),
TOKDEF(high),
TOKDEF(history),
TOKDEF(horizontal),
TOKDEF(host_cad),
TOKDEF(host_version),
TOKDEF(image),
TOKDEF(image_conductor),
TOKDEF(image_image),
TOKDEF(image_image_spacing),
TOKDEF(image_outline_clearance),
TOKDEF(image_set),
TOKDEF(image_type),
TOKDEF(inch),
TOKDEF(include),
TOKDEF(include_pins_in_crosstalk),
TOKDEF(inductance_resolution),
TOKDEF(insert),
TOKDEF(instcnfg),
TOKDEF(inter_layer_clearance),
TOKDEF(jumper),
TOKDEF(junction_type),
TOKDEF(keepout),
TOKDEF(kg),
TOKDEF(kohm),
TOKDEF(large),
TOKDEF(large_large),
TOKDEF(layer),
TOKDEF(layer_depth),
TOKDEF(layer_noise_weight),
TOKDEF(layer_pair),
TOKDEF(layer_rule),
TOKDEF(length),
TOKDEF(length_amplitude),
TOKDEF(length_factor),
TOKDEF(length_gap),
TOKDEF(library),
TOKDEF(library_out),
TOKDEF(limit),
TOKDEF(limit_bends),
TOKDEF(limit_crossing),
TOKDEF(limit_vias),
TOKDEF(limit_way),
TOKDEF(linear),
TOKDEF(linear_interpolation),
TOKDEF(load),
TOKDEF(lock_type),
TOKDEF(logical_part),
TOKDEF(logical_part_mapping),
TOKDEF(low),
TOKDEF(match_fromto_delay),
TOKDEF(match_fromto_length),
TOKDEF(match_group_delay),
TOKDEF(match_group_length),
TOKDEF(match_net_delay),
TOKDEF(match_net_length),
TOKDEF(max_delay),
TOKDEF(max_len),
TOKDEF(max_length),
TOKDEF(max_noise),
TOKDEF(max_restricted_layer_length),
TOKDEF(max_stagger),
TOKDEF(max_stub),
TOKDEF(max_total_delay),
TOKDEF(max_total_length),
TOKDEF(max_total_vias),
TOKDEF(medium),
TOKDEF(mhenry),
TOKDEF(mho),
TOKDEF(microvia),
TOKDEF(mid_driven),
TOKDEF(mil),
TOKDEF(min_gap),
TOKDEF(mirror),
TOKDEF(mirror_first),
TOKDEF(mixed),
TOKDEF(mm),
TOKDEF(negative_diagonal),
TOKDEF(net),
TOKDEF(net_number),
TOKDEF(net_out),
TOKDEF(net_pin_changes),
TOKDEF(nets),
TOKDEF(network),
TOKDEF(network_out),
TOKDEF(no),
TOKDEF(noexpose),
TOKDEF(noise_accumulation),
TOKDEF(noise_calculation),
TOKDEF(normal),
TOKDEF(object_type),
TOKDEF(off),
TOKDEF(off_grid),
TOKDEF(offset),
TOKDEF(on),
TOKDEF(open),
TOKDEF(opposite_side),
TOKDEF(order),
TOKDEF(orthogonal),
TOKDEF(outline),
TOKDEF(overlap),
TOKDEF(pad),
TOKDEF(pad_pad),
TOKDEF(padstack),
TOKDEF(pair),
TOKDEF(parallel),
TOKDEF(parallel_noise),
TOKDEF(parallel_segment),
TOKDEF(parser),
TOKDEF(part_library),
TOKDEF(path),
TOKDEF(pcb),
TOKDEF(permit_orient),
TOKDEF(permit_side),
TOKDEF(physical),
TOKDEF(physical_part_mapping),
TOKDEF(piggyback),
TOKDEF(pin),
TOKDEF(pin_allow),
TOKDEF(pin_cap_via),
TOKDEF(pin_via_cap),
TOKDEF(pin_width_taper),
TOKDEF(pins),
TOKDEF(pintype),
TOKDEF(place),
TOKDEF(place_boundary),
TOKDEF(place_control),
TOKDEF(place_keepout),
TOKDEF(place_rule),
TOKDEF(placement),
TOKDEF(plan),
TOKDEF(plane),
TOKDEF(pn),
TOKDEF(point),
TOKDEF(polyline_path), // used by freerouting.com
TOKDEF(polygon),
TOKDEF(position),
TOKDEF(positive_diagonal),
TOKDEF(power),
TOKDEF(power_dissipation),
TOKDEF(power_fanout),
TOKDEF(prefix),
TOKDEF(primary),
TOKDEF(priority),
TOKDEF(property),
TOKDEF(protect),
TOKDEF(qarc),
TOKDEF(quarter),
TOKDEF(radius),
TOKDEF(ratio),
TOKDEF(ratio_tolerance),
TOKDEF(rect),
TOKDEF(reduced),
TOKDEF(region),
TOKDEF(region_class),
TOKDEF(region_class_class),
TOKDEF(region_net),
TOKDEF(relative_delay),
TOKDEF(relative_group_delay),
TOKDEF(relative_group_length),
TOKDEF(relative_length),
TOKDEF(reorder),
TOKDEF(reroute_order_viols),
TOKDEF(resistance_resolution),
TOKDEF(resistor),
TOKDEF(resolution),
TOKDEF(restricted_layer_length_factor),
TOKDEF(room),
TOKDEF(rotate),
TOKDEF(rotate_first),
TOKDEF(round),
TOKDEF(roundoff_rotation),
TOKDEF(route),
TOKDEF(route_to_fanout_only),
TOKDEF(routes),
TOKDEF(routes_include),
TOKDEF(rule),
TOKDEF(same_net_checking),
TOKDEF(sample_window),
TOKDEF(saturation_length),
TOKDEF(sec),
TOKDEF(secondary),
TOKDEF(self),
TOKDEF(sequence_number),
TOKDEF(session),
TOKDEF(set_color),
TOKDEF(set_pattern),
TOKDEF(shape),
TOKDEF(shield),
TOKDEF(shield_gap),
TOKDEF(shield_loop),
TOKDEF(shield_tie_down_interval),
TOKDEF(shield_width),
TOKDEF(side),
TOKDEF(signal),
TOKDEF(site),
TOKDEF(small),
TOKDEF(smd),
TOKDEF(snap),
TOKDEF(snap_angle),
TOKDEF(soft),
TOKDEF(source),
TOKDEF(space_in_quoted_tokens),
TOKDEF(spacing),
TOKDEF(spare),
TOKDEF(spiral_via),
TOKDEF(square),
TOKDEF(stack_via),
TOKDEF(stack_via_depth),
TOKDEF(standard),
TOKDEF(starburst),
TOKDEF(status),
TOKDEF(structure),
TOKDEF(structure_out),
TOKDEF(subgate),
TOKDEF(subgates),
TOKDEF(substituted),
TOKDEF(such),
TOKDEF(suffix),
TOKDEF(super_placement),
TOKDEF(supply),
TOKDEF(supply_pin),
TOKDEF(swapping),
TOKDEF(switch_window),
TOKDEF(system),
TOKDEF(tandem_noise),
TOKDEF(tandem_segment),
TOKDEF(tandem_shield_overhang),
TOKDEF(terminal),
TOKDEF(terminator),
TOKDEF(term_only),
TOKDEF(test),
TOKDEF(test_points),
TOKDEF(testpoint),
TOKDEF(threshold),
TOKDEF(time_length_factor),
TOKDEF(time_resolution),
TOKDEF(tjunction),
TOKDEF(tolerance),
TOKDEF(top),
TOKDEF(topology),
TOKDEF(total),
TOKDEF(track_id),
TOKDEF(turret),
TOKDEF(type),
TOKDEF(um),
TOKDEF(unassigned),
TOKDEF(unconnects),
TOKDEF(unit),
TOKDEF(up),
TOKDEF(use_array),
TOKDEF(use_layer),
TOKDEF(use_net),
TOKDEF(use_via),
TOKDEF(value),
TOKDEF(vertical),
TOKDEF(via),
TOKDEF(via_array_template),
TOKDEF(via_at_smd),
TOKDEF(via_keepout),
TOKDEF(via_number),
TOKDEF(via_rotate_first),
TOKDEF(via_site),
TOKDEF(via_size),
TOKDEF(virtual_pin),
TOKDEF(volt),
TOKDEF(voltage_resolution),
TOKDEF(was_is),
TOKDEF(way),
TOKDEF(weight),
TOKDEF(width),
TOKDEF(window),
TOKDEF(wire),
TOKDEF(wire_keepout),
TOKDEF(wires),
TOKDEF(wires_include),
TOKDEF(wiring),
TOKDEF(write_resolution),
TOKDEF(x),
TOKDEF(xy),
TOKDEF(y),
};
const unsigned SPECCTRA_DB::keywordCount = DIM(SPECCTRA_DB::keywords);
//-----<SPECCTRA_DB>------------------------------------------------- //-----<SPECCTRA_DB>-------------------------------------------------
#if !defined(STANDALONE) const char* SPECCTRA_DB::TokenName( int aTok )
{
const char* ret;
if( (unsigned) aTok < keywordCount )
{
ret = keywords[aTok].name;
}
else if( aTok < 0 )
{
return DSNLEXER::Syntax( aTok );
}
else
ret = "token too big";
return ret;
}
const char* GetTokenText( int aTok )
{
return SPECCTRA_DB::TokenName( aTok );
}
wxString SPECCTRA_DB::GetTokenString( int aTok )
{
wxString ret;
ret << wxT("'") << CONV_FROM_UTF8( GetTokenText(aTok) ) << wxT("'");
return ret;
}
#if !defined(SPECCTRA_TEST)
void SPECCTRA_DB::buildLayerMaps( BOARD* aBoard ) void SPECCTRA_DB::buildLayerMaps( BOARD* aBoard )
{ {
...@@ -131,7 +566,7 @@ void SPECCTRA_DB::ThrowIOError( const wxChar* fmt, ... ) throw( IOError ) ...@@ -131,7 +566,7 @@ void SPECCTRA_DB::ThrowIOError( const wxChar* fmt, ... ) throw( IOError )
void SPECCTRA_DB::expecting( DSN_T aTok ) throw( IOError ) void SPECCTRA_DB::expecting( DSN_T aTok ) throw( IOError )
{ {
wxString errText( _("Expecting") ); wxString errText( _("Expecting") );
errText << wxT(" ") << LEXER::GetTokenString( aTok ); errText << wxT(" ") << GetTokenString( aTok );
lexer->ThrowIOError( errText, lexer->CurOffset() ); lexer->ThrowIOError( errText, lexer->CurOffset() );
} }
...@@ -145,7 +580,7 @@ void SPECCTRA_DB::expecting( const char* text ) throw( IOError ) ...@@ -145,7 +580,7 @@ void SPECCTRA_DB::expecting( const char* text ) throw( IOError )
void SPECCTRA_DB::unexpected( DSN_T aTok ) throw( IOError ) void SPECCTRA_DB::unexpected( DSN_T aTok ) throw( IOError )
{ {
wxString errText( _("Unexpected") ); wxString errText( _("Unexpected") );
errText << wxT(" ") << LEXER::GetTokenString( aTok ); errText << wxT(" ") << GetTokenString( aTok );
lexer->ThrowIOError( errText, lexer->CurOffset() ); lexer->ThrowIOError( errText, lexer->CurOffset() );
} }
...@@ -159,7 +594,7 @@ void SPECCTRA_DB::unexpected( const char* text ) throw( IOError ) ...@@ -159,7 +594,7 @@ void SPECCTRA_DB::unexpected( const char* text ) throw( IOError )
DSN_T SPECCTRA_DB::nextTok() DSN_T SPECCTRA_DB::nextTok()
{ {
DSN_T ret = lexer->NextTok(); DSN_T ret = (DSN_T) lexer->NextTok();
return ret; return ret;
} }
...@@ -210,7 +645,7 @@ void SPECCTRA_DB::readCOMPnPIN( std::string* component_id, std::string* pin_id ) ...@@ -210,7 +645,7 @@ void SPECCTRA_DB::readCOMPnPIN( std::string* component_id, std::string* pin_id )
static const char pin_def[] = "<pin_reference>::=<component_id>-<pin_id>"; static const char pin_def[] = "<pin_reference>::=<component_id>-<pin_id>";
if( !isSymbol( lexer->CurTok() ) ) if( !isSymbol( (DSN_T) lexer->CurTok() ) )
expecting( pin_def ); expecting( pin_def );
// case for: A12-14, i.e. no wrapping quotes. This should be a single // case for: A12-14, i.e. no wrapping quotes. This should be a single
...@@ -329,7 +764,7 @@ void SPECCTRA_DB::LoadPCB( const wxString& filename ) throw( IOError ) ...@@ -329,7 +764,7 @@ void SPECCTRA_DB::LoadPCB( const wxString& filename ) throw( IOError )
delete lexer; delete lexer;
lexer = 0; lexer = 0;
lexer = new LEXER( file.fp(), filename ); lexer = new DSNLEXER( file.fp(), filename, SPECCTRA_DB::keywords, SPECCTRA_DB::keywordCount );
if( nextTok() != T_LEFT ) if( nextTok() != T_LEFT )
expecting( T_LEFT ); expecting( T_LEFT );
...@@ -359,7 +794,7 @@ void SPECCTRA_DB::LoadSESSION( const wxString& filename ) throw( IOError ) ...@@ -359,7 +794,7 @@ void SPECCTRA_DB::LoadSESSION( const wxString& filename ) throw( IOError )
delete lexer; delete lexer;
lexer = 0; lexer = 0;
lexer = new LEXER( file.fp(), filename ); lexer = new DSNLEXER( file.fp(), filename, SPECCTRA_DB::keywords, SPECCTRA_DB::keywordCount );
if( nextTok() != T_LEFT ) if( nextTok() != T_LEFT )
expecting( T_LEFT ); expecting( T_LEFT );
...@@ -508,7 +943,7 @@ void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError ) ...@@ -508,7 +943,7 @@ void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError )
tok = nextTok(); tok = nextTok();
switch( tok ) switch( tok )
{ {
case T_string_quote: case T_STRING_QUOTE:
tok = nextTok(); tok = nextTok();
if( tok != T_QUOTE_DEF ) if( tok != T_QUOTE_DEF )
expecting( T_QUOTE_DEF ); expecting( T_QUOTE_DEF );
...@@ -2613,9 +3048,6 @@ void SPECCTRA_DB::doCLASS( CLASS* growth ) throw( IOError ) ...@@ -2613,9 +3048,6 @@ void SPECCTRA_DB::doCLASS( CLASS* growth ) throw( IOError )
int bracketNesting = 1; // we already saw the opening T_LEFT int bracketNesting = 1; // we already saw the opening T_LEFT
DSN_T tok = T_NONE; DSN_T tok = T_NONE;
builder += '(';
builder += lexer->CurText();
while( bracketNesting!=0 && tok!=T_EOF ) while( bracketNesting!=0 && tok!=T_EOF )
{ {
tok = nextTok(); tok = nextTok();
...@@ -2628,7 +3060,9 @@ void SPECCTRA_DB::doCLASS( CLASS* growth ) throw( IOError ) ...@@ -2628,7 +3060,9 @@ void SPECCTRA_DB::doCLASS( CLASS* growth ) throw( IOError )
if( bracketNesting >= 1 ) if( bracketNesting >= 1 )
{ {
if( lexer->PrevTok() != T_LEFT && tok!=T_RIGHT ) DSN_T prevTok = (DSN_T) lexer->PrevTok();
if( prevTok!=T_LEFT && prevTok!=T_circuit && tok!=T_RIGHT )
builder += ' '; builder += ' ';
if( tok==T_STRING ) if( tok==T_STRING )
...@@ -2644,7 +3078,6 @@ void SPECCTRA_DB::doCLASS( CLASS* growth ) throw( IOError ) ...@@ -2644,7 +3078,6 @@ void SPECCTRA_DB::doCLASS( CLASS* growth ) throw( IOError )
// to bracketNesting == 0, then save the builder and break; // to bracketNesting == 0, then save the builder and break;
if( bracketNesting == 0 ) if( bracketNesting == 0 )
{ {
builder += ')';
growth->circuit.push_back( builder ); growth->circuit.push_back( builder );
break; break;
} }
...@@ -3518,41 +3951,6 @@ int SPECCTRA_DB::Print( int nestLevel, const char* fmt, ... ) throw( IOError ) ...@@ -3518,41 +3951,6 @@ int SPECCTRA_DB::Print( int nestLevel, const char* fmt, ... ) throw( IOError )
return total; return total;
} }
// factor out a common GetQuoteChar
const char* OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, const char* quote_char )
{
// Include '#' so a symbol is not confused with a comment. We intend
// to wrap any symbol starting with a '#'.
// Our LEXER class handles comments, and comments appear to be an extension
// to the SPECCTRA DSN specification.
if( *wrapee == '#' )
return quote_char;
if( strlen(wrapee)==0 )
return quote_char;
bool isFirst = true;
for( ; *wrapee; ++wrapee, isFirst=false )
{
static const char quoteThese[] = "\t ()"
"%" // per Alfons of freerouting.net, he does not like this unquoted as of 1-Feb-2008
"{}" // guessing that these are problems too
;
// if the string to be wrapped (wrapee) has a delimiter in it,
// return the quote_char so caller wraps the wrapee.
if( strchr( quoteThese, *wrapee ) )
return quote_char;
if( !isFirst && '-' == *wrapee )
return quote_char;
}
return ""; // caller does not need to wrap, can use an unwrapped string.
}
const char* SPECCTRA_DB::GetQuoteChar( const char* wrapee ) const char* SPECCTRA_DB::GetQuoteChar( const char* wrapee )
{ {
...@@ -3627,91 +4025,6 @@ PCB* SPECCTRA_DB::MakePCB() ...@@ -3627,91 +4025,6 @@ PCB* SPECCTRA_DB::MakePCB()
} }
//-----<STRINGFORMATTER>----------------------------------------------------
const char* STRINGFORMATTER::GetQuoteChar( const char* wrapee )
{
// for what we are using STRINGFORMATTER for at this time, we can return the nul string
// always.
return "";
// return OUTPUTFORMATTER::GetQuoteChar( const char* wrapee, "\"" );
}
int STRINGFORMATTER::vprint( const char* fmt, va_list ap )
{
int ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
if( ret >= (int) buffer.size() )
{
buffer.reserve( ret+200 );
ret = vsnprintf( &buffer[0], buffer.size(), fmt, ap );
}
if( ret > 0 )
mystring.append( (const char*) &buffer[0] );
return ret;
}
int STRINGFORMATTER::sprint( const char* fmt, ... )
{
va_list args;
va_start( args, fmt );
int ret = vprint( fmt, args);
va_end( args );
return ret;
}
int STRINGFORMATTER::Print( int nestLevel, const char* fmt, ... ) throw( IOError )
{
va_list args;
va_start( args, fmt );
int result = 0;
int total = 0;
for( int i=0; i<nestLevel; ++i )
{
result = sprint( "%*c", NESTWIDTH, ' ' );
if( result < 0 )
break;
total += result;
}
if( result<0 || (result=vprint( fmt, args ))<0 )
{
throw IOError( _("Error writing to STRINGFORMATTER") );
}
va_end( args );
total += result;
return total;
}
void STRINGFORMATTER::StripUseless()
{
std::string copy = mystring;
mystring.clear();
for( std::string::iterator i=copy.begin(); i!=copy.end(); ++i )
{
if( !isspace( *i ) && *i!=')' && *i!='(' && *i!='"' )
{
mystring += *i;
}
}
}
//-----<ELEM>--------------------------------------------------------------- //-----<ELEM>---------------------------------------------------------------
ELEM::ELEM( DSN_T aType, ELEM* aParent ) : ELEM::ELEM( DSN_T aType, ELEM* aParent ) :
...@@ -3725,6 +4038,10 @@ ELEM::~ELEM() ...@@ -3725,6 +4038,10 @@ ELEM::~ELEM()
{ {
} }
const char* ELEM::Name() const
{
return SPECCTRA_DB::TokenName( type );
}
UNIT_RES* ELEM::GetUnits() const UNIT_RES* ELEM::GetUnits() const
{ {
...@@ -3737,7 +4054,7 @@ UNIT_RES* ELEM::GetUnits() const ...@@ -3737,7 +4054,7 @@ UNIT_RES* ELEM::GetUnits() const
void ELEM::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void ELEM::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) ); out->Print( nestLevel, "(%s\n", Name() );
FormatContents( out, nestLevel+1 ); FormatContents( out, nestLevel+1 );
...@@ -3903,7 +4220,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) ...@@ -3903,7 +4220,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
useMultiLine = true; useMultiLine = true;
out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ), out->Print( nestLevel, "(%s %s%s%s\n", Name(),
quote, component_id.c_str(), quote ); quote, component_id.c_str(), quote );
out->Print( nestLevel+1, "%s", "" ); out->Print( nestLevel+1, "%s", "" );
...@@ -3912,7 +4229,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) ...@@ -3912,7 +4229,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
useMultiLine = false; useMultiLine = false;
out->Print( nestLevel, "(%s %s%s%s", LEXER::GetTokenText( Type() ), out->Print( nestLevel, "(%s %s%s%s", Name(),
quote, component_id.c_str(), quote ); quote, component_id.c_str(), quote );
} }
...@@ -3920,7 +4237,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) ...@@ -3920,7 +4237,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
out->Print( 0, " %.6g %.6g", vertex.x, vertex.y ); out->Print( 0, " %.6g %.6g", vertex.x, vertex.y );
out->Print( 0, " %s", LEXER::GetTokenText( side ) ); out->Print( 0, " %s", GetTokenText( side ) );
out->Print( 0, " %.6g", rotation ); out->Print( 0, " %.6g", rotation );
} }
...@@ -3929,13 +4246,13 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) ...@@ -3929,13 +4246,13 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
if( mirror != T_NONE ) if( mirror != T_NONE )
{ {
out->Print( 0, "%s(mirror %s)", space, LEXER::GetTokenText( mirror ) ); out->Print( 0, "%s(mirror %s)", space, GetTokenText( mirror ) );
space = ""; space = "";
} }
if( status != T_NONE ) if( status != T_NONE )
{ {
out->Print( 0, "%s(status %s)", space, LEXER::GetTokenText( status ) ); out->Print( 0, "%s(status %s)", space, GetTokenText( status ) );
space = ""; space = "";
} }
...@@ -3967,8 +4284,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) ...@@ -3967,8 +4284,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
out->Print( nestLevel+1, ")\n" ); out->Print( nestLevel+1, ")\n" );
} }
if( lock_type != T_NONE ) if( lock_type != T_NONE )
out->Print( nestLevel+1, "(lock_type %s)\n", out->Print( nestLevel+1, "(lock_type %s)\n", GetTokenText(lock_type) );
LEXER::GetTokenText(lock_type) );
if( rules ) if( rules )
rules->Format( out, nestLevel+1 ); rules->Format( out, nestLevel+1 );
...@@ -3986,8 +4302,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) ...@@ -3986,8 +4302,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
if( lock_type != T_NONE ) if( lock_type != T_NONE )
{ {
out->Print( 0, "%s(lock_type %s)", space, out->Print( 0, "%s(lock_type %s)", space, GetTokenText(lock_type) );
LEXER::GetTokenText(lock_type) );
space = ""; space = "";
} }
...@@ -4002,16 +4317,17 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) ...@@ -4002,16 +4317,17 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
out->Print( 0, ")\n" ); out->Print( 0, ")\n" );
} }
} // namespace DSN } // namespace DSN
// unit test this source file // unit test this source file. You can use the beautifiers below to output
// exactly what you read in but beautified and without #comments. This can
#if defined(STANDALONE) // then be used along with program 'diff' to test the parsing and formatting
// of every element. You may have to run the first output back through to
// get two files that should match, the 2nd and 3rd outputs.
#include "common.h" // IsOK() & EDA_FileSelector() #if defined(SPECCTRA_TEST)
using namespace DSN; using namespace DSN;
...@@ -4035,8 +4351,8 @@ int main( int argc, char** argv ) ...@@ -4035,8 +4351,8 @@ int main( int argc, char** argv )
try try
{ {
db.LoadPCB( filename ); // db.LoadPCB( filename );
// db.LoadSESSION( filename ); db.LoadSESSION( filename );
} }
catch( IOError ioe ) catch( IOError ioe )
{ {
...@@ -4048,18 +4364,25 @@ int main( int argc, char** argv ) ...@@ -4048,18 +4364,25 @@ int main( int argc, char** argv )
fprintf( stderr, "loaded OK\n" ); fprintf( stderr, "loaded OK\n" );
// export what we read in, making this test program basically a beautifier // export what we read in, making this test program basically a beautifier
// db.ExportSESSION( wxT("/tmp/export.ses") ); // hose the beautified DSN file to stdout. If an exception occurred,
// db.ExportPCB( wxT("/tmp/export.dsn") ); // we will be outputting only a portion of what we wanted to read in.
db.SetFILE( stdout );
#if 0
// export a PCB
DSN::PCB* pcb = db.GetPCB(); DSN::PCB* pcb = db.GetPCB();
// hose the beautified DSN file to stdout.
db.SetFILE( stdout );
pcb->Format( &db, 0 ); pcb->Format( &db, 0 );
#else
// export a SESSION file.
DSN::SESSION* ses = db.GetSESSION();
ses->Format( &db, 0 );
#endif
SetLocaleTo_Default( ); // revert to the current locale SetLocaleTo_Default( ); // revert to the current locale
} }
#endif #endif
......
...@@ -33,7 +33,9 @@ ...@@ -33,7 +33,9 @@
#include <boost/ptr_container/ptr_set.hpp> #include <boost/ptr_container/ptr_set.hpp>
#include "fctsys.h" #include "fctsys.h"
#include "dsn.h"
#include "dsnlexer.h"
class TYPE_COLLECTOR; // outside the DSN namespace class TYPE_COLLECTOR; // outside the DSN namespace
...@@ -63,131 +65,429 @@ class TYPE_COLLECTOR; // outside the DSN namespace ...@@ -63,131 +65,429 @@ class TYPE_COLLECTOR; // outside the DSN namespace
*/ */
namespace DSN { namespace DSN {
class SPECCTRA_DB;
/**
* 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
{
#if defined(__GNUG__) // The GNU C++ compiler defines this
// 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)))
#else
#define PRINTF_FUNC // nothing
#endif
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;
/** enum DSN_T {
* Function GetQuoteChar
* performs quote character need determination. // these first few are negative special ones for syntax, and are
* It returns the quote character as a single character string for a given // inherited from DSNLEXER.
* input wrapee string. If the wrappee does not need to be quoted, T_NONE = DSN_NONE,
* the return value is "" (the null string), such as when there are no T_STRING_QUOTE = DSN_STRING_QUOTE,
* delimiters in the input wrapee string. If you want the quote_char T_QUOTE_DEF = DSN_QUOTE_DEF,
* to be assuredly not "", then pass in "(" as the wrappee. T_DASH = DSN_DASH,
* @param wrapee A string that might need wrapping on each end. T_SYMBOL = DSN_SYMBOL,
* @return const char* - the quote_char as a single character string, or "" T_NUMBER = DSN_NUMBER,
* if the wrapee does not need to be wrapped. T_RIGHT = DSN_RIGHT, // right bracket, ')'
*/ T_LEFT = DSN_LEFT, // left bracket, '('
virtual const char* GetQuoteChar( const char* wrapee ) = 0; T_STRING = DSN_STRING, // a quoted string, stripped of the quotes
T_EOF = DSN_EOF, // special case for end of file
virtual ~OUTPUTFORMATTER() {}
/** // This should be coordinated with the
* Function GetQuoteChar // const static KEYWORD tokens[] array, and both must be sorted
* performs quote character need determination. // identically and alphabetically. Remember that '_' is less than any
* @param wrapee A string that might need wrapping on each end. // alpha character according to ASCII.
* @param quote_char A single character C string which provides the current
* quote character, should it be needed by the wrapee. T_absolute = 0, // this one should be == zero
* @return const char* - the quote_char as a single character string, or "" T_added,
* if the wrapee does not need to be wrapped. T_add_group,
*/ T_add_pins,
static const char* GetQuoteChar( const char* wrapee, const char* quote_char ); T_allow_antenna,
T_allow_redundant_wiring,
T_amp,
T_ancestor,
T_antipad,
T_aperture_type,
T_array,
T_attach,
T_attr,
T_average_pair_length,
T_back,
T_base_design,
T_bbv_ctr2ctr,
T_bend_keepout,
T_bond,
T_both,
T_bottom,
T_bottom_layer_sel,
T_boundary,
T_brickpat,
T_bundle,
T_bus,
T_bypass,
T_capacitance_resolution,
T_capacitor,
T_case_sensitive,
T_cct1,
T_cct1a,
T_center_center,
T_checking_trim_by_pin,
T_circ,
T_circle,
T_circuit,
T_class,
T_class_class,
T_classes,
T_clear,
T_clearance,
T_cluster,
T_cm,
T_color,
T_colors,
T_comment,
T_comp,
T_comp_edge_center,
T_comp_order,
T_component,
T_composite,
T_conductance_resolution,
T_conductor,
T_conflict,
T_connect,
T_constant,
T_contact,
T_control,
T_corner,
T_corners,
T_cost,
T_created_time,
T_cross,
T_crosstalk_model,
T_current_resolution,
T_delete_pins,
T_deleted,
T_deleted_keepout,
T_delta,
T_diagonal,
T_direction,
T_directory,
T_discrete,
T_effective_via_length,
T_elongate_keepout,
T_exclude,
T_expose,
T_extra_image_directory,
T_family,
T_family_family,
T_family_family_spacing,
T_fanout,
T_farad,
T_file,
T_fit,
T_fix,
T_flip_style,
T_floor_plan,
T_footprint,
T_forbidden,
T_force_to_terminal_point,
T_free,
T_forgotten,
T_fromto,
T_front,
T_front_only,
T_gap,
T_gate,
T_gates,
T_generated_by_freeroute,
T_global,
T_grid,
T_group,
T_group_set,
T_guide,
T_hard,
T_height,
T_high,
T_history,
T_horizontal,
T_host_cad,
T_host_version,
T_image,
T_image_conductor,
T_image_image,
T_image_image_spacing,
T_image_outline_clearance,
T_image_set,
T_image_type,
T_inch,
T_include,
T_include_pins_in_crosstalk,
T_inductance_resolution,
T_insert,
T_instcnfg,
T_inter_layer_clearance,
T_jumper,
T_junction_type,
T_keepout,
T_kg,
T_kohm,
T_large,
T_large_large,
T_layer,
T_layer_depth,
T_layer_noise_weight,
T_layer_pair,
T_layer_rule,
T_length,
T_length_amplitude,
T_length_factor,
T_length_gap,
T_library,
T_library_out,
T_limit,
T_limit_bends,
T_limit_crossing,
T_limit_vias,
T_limit_way,
T_linear,
T_linear_interpolation,
T_load,
T_lock_type,
T_logical_part,
T_logical_part_mapping,
T_low,
T_match_fromto_delay,
T_match_fromto_length,
T_match_group_delay,
T_match_group_length,
T_match_net_delay,
T_match_net_length,
T_max_delay,
T_max_len,
T_max_length,
T_max_noise,
T_max_restricted_layer_length,
T_max_stagger,
T_max_stub,
T_max_total_delay,
T_max_total_length,
T_max_total_vias,
T_medium,
T_mhenry,
T_mho,
T_microvia,
T_mid_driven,
T_mil,
T_min_gap,
T_mirror,
T_mirror_first,
T_mixed,
T_mm,
T_negative_diagonal,
T_net,
T_net_number,
T_net_out,
T_net_pin_changes,
T_nets,
T_network,
T_network_out,
T_no,
T_noexpose,
T_noise_accumulation,
T_noise_calculation,
T_normal,
T_object_type,
T_off,
T_off_grid,
T_offset,
T_on,
T_open,
T_opposite_side,
T_order,
T_orthogonal,
T_outline,
T_overlap,
T_pad,
T_pad_pad,
T_padstack,
T_pair,
T_parallel,
T_parallel_noise,
T_parallel_segment,
T_parser,
T_part_library,
T_path,
T_pcb,
T_permit_orient,
T_permit_side,
T_physical,
T_physical_part_mapping,
T_piggyback,
T_pin,
T_pin_allow,
T_pin_cap_via,
T_pin_via_cap,
T_pin_width_taper,
T_pins,
T_pintype,
T_place,
T_place_boundary,
T_place_control,
T_place_keepout,
T_place_rule,
T_placement,
T_plan,
T_plane,
T_pn,
T_point,
T_polyline_path,
T_polygon,
T_position,
T_positive_diagonal,
T_power,
T_power_dissipation,
T_power_fanout,
T_prefix,
T_primary,
T_priority,
T_property,
T_protect,
T_qarc,
T_quarter,
T_radius,
T_ratio,
T_ratio_tolerance,
T_rect,
T_reduced,
T_region,
T_region_class,
T_region_class_class,
T_region_net,
T_relative_delay,
T_relative_group_delay,
T_relative_group_length,
T_relative_length,
T_reorder,
T_reroute_order_viols,
T_resistance_resolution,
T_resistor,
T_resolution,
T_restricted_layer_length_factor,
T_room,
T_rotate,
T_rotate_first,
T_round,
T_roundoff_rotation,
T_route,
T_route_to_fanout_only,
T_routes,
T_routes_include,
T_rule,
T_same_net_checking,
T_sample_window,
T_saturation_length,
T_sec,
T_secondary,
T_self,
T_sequence_number,
T_session,
T_set_color,
T_set_pattern,
T_shape,
T_shield,
T_shield_gap,
T_shield_loop,
T_shield_tie_down_interval,
T_shield_width,
T_side,
T_signal,
T_site,
T_small,
T_smd,
T_snap,
T_snap_angle,
T_soft,
T_source,
T_space_in_quoted_tokens,
T_spacing,
T_spare,
T_spiral_via,
T_square,
T_stack_via,
T_stack_via_depth,
T_standard,
T_starburst,
T_status,
T_structure,
T_structure_out,
T_subgate,
T_subgates,
T_substituted,
T_such,
T_suffix,
T_super_placement,
T_supply,
T_supply_pin,
T_swapping,
T_switch_window,
T_system,
T_tandem_noise,
T_tandem_segment,
T_tandem_shield_overhang,
T_terminal,
T_terminator,
T_term_only,
T_test,
T_test_points,
T_testpoint,
T_threshold,
T_time_length_factor,
T_time_resolution,
T_tjunction,
T_tolerance,
T_top,
T_topology,
T_total,
T_track_id,
T_turret,
T_type,
T_um,
T_unassigned,
T_unconnects,
T_unit,
T_up,
T_use_array,
T_use_layer,
T_use_net,
T_use_via,
T_value,
T_vertical,
T_via,
T_via_array_template,
T_via_at_smd,
T_via_keepout,
T_via_number,
T_via_rotate_first,
T_via_site,
T_via_size,
T_virtual_pin,
T_volt,
T_voltage_resolution,
T_was_is,
T_way,
T_weight,
T_width,
T_window,
T_wire,
T_wire_keepout,
T_wires,
T_wires_include,
T_wiring,
T_write_resolution,
T_x,
T_xy,
T_y,
}; };
/** class SPECCTRA_DB;
* Class STRINGFORMATTER
* implements OUTPUTFORMATTER to a memory buffer. After Print()ing the
* string is available through GetString()
*/
class STRINGFORMATTER : public OUTPUTFORMATTER
{
std::vector<char> buffer;
std::string mystring;
int sprint( const char* fmt, ... );
int vprint( const char* fmt, va_list ap );
public:
/**
* Constructor STRINGFORMATTER
* reserves space in the buffer
*/
STRINGFORMATTER( int aReserve = 300 ) :
buffer( aReserve, '\0' )
{
}
/**
* Function Clear
* clears the buffer and empties the internal string.
*/
void Clear()
{
mystring.clear();
}
/**
* Function StripUseless
* removes whitespace, '(', and ')' from the mystring.
*/
void StripUseless();
/* /**
const char* c_str() * Function GetTokenText
{ * is in the DSN namespace and returns the C string representing a
return mystring.c_str(); * SPECCTRA_DB::keyword. We needed a non-instanance function to get at
} * the SPECCTRA_DB::keyword[] and class SPECCTRA_DB is not defined yet.
*/ */
const char* GetTokenText( int aTok );
std::string GetString()
{
return mystring;
}
//-----<OUTPUTFORMATTER>------------------------------------------------
int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError );
const char* GetQuoteChar( const char* wrapee );
//-----</OUTPUTFORMATTER>-----------------------------------------------
};
/** /**
...@@ -334,6 +634,8 @@ public: ...@@ -334,6 +634,8 @@ public:
DSN_T Type() const { return type; } DSN_T Type() const { return type; }
const char* Name() const;
/** /**
* Function GetUnits * Function GetUnits
...@@ -529,12 +831,12 @@ public: ...@@ -529,12 +831,12 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
if( type == T_unit ) if( type == T_unit )
out->Print( nestLevel, "(%s %s)\n", LEXER::GetTokenText( Type() ), out->Print( nestLevel, "(%s %s)\n", Name(),
LEXER::GetTokenText(units) ); GetTokenText(units) );
else // T_resolution else // T_resolution
out->Print( nestLevel, "(%s %s %d)\n", LEXER::GetTokenText( Type() ), out->Print( nestLevel, "(%s %s %d)\n", Name(),
LEXER::GetTokenText(units), value ); GetTokenText(units), value );
} }
}; };
...@@ -576,7 +878,7 @@ public: ...@@ -576,7 +878,7 @@ public:
const char* quote = out->GetQuoteChar( layer_id.c_str() ); const char* quote = out->GetQuoteChar( layer_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s %.6g %.6g %.6g %.6g)%s", out->Print( nestLevel, "(%s %s%s%s %.6g %.6g %.6g %.6g)%s",
LEXER::GetTokenText( Type() ), Name(),
quote, layer_id.c_str(), quote, quote, layer_id.c_str(), quote,
point0.x, point0.y, point0.x, point0.y,
point1.x, point1.y, point1.x, point1.y,
...@@ -604,7 +906,7 @@ public: ...@@ -604,7 +906,7 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
out->Print( nestLevel, "(%s", LEXER::GetTokenText( Type() ) ); out->Print( nestLevel, "(%s", Name() );
bool singleLine; bool singleLine;
...@@ -650,7 +952,7 @@ public: ...@@ -650,7 +952,7 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
out->Print( nestLevel, "(%s", LEXER::GetTokenText( Type() ) ); out->Print( nestLevel, "(%s", Name() );
for( STRINGS::const_iterator i=layer_ids.begin(); i!=layer_ids.end(); ++i ) for( STRINGS::const_iterator i=layer_ids.begin(); i!=layer_ids.end(); ++i )
{ {
...@@ -715,7 +1017,7 @@ public: ...@@ -715,7 +1017,7 @@ public:
const int RIGHTMARGIN = 70; const int RIGHTMARGIN = 70;
int perLine = out->Print( nestLevel, "(%s %s%s%s %.6g", int perLine = out->Print( nestLevel, "(%s %s%s%s %.6g",
LEXER::GetTokenText( Type() ), Name(),
quote, layer_id.c_str(), quote, quote, layer_id.c_str(), quote,
aperture_width ); aperture_width );
...@@ -768,7 +1070,7 @@ public: ...@@ -768,7 +1070,7 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) ); out->Print( nestLevel, "(%s\n", Name() );
if( rectangle ) if( rectangle )
rectangle->Format( out, nestLevel+1 ); rectangle->Format( out, nestLevel+1 );
...@@ -804,7 +1106,7 @@ public: ...@@ -804,7 +1106,7 @@ public:
const char* newline = nestLevel ? "\n" : ""; const char* newline = nestLevel ? "\n" : "";
const char* quote = out->GetQuoteChar( layer_id.c_str() ); const char* quote = out->GetQuoteChar( layer_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s %.6g", LEXER::GetTokenText( Type() ), out->Print( nestLevel, "(%s %s%s%s %.6g", Name(),
quote, layer_id.c_str(), quote, quote, layer_id.c_str(), quote,
diameter ); diameter );
...@@ -851,7 +1153,7 @@ public: ...@@ -851,7 +1153,7 @@ public:
const char* newline = nestLevel ? "\n" : ""; const char* newline = nestLevel ? "\n" : "";
const char* quote = out->GetQuoteChar( layer_id.c_str() ); const char* quote = out->GetQuoteChar( layer_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s %.6g", LEXER::GetTokenText( Type() ) , out->Print( nestLevel, "(%s %s%s%s %.6g", Name() ,
quote, layer_id.c_str(), quote, quote, layer_id.c_str(), quote,
aperture_width); aperture_width);
...@@ -930,7 +1232,7 @@ public: ...@@ -930,7 +1232,7 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
out->Print( nestLevel, "(%s ", LEXER::GetTokenText( Type() ) ); out->Print( nestLevel, "(%s ", Name() );
if( shape ) if( shape )
shape->Format( out, 0 ); shape->Format( out, 0 );
...@@ -1015,7 +1317,7 @@ public: ...@@ -1015,7 +1317,7 @@ public:
{ {
const char* newline = "\n"; const char* newline = "\n";
out->Print( nestLevel, "(%s", LEXER::GetTokenText( Type() ) ); out->Print( nestLevel, "(%s", Name() );
if( name.size() ) if( name.size() )
{ {
...@@ -1091,7 +1393,7 @@ public: ...@@ -1091,7 +1393,7 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
const int RIGHTMARGIN = 80; const int RIGHTMARGIN = 80;
int perLine = out->Print( nestLevel, "(%s", LEXER::GetTokenText( Type() ) ); int perLine = out->Print( nestLevel, "(%s", Name() );
for( STRINGS::iterator i=padstacks.begin(); i!=padstacks.end(); ++i ) for( STRINGS::iterator i=padstacks.begin(); i!=padstacks.end(); ++i )
{ {
...@@ -1212,7 +1514,7 @@ public: ...@@ -1212,7 +1514,7 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) ); out->Print( nestLevel, "(%s\n", Name() );
//if( via_at_smd ) //if( via_at_smd )
{ {
...@@ -1269,14 +1571,14 @@ public: ...@@ -1269,14 +1571,14 @@ public:
{ {
const char* quote = out->GetQuoteChar( name.c_str() ); const char* quote = out->GetQuoteChar( name.c_str() );
out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ), out->Print( nestLevel, "(%s %s%s%s\n", Name(),
quote, name.c_str(), quote ); quote, name.c_str(), quote );
out->Print( nestLevel+1, "(type %s)\n", LEXER::GetTokenText( layer_type ) ); out->Print( nestLevel+1, "(type %s)\n", GetTokenText( layer_type ) );
if( properties.size() ) if( properties.size() )
{ {
out->Print( nestLevel+1, "(property \n" ); out->Print( nestLevel+1, "(property\n" );
for( PROPERTIES::iterator i = properties.begin(); i != properties.end(); ++i ) for( PROPERTIES::iterator i = properties.begin(); i != properties.end(); ++i )
{ {
...@@ -1287,7 +1589,7 @@ public: ...@@ -1287,7 +1589,7 @@ public:
if( direction != -1 ) if( direction != -1 )
out->Print( nestLevel+1, "(direction %s)\n", out->Print( nestLevel+1, "(direction %s)\n",
LEXER::GetTokenText( (DSN_T)direction ) ); GetTokenText( (DSN_T)direction ) );
if( rules ) if( rules )
rules->Format( out, nestLevel+1 ); rules->Format( out, nestLevel+1 );
...@@ -1297,10 +1599,10 @@ public: ...@@ -1297,10 +1599,10 @@ public:
if( cost < 0 ) if( cost < 0 )
out->Print( nestLevel+1, "(cost %d", -cost ); // positive integer, stored as negative out->Print( nestLevel+1, "(cost %d", -cost ); // positive integer, stored as negative
else else
out->Print( nestLevel+1, "(cost %s", LEXER::GetTokenText( (DSN_T)cost ) ); out->Print( nestLevel+1, "(cost %s", GetTokenText( (DSN_T)cost ) );
if( cost_type != -1 ) if( cost_type != -1 )
out->Print( 0, " (type %s)", LEXER::GetTokenText( (DSN_T)cost_type ) ); out->Print( 0, " (type %s)", GetTokenText( (DSN_T)cost_type ) );
out->Print( 0, ")\n" ); out->Print( 0, ")\n" );
} }
...@@ -1344,7 +1646,7 @@ public: ...@@ -1344,7 +1646,7 @@ public:
const char* quote0 = out->GetQuoteChar( layer_id0.c_str() ); const char* quote0 = out->GetQuoteChar( layer_id0.c_str() );
const char* quote1 = out->GetQuoteChar( layer_id1.c_str() ); const char* quote1 = out->GetQuoteChar( layer_id1.c_str() );
out->Print( nestLevel, "(%s %s%s%s %s%s%s %.6g)\n", LEXER::GetTokenText( Type() ), out->Print( nestLevel, "(%s %s%s%s %s%s%s %.6g)\n", Name(),
quote0, layer_id0.c_str(), quote0, quote0, layer_id0.c_str(), quote0,
quote1, layer_id1.c_str(), quote1, quote1, layer_id1.c_str(), quote1,
layer_weight ); layer_weight );
...@@ -1368,7 +1670,7 @@ public: ...@@ -1368,7 +1670,7 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) ); out->Print( nestLevel, "(%s\n", Name() );
for( LAYER_PAIRS::iterator i=layer_pairs.begin(); i!=layer_pairs.end(); ++i ) for( LAYER_PAIRS::iterator i=layer_pairs.begin(); i!=layer_pairs.end(); ++i )
i->Format( out, nestLevel+1 ); i->Format( out, nestLevel+1 );
...@@ -1414,8 +1716,8 @@ public: ...@@ -1414,8 +1716,8 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
out->Print( nestLevel, "(%s %s)\n", LEXER::GetTokenText( Type() ), out->Print( nestLevel, "(%s %s)\n", Name(),
LEXER::GetTokenText( value ) ); GetTokenText( value ) );
} }
}; };
...@@ -1442,7 +1744,7 @@ public: ...@@ -1442,7 +1744,7 @@ public:
{ {
const char* quote = out->GetQuoteChar( value.c_str() ); const char* quote = out->GetQuoteChar( value.c_str() );
out->Print( nestLevel, "(%s %s%s%s)\n", LEXER::GetTokenText( Type() ), out->Print( nestLevel, "(%s %s%s%s)\n", Name(),
quote, value.c_str(), quote ); quote, value.c_str(), quote );
} }
}; };
...@@ -1511,11 +1813,11 @@ class GRID : public ELEM ...@@ -1511,11 +1813,11 @@ class GRID : public ELEM
double dimension; double dimension;
DSN_T direction; ///< T_x | T_y | -1 for both int direction; ///< T_x | T_y | -1 for both
double offset; double offset;
DSN_T image_type; int image_type; // DSN_T
public: public:
...@@ -1532,18 +1834,18 @@ public: ...@@ -1532,18 +1834,18 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
out->Print( nestLevel, "(%s %s %.6g", out->Print( nestLevel, "(%s %s %.6g",
LEXER::GetTokenText( Type() ), Name(),
LEXER::GetTokenText( grid_type ), dimension ); GetTokenText( grid_type ), dimension );
if( grid_type == T_place ) if( grid_type == T_place )
{ {
if( image_type==T_smd || image_type==T_pin ) if( image_type==T_smd || image_type==T_pin )
out->Print( 0, " (image_type %s)", LEXER::GetTokenText( image_type ) ); out->Print( 0, " (image_type %s)", GetTokenText( image_type ) );
} }
else else
{ {
if( direction==T_x || direction==T_y ) if( direction==T_x || direction==T_y )
out->Print( 0, " (direction %s)", LEXER::GetTokenText( direction ) ); out->Print( 0, " (direction %s)", GetTokenText( direction ) );
} }
if( offset != 0.0 ) if( offset != 0.0 )
...@@ -1754,17 +2056,18 @@ public: ...@@ -1754,17 +2056,18 @@ public:
PLACE( ELEM* aParent ) : PLACE( ELEM* aParent ) :
ELEM( T_place, aParent ) ELEM( T_place, aParent )
{ {
side = T_front; side = DSN_T( T_front );
rotation = 0.0; rotation = 0.0;
hasVertex = false; hasVertex = false;
mirror = T_NONE; mirror = DSN_T( T_NONE );
status = T_NONE; status = DSN_T( T_NONE );
place_rules = 0; place_rules = 0;
lock_type = T_NONE; lock_type = DSN_T( T_NONE );
rules = 0; rules = 0;
region = 0; region = 0;
} }
...@@ -1828,7 +2131,7 @@ public: ...@@ -1828,7 +2131,7 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
const char* quote = out->GetQuoteChar( image_id.c_str() ); const char* quote = out->GetQuoteChar( image_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ), out->Print( nestLevel, "(%s %s%s%s\n", Name(),
quote, image_id.c_str(), quote ); quote, image_id.c_str(), quote );
FormatContents( out, nestLevel+1 ); FormatContents( out, nestLevel+1 );
...@@ -1860,7 +2163,7 @@ public: ...@@ -1860,7 +2163,7 @@ public:
ELEM( T_placement, aParent ) ELEM( T_placement, aParent )
{ {
unit = 0; unit = 0;
flip_style = T_NONE; flip_style = DSN_T( T_NONE );
} }
~PLACEMENT() ~PLACEMENT()
...@@ -1894,10 +2197,10 @@ public: ...@@ -1894,10 +2197,10 @@ public:
if( unit ) if( unit )
unit->Format( out, nestLevel ); unit->Format( out, nestLevel );
if( flip_style != T_NONE ) if( flip_style != DSN_T( T_NONE ) )
{ {
out->Print( nestLevel, "(place_control (flip_style %s))\n", out->Print( nestLevel, "(place_control (flip_style %s))\n",
LEXER::GetTokenText( flip_style ) ); GetTokenText( flip_style ) );
} }
for( COMPONENTS::iterator i=components.begin(); i!=components.end(); ++i ) for( COMPONENTS::iterator i=components.begin(); i!=components.end(); ++i )
...@@ -1957,13 +2260,13 @@ public: ...@@ -1957,13 +2260,13 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
out->Print( nestLevel, "(%s ", LEXER::GetTokenText( Type() ) ); out->Print( nestLevel, "(%s ", Name() );
if( shape ) if( shape )
shape->Format( out, 0 ); shape->Format( out, 0 );
if( connect == T_off ) if( connect == T_off )
out->Print( 0, "(connect %s)", LEXER::GetTokenText( connect ) ); out->Print( 0, "(connect %s)", GetTokenText( connect ) );
if( windows.size() ) if( windows.size() )
{ {
...@@ -2105,7 +2408,7 @@ public: ...@@ -2105,7 +2408,7 @@ public:
const char* quote = out->GetQuoteChar( imageId.c_str() ); const char* quote = out->GetQuoteChar( imageId.c_str() );
out->Print( nestLevel, "(%s %s%s%s", LEXER::GetTokenText( Type() ), out->Print( nestLevel, "(%s %s%s%s", Name(),
quote, imageId.c_str(), quote ); quote, imageId.c_str(), quote );
FormatContents( out, nestLevel+1 ); FormatContents( out, nestLevel+1 );
...@@ -2117,7 +2420,7 @@ public: ...@@ -2117,7 +2420,7 @@ public:
void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
if( side != T_both ) if( side != T_both )
out->Print( 0, " (side %s)", LEXER::GetTokenText( side ) ); out->Print( 0, " (side %s)", GetTokenText( side ) );
out->Print( 0, "\n"); out->Print( 0, "\n");
...@@ -2218,7 +2521,7 @@ public: ...@@ -2218,7 +2521,7 @@ public:
{ {
const char* quote = out->GetQuoteChar( padstack_id.c_str() ); const char* quote = out->GetQuoteChar( padstack_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ), out->Print( nestLevel, "(%s %s%s%s\n", Name(),
quote, padstack_id.c_str(), quote ); quote, padstack_id.c_str(), quote );
FormatContents( out, nestLevel+1 ); FormatContents( out, nestLevel+1 );
...@@ -2250,10 +2553,10 @@ public: ...@@ -2250,10 +2553,10 @@ public:
} }
if( rotate == T_off ) // print the non-default if( rotate == T_off ) // print the non-default
out->Print( 0, "(rotate %s)", LEXER::GetTokenText( rotate ) ); out->Print( 0, "(rotate %s)", GetTokenText( rotate ) );
if( absolute == T_on ) // print the non-default if( absolute == T_on ) // print the non-default
out->Print( 0, "(absolute %s)", LEXER::GetTokenText( absolute ) ); out->Print( 0, "(absolute %s)", GetTokenText( absolute ) );
out->Print( 0, "\n" ); out->Print( 0, "\n" );
...@@ -2272,6 +2575,7 @@ public: ...@@ -2272,6 +2575,7 @@ public:
}; };
typedef boost::ptr_vector<PADSTACK> PADSTACKS; typedef boost::ptr_vector<PADSTACK> PADSTACKS;
/** /**
* Function operator<() * Function operator<()
* is used by the PADSTACKSET boost::ptr_set below * is used by the PADSTACKSET boost::ptr_set below
...@@ -2538,7 +2842,7 @@ public: ...@@ -2538,7 +2842,7 @@ public:
ELEM( T_fromto, aParent ) ELEM( T_fromto, aParent )
{ {
rules = 0; rules = 0;
fromto_type = T_NONE; fromto_type = DSN_T( T_NONE );
} }
~FROMTO() ~FROMTO()
{ {
...@@ -2549,10 +2853,10 @@ public: ...@@ -2549,10 +2853,10 @@ public:
{ {
// no quoting on these two, the lexer preserved the quotes on input // no quoting on these two, the lexer preserved the quotes on input
out->Print( nestLevel, "(%s %s %s ", out->Print( nestLevel, "(%s %s %s ",
LEXER::GetTokenText( Type() ), fromText.c_str(), toText.c_str() ); Name(), fromText.c_str(), toText.c_str() );
if( fromto_type != T_NONE ) if( fromto_type != DSN_T( T_NONE ) )
out->Print( 0, "(type %s)", LEXER::GetTokenText( fromto_type ) ); out->Print( 0, "(type %s)", GetTokenText( fromto_type ) );
if( net_id.size() ) if( net_id.size() )
{ {
...@@ -2605,7 +2909,7 @@ public: ...@@ -2605,7 +2909,7 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
out->Print( nestLevel, "(%s", LEXER::GetTokenText( Type() ) ); out->Print( nestLevel, "(%s", Name() );
for( STRINGS::iterator i=placement_ids.begin(); i!=placement_ids.end(); ++i ) for( STRINGS::iterator i=placement_ids.begin(); i!=placement_ids.end(); ++i )
{ {
...@@ -2691,7 +2995,7 @@ public: ...@@ -2691,7 +2995,7 @@ public:
const char* quote = out->GetQuoteChar( net_id.c_str() ); const char* quote = out->GetQuoteChar( net_id.c_str() );
const char* space = " "; const char* space = " ";
out->Print( nestLevel, "(%s %s%s%s", LEXER::GetTokenText( Type() ), out->Print( nestLevel, "(%s %s%s%s", Name(),
quote, net_id.c_str(), quote ); quote, net_id.c_str(), quote );
if( unassigned ) if( unassigned )
...@@ -2711,7 +3015,7 @@ public: ...@@ -2711,7 +3015,7 @@ public:
if( pins.size() ) if( pins.size() )
{ {
const int RIGHTMARGIN = 80; const int RIGHTMARGIN = 80;
int perLine = out->Print( nestLevel+1, "(%s", LEXER::GetTokenText( pins_type ) ); int perLine = out->Print( nestLevel+1, "(%s", GetTokenText( pins_type ) );
for( PIN_REFS::iterator i=pins.begin(); i!=pins.end(); ++i ) for( PIN_REFS::iterator i=pins.begin(); i!=pins.end(); ++i )
{ {
...@@ -2732,7 +3036,7 @@ public: ...@@ -2732,7 +3036,7 @@ public:
comp_order->Format( out, nestLevel+1 ); comp_order->Format( out, nestLevel+1 );
if( type != T_NONE ) if( type != T_NONE )
out->Print( nestLevel+1, "(type %s)\n", LEXER::GetTokenText( type ) ); out->Print( nestLevel+1, "(type %s)\n", GetTokenText( type ) );
if( rules ) if( rules )
rules->Format( out, nestLevel+1 ); rules->Format( out, nestLevel+1 );
...@@ -2815,7 +3119,7 @@ public: ...@@ -2815,7 +3119,7 @@ public:
const char* quote = out->GetQuoteChar( class_id.c_str() ); const char* quote = out->GetQuoteChar( class_id.c_str() );
int perLine = out->Print( nestLevel, "(%s %s%s%s", int perLine = out->Print( nestLevel, "(%s %s%s%s",
LEXER::GetTokenText( Type() ), Name(),
quote, class_id.c_str(), quote ); quote, class_id.c_str(), quote );
const int RIGHTMARGIN = 72; const int RIGHTMARGIN = 72;
...@@ -2962,7 +3266,7 @@ public: ...@@ -2962,7 +3266,7 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
out->Print( nestLevel, "(%s ", LEXER::GetTokenText( Type() ) ); out->Print( nestLevel, "(%s ", Name() );
if( shape ) if( shape )
shape->Format( out, 0 ); shape->Format( out, 0 );
...@@ -2978,10 +3282,10 @@ public: ...@@ -2978,10 +3282,10 @@ public:
out->Print( 0, "(turrent %d)", turret ); out->Print( 0, "(turrent %d)", turret );
if( wire_type != T_NONE ) if( wire_type != T_NONE )
out->Print( 0, "(type %s)", LEXER::GetTokenText( wire_type ) ); out->Print( 0, "(type %s)", GetTokenText( wire_type ) );
if( attr != T_NONE ) if( attr != T_NONE )
out->Print( 0, "(attr %s)", LEXER::GetTokenText( attr ) ); out->Print( 0, "(attr %s)", GetTokenText( attr ) );
if( shield.size() ) if( shield.size() )
{ {
...@@ -3050,7 +3354,7 @@ public: ...@@ -3050,7 +3354,7 @@ public:
const int RIGHTMARGIN = 80; const int RIGHTMARGIN = 80;
int perLine = out->Print( nestLevel, "(%s %s%s%s", int perLine = out->Print( nestLevel, "(%s %s%s%s",
LEXER::GetTokenText( Type() ), Name(),
quote, padstack_id.c_str(), quote ); quote, padstack_id.c_str(), quote );
for( POINTS::iterator i=vertexes.begin(); i!=vertexes.end(); ++i ) for( POINTS::iterator i=vertexes.begin(); i!=vertexes.end(); ++i )
...@@ -3097,7 +3401,7 @@ public: ...@@ -3097,7 +3401,7 @@ public:
out->Print( 0, "\n" ); out->Print( 0, "\n" );
perLine = out->Print( nestLevel+1, "%s", "" ); perLine = out->Print( nestLevel+1, "%s", "" );
} }
perLine += out->Print( 0, "(type %s)", LEXER::GetTokenText( via_type ) ); perLine += out->Print( 0, "(type %s)", GetTokenText( via_type ) );
} }
if( attr != T_NONE ) if( attr != T_NONE )
...@@ -3114,7 +3418,7 @@ public: ...@@ -3114,7 +3418,7 @@ public:
quote, virtual_pin_name.c_str(), quote ); quote, virtual_pin_name.c_str(), quote );
} }
else else
perLine += out->Print( 0, "(attr %s)", LEXER::GetTokenText( attr ) ); perLine += out->Print( 0, "(attr %s)", GetTokenText( attr ) );
} }
if( supply ) if( supply )
...@@ -3237,7 +3541,7 @@ public: ...@@ -3237,7 +3541,7 @@ public:
{ {
const char* quote = out->GetQuoteChar( pcbname.c_str() ); const char* quote = out->GetQuoteChar( pcbname.c_str() );
out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ), out->Print( nestLevel, "(%s %s%s%s\n", Name(),
quote, pcbname.c_str(), quote ); quote, pcbname.c_str(), quote );
if( parser ) if( parser )
...@@ -3307,7 +3611,7 @@ public: ...@@ -3307,7 +3611,7 @@ public:
// format the time first to temp // format the time first to temp
// filename may be empty, so quote it just in case. // filename may be empty, so quote it just in case.
out->Print( nestLevel, "(%s \"%s\" (created_time %s)\n", out->Print( nestLevel, "(%s \"%s\" (created_time %s)\n",
LEXER::GetTokenText( Type() ), Name(),
filename.c_str(), filename.c_str(),
temp ); temp );
...@@ -3386,7 +3690,7 @@ public: ...@@ -3386,7 +3690,7 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
bool singleLine = pin_refs.size() <= 1; bool singleLine = pin_refs.size() <= 1;
out->Print( nestLevel, "(%s", LEXER::GetTokenText( Type() ) ); out->Print( nestLevel, "(%s", Name() );
if( singleLine ) if( singleLine )
{ {
...@@ -3612,7 +3916,7 @@ class SESSION : public ELEM ...@@ -3612,7 +3916,7 @@ class SESSION : public ELEM
public: public:
SESSION( ELEM* aParent = 0 ) : SESSION( ELEM* aParent = 0 ) :
ELEM( T_pcb, aParent ) ELEM( T_session, aParent )
{ {
history = 0; history = 0;
structure = 0; structure = 0;
...@@ -3632,7 +3936,7 @@ public: ...@@ -3632,7 +3936,7 @@ public:
void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError )
{ {
const char* quote = out->GetQuoteChar( session_id.c_str() ); const char* quote = out->GetQuoteChar( session_id.c_str() );
out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ), out->Print( nestLevel, "(%s %s%s%s\n", Name(),
quote, session_id.c_str(), quote ); quote, session_id.c_str(), quote );
out->Print( nestLevel+1, "(base_design \"%s\")\n", base_design.c_str() ); out->Print( nestLevel+1, "(base_design \"%s\")\n", base_design.c_str() );
...@@ -3656,7 +3960,6 @@ public: ...@@ -3656,7 +3960,6 @@ public:
} }
}; };
typedef boost::ptr_set<PADSTACK> PADSTACKSET; typedef boost::ptr_set<PADSTACK> PADSTACKSET;
...@@ -3666,7 +3969,11 @@ typedef boost::ptr_set<PADSTACK> PADSTACKSET; ...@@ -3666,7 +3969,11 @@ typedef boost::ptr_set<PADSTACK> PADSTACKSET;
*/ */
class SPECCTRA_DB : public OUTPUTFORMATTER class SPECCTRA_DB : public OUTPUTFORMATTER
{ {
LEXER* lexer; /// specctra DSN keywords
static const KEYWORD keywords[];
static const unsigned keywordCount;
DSNLEXER* lexer;
PCB* pcb; PCB* pcb;
...@@ -3721,7 +4028,11 @@ class SPECCTRA_DB : public OUTPUTFORMATTER ...@@ -3721,7 +4028,11 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
/** /**
* Function nextTok * Function nextTok
* returns the next token from the lexer. * returns the next token from the lexer as a DSN_T. Note to anybody
* who wants to use SPECCTRA_DB as a model for usage of DSNLEXER, you
* want to have this function return an enum, not an int, and to use
* that enum type whereever you can, because this allows the debugger
* to show you symbolic values for your tokens.
*/ */
DSN_T nextTok(); DSN_T nextTok();
...@@ -3810,10 +4121,10 @@ class SPECCTRA_DB : public OUTPUTFORMATTER ...@@ -3810,10 +4121,10 @@ class SPECCTRA_DB : public OUTPUTFORMATTER
/** /**
* Function expecting * Function expecting
* throws an IOError exception with an input file specific error message. * 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. * @param int is the token type which was expected at the current input location.
* @throw IOError with the location within the input file of the problem. * @throw IOError with the location within the input file of the problem.
*/ */
void expecting( DSN_T ) throw( IOError ); void expecting( DSN_T aTok ) throw( IOError );
void expecting( const char* text ) throw( IOError ); void expecting( const char* text ) throw( IOError );
void unexpected( DSN_T aTok ) throw( IOError ); void unexpected( DSN_T aTok ) throw( IOError );
void unexpected( const char* text ) throw( IOError ); void unexpected( const char* text ) throw( IOError );
...@@ -3995,6 +4306,15 @@ public: ...@@ -3995,6 +4306,15 @@ public:
const char* GetQuoteChar( const char* wrapee ); const char* GetQuoteChar( const char* wrapee );
//-----</OUTPUTFORMATTER>------------------------------------------------ //-----</OUTPUTFORMATTER>------------------------------------------------
static const char* TokenName( int aToken );
/**
* Function GetTokenString
* returns the wxString representation of aToken.
*/
static wxString GetTokenString( int aToken );
/** /**
* Function MakePCB * Function MakePCB
* makes a PCB with all the default ELEMs and parts on the heap. * makes a PCB with all the default ELEMs and parts on the heap.
...@@ -4026,6 +4346,7 @@ public: ...@@ -4026,6 +4346,7 @@ public:
delete session; delete session;
session = aSession; session = aSession;
} }
SESSION* GetSESSION() { return session; }
/** /**
...@@ -4043,7 +4364,7 @@ public: ...@@ -4043,7 +4364,7 @@ public:
/** /**
* Function LoadSESSION * Function LoadSESSION
* is a recursive descent parser for a SPECCTRA DSN "session" file. * 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 * A session file is a 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 * tool (PCBNEW) and should be used to update a BOARD object with the new
* tracks, vias, and component locations. * tracks, vias, and component locations.
* *
......
/* /*
* This program source code file is part of KICAD, a free EDA CAD application. * This program source code file is part of KICAD, a free EDA CAD application.
* *
* Copyright (C) 2007-2008 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com> * Copyright (C) 2007-2010 SoftPLC Corporation, Dick Hollenbeck <dick@softplc.com>
* Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors. * Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors.
* *
* This program is free software; you can redistribute it and/or * This program is free software; you can redistribute it and/or
...@@ -257,8 +257,8 @@ SEGVIA* SPECCTRA_DB::makeVIA( PADSTACK* aPadstack, const POINT& aPoint, int aNet ...@@ -257,8 +257,8 @@ SEGVIA* SPECCTRA_DB::makeVIA( PADSTACK* aPadstack, const POINT& aPoint, int aNet
shape = (SHAPE*) (*aPadstack)[0]; shape = (SHAPE*) (*aPadstack)[0];
DSN_T type = shape->shape->Type(); DSN_T type = shape->shape->Type();
if( type != T_circle ) if( type != T_circle )
ThrowIOError( _( "Unsupported via shape: \"%s\""), ThrowIOError( _( "Unsupported via shape: %s"),
GetChars( LEXER::GetTokenString( type ) ) ); GetChars( GetTokenString( type ) ) );
CIRCLE* circle = (CIRCLE*) shape->shape; CIRCLE* circle = (CIRCLE*) shape->shape;
int viaDiam = scale( circle->diameter, routeResolution ); int viaDiam = scale( circle->diameter, routeResolution );
...@@ -275,8 +275,8 @@ SEGVIA* SPECCTRA_DB::makeVIA( PADSTACK* aPadstack, const POINT& aPoint, int aNet ...@@ -275,8 +275,8 @@ SEGVIA* SPECCTRA_DB::makeVIA( PADSTACK* aPadstack, const POINT& aPoint, int aNet
shape = (SHAPE*) (*aPadstack)[0]; shape = (SHAPE*) (*aPadstack)[0];
DSN_T type = shape->shape->Type(); DSN_T type = shape->shape->Type();
if( type != T_circle ) if( type != T_circle )
ThrowIOError( _( "Unsupported via shape: \"%s\""), ThrowIOError( _( "Unsupported via shape: %s"),
GetChars( LEXER::GetTokenString( type ) ) ); GetChars( GetTokenString( type ) ) );
CIRCLE* circle = (CIRCLE*) shape->shape; CIRCLE* circle = (CIRCLE*) shape->shape;
int viaDiam = scale( circle->diameter, routeResolution ); int viaDiam = scale( circle->diameter, routeResolution );
...@@ -299,8 +299,8 @@ SEGVIA* SPECCTRA_DB::makeVIA( PADSTACK* aPadstack, const POINT& aPoint, int aNet ...@@ -299,8 +299,8 @@ SEGVIA* SPECCTRA_DB::makeVIA( PADSTACK* aPadstack, const POINT& aPoint, int aNet
shape = (SHAPE*) (*aPadstack)[i]; shape = (SHAPE*) (*aPadstack)[i];
DSN_T type = shape->shape->Type(); DSN_T type = shape->shape->Type();
if( type != T_circle ) if( type != T_circle )
ThrowIOError( _( "Unsupported via shape: \"%s\""), ThrowIOError( _( "Unsupported via shape: %s"),
GetChars( LEXER::GetTokenString( type ) ) ); GetChars( GetTokenString( type ) ) );
CIRCLE* circle = (CIRCLE*) shape->shape; CIRCLE* circle = (CIRCLE*) shape->shape;
...@@ -473,7 +473,7 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard ) throw( IOError ) ...@@ -473,7 +473,7 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard ) throw( IOError )
wxString netId = CONV_FROM_UTF8( wire->net_id.c_str() ); wxString netId = CONV_FROM_UTF8( wire->net_id.c_str() );
ThrowIOError( ThrowIOError(
_("Unsupported wire shape: \"%s\" for net: \"%s\""), _("Unsupported wire shape: \"%s\" for net: \"%s\""),
LEXER::GetTokenString(shape).GetData(), DLEX::GetTokenString(shape).GetData(),
netId.GetData() netId.GetData()
); );
*/ */
......
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