From: David Levine Date: Sun, 16 Jul 2017 13:02:08 +0000 (-0400) Subject: Enhanced mhical syntax error message to provide some context. X-Git-Url: https://diplodocus.org/git/nmh/commitdiff_plain/7eecb2dcc4a30573ee644491a04e18d1acd7ec81?ds=inline;hp=2be30ff9e8cbddfb711610d66d5f900064b41831 Enhanced mhical syntax error message to provide some context. Specifically for the case of improperly folded lines. --- diff --git a/h/icalendar.h b/h/icalendar.h index 9f8546c8..be7244e2 100644 --- a/h/icalendar.h +++ b/h/icalendar.h @@ -39,6 +39,7 @@ typedef struct contentline { char *input_line; /* The (unfolded) input line. */ size_t input_line_len; /* Amount of text stored in input_line. */ size_t input_line_size; /* Size of allocated input_line. */ + charstring_t unexpected; /* Accumulate unexpected characters in input. */ cr_indicator cr_before_lf; /* To support CR before LF. If the first line of the input has a CR before its LF, @@ -92,12 +93,13 @@ extern int icaldebug; int icalparse (void); extern vevent vevents; int icallex (void); +extern int parser_status; /* And this is for the icalendar scanner. */ extern YYSTYPE icallval; /* - * For directing the scanner to use a files other than stdin/stdout. + * For directing the scanner to use files other than stdin/stdout. * These don't use the accessors provided by modern flex because * flex 2.5.4 doesn't supply them. */ diff --git a/sbr/icalendar.l b/sbr/icalendar.l index 11006e79..8b0721bf 100644 --- a/sbr/icalendar.l +++ b/sbr/icalendar.l @@ -257,7 +257,15 @@ folded-value {VALUE-CHAR}*({fold}{VALUE-CHAR}*)+ . { /* By default, flex will just pass unmatched text. Catch it instead. */ - inform("unexpected input: |%s|\n", icaltext); + contentline *clines = vevents.last->contentlines; + contentline *cline; + + if (clines && (cline = clines->last)) { + if (cline->unexpected == NULL) { + cline->unexpected = charstring_create (0); + } + charstring_append_cstring (cline->unexpected, icaltext); + } } diff --git a/sbr/icalparse.y b/sbr/icalparse.y index dc58d4aa..88edb0c8 100644 --- a/sbr/icalparse.y +++ b/sbr/icalparse.y @@ -38,7 +38,7 @@ #include "h/utils.h" static char *append (contentline *, const char *, const size_t); -static void new_input_line (contentline **); +static void new_content_line (contentline **); static void new_vevent (vevent *); static void free_param_names (param_list *); static void free_param_values (value_list *); @@ -62,7 +62,7 @@ contentline_list /* contentline = name *(";" param ) ":" value CRLF */ contentline : ICAL_NAME { - new_input_line (&vevents.last->contentlines); + new_content_line (&vevents.last->contentlines); append (vevents.last->contentlines->last, $1, strlen ($1)); vevents.last->contentlines->last->name = $1; } ICAL_COLON { @@ -87,7 +87,7 @@ contentline } } | ICAL_NAME { - new_input_line (&vevents.last->contentlines); + new_content_line (&vevents.last->contentlines); append (vevents.last->contentlines->last, $1, strlen ($1)); vevents.last->contentlines->last->name = $1; } param_list ICAL_COLON { @@ -211,7 +211,7 @@ append (contentline *cline, const char *src, const size_t src_len) { } static void -new_input_line (contentline **cline) { +new_content_line (contentline **cline) { contentline *new_node; NEW0(new_node); @@ -296,6 +296,7 @@ free_contentlines (contentline *root) { } free (i->value); free (i->input_line); + charstring_free (i->unexpected); next = i->next; free (i); } @@ -326,11 +327,27 @@ free_param_values (value_list *v) { static int icalerror (const char *error) { + contentline *c; + charstring_t context = NULL; + + /* Find last chunk of unexpected text. */ + for (c = vevents.last->contentlines; c; c = c->next) { + if (c->unexpected) { + context = c->unexpected; + } + } + if (! strcmp ("syntax error, unexpected $end, expecting ICAL_NAME", error)) { /* Empty input: produce no output. */ } else { - adios (NULL, "%s", error); + if (context) { + inform ("%s after \"%s\"", error, charstring_buffer (context)); + } else { + inform ("%s", error); + } + parser_status = -1; + return -1; } return 0; /* The return value isn't used anyway. */ diff --git a/test/mhical/test-mhical b/test/mhical/test-mhical index f6d75af0..930c35f6 100755 --- a/test/mhical/test-mhical +++ b/test/mhical/test-mhical @@ -841,5 +841,38 @@ END:VCALENDAR" | TZ=UTC mhical >"$actual" check "$expected" "$actual" +# check invalid line folding +start_test "invalid line folding" + +cat >"$expected" <<'EOF' +Summary: test +Description: this file does not end with a newline +At: Sun, 14 May 2017 13:00 +0000 +To: Sun, 14 May 2017 14:00 +EOF + +cat >"$expected_err" <<'EOF' +mhical: syntax error, unexpected ICAL_COMMA, expecting ICAL_COLON after " this line is not folded" +EOF + +set +e +printf %s \ +"BEGIN:VCALENDAR +VERSION:2.0 +PRODID:-//TDP v3.0//EN +BEGIN:VEVENT +DTSTAMP:20170514T122300Z +DTSTART:20170514T130000Z +DTEND:20170514T140000Z +SUMMARY:test +DESCRIPTION:this file does not end with a newline +and this line is not folded, +END:VEVENT +END:VCALENDAR" | TZ=UTC mhical >"$actual" 2>"$actual_err" +set -e +check "$expected" "$actual" +check "$expected_err" "$actual_err" + + finish_test exit $failed diff --git a/uip/mhical.c b/uip/mhical.c index 67ba90da..650b9821 100644 --- a/uip/mhical.c +++ b/uip/mhical.c @@ -56,6 +56,7 @@ DEFINE_SWITCH_ARRAY(MHICAL, switches); #undef X vevent vevents = { NULL, NULL, NULL}; +int parser_status = 0; int main (int argc, char *argv[]) { @@ -236,7 +237,7 @@ main (int argc, char *argv[]) { free (outfile); } - return 0; + return parser_status; } /*