diff --git a/eeschema/CMakeLists.txt b/eeschema/CMakeLists.txt index a0ac2fec17..7db0b4903a 100644 --- a/eeschema/CMakeLists.txt +++ b/eeschema/CMakeLists.txt @@ -249,6 +249,7 @@ set( EESCHEMA_SRCS sch_plugins/kicad/sch_sexpr_parser.cpp sch_plugins/kicad/sch_sexpr_plugin.cpp sch_plugins/legacy/sch_legacy_plugin.cpp + sch_plugins/legacy/sch_legacy_plugin_helpers.cpp # Simulator settings must get built even when the simulator build option is disabled. sim/spice_settings.cpp diff --git a/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp b/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp index 4303360234..27362bd29a 100644 --- a/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp +++ b/eeschema/sch_plugins/legacy/sch_legacy_plugin.cpp @@ -54,6 +54,7 @@ #include #include #include +#include #include #include #include @@ -88,15 +89,6 @@ #define USE_OLD_DOC_FILE_FORMAT( major, minor ) \ ( LIB_VERSION( major, minor ) <= LIB_VERSION( 2, 4 ) ) - -#define SCH_PARSE_ERROR( text, reader, pos ) \ - THROW_PARSE_ERROR( text, reader.GetSource(), reader.Line(), \ - reader.LineNumber(), pos - reader.Line() ) - - -// Token delimiters. -const char* delims = " \t\r\n"; - // Tokens to read/save graphic lines style #define T_STYLE "style" #define T_COLOR "rgb" // cannot be modified (used by wxWidgets) @@ -104,381 +96,6 @@ const char* delims = " \t\r\n"; #define T_WIDTH "width" -static bool is_eol( char c ) -{ - // The default file eol character used internally by KiCad. - // | - // | Possible eol if someone edited the file by hand on certain platforms. - // | | - // | | May have gone past eol with strtok(). - // | | | - if( c == '\n' || c == '\r' || c == 0 ) - return true; - - return false; -} - - -/** - * Compare \a aString to the string starting at \a aLine and advances the character point to - * the end of \a String and returns the new pointer position in \a aOutput if it is not NULL. - * - * @param aString - A pointer to the string to compare. - * @param aLine - A pointer to string to begin the comparison. - * @param aOutput - A pointer to a string pointer to the end of the comparison if not NULL. - * @return true if \a aString was found starting at \a aLine. Otherwise false. - */ -static bool strCompare( const char* aString, const char* aLine, const char** aOutput = nullptr ) -{ - size_t len = strlen( aString ); - bool retv = ( strncasecmp( aLine, aString, len ) == 0 ) && - ( isspace( aLine[ len ] ) || aLine[ len ] == 0 ); - - if( retv && aOutput ) - { - const char* tmp = aLine; - - // Move past the end of the token. - tmp += len; - - // Move to the beginning of the next token. - while( *tmp && isspace( *tmp ) ) - tmp++; - - *aOutput = tmp; - } - - return retv; -} - - -/** - * Parse an ASCII integer string with possible leading whitespace into - * an integer and updates the pointer at \a aOutput if it is not NULL, just - * like "man strtol()". - * - * @param aReader - The line reader used to generate exception throw information. - * @param aLine - A pointer the current position in a string. - * @param aOutput - The pointer to a string pointer to copy the string pointer position when - * the parsing is complete. - * @return A valid integer value. - * @throw An #IO_ERROR on an unexpected end of line. - * @throw A #PARSE_ERROR if the parsed token is not a valid integer. - */ -static int parseInt( LINE_READER& aReader, const char* aLine, const char** aOutput = nullptr ) -{ - if( !*aLine ) - SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aLine ); - - // Clear errno before calling strtol() in case some other crt call set it. - errno = 0; - - long retv = strtol( aLine, (char**) aOutput, 10 ); - - // Make sure no error occurred when calling strtol(). - if( errno == ERANGE ) - SCH_PARSE_ERROR( "invalid integer value", aReader, aLine ); - - // strtol does not strip off whitespace before the next token. - if( aOutput ) - { - const char* next = *aOutput; - - while( *next && isspace( *next ) ) - next++; - - *aOutput = next; - } - - return (int) retv; -} - - -/** - * Parse an ASCII hex integer string with possible leading whitespace into - * a long integer and updates the pointer at \a aOutput if it is not NULL, just - * like "man strtoll". - * - * @param aReader - The line reader used to generate exception throw information. - * @param aLine - A pointer the current position in a string. - * @param aOutput - The pointer to a string pointer to copy the string pointer position when - * the parsing is complete. - * @return A valid uint32_t value. - * @throw IO_ERROR on an unexpected end of line. - * @throw PARSE_ERROR if the parsed token is not a valid integer. - */ -static uint32_t parseHex( LINE_READER& aReader, const char* aLine, const char** aOutput = nullptr ) -{ - if( !*aLine ) - SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aLine ); - - // Due to some issues between some files created by a 64 bits version and those - // created by a 32 bits version, we use here a temporary at least 64 bits storage: - unsigned long long retv; - - // Clear errno before calling strtoull() in case some other crt call set it. - errno = 0; - retv = strtoull( aLine, (char**) aOutput, 16 ); - - // Make sure no error occurred when calling strtoull(). - if( errno == ERANGE ) - SCH_PARSE_ERROR( "invalid hexadecimal number", aReader, aLine ); - - // Strip off whitespace before the next token. - if( aOutput ) - { - const char* next = *aOutput; - - while( *next && isspace( *next ) ) - next++; - - *aOutput = next; - } - - return (uint32_t)retv; -} - - -/** - * Parses an ASCII point string with possible leading whitespace into a double precision - * floating point number and updates the pointer at \a aOutput if it is not NULL, just - * like "man strtod". - * - * @param aReader - The line reader used to generate exception throw information. - * @param aLine - A pointer the current position in a string. - * @param aOutput - The pointer to a string pointer to copy the string pointer position when - * the parsing is complete. - * @return A valid double value. - * @throw IO_ERROR on an unexpected end of line. - * @throw PARSE_ERROR if the parsed token is not a valid integer. - */ -static double parseDouble( LINE_READER& aReader, const char* aLine, - const char** aOutput = nullptr ) -{ - if( !*aLine ) - SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aLine ); - - // Clear errno before calling strtod() in case some other crt call set it. - errno = 0; - - double retv = strtod( aLine, (char**) aOutput ); - - // Make sure no error occurred when calling strtod(). - if( errno == ERANGE ) - SCH_PARSE_ERROR( "invalid floating point number", aReader, aLine ); - - // strtod does not strip off whitespace before the next token. - if( aOutput ) - { - const char* next = *aOutput; - - while( *next && isspace( *next ) ) - next++; - - *aOutput = next; - } - - return retv; -} - - -/** - * Parse a single ASCII character and updates the pointer at \a aOutput if it is not NULL. - * - * @param aReader - The line reader used to generate exception throw information. - * @param aCurrentToken - A pointer the current position in a string. - * @param aNextToken - The pointer to a string pointer to copy the string pointer position when - * the parsing is complete. - * @return A valid ASCII character. - * @throw IO_ERROR on an unexpected end of line. - * @throw PARSE_ERROR if the parsed token is not a single character token. - */ -static char parseChar( LINE_READER& aReader, const char* aCurrentToken, - const char** aNextToken = nullptr ) -{ - while( *aCurrentToken && isspace( *aCurrentToken ) ) - aCurrentToken++; - - if( !*aCurrentToken ) - SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aCurrentToken ); - - if( !isspace( *( aCurrentToken + 1 ) ) ) - SCH_PARSE_ERROR( "expected single character token", aReader, aCurrentToken ); - - if( aNextToken ) - { - const char* next = aCurrentToken + 2; - - while( *next && isspace( *next ) ) - next++; - - *aNextToken = next; - } - - return *aCurrentToken; -} - - -/** - * Parse an unquoted utf8 string and updates the pointer at \a aOutput if it is not NULL. - * - * The parsed string must be a continuous string with no white space. - * - * @param aString - A reference to the parsed string. - * @param aReader - The line reader used to generate exception throw information. - * @param aCurrentToken - A pointer the current position in a string. - * @param aNextToken - The pointer to a string pointer to copy the string pointer position when - * the parsing is complete. - * @param aCanBeEmpty - True if the parsed string is optional. False if it is mandatory. - * @throw IO_ERROR on an unexpected end of line. - * @throw PARSE_ERROR if the \a aCanBeEmpty is false and no string was parsed. - */ -static void parseUnquotedString( wxString& aString, LINE_READER& aReader, - const char* aCurrentToken, const char** aNextToken = nullptr, - bool aCanBeEmpty = false ) -{ - if( !*aCurrentToken ) - { - if( aCanBeEmpty ) - return; - else - SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aCurrentToken ); - } - - const char* tmp = aCurrentToken; - - while( *tmp && isspace( *tmp ) ) - tmp++; - - if( !*tmp ) - { - if( aCanBeEmpty ) - return; - else - SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aCurrentToken ); - } - - std::string utf8; - - while( *tmp && !isspace( *tmp ) ) - utf8 += *tmp++; - - aString = FROM_UTF8( utf8.c_str() ); - - if( aString.IsEmpty() && !aCanBeEmpty ) - SCH_PARSE_ERROR( _( "expected unquoted string" ), aReader, aCurrentToken ); - - if( aNextToken ) - { - const char* next = tmp; - - while( *next && isspace( *next ) ) - next++; - - *aNextToken = next; - } -} - - -/** - * Parse an quoted ASCII utf8 and updates the pointer at \a aOutput if it is not NULL. - * - * The parsed string must be contained within a single line. There are no multi-line - * quoted strings in the legacy schematic file format. - * - * @param aString - A reference to the parsed string. - * @param aReader - The line reader used to generate exception throw information. - * @param aCurrentToken - A pointer the current position in a string. - * @param aNextToken - The pointer to a string pointer to copy the string pointer position when - * the parsing is complete. - * @param aCanBeEmpty - True if the parsed string is optional. False if it is mandatory. - * @throw IO_ERROR on an unexpected end of line. - * @throw PARSE_ERROR if the \a aCanBeEmpty is false and no string was parsed. - */ -static void parseQuotedString( wxString& aString, LINE_READER& aReader, - const char* aCurrentToken, const char** aNextToken = nullptr, - bool aCanBeEmpty = false ) -{ - if( !*aCurrentToken ) - { - if( aCanBeEmpty ) - return; - else - SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aCurrentToken ); - } - - const char* tmp = aCurrentToken; - - while( *tmp && isspace( *tmp ) ) - tmp++; - - if( !*tmp ) - { - if( aCanBeEmpty ) - return; - else - SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aCurrentToken ); - } - - // Verify opening quote. - if( *tmp != '"' ) - SCH_PARSE_ERROR( "expecting opening quote", aReader, aCurrentToken ); - - tmp++; - - std::string utf8; // utf8 without escapes and quotes. - - // Fetch everything up to closing quote. - while( *tmp ) - { - if( *tmp == '\\' ) - { - tmp++; - - if( !*tmp ) - SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aCurrentToken ); - - // Do not copy the escape byte if it is followed by \ or " - if( *tmp != '"' && *tmp != '\\' ) - utf8 += '\\'; - - utf8 += *tmp; - } - else if( *tmp == '"' ) // Closing double quote. - { - break; - } - else - { - utf8 += *tmp; - } - - tmp++; - } - - aString = FROM_UTF8( utf8.c_str() ); - - if( aString.IsEmpty() && !aCanBeEmpty ) - SCH_PARSE_ERROR( "expected quoted string", aReader, aCurrentToken ); - - if( *tmp && *tmp != '"' ) - SCH_PARSE_ERROR( "no closing quote for string found", aReader, tmp ); - - // Move past the closing quote. - tmp++; - - if( aNextToken ) - { - const char* next = tmp; - - while( *next == ' ' ) - next++; - - *aNextToken = next; - } -} - - /** * A cache assistant for the symbol library portion of the #SCH_PLUGIN API, and only for the * #SCH_LEGACY_PLUGIN, so therefore is private to this implementation file, i.e. not placed diff --git a/eeschema/sch_plugins/legacy/sch_legacy_plugin_helpers.cpp b/eeschema/sch_plugins/legacy/sch_legacy_plugin_helpers.cpp new file mode 100644 index 0000000000..7994308071 --- /dev/null +++ b/eeschema/sch_plugins/legacy/sch_legacy_plugin_helpers.cpp @@ -0,0 +1,313 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 KiCad Developers, see AUTHORS.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, see . + */ + +#include +#include + +#include +#include + +#include "sch_legacy_plugin_helpers.h" + + +// Token delimiters. +const char* delims = " \t\r\n"; + + +bool is_eol( char c ) +{ + // The default file eol character used internally by KiCad. + // | + // | Possible eol if someone edited the file by hand on certain platforms. + // | | + // | | May have gone past eol with strtok(). + // | | | + if( c == '\n' || c == '\r' || c == 0 ) + return true; + + return false; +} + + +bool strCompare( const char* aString, const char* aLine, const char** aOutput ) +{ + size_t len = strlen( aString ); + bool retv = ( strncasecmp( aLine, aString, len ) == 0 ) && + ( isspace( aLine[ len ] ) || aLine[ len ] == 0 ); + + if( retv && aOutput ) + { + const char* tmp = aLine; + + // Move past the end of the token. + tmp += len; + + // Move to the beginning of the next token. + while( *tmp && isspace( *tmp ) ) + tmp++; + + *aOutput = tmp; + } + + return retv; +} + + +int parseInt( LINE_READER& aReader, const char* aLine, const char** aOutput ) +{ + if( !*aLine ) + SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aLine ); + + // Clear errno before calling strtol() in case some other crt call set it. + errno = 0; + + long retv = strtol( aLine, (char**) aOutput, 10 ); + + // Make sure no error occurred when calling strtol(). + if( errno == ERANGE ) + SCH_PARSE_ERROR( "invalid integer value", aReader, aLine ); + + // strtol does not strip off whitespace before the next token. + if( aOutput ) + { + const char* next = *aOutput; + + while( *next && isspace( *next ) ) + next++; + + *aOutput = next; + } + + return (int) retv; +} + + +uint32_t parseHex( LINE_READER& aReader, const char* aLine, const char** aOutput ) +{ + if( !*aLine ) + SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aLine ); + + // Due to some issues between some files created by a 64 bits version and those + // created by a 32 bits version, we use here a temporary at least 64 bits storage: + unsigned long long retv; + + // Clear errno before calling strtoull() in case some other crt call set it. + errno = 0; + retv = strtoull( aLine, (char**) aOutput, 16 ); + + // Make sure no error occurred when calling strtoull(). + if( errno == ERANGE ) + SCH_PARSE_ERROR( "invalid hexadecimal number", aReader, aLine ); + + // Strip off whitespace before the next token. + if( aOutput ) + { + const char* next = *aOutput; + + while( *next && isspace( *next ) ) + next++; + + *aOutput = next; + } + + return (uint32_t)retv; +} + + +double parseDouble( LINE_READER& aReader, const char* aLine, const char** aOutput ) +{ + if( !*aLine ) + SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aLine ); + + // Clear errno before calling strtod() in case some other crt call set it. + errno = 0; + + double retv = strtod( aLine, (char**) aOutput ); + + // Make sure no error occurred when calling strtod(). + if( errno == ERANGE ) + SCH_PARSE_ERROR( "invalid floating point number", aReader, aLine ); + + // strtod does not strip off whitespace before the next token. + if( aOutput ) + { + const char* next = *aOutput; + + while( *next && isspace( *next ) ) + next++; + + *aOutput = next; + } + + return retv; +} + + +char parseChar( LINE_READER& aReader, const char* aCurrentToken, const char** aNextToken ) +{ + while( *aCurrentToken && isspace( *aCurrentToken ) ) + aCurrentToken++; + + if( !*aCurrentToken ) + SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aCurrentToken ); + + if( !isspace( *( aCurrentToken + 1 ) ) ) + SCH_PARSE_ERROR( "expected single character token", aReader, aCurrentToken ); + + if( aNextToken ) + { + const char* next = aCurrentToken + 2; + + while( *next && isspace( *next ) ) + next++; + + *aNextToken = next; + } + + return *aCurrentToken; +} + + +void parseUnquotedString( wxString& aString, LINE_READER& aReader, const char* aCurrentToken, + const char** aNextToken, bool aCanBeEmpty ) +{ + if( !*aCurrentToken ) + { + if( aCanBeEmpty ) + return; + else + SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aCurrentToken ); + } + + const char* tmp = aCurrentToken; + + while( *tmp && isspace( *tmp ) ) + tmp++; + + if( !*tmp ) + { + if( aCanBeEmpty ) + return; + else + SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aCurrentToken ); + } + + std::string utf8; + + while( *tmp && !isspace( *tmp ) ) + utf8 += *tmp++; + + aString = FROM_UTF8( utf8.c_str() ); + + if( aString.IsEmpty() && !aCanBeEmpty ) + SCH_PARSE_ERROR( _( "expected unquoted string" ), aReader, aCurrentToken ); + + if( aNextToken ) + { + const char* next = tmp; + + while( *next && isspace( *next ) ) + next++; + + *aNextToken = next; + } +} + + +void parseQuotedString( wxString& aString, LINE_READER& aReader, const char* aCurrentToken, + const char** aNextToken, bool aCanBeEmpty ) +{ + if( !*aCurrentToken ) + { + if( aCanBeEmpty ) + return; + else + SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aCurrentToken ); + } + + const char* tmp = aCurrentToken; + + while( *tmp && isspace( *tmp ) ) + tmp++; + + if( !*tmp ) + { + if( aCanBeEmpty ) + return; + else + SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aCurrentToken ); + } + + // Verify opening quote. + if( *tmp != '"' ) + SCH_PARSE_ERROR( "expecting opening quote", aReader, aCurrentToken ); + + tmp++; + + std::string utf8; // utf8 without escapes and quotes. + + // Fetch everything up to closing quote. + while( *tmp ) + { + if( *tmp == '\\' ) + { + tmp++; + + if( !*tmp ) + SCH_PARSE_ERROR( _( "unexpected end of line" ), aReader, aCurrentToken ); + + // Do not copy the escape byte if it is followed by \ or " + if( *tmp != '"' && *tmp != '\\' ) + utf8 += '\\'; + + utf8 += *tmp; + } + else if( *tmp == '"' ) // Closing double quote. + { + break; + } + else + { + utf8 += *tmp; + } + + tmp++; + } + + aString = FROM_UTF8( utf8.c_str() ); + + if( aString.IsEmpty() && !aCanBeEmpty ) + SCH_PARSE_ERROR( "expected quoted string", aReader, aCurrentToken ); + + if( *tmp && *tmp != '"' ) + SCH_PARSE_ERROR( "no closing quote for string found", aReader, tmp ); + + // Move past the closing quote. + tmp++; + + if( aNextToken ) + { + const char* next = tmp; + + while( *next == ' ' ) + next++; + + *aNextToken = next; + } +} diff --git a/eeschema/sch_plugins/legacy/sch_legacy_plugin_helpers.h b/eeschema/sch_plugins/legacy/sch_legacy_plugin_helpers.h new file mode 100644 index 0000000000..a241485110 --- /dev/null +++ b/eeschema/sch_plugins/legacy/sch_legacy_plugin_helpers.h @@ -0,0 +1,145 @@ +/* + * This program source code file is part of KiCad, a free EDA CAD application. + * + * Copyright (C) 2022 KiCad Developers, see AUTHORS.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, see . + */ + +#ifndef _SCH_LEGACY_PLUGIN_HELPERS_H_ +#define _SCH_LEGACY_PLUGIN_HELPERS_H_ + +#include + + +#define SCH_PARSE_ERROR( text, reader, pos ) \ + THROW_PARSE_ERROR( text, reader.GetSource(), reader.Line(), \ + reader.LineNumber(), pos - reader.Line() ) + + +class LINE_READER; +class wxString; + + +extern bool is_eol( char c ); + +/** + * Compare \a aString to the string starting at \a aLine and advances the character point to + * the end of \a String and returns the new pointer position in \a aOutput if it is not NULL. + * + * @param aString - A pointer to the string to compare. + * @param aLine - A pointer to string to begin the comparison. + * @param aOutput - A pointer to a string pointer to the end of the comparison if not NULL. + * @return true if \a aString was found starting at \a aLine. Otherwise false. + */ +extern bool strCompare( const char* aString, const char* aLine, const char** aOutput = nullptr ); + +/** + * Parse an ASCII integer string with possible leading whitespace into + * an integer and updates the pointer at \a aOutput if it is not NULL, just + * like "man strtol()". + * + * @param aReader - The line reader used to generate exception throw information. + * @param aLine - A pointer the current position in a string. + * @param aOutput - The pointer to a string pointer to copy the string pointer position when + * the parsing is complete. + * @return A valid integer value. + * @throw An #IO_ERROR on an unexpected end of line. + * @throw A #PARSE_ERROR if the parsed token is not a valid integer. + */ +extern int parseInt( LINE_READER& aReader, const char* aLine, const char** aOutput = nullptr ); + +/** + * Parse an ASCII hex integer string with possible leading whitespace into + * a long integer and updates the pointer at \a aOutput if it is not NULL, just + * like "man strtoll". + * + * @param aReader - The line reader used to generate exception throw information. + * @param aLine - A pointer the current position in a string. + * @param aOutput - The pointer to a string pointer to copy the string pointer position when + * the parsing is complete. + * @return A valid uint32_t value. + * @throw IO_ERROR on an unexpected end of line. + * @throw PARSE_ERROR if the parsed token is not a valid integer. + */ +extern uint32_t parseHex( LINE_READER& aReader, const char* aLine, const char** aOutput = nullptr ); + +/** + * Parses an ASCII point string with possible leading whitespace into a double precision + * floating point number and updates the pointer at \a aOutput if it is not NULL, just + * like "man strtod". + * + * @param aReader - The line reader used to generate exception throw information. + * @param aLine - A pointer the current position in a string. + * @param aOutput - The pointer to a string pointer to copy the string pointer position when + * the parsing is complete. + * @return A valid double value. + * @throw IO_ERROR on an unexpected end of line. + * @throw PARSE_ERROR if the parsed token is not a valid integer. + */ +extern double parseDouble( LINE_READER& aReader, const char* aLine, + const char** aOutput = nullptr ); + +/** + * Parse a single ASCII character and updates the pointer at \a aOutput if it is not NULL. + * + * @param aReader - The line reader used to generate exception throw information. + * @param aCurrentToken - A pointer the current position in a string. + * @param aNextToken - The pointer to a string pointer to copy the string pointer position when + * the parsing is complete. + * @return A valid ASCII character. + * @throw IO_ERROR on an unexpected end of line. + * @throw PARSE_ERROR if the parsed token is not a single character token. + */ +extern char parseChar( LINE_READER& aReader, const char* aCurrentToken, + const char** aNextToken = nullptr ); + +/** + * Parse an unquoted utf8 string and updates the pointer at \a aOutput if it is not NULL. + * + * The parsed string must be a continuous string with no white space. + * + * @param aString - A reference to the parsed string. + * @param aReader - The line reader used to generate exception throw information. + * @param aCurrentToken - A pointer the current position in a string. + * @param aNextToken - The pointer to a string pointer to copy the string pointer position when + * the parsing is complete. + * @param aCanBeEmpty - True if the parsed string is optional. False if it is mandatory. + * @throw IO_ERROR on an unexpected end of line. + * @throw PARSE_ERROR if the \a aCanBeEmpty is false and no string was parsed. + */ +extern void parseUnquotedString( wxString& aString, LINE_READER& aReader, const char* aCurrentToken, + const char** aNextToken = nullptr, bool aCanBeEmpty = false ); + +/** + * Parse an quoted ASCII utf8 and updates the pointer at \a aOutput if it is not NULL. + * + * The parsed string must be contained within a single line. There are no multi-line + * quoted strings in the legacy schematic file format. + * + * @param aString - A reference to the parsed string. + * @param aReader - The line reader used to generate exception throw information. + * @param aCurrentToken - A pointer the current position in a string. + * @param aNextToken - The pointer to a string pointer to copy the string pointer position when + * the parsing is complete. + * @param aCanBeEmpty - True if the parsed string is optional. False if it is mandatory. + * @throw IO_ERROR on an unexpected end of line. + * @throw PARSE_ERROR if the \a aCanBeEmpty is false and no string was parsed. + */ +extern void parseQuotedString( wxString& aString, LINE_READER& aReader, const char* aCurrentToken, + const char** aNextToken = nullptr, bool aCanBeEmpty = false ); + + + +#endif // _SCH_LEGACY_PLUGIN_HELPERS_H_