Specifically for the case of improperly folded lines.
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,
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.
*/
. {
/* 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);
+ }
}
<INITIAL>
#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 *);
/* 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 {
}
}
| 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 {
}
static void
-new_input_line (contentline **cline) {
+new_content_line (contentline **cline) {
contentline *new_node;
NEW0(new_node);
}
free (i->value);
free (i->input_line);
+ charstring_free (i->unexpected);
next = i->next;
free (i);
}
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. */
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
#undef X
vevent vevents = { NULL, NULL, NULL};
+int parser_status = 0;
int
main (int argc, char *argv[]) {
free (outfile);
}
- return 0;
+ return parser_status;
}
/*