diff --git a/common/filter_reader.cpp b/common/filter_reader.cpp index f97172846f..20f58ceb62 100644 --- a/common/filter_reader.cpp +++ b/common/filter_reader.cpp @@ -27,14 +27,41 @@ #include #include -unsigned FILTER_READER::ReadLine() throw( IO_ERROR ) -{ - unsigned ret; - while( ( ret = reader.ReadLine() ) != 0 ) +FILTER_READER::FILTER_READER( LINE_READER& aReader ) : + LINE_READER( 1 ), + reader( aReader ) +{ + // Not using our own line buffer, will be using aReader's. This changes + // the meaning of this->line to be merely a pointer to aReader's line, which of course + // is not owned here. + delete [] line; + + line = 0; +} + + +FILTER_READER::~FILTER_READER() +{ + // Our 'line' points to aReader's, and he will delete that buffer. + // Prevent subsequent call to ~LINE_READER() from deleting a buffer we do not own. + line = 0; +} + + +char* FILTER_READER::ReadLine() throw( IO_ERROR ) +{ + char* s; + + while( ( s = reader.ReadLine() ) != NULL ) { - if( !strchr( "#\n\r", reader[0] ) ) + if( !strchr( "#\n\r", s[0] ) ) break; } - return ret; + + line = reader.Line(); + length = reader.Length(); + + return length ? line : NULL; } + diff --git a/common/richio.cpp b/common/richio.cpp index ca3dcae702..19ccb838f7 100644 --- a/common/richio.cpp +++ b/common/richio.cpp @@ -64,6 +64,12 @@ LINE_READER::LINE_READER( unsigned aMaxLineLength ) } +LINE_READER::~LINE_READER() +{ + delete[] line; +} + + void LINE_READER::expandCapacity( unsigned newsize ) { // length can equal maxLineLength and nothing breaks, there's room for @@ -134,40 +140,8 @@ FILE_LINE_READER::~FILE_LINE_READER() fclose( fp ); } -#if 0 -// The strlen() will trip on embedded nuls which can come in via bad data files. -// Try an alternate technique below. - -unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR ) -{ - length = 0; - line[0] = 0; - - // fgets always puts a terminating nul at end of its read. - while( fgets( line + length, capacity - length, fp ) ) - { - length += strlen( line + length ); - - if( length >= maxLineLength ) - THROW_IO_ERROR( _("Line length exceeded") ); - - // a normal line breaks here, once through while loop - if( length+1 < capacity || line[length-1] == '\n' ) - break; - - expandCapacity( capacity * 2 ); - } - - // lineNum is incremented even if there was no line read, because this - // leads to better error reporting when we hit an end of file. - ++lineNum; - - return length; -} - -#else -unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR ) +char* FILE_LINE_READER::ReadLine() throw( IO_ERROR ) { length = 0; @@ -196,9 +170,8 @@ unsigned FILE_LINE_READER::ReadLine() throw( IO_ERROR ) // leads to better error reporting when we hit an end of file. ++lineNum; - return length; + return length ? line : NULL; } -#endif STRING_LINE_READER::STRING_LINE_READER( const std::string& aString, const wxString& aSource ) : @@ -224,7 +197,8 @@ STRING_LINE_READER::STRING_LINE_READER( const STRING_LINE_READER& aStartingPoint lineNum = aStartingPoint.lineNum; } -unsigned STRING_LINE_READER::ReadLine() throw( IO_ERROR ) + +char* STRING_LINE_READER::ReadLine() throw( IO_ERROR ) { size_t nlOffset = lines.find( '\n', ndx ); @@ -252,7 +226,7 @@ unsigned STRING_LINE_READER::ReadLine() throw( IO_ERROR ) line[length] = 0; - return length; + return length ? line : NULL; } @@ -263,7 +237,7 @@ INPUTSTREAM_LINE_READER::INPUTSTREAM_LINE_READER( wxInputStream* aStream ) : } -unsigned INPUTSTREAM_LINE_READER::ReadLine() throw( IO_ERROR ) +char* INPUTSTREAM_LINE_READER::ReadLine() throw( IO_ERROR ) { length = 0; @@ -293,7 +267,7 @@ unsigned INPUTSTREAM_LINE_READER::ReadLine() throw( IO_ERROR ) // leads to better error reporting when we hit an end of file. ++lineNum; - return length; + return length ? line : NULL; } diff --git a/include/dsnlexer.h b/include/dsnlexer.h index aa3c3e99b1..35da414b6a 100644 --- a/include/dsnlexer.h +++ b/include/dsnlexer.h @@ -117,7 +117,9 @@ protected: { if( reader ) { - unsigned len = reader->ReadLine(); + reader->ReadLine(); + + unsigned len = reader->Length(); // start may have changed in ReadLine(), which can resize and // relocate reader's line buffer. diff --git a/include/filter_reader.h b/include/filter_reader.h index 51240c8d4f..84aa14fc59 100644 --- a/include/filter_reader.h +++ b/include/filter_reader.h @@ -45,32 +45,21 @@ public: * Constructor ( LINE_READER& ) * does not take ownership over @a aReader, so will not destroy it. */ - FILTER_READER( LINE_READER& aReader ) : - reader( aReader ) - { - } + FILTER_READER( LINE_READER& aReader ); - unsigned ReadLine() throw( IO_ERROR ); + ~FILTER_READER(); + + char* ReadLine() throw( IO_ERROR ); const wxString& GetSource() const { return reader.GetSource(); } - char* Line() const - { - return reader.Line(); - } - unsigned LineNumber() const { return reader.LineNumber(); } - - unsigned Length() const - { - return reader.Length(); - } }; #endif // FILTER_READER_H_ diff --git a/include/richio.h b/include/richio.h index e3ff677773..14411aee4d 100644 --- a/include/richio.h +++ b/include/richio.h @@ -227,20 +227,17 @@ public: */ LINE_READER( unsigned aMaxLineLength = LINE_READER_LINE_DEFAULT_MAX ); - virtual ~LINE_READER() - { - delete[] line; - } + virtual ~LINE_READER(); /** * Function ReadLine * reads a line of text into the buffer and increments the line number * counter. If the line is larger than aMaxLineLength passed to the * constructor, then an exception is thrown. The line is nul terminated. - * @return unsigned - The number of bytes read, 0 at end of file. + * @return char* - The beginning of the read line, or NULL if EOF. * @throw IO_ERROR when a line is too long. */ - virtual unsigned ReadLine() throw( IO_ERROR ) = 0; + virtual char* ReadLine() throw( IO_ERROR ) = 0; /** * Function GetSource @@ -258,7 +255,7 @@ public: * Function Line * returns a pointer to the last line that was read in. */ - virtual char* Line() const + char* Line() const { return line; } @@ -287,7 +284,7 @@ public: * Function Length * returns the number of bytes in the last line read from this LINE_READER. */ - virtual unsigned Length() const + unsigned Length() const { return length; } @@ -354,7 +351,7 @@ public: */ ~FILE_LINE_READER(); - unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description + char* ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description /** * Function Rewind @@ -401,7 +398,7 @@ public: */ STRING_LINE_READER( const STRING_LINE_READER& aStartingPoint ); - unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description + char* ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description }; @@ -423,7 +420,7 @@ public: */ INPUTSTREAM_LINE_READER( wxInputStream* aStream ); - unsigned ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description + char* ReadLine() throw( IO_ERROR ); // see LINE_READER::ReadLine() description }; diff --git a/pcbnew/legacy_plugin.cpp b/pcbnew/legacy_plugin.cpp index e7505df754..258579bd87 100644 --- a/pcbnew/legacy_plugin.cpp +++ b/pcbnew/legacy_plugin.cpp @@ -127,9 +127,9 @@ static bool inline isSpace( int c ) { return strchr( delims, c ) != 0; } /// The function and macro which follow comprise a shim which can be a /// monitor on lines of text read in from the input file. /// And it can be used as a trap. -static inline unsigned ReadLine( LINE_READER* rdr, const char* caller ) +static inline char* ReadLine( LINE_READER* rdr, const char* caller ) { - unsigned ret = rdr->ReadLine(); + char* ret = rdr->ReadLine(); const char* line = rdr->Line(); printf( "%-6u %s: %s", rdr->LineNumber(), caller, line ); @@ -268,11 +268,10 @@ void LEGACY_PLUGIN::loadAllSections( bool doAppend ) // $SETUP section is next // Then follows $EQUIPOT and all the rest + char* line; - while( READLINE( m_reader ) ) + while( ( line = READLINE( m_reader ) ) != NULL ) { - char* line = m_reader->Line(); - // put the more frequent ones at the top, but realize TRACKs are loaded as a group if( TESTLINE( "$MODULE" ) ) @@ -344,10 +343,9 @@ void LEGACY_PLUGIN::loadAllSections( bool doAppend ) } else { - while( READLINE( m_reader ) ) + while( ( line = READLINE( m_reader ) ) != NULL ) { - line = m_reader->Line(); // gobble until $EndSetup - + // gobble until $EndSetup if( TESTLINE( "$EndSETUP" ) ) break; } @@ -395,9 +393,10 @@ void LEGACY_PLUGIN::checkVersion() void LEGACY_PLUGIN::loadGENERAL() { - while( READLINE( m_reader ) ) + char* line; + + while( ( line = READLINE( m_reader ) ) != NULL ) { - char* line = m_reader->Line(); const char* data; if( TESTLINE( "Units" ) ) @@ -516,11 +515,10 @@ void LEGACY_PLUGIN::loadSHEET() { char buf[260]; TITLE_BLOCK tb; + char* line; - while( READLINE( m_reader ) ) + while( ( line = READLINE( m_reader ) ) != NULL ) { - char* line = m_reader->Line(); - if( TESTLINE( "Sheet" ) ) { // e.g. "Sheet A3 16535 11700" @@ -628,14 +626,14 @@ void LEGACY_PLUGIN::loadSHEET() void LEGACY_PLUGIN::loadSETUP() { - NETCLASS* netclass_default = m_board->m_NetClasses.GetDefault(); + NETCLASS* netclass_default = m_board->m_NetClasses.GetDefault(); BOARD_DESIGN_SETTINGS bds = m_board->GetDesignSettings(); ZONE_SETTINGS zs = m_board->GetZoneSettings(); + char* line; - while( READLINE( m_reader ) ) + while( ( line = READLINE( m_reader ) ) != NULL ) { const char* data; - char* line = m_reader->Line(); if( TESTLINE( "PcbPlotParams" ) ) { @@ -928,12 +926,11 @@ void LEGACY_PLUGIN::loadSETUP() MODULE* LEGACY_PLUGIN::LoadMODULE() { - auto_ptr module( new MODULE( m_board ) ); + auto_ptr module( new MODULE( m_board ) ); + char* line; - while( READLINE( m_reader ) ) + while( ( line = READLINE( m_reader ) ) != NULL ) { - char* line = m_reader->Line(); - const char* data; // most frequently encountered ones at the top @@ -1139,11 +1136,11 @@ MODULE* LEGACY_PLUGIN::LoadMODULE() void LEGACY_PLUGIN::loadPAD( MODULE* aModule ) { auto_ptr pad( new D_PAD( aModule ) ); + char* line; - while( READLINE( m_reader ) ) + while( ( line = READLINE( m_reader ) ) != NULL ) { const char* data; - char* line = m_reader->Line(); if( TESTLINE( "Sh" ) ) // (Sh)ape and padname { @@ -1450,13 +1447,11 @@ void LEGACY_PLUGIN::loadMODULE_EDGE( MODULE* aModule ) for( int ii = 0; iiLine(); - // e.g. "Dl 23 44\n" if( !TESTLINE( "Dl" ) ) @@ -1625,10 +1620,9 @@ void LEGACY_PLUGIN::load3D( MODULE* aModule ) t3D = n3D; } - while( READLINE( m_reader ) ) + char* line; + while( ( line = READLINE( m_reader ) ) != NULL ) { - char* line = m_reader->Line(); - if( TESTLINE( "Na" ) ) // Shape File Name { char buf[512]; @@ -1677,12 +1671,12 @@ void LEGACY_PLUGIN::loadPCB_LINE() $EndDRAWSEGMENT */ - auto_ptr dseg( new DRAWSEGMENT( m_board ) ); + auto_ptr dseg( new DRAWSEGMENT( m_board ) ); + char* line; - while( READLINE( m_reader ) ) + while( ( line = READLINE( m_reader ) ) != NULL ) { const char* data; - char* line = m_reader->Line(); if( TESTLINE( "Po" ) ) { @@ -1783,12 +1777,12 @@ void LEGACY_PLUGIN::loadNETINFO_ITEM() { char buf[1024]; - NETINFO_ITEM* net = new NETINFO_ITEM( m_board ); + NETINFO_ITEM* net = new NETINFO_ITEM( m_board ); + char* line; - while( READLINE( m_reader ) ) + while( ( line = READLINE( m_reader ) ) != NULL ) { const char* data; - char* line = m_reader->Line(); if( TESTLINE( "Na" ) ) { @@ -1842,13 +1836,14 @@ void LEGACY_PLUGIN::loadPCB_TEXT() char text[1024]; // maybe someday a constructor that takes all this data in one call? - TEXTE_PCB* pcbtxt = new TEXTE_PCB( m_board ); + TEXTE_PCB* pcbtxt = new TEXTE_PCB( m_board ); m_board->Add( pcbtxt, ADD_APPEND ); - while( READLINE( m_reader ) ) + char* line; + + while( ( line = READLINE( m_reader ) ) != NULL ) { const char* data; - char* line = m_reader->Line(); if( TESTLINE( "Te" ) ) // Text line (or first line for multi line texts) { @@ -1947,7 +1942,9 @@ void LEGACY_PLUGIN::loadPCB_TEXT() void LEGACY_PLUGIN::loadTrackList( int aStructType ) { - while( READLINE( m_reader ) ) + char* line; + + while( ( line = READLINE( m_reader ) ) != NULL ) { // read two lines per loop iteration, each loop is one TRACK or VIA // example first line: @@ -1955,7 +1952,6 @@ void LEGACY_PLUGIN::loadTrackList( int aStructType ) // e.g. "Po 3 21086 17586 21086 17586 180 -1" for a via (uses sames start and end) const char* data; - char* line = m_reader->Line(); if( line[0] == '$' ) // $EndTRACK return; // preferred exit @@ -2065,6 +2061,7 @@ void LEGACY_PLUGIN::loadNETCLASS() { char buf[1024]; wxString netname; + char* line; // create an empty NETCLASS without a name, but do not add it to the BOARD // yet since that would bypass duplicate netclass name checking within the BOARD. @@ -2072,10 +2069,8 @@ void LEGACY_PLUGIN::loadNETCLASS() // just before returning. auto_ptr nc( new NETCLASS( m_board, wxEmptyString ) ); - while( READLINE( m_reader ) ) + while( ( line = READLINE( m_reader ) ) != NULL ) { - char* line = m_reader->Line(); - if( TESTLINE( "AddNet" ) ) // most frequent type of line { // e.g. "AddNet "V3.3D"\n" @@ -2164,11 +2159,11 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER() CPolyLine::HATCH_STYLE outline_hatch = CPolyLine::NO_HATCH; bool sawCorner = false; char buf[1024]; + char* line; - while( READLINE( m_reader ) ) + while( ( line = READLINE( m_reader ) ) != NULL ) { const char* data; - char* line = m_reader->Line(); if( TESTLINE( "ZCorner" ) ) // new corner found { @@ -2349,10 +2344,8 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER() // Read the PolysList (polygons used for fill areas in the zone) std::vector polysList; - while( READLINE( m_reader ) ) + while( ( line = READLINE( m_reader ) ) != NULL ) { - line = m_reader->Line(); - if( TESTLINE( "$endPOLYSCORNERS" ) ) break; @@ -2370,10 +2363,8 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER() else if( TESTLINE( "$FILLSEGMENTS" ) ) { - while( READLINE( m_reader ) ) + while( ( line = READLINE( m_reader ) ) != NULL ) { - line = m_reader->Line(); - if( TESTLINE( "$endFILLSEGMENTS" ) ) break; @@ -2422,11 +2413,11 @@ void LEGACY_PLUGIN::loadZONE_CONTAINER() void LEGACY_PLUGIN::loadDIMENSION() { auto_ptr dim( new DIMENSION( m_board ) ); + char* line; - while( READLINE( m_reader ) ) + while( ( line = READLINE( m_reader ) ) != NULL ) { const char* data; - char* line = m_reader->Line(); if( TESTLINE( "$endCOTATION" ) ) { @@ -2617,10 +2608,11 @@ void LEGACY_PLUGIN::loadDIMENSION() void LEGACY_PLUGIN::loadPCB_TARGET() { - while( READLINE( m_reader ) ) + char* line; + + while( ( line = READLINE( m_reader ) ) != NULL ) { const char* data; - char* line = m_reader->Line(); if( TESTLINE( "$EndPCB_TARGET" ) || TESTLINE( "$EndMIREPCB" ) ) { @@ -3951,18 +3943,16 @@ void FPL_CACHE::Load() void FPL_CACHE::ReadAndVerifyHeader( LINE_READER* aReader ) { - char* line; + char* line = aReader->ReadLine(); - if( !aReader->ReadLine() ) + if( !line ) goto L_bad_library; - line = aReader->Line(); if( !TESTLINE( "PCBNEW-LibModule-V1" ) ) goto L_bad_library; - while( aReader->ReadLine() ) + while( ( line = aReader->ReadLine() ) != NULL ) { - line = aReader->Line(); if( TESTLINE( "Units" ) ) { const char* units = strtok( line + SZ( "Units" ), delims ); @@ -3992,20 +3982,17 @@ void FPL_CACHE::SkipIndex( LINE_READER* aReader ) // Some broken INDEX sections have more than one section, due to prior bugs. // So we must read the next line after $EndINDEX tag, // to see if this is not a new $INDEX tag. - bool exit = false; + bool exit = false; + char* line = aReader->Line(); do { - char* line = aReader->Line(); - if( TESTLINE( "$INDEX" ) ) { exit = false; - while( aReader->ReadLine() ) + while( ( line = aReader->ReadLine() ) != NULL ) { - line = aReader->Line(); - if( TESTLINE( "$EndINDEX" ) ) { exit = true; @@ -4015,7 +4002,7 @@ void FPL_CACHE::SkipIndex( LINE_READER* aReader ) } else if( exit ) break; - } while( aReader->ReadLine() ); + } while( ( line = aReader->ReadLine() ) != NULL ); } @@ -4023,11 +4010,11 @@ void FPL_CACHE::LoadModules( LINE_READER* aReader ) { m_owner->SetReader( aReader ); + char* line = aReader->Line(); + do { // test first for the $MODULE, even before reading because of INDEX bug. - char* line = aReader->Line(); - if( TESTLINE( "$MODULE" ) ) { MODULE* m = m_owner->LoadMODULE(); @@ -4089,7 +4076,7 @@ void FPL_CACHE::LoadModules( LINE_READER* aReader ) } } - } while( aReader->ReadLine() ); + } while( ( line = aReader->ReadLine() ) != NULL ); } diff --git a/pcbnew/netlist_reader_firstformat.cpp b/pcbnew/netlist_reader_firstformat.cpp index 2b6f93bd43..fcb3072d07 100644 --- a/pcbnew/netlist_reader_firstformat.cpp +++ b/pcbnew/netlist_reader_firstformat.cpp @@ -365,25 +365,24 @@ bool NETLIST_READER::SetPadNetName( char* aText ) */ bool NETLIST_READER::ReadOldFmtFootprintFilterList( FILE_LINE_READER& aNetlistReader ) { - wxString cmpRef; + wxString cmpRef; COMPONENT_INFO* cmp_info = NULL; + char* line; - while( aNetlistReader.ReadLine() ) + while( ( line = aNetlistReader.ReadLine() ) != NULL ) { - const char* Line = aNetlistReader.Line(); - - if( strnicmp( Line, "$endlist", 8 ) == 0 ) // end of list for the current component + if( strnicmp( line, "$endlist", 8 ) == 0 ) // end of list for the current component { cmp_info = NULL; continue; } - if( strnicmp( Line, "$endfootprintlist", 4 ) == 0 ) + if( strnicmp( line, "$endfootprintlist", 4 ) == 0 ) // End of this section return 0; - if( strnicmp( Line, "$component", 10 ) == 0 ) // New component reference found + if( strnicmp( line, "$component", 10 ) == 0 ) // New component reference found { - cmpRef = FROM_UTF8( Line + 11 ); + cmpRef = FROM_UTF8( line + 11 ); cmpRef.Trim( true ); cmpRef.Trim( false ); @@ -400,7 +399,7 @@ bool NETLIST_READER::ReadOldFmtFootprintFilterList( FILE_LINE_READER& aNetlistR else if( cmp_info ) { // Add new filter to list - wxString fp = FROM_UTF8( Line + 1 ); + wxString fp = FROM_UTF8( line + 1 ); fp.Trim( false ); fp.Trim( true ); cmp_info->m_FootprintFilter.Add( fp );