diff --git a/src/orderfile.c b/src/orderfile.c index 8fdc75485..33a9c19f7 100644 --- a/src/orderfile.c +++ b/src/orderfile.c @@ -348,7 +348,7 @@ int parseorders(FILE *F) done = feof(F); if (OP_Parse(parser, buf, len, done) == OP_STATUS_ERROR) { /* TODO: error message */ - err = -1; + err = (int)OP_GetErrorCode(parser); break; } } diff --git a/src/util/order_parser.c b/src/util/order_parser.c index f303ff3f1..88a42f0ab 100644 --- a/src/util/order_parser.c +++ b/src/util/order_parser.c @@ -5,7 +5,7 @@ #include "order_parser.h" #include -#include +#include #include #include @@ -19,6 +19,10 @@ struct OrderParserStruct { int m_lineNumber; }; +enum OP_Error OP_GetErrorCode(OP_Parser parser) { + return parser->m_errorCode; +} + void OP_SetOrderHandler(OP_Parser parser, OP_OrderHandler handler) { parser->m_orderHandler = handler; } @@ -87,8 +91,9 @@ static enum OP_Error buffer_append(OP_Parser parser, const char *s, int len) static char *skip_spaces(char *pos) { char *next; for (next = pos; *next && *next != '\n'; ++next) { + wint_t wch = *(unsigned char *)next; /* TODO: handle unicode whitespace */ - if (!isspace(*next)) break; + if (!iswspace(wch)) break; } return next; } @@ -110,6 +115,7 @@ static enum OP_Status parse_buffer(OP_Parser parser, int isFinal) enum OP_Error code; size_t len = pos - parser->m_bufferPtr; char *next; + int continue_comment = 0; switch (*pos) { case '\n': @@ -164,9 +170,8 @@ static enum OP_Status parse_buffer(OP_Parser parser, int isFinal) if (next) { if (*next == '\n') { /* no more lines in this comment, we're done: */ - pos = next + 1; ++parser->m_lineNumber; - break; + break; /* exit loop */ } else { /* is this backslash the final character? */ @@ -184,25 +189,42 @@ static enum OP_Status parse_buffer(OP_Parser parser, int isFinal) } } while (next && *next); - if (next && pos < parser->m_bufferEnd) { - /* we skip the comment, and there is more data in the buffer */ - parser->m_bufferPtr = pos; - } - else { - /* we exhausted the buffer before we got to the end of the comment */ + if (!next) { + /* we exhausted the buffer before we finished the line */ if (isFinal) { - /* the input ended on this comment line, which is fine */ + /* this comment was at the end of the file, it just has no newline. done! */ return OP_STATUS_OK; } else { - /* skip what we have of the comment, keep the semicolon, keep going */ - ptrdiff_t skip = parser->m_bufferEnd - parser->m_bufferPtr; - if (skip > 1) { - parser->m_bufferPtr += (skip - 1); - parser->m_bufferPtr[0] = ';'; - } + /* there is more of this line in the next buffer, save the semicolon */ + continue_comment = 1; } } + else { + if (*next) { + /* end comment parsing, begin parsing a new line */ + pos = next + 1; + continue_comment = 0; + } + else { + /* reached end of input naturally, need more data to finish */ + continue_comment = 1; + } + } + + if (continue_comment) { + ptrdiff_t skip = parser->m_bufferEnd - parser->m_bufferPtr; + continue_comment = 0; + if (skip > 0) { + /* should always be true */ + parser->m_bufferPtr += (skip - 1); + parser->m_bufferPtr[0] = ';'; + } + return OP_STATUS_OK; + } + /* continue the outer loop */ + parser->m_bufferPtr = pos; + pos = strpbrk(pos, "\\;\n"); break; default: parser->m_errorCode = OP_ERROR_SYNTAX; diff --git a/src/util/order_parser.h b/src/util/order_parser.h index fde29a380..159fd6594 100644 --- a/src/util/order_parser.h +++ b/src/util/order_parser.h @@ -37,5 +37,6 @@ void OP_ParserReset(OP_Parser parser); enum OP_Status OP_Parse(OP_Parser parser, const char *s, int len, int isFinal); void OP_SetOrderHandler(OP_Parser parser, OP_OrderHandler handler); void OP_SetUserData(OP_Parser parser, void *userData); +enum OP_Error OP_GetErrorCode(OP_Parser parser); #endif diff --git a/src/util/order_parser.test.c b/src/util/order_parser.test.c index 2d113655a..630bcc4d4 100644 --- a/src/util/order_parser.test.c +++ b/src/util/order_parser.test.c @@ -57,16 +57,22 @@ static void test_parse_orders(CuTest *tc) { CuAssertStrEquals(tc, "Hello\\World", lastline); OP_ParserReset(parser); + lastline[0] = 0; + CuAssertIntEquals(tc, OP_STATUS_OK, OP_Parse(parser, ";\n", 2, 0)); + CuAssertIntEquals(tc, OP_STATUS_OK, OP_Parse(parser, "Hello World", 11, 1)); + CuAssertStrEquals(tc, "Hello World", lastline); + OP_ParserReset(parser); + lastline[0] = 0; CuAssertIntEquals(tc, OP_STATUS_OK, OP_Parse(parser, ";Hello \\", 8, 0)); - CuAssertIntEquals(tc, OP_STATUS_OK, OP_Parse(parser, "\nWorld\n", 7, 1)); + CuAssertIntEquals(tc, OP_STATUS_OK, OP_Parse(parser, "\nWorld\n", 7, 0)); CuAssertIntEquals(tc, OP_STATUS_OK, OP_Parse(parser, "Enno", 4, 1)); CuAssertStrEquals(tc, "Enno", lastline); OP_ParserReset(parser); lastline[0] = 0; CuAssertIntEquals(tc, OP_STATUS_OK, OP_Parse(parser, ";Hello", 6, 0)); - CuAssertIntEquals(tc, OP_STATUS_OK, OP_Parse(parser, "World\n", 6, 1)); + CuAssertIntEquals(tc, OP_STATUS_OK, OP_Parse(parser, "World\n", 6, 0)); CuAssertIntEquals(tc, OP_STATUS_OK, OP_Parse(parser, "Enno", 4, 1)); CuAssertStrEquals(tc, "Enno", lastline); OP_ParserReset(parser); @@ -82,6 +88,11 @@ static void test_parse_orders(CuTest *tc) { CuAssertStrEquals(tc, "World", lastline); OP_ParserReset(parser); + lastline[0] = 0; + CuAssertIntEquals(tc, OP_STATUS_OK, OP_Parse(parser, "Hello\n", 6, 0)); + CuAssertIntEquals(tc, OP_STATUS_OK, OP_Parse(parser, "World\n", 6, 1)); + CuAssertStrEquals(tc, "World", lastline); + OP_ParserReset(parser); lastline[0] = 0; CuAssertIntEquals(tc, OP_STATUS_OK, OP_Parse(parser, "Hello \\", 7, 0)); CuAssertIntEquals(tc, OP_STATUS_OK, OP_Parse(parser, "\nWorld", 6, 1));