Commit 1f9ee2e4 authored by Dick Hollenbeck's avatar Dick Hollenbeck

Support for 'initial single line comments' in the pretty footprint format.

This is limited to round tripping the lines of commented text in the
loading and saving to disk through PCBIO::Format() and PCBIO::Parse().
No editing of the comments is given.
parent 2b25beb0
......@@ -50,7 +50,7 @@ static int compare( const void* a1, const void* a2 )
//-----<DSNLEXER>-------------------------------------------------------------
void DSNLEXER::init()
inline void DSNLEXER::init()
{
curTok = DSN_NONE;
prevTok = DSN_NONE;
......@@ -502,10 +502,16 @@ L_read:
{
if( commentsAreTokens )
{
// save the entire line, including new line as the current token.
// the '#' character may not be at offset zero.
curText = start; // entire line is the token
cur = start; // ensure a good curOffset below
// Grab the entire current line [excluding end of line char(s)] as the
// current token. The '#' character may not be at offset zero.
while( limit[-1] == '\n' || limit[-1] == '\r' )
--limit;
curText.clear();
curText.append( start, limit );
cur = start; // ensure a good curOffset below
curTok = DSN_COMMENT;
head = limit; // do a readLine() on next call in here.
goto exit;
......@@ -739,3 +745,23 @@ exit: // single point of exit, no returns elsewhere please.
return curTok;
}
wxArrayString* DSNLEXER::ReadCommentLines() throw( IO_ERROR )
{
wxArrayString* ret = 0;
bool cmt_setting = SetCommentsAreTokens( true );
int tok = NextTok();
if( tok == DSN_COMMENT )
{
ret = new wxArrayString();
do
ret->Add( FromUTF8() );
while( ( tok = NextTok() ) == DSN_COMMENT );
}
SetCommentsAreTokens( cmt_setting );
return ret;
}
......@@ -101,12 +101,12 @@ protected:
bool commentsAreTokens; ///< true if should return comments as tokens
int prevTok; ///< curTok from previous NextTok() call.
int curOffset; ///< offset within current line of the current token
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
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;
......@@ -368,6 +368,19 @@ public:
return old;
}
/**
* Function ReadCommentLines
* checks the next sequence of tokens and reads them into a wxArrayString
* if they are comments. Reading continues until a non-comment token is
* encountered, and such last read token remains as CurTok() and as CurText().
* No push back or "un get" mechanism is used for this support. Upon return
* you simply avoid calling NextTok() for the next token, but rather CurTok().
*
* @return wxArrayString* - heap allocated block of comments, or NULL if none;
* caller owns the allocation and must delete if not NULL.
*/
wxArrayString* ReadCommentLines() throw( IO_ERROR );
/**
* Function IsSymbol
* tests a token to see if it is a symbol. This means it cannot be a
......
......@@ -53,7 +53,8 @@
MODULE::MODULE( BOARD* parent ) :
BOARD_ITEM( (BOARD_ITEM*) parent, PCB_MODULE_T )
BOARD_ITEM( (BOARD_ITEM*) parent, PCB_MODULE_T ),
m_initial_comments( 0 )
{
m_Attributs = MOD_DEFAULT;
m_Layer = LAYER_N_FRONT;
......@@ -82,7 +83,8 @@ MODULE::MODULE( BOARD* parent ) :
MODULE::MODULE( const MODULE& aModule ) :
BOARD_ITEM( aModule )
BOARD_ITEM( aModule ),
m_initial_comments( 0 )
{
m_Pos = aModule.m_Pos;
m_LibRef = aModule.m_LibRef;
......@@ -171,6 +173,7 @@ MODULE::~MODULE()
{
delete m_Reference;
delete m_Value;
delete m_initial_comments;
}
......@@ -185,7 +188,7 @@ void MODULE::DrawAncre( EDA_DRAW_PANEL* panel, wxDC* DC, const wxPoint& offset,
if( GetBoard()->IsElementVisible( ANCHOR_VISIBLE ) )
{
GRDrawAnchor( panel->GetClipBox(), DC, m_Pos.x, m_Pos.y,
GRDrawAnchor( panel->GetClipBox(), DC, m_Pos.x, m_Pos.y,
dim_ancre,
g_ColorsSettings.GetItemColor( ANCHOR_VISIBLE ) );
}
......
......@@ -473,6 +473,30 @@ public:
*/
static const wxChar* ReturnStringLibNameInvalidChars( bool aUserReadable );
/**
* Function SetInitialComments
* takes ownership of caller's heap allocated aInitialComments block. The comments
* are single line strings already containing the s-expression comments with
* optional leading whitespace and then a '#' character followed by optional
* single line text (text with no line endings, not even one).
* This block of single line comments will be output upfront of any generated
* s-expression text in the PCBIO::Format() function.
* <p>
* Note that a block of single line comments constitutes a multiline block of
* single line comments. That is, the block is made of consecutive single line
* comments.
* @param aInitialComments is a heap allocated wxArrayString or NULL, which the caller
* gives up ownership of over to this MODULE.
*/
void SetInitialComments( wxArrayString* aInitialComments )
{
delete m_initial_comments;
m_initial_comments = aInitialComments;
}
/// Return the initial comments block or NULL if none, without transfer of ownership.
const wxArrayString* GetInitialComments() { return m_initial_comments; }
#if defined(DEBUG)
virtual void Show( int nestLevel, std::ostream& os ) const { ShowDummy( os ); } // override
#endif
......@@ -512,6 +536,9 @@ private:
int m_LocalSolderPasteMargin; ///< Solder paste margin absolute value
double m_LocalSolderPasteMarginRatio; ///< Solder mask margin ratio
///< value of pad size
wxArrayString* m_initial_comments; ///< leading s-expression comments in the module,
///< lazily allocated only if needed for speed
};
#endif // MODULE_H_
......@@ -881,6 +881,14 @@ void PCB_IO::format( PCB_TARGET* aTarget, int aNestLevel ) const
void PCB_IO::format( MODULE* aModule, int aNestLevel ) const
throw( IO_ERROR )
{
const wxArrayString* initial_comments = aModule->GetInitialComments();
if( initial_comments )
{
for( unsigned i=0; i<initial_comments->GetCount(); ++i )
m_out->Print( aNestLevel, "%s\n", TO_UTF8( (*initial_comments)[i] ) );
}
m_out->Print( aNestLevel, "(module %s", m_out->Quotew( aModule->GetLibRef() ).c_str() );
if( aModule->IsLocked() )
......
......@@ -328,11 +328,16 @@ S3D_MASTER* PCB_PARSER::parse3DModel() throw( PARSE_ERROR )
BOARD_ITEM* PCB_PARSER::Parse() throw( IO_ERROR, PARSE_ERROR )
{
T token;
BOARD_ITEM* item;
LOCALE_IO toggle; // toggles on, then off, the C locale.
T token;
BOARD_ITEM* item;
LOCALE_IO toggle;
token = NextTok();
// MODULEs can be prefixed with an initial block of single line comments and these
// are kept for Format() so they round trip in s-expression form. BOARDs might
// eventually do the same, but currently do not.
std::auto_ptr<wxArrayString> initial_comments( ReadCommentLines() );
token = CurTok();
if( token != T_LEFT )
Expecting( T_LEFT );
......@@ -347,7 +352,7 @@ BOARD_ITEM* PCB_PARSER::Parse() throw( IO_ERROR, PARSE_ERROR )
break;
case T_module:
item = (BOARD_ITEM*) parseMODULE();
item = (BOARD_ITEM*) parseMODULE( initial_comments.release() );
break;
default:
......@@ -1514,7 +1519,7 @@ DIMENSION* PCB_PARSER::parseDIMENSION() throw( IO_ERROR, PARSE_ERROR )
}
MODULE* PCB_PARSER::parseMODULE() throw( IO_ERROR, PARSE_ERROR )
MODULE* PCB_PARSER::parseMODULE( wxArrayString* aInitialComments ) throw( IO_ERROR, PARSE_ERROR )
{
wxCHECK_MSG( CurTok() == T_module, NULL,
wxT( "Cannot parse " ) + GetTokenString( CurTok() ) + wxT( " as MODULE." ) );
......@@ -1524,6 +1529,8 @@ MODULE* PCB_PARSER::parseMODULE() throw( IO_ERROR, PARSE_ERROR )
auto_ptr< MODULE > module( new MODULE( m_board ) );
module->SetInitialComments( aInitialComments );
NeedSYMBOLorNUMBER();
module->SetLibRef( FromUTF8() );
......
......@@ -82,18 +82,26 @@ class PCB_PARSER : public PCB_LEXER
void parseSetup() throw( IO_ERROR, PARSE_ERROR );
void parseNETINFO_ITEM() throw( IO_ERROR, PARSE_ERROR );
void parseNETCLASS() throw( IO_ERROR, PARSE_ERROR );
DRAWSEGMENT* parseDRAWSEGMENT() throw( IO_ERROR, PARSE_ERROR );
TEXTE_PCB* parseTEXTE_PCB() throw( IO_ERROR, PARSE_ERROR );
DIMENSION* parseDIMENSION() throw( IO_ERROR, PARSE_ERROR );
MODULE* parseMODULE() throw( IO_ERROR, PARSE_ERROR );
TEXTE_MODULE* parseTEXTE_MODULE() throw( IO_ERROR, PARSE_ERROR );
EDGE_MODULE* parseEDGE_MODULE() throw( IO_ERROR, PARSE_ERROR );
D_PAD* parseD_PAD() throw( IO_ERROR, PARSE_ERROR );
TRACK* parseTRACK() throw( IO_ERROR, PARSE_ERROR );
SEGVIA* parseSEGVIA() throw( IO_ERROR, PARSE_ERROR );
DRAWSEGMENT* parseDRAWSEGMENT() throw( IO_ERROR, PARSE_ERROR );
TEXTE_PCB* parseTEXTE_PCB() throw( IO_ERROR, PARSE_ERROR );
DIMENSION* parseDIMENSION() throw( IO_ERROR, PARSE_ERROR );
/**
* Function parseModule
* @param aInitialComments may be a pointer to a heap allocated initial comment block
* or NULL. If not NULL, then caller has given ownership of a wxArrayString to
* this function and care must be taken to delete it even on exception.
*/
MODULE* parseMODULE( wxArrayString* aInitialComments = 0 ) throw( IO_ERROR, PARSE_ERROR );
TEXTE_MODULE* parseTEXTE_MODULE() throw( IO_ERROR, PARSE_ERROR );
EDGE_MODULE* parseEDGE_MODULE() throw( IO_ERROR, PARSE_ERROR );
D_PAD* parseD_PAD() throw( IO_ERROR, PARSE_ERROR );
TRACK* parseTRACK() throw( IO_ERROR, PARSE_ERROR );
SEGVIA* parseSEGVIA() throw( IO_ERROR, PARSE_ERROR );
ZONE_CONTAINER* parseZONE_CONTAINER() throw( IO_ERROR, PARSE_ERROR );
PCB_TARGET* parsePCB_TARGET() throw( IO_ERROR, PARSE_ERROR );
BOARD* parseBOARD() throw( IO_ERROR, PARSE_ERROR );
PCB_TARGET* parsePCB_TARGET() throw( IO_ERROR, PARSE_ERROR );
BOARD* parseBOARD() throw( IO_ERROR, PARSE_ERROR );
/**
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment