diff --git a/CHANGELOG.txt b/CHANGELOG.txt index 8e3c7b8d0f..f5ed65732c 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -4,6 +4,21 @@ KiCad ChangeLog 2009 Please add newer entries at the top, list the date and your name with email address. + +2009-Dec-10 UPDATE Dick Hollenbeck +================================================================================ +++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 ================================================================================ ++pcbnew & gerbview diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 3af35c2bf2..d88257bfba 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -13,7 +13,7 @@ set(COMMON_SRCS bezier_curves.cpp block_commande.cpp class_marker_base.cpp - class_plotter.cpp + class_plotter.cpp class_undoredo_container.cpp common.cpp common_plot_functions.cpp @@ -24,13 +24,14 @@ set(COMMON_SRCS confirm.cpp copy_to_clipboard.cpp dialog_display_info_HTML_base.cpp - dialog_load_error.cpp + dialog_load_error.cpp dcsvg.cpp displlst.cpp dlist.cpp drawframe.cpp drawpanel.cpp drawtxt.cpp + dsnlexer.cpp edaappl.cpp eda_dde.cpp eda_doc.cpp @@ -41,6 +42,7 @@ set(COMMON_SRCS msgpanel.cpp projet_config.cpp # pyhandler.cpp + richio.cpp selcolor.cpp string.cpp toolbars.cpp diff --git a/common/about_kicad.cpp b/common/about_kicad.cpp index 58853e1919..1fcb0ad8d4 100644 --- a/common/about_kicad.cpp +++ b/common/about_kicad.cpp @@ -11,14 +11,6 @@ #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) # include "version.h" #ifndef KICAD_ABOUT_VERSION @@ -30,6 +22,15 @@ wxString g_BuildAboutVersion( wxT( BUILD_VERSION ) ); #endif +/** Function GetAboutBuildVersion() + * Return custom build date for about dialog + */ +wxString GetAboutBuildVersion() +{ + return g_BuildAboutVersion; +} + + /**********************************/ wxString SetMsg( const wxString& msg ) /**********************************/ @@ -40,13 +41,13 @@ wxString SetMsg( const wxString& msg ) * Perhaps depending on wxWidgets versions */ { - wxString message; + wxString message; #if 1 /* Windows */ - message = wxT( "\n" ); + message = wxT( "\n" ); #endif - message << msg; - return message; + message << msg; + return message; } @@ -54,116 +55,116 @@ wxString SetMsg( const wxString& msg ) void InitKiCadAbout( wxAboutDialogInfo& info ) /**************************************************/ { - /* Set name and title */ - info.SetName( wxGetApp().GetTitle() ); + /* Set name and title */ + info.SetName( wxGetApp().GetTitle() ); - /* Set description */ - wxString description; + /* Set description */ + wxString description; - /* KiCad build version */ - description << ( _T( "Build: " ) ) << GetAboutBuildVersion(); + /* KiCad build version */ + description << ( _T( "Build: " ) ) << GetAboutBuildVersion(); - /* Print for wxversion */ - description << ( wxT( "\n\nwxWidgets " ) ) - << wxMAJOR_VERSION - << wxT( "." ) - << wxMINOR_VERSION << wxT( "." ) - << wxRELEASE_NUMBER + /* Print for wxversion */ + description << ( wxT( "\n\nwxWidgets " ) ) + << wxMAJOR_VERSION + << wxT( "." ) + << wxMINOR_VERSION << wxT( "." ) + << wxRELEASE_NUMBER - /* Show Unicode or Ansi version */ + /* Show Unicode or Ansi version */ #if wxUSE_UNICODE - << ( wxT( " Unicode " ) ); + << ( wxT( " Unicode " ) ); # else - << ( wxT( " Ansi " ) ); + << ( wxT( " Ansi " ) ); #endif - /************************** - * Check Operating System * - **************************/ + /************************** + * Check Operating System * + **************************/ #if defined __WINDOWS__ description << ( wxT( "on Windows" ) ); - /* Check for wxMAC */ + /* Check for wxMAC */ # elif defined __WXMAC__ - description << ( wxT( "on Macintosh" ) ); + description << ( wxT( "on Macintosh" ) ); - /* Linux 64 bits */ + /* Linux 64 bits */ # elif defined _LP64 && __LINUX__ - description << ( wxT( "on 64 Bits GNU/Linux" ) ); + description << ( wxT( "on 64 Bits GNU/Linux" ) ); - /* Linux 32 bits */ + /* Linux 32 bits */ # elif defined __LINUX__ - description << ( wxT( "on 32 Bits GNU/Linux" ) ); + description << ( wxT( "on 32 Bits GNU/Linux" ) ); - /* OpenBSD */ + /* OpenBSD */ # elif defined __OpenBSD__ - description << ( wxT ("on OpenBSD") ); + description << ( wxT ("on OpenBSD") ); - /* FreeBSD */ + /* FreeBSD */ # elif defined __FreeBSD__ - description << ( wxT ("on FreeBSD") ); + description << ( wxT ("on FreeBSD") ); #endif /* Websites */ - description << wxT( "\n\nKiCad on the web\n\n" ); - description << wxT( "http://iut-tice.ujf-grenoble.fr/kicad \n" ); - description << wxT( "http://kicad.sourceforge.net \n" ); - description << wxT( "http://www.kicadlib.org" ); + description << wxT( "\n\nKiCad on the web\n\n" ); + description << wxT( "http://iut-tice.ujf-grenoble.fr/kicad \n" ); + description << wxT( "http://kicad.sourceforge.net \n" ); + description << wxT( "http://www.kicadlib.org" ); - /* Set the complete about description */ - info.SetDescription( description ); + /* Set the complete about description */ + info.SetDescription( description ); - /* Set copyright dialog */ - info.SetCopyright( _T( "(C) 1992-2009 KiCad Developers Team" ) ); + /* Set copyright dialog */ + info.SetCopyright( _T( "(C) 1992-2009 KiCad Developers Team" ) ); - /* Set license dialog */ - info.SetLicence( wxString::FromAscii - ( "The complete KiCad EDA Suite is released under the\n" - "GNU General Public License version 2.\n" - "See for more information." - )); + /* Set license dialog */ + info.SetLicence( wxString::FromAscii + ( "The complete KiCad EDA Suite is released under the\n" + "GNU General Public License version 2.\n" + "See for more information." + )); - /* Add developers */ - info.AddDeveloper( wxT( "Jean-Pierre Charras " ) ); - info.AddDeveloper( SetMsg( wxT( "Dick Hollenbeck " ) ) ); - info.AddDeveloper( SetMsg( wxT( "Hauptmech ") ) ); - info.AddDeveloper( SetMsg( wxT( "Jerry Jacobs " ) ) ); - info.AddDeveloper( SetMsg( wxT( "Jonas Diemer " ) ) ); - info.AddDeveloper( SetMsg( wxT( "KBool Library " ) ) ); - info.AddDeveloper( SetMsg( wxT( "Lorenzo " ) ) ); - info.AddDeveloper( SetMsg( wxT( "Marco Serantoni " ) ) ); - info.AddDeveloper( SetMsg( wxT( "Rok Markovic " ) ) ); - info.AddDeveloper( SetMsg( wxT( "Tim Hanson " ) ) ); - info.AddDeveloper( SetMsg( wxT( "Vesa Solonen " ) ) ); - info.AddDeveloper( SetMsg( wxT( "Wayne Stambaugh " ) ) ); + /* Add developers */ + info.AddDeveloper( wxT( "Jean-Pierre Charras " ) ); + info.AddDeveloper( SetMsg( wxT( "Dick Hollenbeck " ) ) ); + info.AddDeveloper( SetMsg( wxT( "Hauptmech ") ) ); + info.AddDeveloper( SetMsg( wxT( "Jerry Jacobs " ) ) ); + info.AddDeveloper( SetMsg( wxT( "Jonas Diemer " ) ) ); + info.AddDeveloper( SetMsg( wxT( "KBool Library " ) ) ); + info.AddDeveloper( SetMsg( wxT( "Lorenzo " ) ) ); + info.AddDeveloper( SetMsg( wxT( "Marco Serantoni " ) ) ); + info.AddDeveloper( SetMsg( wxT( "Rok Markovic " ) ) ); + info.AddDeveloper( SetMsg( wxT( "Tim Hanson " ) ) ); + info.AddDeveloper( SetMsg( wxT( "Vesa Solonen " ) ) ); + info.AddDeveloper( SetMsg( wxT( "Wayne Stambaugh " ) ) ); - /* Add document writers*/ - info.AddDocWriter( wxT( "Jean-Pierre Charras " ) ); - info.AddDocWriter( SetMsg( wxT( "Igor Plyatov " ) ) ); + /* Add document writers*/ + info.AddDocWriter( wxT( "Jean-Pierre Charras " ) ); + info.AddDocWriter( SetMsg( wxT( "Igor Plyatov " ) ) ); - /* Add translators */ - info.AddTranslator( wxT( "Czech (CZ) Martin Kratoška " ) ); - info.AddTranslator( SetMsg( wxT( "Dutch (NL) Jerry Jacobs " ) ) ); - info.AddTranslator( SetMsg( wxT( "French (FR) Jean-Pierre Charras " ) ) ); - info.AddTranslator( SetMsg( wxT( "Polish (PL) Mateusz Skowroński " ) ) ); - info.AddTranslator( SetMsg( wxT( "Portuguese (PT) Renie Marquet " ) ) ); - info.AddTranslator( SetMsg( wxT( "Russian (RU) Igor Plyatov " ) ) ); - info.AddTranslator( SetMsg( wxT( "Spanish (ES) Pedro Martin del Valle " ) ) ); - info.AddTranslator( SetMsg( wxT( "Spanish (ES) Iñigo Zuluaga " ) ) ); - info.AddTranslator( SetMsg( wxT( "German (DE) Rafael Sokolowski " ) ) ); + /* Add translators */ + info.AddTranslator( wxT( "Czech (CZ) Martin Kratoška " ) ); + info.AddTranslator( SetMsg( wxT( "Dutch (NL) Jerry Jacobs " ) ) ); + info.AddTranslator( SetMsg( wxT( "French (FR) Jean-Pierre Charras " ) ) ); + info.AddTranslator( SetMsg( wxT( "Polish (PL) Mateusz Skowroński " ) ) ); + info.AddTranslator( SetMsg( wxT( "Portuguese (PT) Renie Marquet " ) ) ); + info.AddTranslator( SetMsg( wxT( "Russian (RU) Igor Plyatov " ) ) ); + info.AddTranslator( SetMsg( wxT( "Spanish (ES) Pedro Martin del Valle " ) ) ); + info.AddTranslator( SetMsg( wxT( "Spanish (ES) Iñigo Zuluaga " ) ) ); + info.AddTranslator( SetMsg( wxT( "German (DE) Rafael Sokolowski " ) ) ); - /* TODO are these all russian translators, placed them here now TODO - TODO or else align them below other language maintainer with mail adres TODO*/ - info.AddTranslator( SetMsg( wxT( "\nRemy Halvick" ) ) ); - info.AddTranslator( SetMsg( wxT( "David Briscoe" ) ) ); - info.AddTranslator( SetMsg( wxT( "Dominique Laigle" ) ) ); - info.AddTranslator( SetMsg( wxT( "Paul Burke" ) ) ); + /* TODO are these all russian translators, placed them here now TODO + TODO or else align them below other language maintainer with mail adres TODO*/ + info.AddTranslator( SetMsg( wxT( "\nRemy Halvick" ) ) ); + info.AddTranslator( SetMsg( wxT( "David Briscoe" ) ) ); + info.AddTranslator( SetMsg( wxT( "Dominique Laigle" ) ) ); + info.AddTranslator( SetMsg( wxT( "Paul Burke" ) ) ); - /* Add programm credits for icons */ - info.AddArtist( wxT( "Icons by Iñigo Zuluagaz " ) ); - info.AddArtist( SetMsg( wxT( "3D modules by Renie Marquet " ) ) ); - info.AddArtist( SetMsg( wxT( "3D modules by Christophe Boschat " ) ) ); + /* Add programm credits for icons */ + info.AddArtist( wxT( "Icons by Iñigo Zuluagaz " ) ); + info.AddArtist( SetMsg( wxT( "3D modules by Renie Marquet " ) ) ); + info.AddArtist( SetMsg( wxT( "3D modules by Christophe Boschat " ) ) ); } diff --git a/common/common.cpp b/common/common.cpp index 778ad8edc4..a6ea78a96d 100644 --- a/common/common.cpp +++ b/common/common.cpp @@ -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() * Return the build date */ @@ -127,15 +138,6 @@ wxString GetBuildVersion() } -/** Function GetAboutBuildVersion() - * Return custom build date for about dialog - */ -wxString GetAboutBuildVersion() -{ - return g_BuildAboutVersion; -} - - /** function SetLocaleTo_C_standard * because kicad is internationalized, switch internalization to "C" standard * i.e. uses the . (dot) as separator in print/read float numbers diff --git a/common/dsnlexer.cpp b/common/dsnlexer.cpp new file mode 100644 index 0000000000..c74b777888 --- /dev/null +++ b/common/dsnlexer.cpp @@ -0,0 +1,404 @@ + +/* + * This program source code file is part of KICAD, a free EDA CAD application. + * + * Copyright (C) 2007-2008 SoftPLC Corporation, Dick Hollenbeck + * 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 +#include +#include // bsearch() +#include + + +#include "dsnlexer.h" + +#include "fctsys.h" +#include "pcbnew.h" + + +static int compare( const void* a1, const void* a2 ) +{ + const KEYWORD* k1 = (const KEYWORD*) a1; + const KEYWORD* k2 = (const KEYWORD*) a2; + + int ret = strcmp( k1->name, k2->name ); + return ret; +} + + +//------------------------------------------------------------------ + +DSNLEXER::DSNLEXER( FILE* aFile, const wxString& aFilename, + const KEYWORD* aKeywordTable, unsigned aKeywordCount ) : + reader( aFile, 4096 ) + +{ + keywords = aKeywordTable; + keywordCount = aKeywordCount; + + curTok = DSN_NONE; + stringDelimiter = '"'; + filename = aFilename; + + space_in_quoted_tokens = true; + + // "start" should never change until we change the reader. The DSN + // format spec supports an include file mechanism but we can add that later + // using a std::stack to hold a stack of LINE_READERs to track nesting. + start = (char*) reader; + + limit = start; + next = start; +} + + +int DSNLEXER::findToken( const std::string& tok ) +{ + // convert to lower case once, this should be faster than using strcasecmp() + // for each test in compare(). + lowercase.clear(); + + for( std::string::const_iterator iter = tok.begin(); iter!=tok.end(); ++iter ) + lowercase += (char) tolower( *iter ); + + KEYWORD search; + + 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, + keywords, keywordCount, + sizeof(KEYWORD), compare ); + if( findings ) + return findings->token; + else + return -1; +} + + +const char* DSNLEXER::Syntax( int aTok ) +{ + const char* ret; + + switch( aTok ) + { + case DSN_NONE: + ret = "NONE"; + break; + case DSN_QUOTE_DEF: + ret = "quoted text delimiter"; + break; + case DSN_DASH: + ret = "-"; + break; + case DSN_SYMBOL: + ret = "symbol"; + break; + case DSN_NUMBER: + ret = "number"; + break; + case DSN_RIGHT: + ret = ")"; + break; + case DSN_LEFT: + ret = "("; + break; + case DSN_STRING: + ret = "quoted string"; + break; + case DSN_EOF: + ret = "end of file"; + break; + default: + ret = "???"; + } + + return ret; +} + + +const char* DSNLEXER::GetTokenText( int aTok ) +{ + const char* ret; + + if( aTok < 0 ) + { + return Syntax( aTok ); + } + else if( (unsigned) aTok < keywordCount ) + { + ret = keywords[aTok].name; + } + else + ret = "token too big"; + + return ret; +} + + +void DSNLEXER::ThrowIOError( wxString aText, int charOffset ) throw (IOError) +{ + aText << wxT(" ") << _("in file") << wxT(" \"") << filename + << wxT("\" ") << _("on line") << wxT(" ") << reader.LineNumber() + << wxT(" ") << _("at offset") << wxT(" ") << charOffset; + + throw IOError( aText ); +} + + +/** + * Function isspace + * strips the upper bits of the int to ensure the value passed to ::isspace() is + * in the range of 0-255 + */ +static inline bool isSpace( int cc ) +{ + // make sure int passed to ::isspace() is 0-255 + return ::isspace( cc & 0xff ); +} + + +int DSNLEXER::NextTok() throw (IOError) +{ + char* cur = next; + char* head = cur; + + prevTok = curTok; + + if( curTok != DSN_EOF ) + { + if( cur >= limit ) + { +L_read: + int len = readLine(); + if( len == 0 ) + { + curTok = DSN_EOF; + goto exit; + } + + cur = start; + + // skip leading whitespace + while( cur= limit ) + goto L_read; + + // switching the string_quote character + if( prevTok == DSN_STRING_QUOTE ) + { + static const wxString errtxt( _("String delimiter must be a single character of ', \", or $")); + + char cc = *cur; + switch( cc ) + { + case '\'': + case '$': + case '"': + break; + default: + ThrowIOError( errtxt, CurOffset() ); + } + + curText.clear(); + curText += cc; + + head = cur+1; + + if( head which is embedded for example + like: U2-14 or "U2"-"14" + This is detectable by a non-space immediately preceeding the dash. + */ + if( *cur == '-' && cur>start && !isSpace( cur[-1] ) ) + { + head = cur+1; + curText.clear(); + curText += '-'; + curTok = DSN_DASH; + goto exit; + } + + // handle DSN_NUMBER + if( strchr( "+-.0123456789", *cur ) ) + { + head = cur+1; + while( head= limit ) + { + wxString errtxt(_("Un-terminated delimited string") ); + ThrowIOError( errtxt, CurOffset() ); + } + + curText.clear(); + curText.append( cur, head ); + + ++head; // skip over the trailing delimiter + + curTok = DSN_STRING; + goto exit; + } + + // Maybe it is a token we will find in the token table. + // If not, then call it a DSN_SYMBOL. + { + head = cur+1; + while( head + * 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 + +#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( 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; +} + + + +//--------------------------------------------------------- + +// 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* 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 + * 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 _DSNLEXER_H +#define _DSNLEXER_H + +#include +#include + +#include "fctsys.h" +#include "pcbnew.h" + +#include "richio.h" + + +/** + * Struct KEYWORD + * holds a keyword string and its unique integer token. + */ +struct KEYWORD +{ + const char* name; ///< unique keyword. + int token; ///< a zero based index into an array of KEYWORDs +}; + +// 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 } + + +/** + * Enum DSN_SYNTAX_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_SYNTAX_T { + DSN_NONE = -10, + DSN_STRING_QUOTE = -9, + DSN_QUOTE_DEF = -8, + DSN_DASH = -7, + DSN_SYMBOL = -6, + DSN_NUMBER = -5, + DSN_RIGHT = -4, // right bracket, ')' + DSN_LEFT = -3, // left bracket, '(' + DSN_STRING = -2, // a quoted string, stripped of the quotes + DSN_EOF = -1, // special case for end of file +}; + + +/** + * Class DLEXER + * 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. + */ +class DSNLEXER +{ + char* next; + char* start; + char* limit; + + LINE_READER reader; + int stringDelimiter; + bool space_in_quoted_tokens; ///< blank spaces within quoted strings + + wxString filename; + int prevTok; ///< curTok from previous NextTok() call. + int curOffset; ///< offset within current line of the current token + + int curTok; ///< the current token obtained on last NextTok() + std::string curText; ///< the text of the current token + std::string lowercase; ///< a scratch buf holding token in lowercase + + const KEYWORD* keywords; + unsigned keywordCount; + + + int readLine() throw (IOError) + { + int len = reader.ReadLine(); + + next = start; + limit = start + len; + + return len; + } + + + /** + * Function findToken + * takes a string and looks up the string in the list of expected + * tokens. + * + * @param tok A string holding the token text to lookup, in an + * unpredictable case: uppercase or lowercase + * @return int - DSN_T or -1 if argument string is not a recognized token. + */ + int findToken( const std::string& tok ); + + bool isStringTerminator( char cc ) + { + if( !space_in_quoted_tokens && cc==' ' ) + return true; + + if( cc == stringDelimiter ) + return true; + + return false; + } + + +public: + + /** + * 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 + * changes the string delimiter from the default " to some other character + * and returns the old value. + * @param aStringDelimiter The character in lowest 8 bits. + * @return int - The old delimiter in the lowest 8 bits. + */ + int SetStringDelimiter( int aStringDelimiter ) + { + int old = stringDelimiter; + stringDelimiter = aStringDelimiter; + return old; + } + + /** + * Function SetSpaceInQuotedTokens + * changes the setting controlling whether a space in a quoted string is + * a terminator. + * @param val If true, means + */ + bool SetSpaceInQuotedTokens( bool val ) + { + bool old = space_in_quoted_tokens; + space_in_quoted_tokens = val; + return old; + } + + + /** + * Function NextTok + * returns the next token found in the input file or T_EOF when reaching + * the end of file. + * @return int - the type of token found next. + * @throw IOError - only if the LINE_READER throws it. + */ + int NextTok() throw (IOError); + + + /** + * Function ThrowIOError + * encapsulates the formatting of an error message which contains the exact + * location within the input file of something the caller is rejecting. + */ + void ThrowIOError( wxString aText, int charOffset ) throw (IOError); + + /** + * Function GetTokenString + * returns the C string representation of a DSN_T value. + */ + const char* GetTokenText( int aTok ); + + static const char* Syntax( int aTok ); + + + /** + * Function CurText + * returns a pointer to the current token's text. + */ + const char* CurText() + { + return curText.c_str(); + } + + /** + * Function CurTok + * returns whatever NextTok() returned the last time it was called. + */ + int CurTok() + { + return curTok; + } + + /** + * Function CurLineNumber + * returns the current line number within my LINE_READER + */ + int CurLineNumber() + { + return reader.LineNumber(); + } + + /** + * Function CurFilename + * returns the current input filename. + * @return const wxString& - the filename. + */ + const wxString& CurFilename() + { + return filename; + } + + /** + * Function PrevTok + * returns whatever NextTok() returned the 2nd to last time it was called. + */ + int PrevTok() + { + return prevTok; + } + + /** + * Function CurOffset + * returns the char offset within the current line, using a 1 based index. + * @return int - a one based index into the current line. + */ + int CurOffset() + { + return curOffset + 1; + } +}; + +#endif // _DSNLEXER_H diff --git a/include/richio.h b/include/richio.h new file mode 100644 index 0000000000..4951a2c6ea --- /dev/null +++ b/include/richio.h @@ -0,0 +1,265 @@ + +/* + * This program source code file is part of KICAD, a free EDA CAD application. + * + * Copyright (C) 2007-2010 SoftPLC Corporation, Dick Hollenbeck + * 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 +#include + +// I really did not want to be dependent on wxWidgets in richio +// but the errorText needs to be wide char so wxString rules. +#include +#include // 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(). + *

+ * 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. + *

+ * 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 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; + } + + + //----------------------------------------------------- + int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError ); + const char* GetQuoteChar( const char* wrapee ); + //---------------------------------------------------- +}; + + +#endif // RICHIO_H_ + diff --git a/pcbnew/CMakeLists.txt b/pcbnew/CMakeLists.txt index 5d6e686d6b..75f922abf8 100644 --- a/pcbnew/CMakeLists.txt +++ b/pcbnew/CMakeLists.txt @@ -78,7 +78,6 @@ set(PCBNEW_SRCS dist.cpp dragsegm.cpp drc.cpp - dsn.cpp edgemod.cpp edit.cpp editedge.cpp @@ -222,9 +221,9 @@ install(TARGETS pcbnew # This one gets made only when testing. -add_executable(dsntest EXCLUDE_FROM_ALL dsn.cpp) -target_link_libraries(dsntest common ${wxWidgets_LIBRARIES}) +#add_executable(dsntest EXCLUDE_FROM_ALL dsn.cpp) +#target_link_libraries(dsntest common ${wxWidgets_LIBRARIES}) # 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}) diff --git a/pcbnew/dsn.cpp b/pcbnew/dsn.cpp deleted file mode 100644 index 13feb3db5b..0000000000 --- a/pcbnew/dsn.cpp +++ /dev/null @@ -1,856 +0,0 @@ - -/* - * This program source code file is part of KICAD, a free EDA CAD application. - * - * Copyright (C) 2007-2008 SoftPLC Corporation, Dick Hollenbeck - * 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 -#include -#include // bsearch() -#include - - -#include "dsn.h" - -#include "fctsys.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 ) -{ - const KEYWORD* k1 = (const KEYWORD*) a1; - const KEYWORD* k2 = (const KEYWORD*) a2; - - int ret = strcmp( k1->name, k2->name ); - return ret; -} - - -//----------------------------------------------------------- - -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; -} - - -//------------------------------------------------------------------ - - -LEXER::LEXER( FILE* aFile, const wxString& aFilename ) : - reader( aFile, 4096 ) -{ - curTok = T_END; - stringDelimiter = '"'; - filename = aFilename; - - space_in_quoted_tokens = true; - - // "start" should never change until we change the reader. The DSN - // format spec supports an include file mechanism but we can add that later - // using a std::stack to hold a stack of LINE_READERs to track nesting. - start = (char*) reader; - - limit = start; - next = start; -} - - -int LEXER::findToken( const std::string& tok ) -{ - // convert to lower case once, this should be faster than using strcasecmp() - // for each test in compare(). - lowercase.clear(); - - for( std::string::const_iterator iter = tok.begin(); iter!=tok.end(); ++iter ) - lowercase += (char) tolower( *iter ); - - KEYWORD search; - search.name = lowercase.c_str(); - - const KEYWORD* findings = (const KEYWORD*) bsearch( &search, - tokens, sizeof(tokens)/sizeof(tokens[0]), - sizeof(KEYWORD), compare ); - if( findings ) -// return findings->token; - return findings - tokens; - else - return -1; -} - - -const char* LEXER::GetTokenText( DSN_T aTok ) -{ - const char* ret; - - if( aTok < 0 ) - { - switch( aTok ) - { - case T_NONE: - ret = "NONE"; - break; - case T_QUOTE_DEF: - ret = "quoted text delimiter"; - break; - case T_DASH: - ret = "-"; - break; - case T_SYMBOL: - ret = "symbol"; - break; - case T_NUMBER: - ret = "number"; - break; - case T_RIGHT: - ret = ")"; - break; - case T_LEFT: - ret = "("; - break; - case T_STRING: - ret = "quoted string"; - break; - case T_EOF: - ret = "end of file"; - break; - default: - ret = "???"; - } - } - else - { - ret = tokens[aTok].name; - } - - return ret; -} - - -wxString LEXER::GetTokenString( DSN_T aTok ) -{ - wxString ret; - - ret << wxT("'") << CONV_FROM_UTF8( GetTokenText(aTok) ) << wxT("'"); - - return ret; -} - - -void LEXER::ThrowIOError( wxString aText, int charOffset ) throw (IOError) -{ - aText << wxT(" ") << _("in file") << wxT(" \"") << filename - << wxT("\" ") << _("on line") << wxT(" ") << reader.LineNumber() - << wxT(" ") << _("at offset") << wxT(" ") << charOffset; - - throw IOError( aText ); -} - - -/** - * Function isspace - * strips the upper bits of the int to ensure the value passed to ::isspace() is - * in the range of 0-255 - */ -static inline bool isSpace( int cc ) -{ - // make sure int passed to ::isspace() is 0-255 - return ::isspace( cc & 0xff ); -} - - -DSN_T LEXER::NextTok() throw (IOError) -{ - char* cur = next; - char* head = cur; - - prevTok = curTok; - - if( curTok != T_EOF ) - { - if( cur >= limit ) - { -L_read: - int len = readLine(); - if( len == 0 ) - { - curTok = T_EOF; - goto exit; - } - - cur = start; - - // skip leading whitespace - while( cur= limit ) - goto L_read; - - // switching the string_quote character - if( prevTok == T_string_quote ) - { - static const wxString errtxt( _("String delimiter must be a single character of ', \", or $")); - - char cc = *cur; - switch( cc ) - { - case '\'': - case '$': - case '"': - break; - default: - ThrowIOError( errtxt, CurOffset() ); - } - - curText.clear(); - curText += cc; - - head = cur+1; - - if( head which is embedded for example - like: U2-14 or "U2"-"14" - This is detectable by a non-space immediately preceeding the dash. - */ - if( *cur == '-' && cur>start && !isSpace( cur[-1] ) ) - { - head = cur+1; - curText.clear(); - curText += '-'; - curTok = T_DASH; - goto exit; - } - - // handle T_NUMBER - if( strchr( "+-.0123456789", *cur ) ) - { - head = cur+1; - while( head= limit ) - { - wxString errtxt(_("Un-terminated delimited string") ); - ThrowIOError( errtxt, CurOffset() ); - } - - curText.clear(); - curText.append( cur, head ); - - ++head; // skip over the trailing delimiter - - curTok = T_STRING; - goto exit; - } - - // a token we hope to find in the tokens[] array. If not, then - // call it a T_SYMBOL. - { - head = cur+1; - while( head - * 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 _DSN_H -#define _DSN_H - -#include -#include - -#include "fctsys.h" -#include "pcbnew.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 - * is a class used to hold an error message and may be thrown from the LEXER. - */ -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 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. - */ -class LEXER -{ - char* next; - char* start; - char* limit; - - LINE_READER reader; - int stringDelimiter; - bool space_in_quoted_tokens; ///< blank spaces within quoted strings - - wxString filename; - DSN_T prevTok; ///< curTok from previous NextTok() call. - int curOffset; ///< offset within current line of the current token - - DSN_T curTok; ///< the current token obtained on last NextTok() - std::string curText; ///< the text of the current token - std::string lowercase; ///< a scratch buf holding token in lowercase - - - int readLine() throw (IOError) - { - int len = reader.ReadLine(); - - next = start; - limit = start + len; - - return len; - } - - - /** - * Function findToken - * takes a string and looks up the string in the list of expected - * tokens. - * - * @param tok A string holding the token text to lookup, in an - * unpredictable case: uppercase or lowercase - * @return int - DSN_T or -1 if argument string is not a recognized token. - */ - int findToken( const std::string& tok ); - - bool isStringTerminator( char cc ) - { - if( !space_in_quoted_tokens && cc==' ' ) - return true; - - if( cc == stringDelimiter ) - return true; - - return false; - } - - -public: - LEXER( FILE* aFile, const wxString& aFilename ); - - - /** - * Function SetStringDelimiter - * changes the string delimiter from the default " to some other character - * and returns the old value. - * @param aStringDelimiter The character in lowest 8 bits. - * @return int - The old delimiter in the lowest 8 bits. - */ - int SetStringDelimiter( int aStringDelimiter ) - { - int old = stringDelimiter; - stringDelimiter = aStringDelimiter; - return old; - } - - /** - * Function SetSpaceInQuotedTokens - * changes the setting controlling whether a space in a quoted string is - * a terminator. - * @param val If true, means - */ - bool SetSpaceInQuotedTokens( bool val ) - { - bool old = space_in_quoted_tokens; - space_in_quoted_tokens = val; - return old; - } - - - /** - * Function NextTok - * returns the next token found in the input file or T_EOF when reaching - * the end of file. - * @return DSN_T - the type of token found next. - * @throw IOError - only if the LINE_READER throws it. - */ - DSN_T NextTok() throw (IOError); - - - /** - * Function ThrowIOError - * encapsulates the formatting of an error message which contains the exact - * location within the input file of something the caller is rejecting. - */ - 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 - * returns the C string representation of a DSN_T value. - */ - static const char* GetTokenText( DSN_T aTok ); - - - /** - * Function CurText - * returns a pointer to the current token's text. - */ - const char* CurText() - { - return curText.c_str(); - } - - /** - * Function CurTok - * returns whatever NextTok() returned the last time it was called. - */ - DSN_T CurTok() - { - return curTok; - } - - /** - * Function CurLineNumber - * returns the current line number within my LINE_READER - */ - int CurLineNumber() - { - return reader.LineNumber(); - } - - /** - * Function CurFilename - * returns the current input filename. - * @return const wxString& - the filename. - */ - const wxString& CurFilename() - { - return filename; - } - - /** - * Function PrevTok - * returns whatever NextTok() returned the 2nd to last time it was called. - */ - DSN_T PrevTok() - { - return prevTok; - } - - /** - * Function CurOffset - * returns the char offset within the current line, using a 1 based index. - * @return int - a one based index into the current line. - */ - int CurOffset() - { - return curOffset + 1; - } - -}; - - -} // namespace DSN - -#endif // _DSN_H diff --git a/pcbnew/specctra.cpp b/pcbnew/specctra.cpp index 28a439326f..abc910fccd 100644 --- a/pcbnew/specctra.cpp +++ b/pcbnew/specctra.cpp @@ -47,20 +47,21 @@ */ + #include #include #include "specctra.h" +#include "common.h" // IsOK() & EDA_FileSelector() #include - // To build the DSN beautifier and unit tester, simply uncomment this and then // 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 #undef COMMON_GLOBL #define COMMON_GLOBL // build_version.h behavior @@ -72,11 +73,445 @@ namespace DSN { #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); //------------------------------------------------------ -#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 ) { @@ -131,7 +566,7 @@ void SPECCTRA_DB::ThrowIOError( const wxChar* fmt, ... ) throw( IOError ) void SPECCTRA_DB::expecting( DSN_T aTok ) throw( IOError ) { wxString errText( _("Expecting") ); - errText << wxT(" ") << LEXER::GetTokenString( aTok ); + errText << wxT(" ") << GetTokenString( aTok ); lexer->ThrowIOError( errText, lexer->CurOffset() ); } @@ -145,7 +580,7 @@ void SPECCTRA_DB::expecting( const char* text ) throw( IOError ) void SPECCTRA_DB::unexpected( DSN_T aTok ) throw( IOError ) { wxString errText( _("Unexpected") ); - errText << wxT(" ") << LEXER::GetTokenString( aTok ); + errText << wxT(" ") << GetTokenString( aTok ); lexer->ThrowIOError( errText, lexer->CurOffset() ); } @@ -159,7 +594,7 @@ void SPECCTRA_DB::unexpected( const char* text ) throw( IOError ) DSN_T SPECCTRA_DB::nextTok() { - DSN_T ret = lexer->NextTok(); + DSN_T ret = (DSN_T) lexer->NextTok(); return ret; } @@ -198,7 +633,7 @@ DSN_T SPECCTRA_DB::needSYMBOL() throw( IOError ) DSN_T SPECCTRA_DB::needSYMBOLorNUMBER() throw( IOError ) { - DSN_T tok = nextTok(); + DSN_T tok = nextTok(); if( !isSymbol( tok ) && tok!=T_NUMBER ) expecting( "symbol|number" ); return tok; @@ -206,11 +641,11 @@ DSN_T SPECCTRA_DB::needSYMBOLorNUMBER() throw( IOError ) void SPECCTRA_DB::readCOMPnPIN( std::string* component_id, std::string* pin_id ) throw( IOError ) { - DSN_T tok; + DSN_T tok; static const char pin_def[] = "::=-"; - if( !isSymbol( lexer->CurTok() ) ) + if( !isSymbol( (DSN_T) lexer->CurTok() ) ) expecting( pin_def ); // 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 ) delete lexer; lexer = 0; - lexer = new LEXER( file.fp(), filename ); + lexer = new DSNLEXER( file.fp(), filename, SPECCTRA_DB::keywords, SPECCTRA_DB::keywordCount ); if( nextTok() != T_LEFT ) expecting( T_LEFT ); @@ -359,7 +794,7 @@ void SPECCTRA_DB::LoadSESSION( const wxString& filename ) throw( IOError ) delete lexer; lexer = 0; - lexer = new LEXER( file.fp(), filename ); + lexer = new DSNLEXER( file.fp(), filename, SPECCTRA_DB::keywords, SPECCTRA_DB::keywordCount ); if( nextTok() != T_LEFT ) expecting( T_LEFT ); @@ -508,7 +943,7 @@ void SPECCTRA_DB::doPARSER( PARSER* growth ) throw( IOError ) tok = nextTok(); switch( tok ) { - case T_string_quote: + case T_STRING_QUOTE: tok = nextTok(); if( tok != T_QUOTE_DEF ) expecting( T_QUOTE_DEF ); @@ -1200,7 +1635,7 @@ void SPECCTRA_DB::doSTRINGPROP( STRINGPROP* growth ) throw( IOError ) void SPECCTRA_DB::doTOKPROP( TOKPROP* growth ) throw( IOError ) { - DSN_T tok = nextTok(); + DSN_T tok = nextTok(); if( tok<0 ) unexpected( lexer->CurText() ); @@ -2613,9 +3048,6 @@ void SPECCTRA_DB::doCLASS( CLASS* growth ) throw( IOError ) int bracketNesting = 1; // we already saw the opening T_LEFT DSN_T tok = T_NONE; - builder += '('; - builder += lexer->CurText(); - while( bracketNesting!=0 && tok!=T_EOF ) { tok = nextTok(); @@ -2628,7 +3060,9 @@ void SPECCTRA_DB::doCLASS( CLASS* growth ) throw( IOError ) 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 += ' '; if( tok==T_STRING ) @@ -2644,9 +3078,8 @@ void SPECCTRA_DB::doCLASS( CLASS* growth ) throw( IOError ) // to bracketNesting == 0, then save the builder and break; if( bracketNesting == 0 ) { - builder += ')'; - growth->circuit.push_back( builder ); - break; + growth->circuit.push_back( builder ); + break; } } @@ -2656,7 +3089,7 @@ void SPECCTRA_DB::doCLASS( CLASS* growth ) throw( IOError ) break; default: - unexpected( lexer->CurText() ); + unexpected( lexer->CurText() ); } // switch tok = nextTok(); @@ -3518,41 +3951,6 @@ int SPECCTRA_DB::Print( int nestLevel, const char* fmt, ... ) throw( IOError ) 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 ) { @@ -3627,91 +4025,6 @@ PCB* SPECCTRA_DB::MakePCB() } -//--------------------------------------------------------- - -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--------------------------------------------------------------- ELEM::ELEM( DSN_T aType, ELEM* aParent ) : @@ -3725,6 +4038,10 @@ ELEM::~ELEM() { } +const char* ELEM::Name() const +{ + return SPECCTRA_DB::TokenName( type ); +} UNIT_RES* ELEM::GetUnits() const { @@ -3737,7 +4054,7 @@ UNIT_RES* ELEM::GetUnits() const 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 ); @@ -3903,7 +4220,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { 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 ); out->Print( nestLevel+1, "%s", "" ); @@ -3912,7 +4229,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { 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 ); } @@ -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, " %s", LEXER::GetTokenText( side ) ); + out->Print( 0, " %s", GetTokenText( side ) ); out->Print( 0, " %.6g", rotation ); } @@ -3929,13 +4246,13 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) if( mirror != T_NONE ) { - out->Print( 0, "%s(mirror %s)", space, LEXER::GetTokenText( mirror ) ); + out->Print( 0, "%s(mirror %s)", space, GetTokenText( mirror ) ); space = ""; } if( status != T_NONE ) { - out->Print( 0, "%s(status %s)", space, LEXER::GetTokenText( status ) ); + out->Print( 0, "%s(status %s)", space, GetTokenText( status ) ); space = ""; } @@ -3967,8 +4284,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) out->Print( nestLevel+1, ")\n" ); } if( lock_type != T_NONE ) - out->Print( nestLevel+1, "(lock_type %s)\n", - LEXER::GetTokenText(lock_type) ); + out->Print( nestLevel+1, "(lock_type %s)\n", GetTokenText(lock_type) ); if( rules ) rules->Format( out, nestLevel+1 ); @@ -3986,8 +4302,7 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { if( lock_type != T_NONE ) { - out->Print( 0, "%s(lock_type %s)", space, - LEXER::GetTokenText(lock_type) ); + out->Print( 0, "%s(lock_type %s)", space, GetTokenText(lock_type) ); space = ""; } @@ -4002,16 +4317,17 @@ void PLACE::Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) out->Print( 0, ")\n" ); } - } // namespace DSN -// unit test this source file - -#if defined(STANDALONE) +// 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 +// 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; @@ -4035,8 +4351,8 @@ int main( int argc, char** argv ) try { - db.LoadPCB( filename ); -// db.LoadSESSION( filename ); +// db.LoadPCB( filename ); + db.LoadSESSION( filename ); } catch( IOError ioe ) { @@ -4048,18 +4364,25 @@ int main( int argc, char** argv ) fprintf( stderr, "loaded OK\n" ); // export what we read in, making this test program basically a beautifier -// db.ExportSESSION( wxT("/tmp/export.ses") ); -// db.ExportPCB( wxT("/tmp/export.dsn") ); - - DSN::PCB* pcb = db.GetPCB(); - - // hose the beautified DSN file to stdout. + // hose the beautified DSN file to stdout. If an exception occurred, + // 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(); 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 } + #endif diff --git a/pcbnew/specctra.h b/pcbnew/specctra.h index 1bf0bb9f45..77dbc17f18 100644 --- a/pcbnew/specctra.h +++ b/pcbnew/specctra.h @@ -33,7 +33,9 @@ #include #include "fctsys.h" -#include "dsn.h" + +#include "dsnlexer.h" + class TYPE_COLLECTOR; // outside the DSN namespace @@ -63,131 +65,429 @@ class TYPE_COLLECTOR; // outside the DSN namespace */ namespace DSN { + +enum DSN_T { + + // these first few are negative special ones for syntax, and are + // inherited from DSNLEXER. + T_NONE = DSN_NONE, + T_STRING_QUOTE = DSN_STRING_QUOTE, + T_QUOTE_DEF = DSN_QUOTE_DEF, + T_DASH = DSN_DASH, + T_SYMBOL = DSN_SYMBOL, + T_NUMBER = DSN_NUMBER, + T_RIGHT = DSN_RIGHT, // right bracket, ')' + T_LEFT = DSN_LEFT, // left bracket, '(' + T_STRING = DSN_STRING, // a quoted string, stripped of the quotes + T_EOF = DSN_EOF, // special case for end of file + + + // This should be coordinated with the + // const static KEYWORD tokens[] array, and both must be sorted + // identically and alphabetically. Remember that '_' is less than any + // alpha character according to ASCII. + + T_absolute = 0, // 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_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 OUTPUTFORMATTER - * is an interface (abstract class) used to output ASCII text. The destination - * of the ASCII text is up to the implementer. + * Function GetTokenText + * is in the DSN namespace and returns the C string representing a + * SPECCTRA_DB::keyword. We needed a non-instanance function to get at + * the SPECCTRA_DB::keyword[] and class SPECCTRA_DB is not defined yet. */ -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. - * @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. - * @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 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() - { - return mystring.c_str(); - } - */ - - std::string GetString() - { - return mystring; - } - - - //----------------------------------------------------- - int PRINTF_FUNC Print( int nestLevel, const char* fmt, ... ) throw( IOError ); - const char* GetQuoteChar( const char* wrapee ); - //---------------------------------------------------- -}; +const char* GetTokenText( int aTok ); /** @@ -334,6 +634,8 @@ public: DSN_T Type() const { return type; } + const char* Name() const; + /** * Function GetUnits @@ -529,12 +831,12 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { if( type == T_unit ) - out->Print( nestLevel, "(%s %s)\n", LEXER::GetTokenText( Type() ), - LEXER::GetTokenText(units) ); + out->Print( nestLevel, "(%s %s)\n", Name(), + GetTokenText(units) ); else // T_resolution - out->Print( nestLevel, "(%s %s %d)\n", LEXER::GetTokenText( Type() ), - LEXER::GetTokenText(units), value ); + out->Print( nestLevel, "(%s %s %d)\n", Name(), + GetTokenText(units), value ); } }; @@ -576,7 +878,7 @@ public: const char* quote = out->GetQuoteChar( layer_id.c_str() ); out->Print( nestLevel, "(%s %s%s%s %.6g %.6g %.6g %.6g)%s", - LEXER::GetTokenText( Type() ), + Name(), quote, layer_id.c_str(), quote, point0.x, point0.y, point1.x, point1.y, @@ -604,7 +906,7 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { - out->Print( nestLevel, "(%s", LEXER::GetTokenText( Type() ) ); + out->Print( nestLevel, "(%s", Name() ); bool singleLine; @@ -650,7 +952,7 @@ public: 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 ) { @@ -715,7 +1017,7 @@ public: const int RIGHTMARGIN = 70; int perLine = out->Print( nestLevel, "(%s %s%s%s %.6g", - LEXER::GetTokenText( Type() ), + Name(), quote, layer_id.c_str(), quote, aperture_width ); @@ -768,7 +1070,7 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { - out->Print( nestLevel, "(%s\n", LEXER::GetTokenText( Type() ) ); + out->Print( nestLevel, "(%s\n", Name() ); if( rectangle ) rectangle->Format( out, nestLevel+1 ); @@ -804,7 +1106,7 @@ public: const char* newline = nestLevel ? "\n" : ""; 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, diameter ); @@ -851,7 +1153,7 @@ public: const char* newline = nestLevel ? "\n" : ""; 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, aperture_width); @@ -930,7 +1232,7 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { - out->Print( nestLevel, "(%s ", LEXER::GetTokenText( Type() ) ); + out->Print( nestLevel, "(%s ", Name() ); if( shape ) shape->Format( out, 0 ); @@ -1015,7 +1317,7 @@ public: { const char* newline = "\n"; - out->Print( nestLevel, "(%s", LEXER::GetTokenText( Type() ) ); + out->Print( nestLevel, "(%s", Name() ); if( name.size() ) { @@ -1091,7 +1393,7 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { 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 ) { @@ -1212,7 +1514,7 @@ public: 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 ) { @@ -1269,14 +1571,14 @@ public: { 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 ); - out->Print( nestLevel+1, "(type %s)\n", LEXER::GetTokenText( layer_type ) ); + out->Print( nestLevel+1, "(type %s)\n", GetTokenText( layer_type ) ); 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 ) { @@ -1287,7 +1589,7 @@ public: if( direction != -1 ) out->Print( nestLevel+1, "(direction %s)\n", - LEXER::GetTokenText( (DSN_T)direction ) ); + GetTokenText( (DSN_T)direction ) ); if( rules ) rules->Format( out, nestLevel+1 ); @@ -1297,10 +1599,10 @@ public: if( cost < 0 ) out->Print( nestLevel+1, "(cost %d", -cost ); // positive integer, stored as negative else - out->Print( nestLevel+1, "(cost %s", LEXER::GetTokenText( (DSN_T)cost ) ); + out->Print( nestLevel+1, "(cost %s", GetTokenText( (DSN_T)cost ) ); 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" ); } @@ -1344,7 +1646,7 @@ public: const char* quote0 = out->GetQuoteChar( layer_id0.c_str() ); const char* quote1 = out->GetQuoteChar( layer_id1.c_str() ); - out->Print( nestLevel, "(%s %s%s%s %s%s%s %.6g)\n", LEXER::GetTokenText( Type() ), + out->Print( nestLevel, "(%s %s%s%s %s%s%s %.6g)\n", Name(), quote0, layer_id0.c_str(), quote0, quote1, layer_id1.c_str(), quote1, layer_weight ); @@ -1368,7 +1670,7 @@ public: 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 ) i->Format( out, nestLevel+1 ); @@ -1414,8 +1716,8 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { - out->Print( nestLevel, "(%s %s)\n", LEXER::GetTokenText( Type() ), - LEXER::GetTokenText( value ) ); + out->Print( nestLevel, "(%s %s)\n", Name(), + GetTokenText( value ) ); } }; @@ -1442,7 +1744,7 @@ public: { 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 ); } }; @@ -1511,11 +1813,11 @@ class GRID : public ELEM double dimension; - DSN_T direction; ///< T_x | T_y | -1 for both + int direction; ///< T_x | T_y | -1 for both double offset; - DSN_T image_type; + int image_type; // DSN_T public: @@ -1532,18 +1834,18 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { out->Print( nestLevel, "(%s %s %.6g", - LEXER::GetTokenText( Type() ), - LEXER::GetTokenText( grid_type ), dimension ); + Name(), + GetTokenText( grid_type ), dimension ); if( grid_type == T_place ) { if( image_type==T_smd || image_type==T_pin ) - out->Print( 0, " (image_type %s)", LEXER::GetTokenText( image_type ) ); + out->Print( 0, " (image_type %s)", GetTokenText( image_type ) ); } else { 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 ) @@ -1754,17 +2056,18 @@ public: PLACE( ELEM* aParent ) : ELEM( T_place, aParent ) { - side = T_front; + side = DSN_T( T_front ); rotation = 0.0; hasVertex = false; - mirror = T_NONE; - status = T_NONE; + mirror = DSN_T( T_NONE ); + status = DSN_T( T_NONE ); + place_rules = 0; - lock_type = T_NONE; + lock_type = DSN_T( T_NONE ); rules = 0; region = 0; } @@ -1828,7 +2131,7 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { const char* quote = out->GetQuoteChar( image_id.c_str() ); - out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ), + out->Print( nestLevel, "(%s %s%s%s\n", Name(), quote, image_id.c_str(), quote ); FormatContents( out, nestLevel+1 ); @@ -1860,7 +2163,7 @@ public: ELEM( T_placement, aParent ) { unit = 0; - flip_style = T_NONE; + flip_style = DSN_T( T_NONE ); } ~PLACEMENT() @@ -1894,10 +2197,10 @@ public: if( unit ) 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", - LEXER::GetTokenText( flip_style ) ); + GetTokenText( flip_style ) ); } for( COMPONENTS::iterator i=components.begin(); i!=components.end(); ++i ) @@ -1957,13 +2260,13 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { - out->Print( nestLevel, "(%s ", LEXER::GetTokenText( Type() ) ); + out->Print( nestLevel, "(%s ", Name() ); if( shape ) shape->Format( out, 0 ); if( connect == T_off ) - out->Print( 0, "(connect %s)", LEXER::GetTokenText( connect ) ); + out->Print( 0, "(connect %s)", GetTokenText( connect ) ); if( windows.size() ) { @@ -2105,7 +2408,7 @@ public: 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 ); FormatContents( out, nestLevel+1 ); @@ -2117,7 +2420,7 @@ public: void FormatContents( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { if( side != T_both ) - out->Print( 0, " (side %s)", LEXER::GetTokenText( side ) ); + out->Print( 0, " (side %s)", GetTokenText( side ) ); out->Print( 0, "\n"); @@ -2218,7 +2521,7 @@ public: { 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 ); FormatContents( out, nestLevel+1 ); @@ -2250,10 +2553,10 @@ public: } 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 - out->Print( 0, "(absolute %s)", LEXER::GetTokenText( absolute ) ); + out->Print( 0, "(absolute %s)", GetTokenText( absolute ) ); out->Print( 0, "\n" ); @@ -2272,6 +2575,7 @@ public: }; typedef boost::ptr_vector PADSTACKS; + /** * Function operator<() * is used by the PADSTACKSET boost::ptr_set below @@ -2538,7 +2842,7 @@ public: ELEM( T_fromto, aParent ) { rules = 0; - fromto_type = T_NONE; + fromto_type = DSN_T( T_NONE ); } ~FROMTO() { @@ -2549,10 +2853,10 @@ public: { // no quoting on these two, the lexer preserved the quotes on input out->Print( nestLevel, "(%s %s %s ", - LEXER::GetTokenText( Type() ), fromText.c_str(), toText.c_str() ); + Name(), fromText.c_str(), toText.c_str() ); - if( fromto_type != T_NONE ) - out->Print( 0, "(type %s)", LEXER::GetTokenText( fromto_type ) ); + if( fromto_type != DSN_T( T_NONE ) ) + out->Print( 0, "(type %s)", GetTokenText( fromto_type ) ); if( net_id.size() ) { @@ -2605,7 +2909,7 @@ public: 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 ) { @@ -2691,7 +2995,7 @@ public: const char* quote = out->GetQuoteChar( net_id.c_str() ); 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 ); if( unassigned ) @@ -2711,7 +3015,7 @@ public: if( pins.size() ) { 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 ) { @@ -2732,7 +3036,7 @@ public: comp_order->Format( out, nestLevel+1 ); 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 ) rules->Format( out, nestLevel+1 ); @@ -2815,7 +3119,7 @@ public: const char* quote = out->GetQuoteChar( class_id.c_str() ); int perLine = out->Print( nestLevel, "(%s %s%s%s", - LEXER::GetTokenText( Type() ), + Name(), quote, class_id.c_str(), quote ); const int RIGHTMARGIN = 72; @@ -2962,7 +3266,7 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { - out->Print( nestLevel, "(%s ", LEXER::GetTokenText( Type() ) ); + out->Print( nestLevel, "(%s ", Name() ); if( shape ) shape->Format( out, 0 ); @@ -2978,10 +3282,10 @@ public: out->Print( 0, "(turrent %d)", turret ); 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 ) - out->Print( 0, "(attr %s)", LEXER::GetTokenText( attr ) ); + out->Print( 0, "(attr %s)", GetTokenText( attr ) ); if( shield.size() ) { @@ -3050,7 +3354,7 @@ public: const int RIGHTMARGIN = 80; int perLine = out->Print( nestLevel, "(%s %s%s%s", - LEXER::GetTokenText( Type() ), + Name(), quote, padstack_id.c_str(), quote ); for( POINTS::iterator i=vertexes.begin(); i!=vertexes.end(); ++i ) @@ -3097,7 +3401,7 @@ public: out->Print( 0, "\n" ); 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 ) @@ -3114,7 +3418,7 @@ public: quote, virtual_pin_name.c_str(), quote ); } else - perLine += out->Print( 0, "(attr %s)", LEXER::GetTokenText( attr ) ); + perLine += out->Print( 0, "(attr %s)", GetTokenText( attr ) ); } if( supply ) @@ -3237,7 +3541,7 @@ public: { 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 ); if( parser ) @@ -3307,7 +3611,7 @@ public: // format the time first to temp // filename may be empty, so quote it just in case. out->Print( nestLevel, "(%s \"%s\" (created_time %s)\n", - LEXER::GetTokenText( Type() ), + Name(), filename.c_str(), temp ); @@ -3386,7 +3690,7 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { bool singleLine = pin_refs.size() <= 1; - out->Print( nestLevel, "(%s", LEXER::GetTokenText( Type() ) ); + out->Print( nestLevel, "(%s", Name() ); if( singleLine ) { @@ -3612,7 +3916,7 @@ class SESSION : public ELEM public: SESSION( ELEM* aParent = 0 ) : - ELEM( T_pcb, aParent ) + ELEM( T_session, aParent ) { history = 0; structure = 0; @@ -3632,7 +3936,7 @@ public: void Format( OUTPUTFORMATTER* out, int nestLevel ) throw( IOError ) { const char* quote = out->GetQuoteChar( session_id.c_str() ); - out->Print( nestLevel, "(%s %s%s%s\n", LEXER::GetTokenText( Type() ), + out->Print( nestLevel, "(%s %s%s%s\n", Name(), quote, session_id.c_str(), quote ); out->Print( nestLevel+1, "(base_design \"%s\")\n", base_design.c_str() ); @@ -3656,7 +3960,6 @@ public: } }; - typedef boost::ptr_set PADSTACKSET; @@ -3666,7 +3969,11 @@ typedef boost::ptr_set PADSTACKSET; */ class SPECCTRA_DB : public OUTPUTFORMATTER { - LEXER* lexer; + /// specctra DSN keywords + static const KEYWORD keywords[]; + static const unsigned keywordCount; + + DSNLEXER* lexer; PCB* pcb; @@ -3721,7 +4028,11 @@ class SPECCTRA_DB : public OUTPUTFORMATTER /** * 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(); @@ -3810,10 +4121,10 @@ class SPECCTRA_DB : public OUTPUTFORMATTER /** * Function expecting * throws an IOError exception with an input file specific error message. - * @param DSN_T The token type which was expected at the current input location. + * @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. */ - void expecting( DSN_T ) throw( IOError ); + void expecting( DSN_T aTok ) throw( IOError ); void expecting( const char* text ) throw( IOError ); void unexpected( DSN_T aTok ) throw( IOError ); void unexpected( const char* text ) throw( IOError ); @@ -3995,6 +4306,15 @@ public: const char* GetQuoteChar( const char* wrapee ); //----------------------------------------------------- + static const char* TokenName( int aToken ); + + + /** + * Function GetTokenString + * returns the wxString representation of aToken. + */ + static wxString GetTokenString( int aToken ); + /** * Function MakePCB * makes a PCB with all the default ELEMs and parts on the heap. @@ -4026,6 +4346,7 @@ public: delete session; session = aSession; } + SESSION* GetSESSION() { return session; } /** @@ -4043,7 +4364,7 @@ public: /** * Function LoadSESSION * is a recursive descent parser for a SPECCTRA DSN "session" file. - * A session file is file that is fed back from the router to the layout + * 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 * tracks, vias, and component locations. * diff --git a/pcbnew/specctra_import.cpp b/pcbnew/specctra_import.cpp index 40f47e1b2b..6cc679ff97 100644 --- a/pcbnew/specctra_import.cpp +++ b/pcbnew/specctra_import.cpp @@ -1,7 +1,7 @@ /* * This program source code file is part of KICAD, a free EDA CAD application. * - * Copyright (C) 2007-2008 SoftPLC Corporation, Dick Hollenbeck + * Copyright (C) 2007-2010 SoftPLC Corporation, Dick Hollenbeck * Copyright (C) 2007 Kicad Developers, see change_log.txt for contributors. * * 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 shape = (SHAPE*) (*aPadstack)[0]; DSN_T type = shape->shape->Type(); if( type != T_circle ) - ThrowIOError( _( "Unsupported via shape: \"%s\""), - GetChars( LEXER::GetTokenString( type ) ) ); + ThrowIOError( _( "Unsupported via shape: %s"), + GetChars( GetTokenString( type ) ) ); CIRCLE* circle = (CIRCLE*) shape->shape; int viaDiam = scale( circle->diameter, routeResolution ); @@ -275,8 +275,8 @@ SEGVIA* SPECCTRA_DB::makeVIA( PADSTACK* aPadstack, const POINT& aPoint, int aNet shape = (SHAPE*) (*aPadstack)[0]; DSN_T type = shape->shape->Type(); if( type != T_circle ) - ThrowIOError( _( "Unsupported via shape: \"%s\""), - GetChars( LEXER::GetTokenString( type ) ) ); + ThrowIOError( _( "Unsupported via shape: %s"), + GetChars( GetTokenString( type ) ) ); CIRCLE* circle = (CIRCLE*) shape->shape; int viaDiam = scale( circle->diameter, routeResolution ); @@ -299,8 +299,8 @@ SEGVIA* SPECCTRA_DB::makeVIA( PADSTACK* aPadstack, const POINT& aPoint, int aNet shape = (SHAPE*) (*aPadstack)[i]; DSN_T type = shape->shape->Type(); if( type != T_circle ) - ThrowIOError( _( "Unsupported via shape: \"%s\""), - GetChars( LEXER::GetTokenString( type ) ) ); + ThrowIOError( _( "Unsupported via shape: %s"), + GetChars( GetTokenString( type ) ) ); CIRCLE* circle = (CIRCLE*) shape->shape; @@ -473,7 +473,7 @@ void SPECCTRA_DB::FromSESSION( BOARD* aBoard ) throw( IOError ) wxString netId = CONV_FROM_UTF8( wire->net_id.c_str() ); ThrowIOError( _("Unsupported wire shape: \"%s\" for net: \"%s\""), - LEXER::GetTokenString(shape).GetData(), + DLEX::GetTokenString(shape).GetData(), netId.GetData() ); */