/* Lexical analysis. */
enum json_lex_state lex_state;
struct ds buffer; /* Buffer for accumulating token text. */
+ int line_number;
+ int column_number;
+ int byte_number;
/* Parsing. */
enum json_parse_state parse_state;
}
static bool
-json_lex_input(struct json_parser *p, int c)
+json_lex_input(struct json_parser *p, unsigned char c)
{
struct json_token token;
+ p->byte_number++;
+ if (c == '\n') {
+ p->column_number = 0;
+ p->line_number++;
+ } else {
+ p->column_number++;
+ }
+
switch (p->lex_state) {
case JSON_LEX_START:
switch (c) {
json_error(struct json_parser *p, const char *format, ...)
{
if (!p->error) {
+ struct ds msg;
va_list args;
+ ds_init(&msg);
+ ds_put_format(&msg, "line %d, column %d, byte %d: ",
+ p->line_number, p->column_number, p->byte_number);
va_start(args, format);
- p->error = xvasprintf(format, args);
+ ds_put_format_valist(&msg, format, args);
va_end(args);
+ p->error = ds_steal_cstr(&msg);
+
p->done = true;
}
}
[AT_SETUP([$1])
AT_KEYWORDS([json positive])
AT_CHECK([printf %s "AS_ESCAPE([$2])" > input])
- OVS_CHECK_LCOV([test-json $4 input], [0], [$3
-], [])
+ AT_CAPTURE_FILE([input])
+ OVS_CHECK_LCOV([test-json $4 input], [0], [stdout], [])
+ AT_CHECK([cat stdout], [0], [$3
+])
AT_CLEANUP])
m4_define([JSON_CHECK_NEGATIVE],
[AT_SETUP([$1])
AT_KEYWORDS([json negative])
AT_CHECK([printf %s "AS_ESCAPE([$2])" > input])
- OVS_CHECK_LCOV([test-json $4 input], [1], [$3
+ AT_CAPTURE_FILE([input])
+ OVS_CHECK_LCOV([test-json $4 input], [1], [stdout], [])
+ AT_CHECK([[sed 's/^error: [^:]*:/error:/' < stdout]], [0], [$3
])
AT_CLEANUP])
AT_SETUP([end of input in quoted string])
AT_KEYWORDS([json negative])
AT_CHECK([printf '\"xxx' | test-json -], [1],
- [error: unexpected end of input in quoted string
+ [error: line 0, column 4, byte 4: unexpected end of input in quoted string
])
AT_CLEANUP
AT_SETUP([input may not be empty])
AT_KEYWORDS([json negative])
-AT_CHECK([test-json /dev/null], [1], [error: empty input stream
+AT_CHECK([test-json /dev/null], [1], [error: line 0, column 0, byte 0: empty input stream
])
AT_CLEANUP