]> diplodocus.org Git - nmh/commitdiff
Enhanced mhical syntax error message to provide some context.
authorDavid Levine <levinedl@acm.org>
Sun, 16 Jul 2017 13:02:08 +0000 (09:02 -0400)
committerDavid Levine <levinedl@acm.org>
Sun, 16 Jul 2017 13:02:08 +0000 (09:02 -0400)
Specifically for the case of improperly folded lines.

h/icalendar.h
sbr/icalendar.l
sbr/icalparse.y
test/mhical/test-mhical
uip/mhical.c

index 9f8546c8d857e776c6cc8d3a8c1865f7dfd5aa04..be7244e280c10cdd72e4d73fcd62fd082ad93336 100644 (file)
@@ -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 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.
  */
index 11006e79cbb7d41f876c907a6c6f350b3e755f82..8b0721bfe0a55416b6403e919fe30d386d15b6ca 100644 (file)
@@ -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);
+    }
 }
 
 <INITIAL>
index dc58d4aa5cc2aeb9ad327aeb73123878868ee5fa..88edb0c83eb66a05f996b511be45abb89d9fb1f1 100644 (file)
@@ -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. */
index f6d75af0ee84539c1f1384471b2b688839863443..930c35f694a3ac0faa4ea36d8bd56a0b805f14ec 100755 (executable)
@@ -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
index 67ba90da57f3b67dec3ce8da1c14e08496baa6a8..650b982131c226d48dd00682b7d98ecc029a4fff 100644 (file)
@@ -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;
 }
 
 /*