MINOR: config: improve .if condition error reporting

Let's return the position of the first unparsable character on error,
so that instead of just saying "unparsable conditional expression blah"
we can have:

  [ALERT] 125/150618 (13995) : parsing [test-conds2.cfg:1]: unparsable conditional expression '12/blah' in '.if' at position 1:
    .if 12/blah
        ^
This is important because conditions will be made from environment
variables or later from more complex expressions where the error will
not always be easy to locate.
diff --git a/src/cfgparse.c b/src/cfgparse.c
index 168cabb..1d85943 100644
--- a/src/cfgparse.c
+++ b/src/cfgparse.c
@@ -1636,9 +1636,10 @@
 
 /* evaluate a condition on a .if/.elif line. The condition is already tokenized
  * in <err>. Returns -1 on error (in which case err is filled with a message,
- * and only in this case), 0 if the condition is false, 1 if it's true.
+ * and only in this case), 0 if the condition is false, 1 if it's true. If
+ * <errptr> is not NULL, it's set to the first invalid character on error.
  */
-static int cfg_eval_condition(char **args, char **err)
+static int cfg_eval_condition(char **args, char **err, const char **errptr)
 {
 	char *end;
 	long val;
@@ -1650,7 +1651,9 @@
 	if (end && *end == '\0')
 		return val != 0;
 
-	memprintf(err, "unparsable conditional expression '%s'.\n", args[0]);
+	memprintf(err, "unparsable conditional expression '%s'", args[0]);
+	if (errptr)
+		*errptr = args[0];
 	return -1;
 }
 
@@ -1871,6 +1874,7 @@
 		/* check for config macros */
 		if (*args[0] == '.') {
 			if (strcmp(args[0], ".if") == 0) {
+				const char *errptr = NULL;
 				char *errmsg = NULL;
 				int cond;
 
@@ -1891,9 +1895,14 @@
 					goto next_line;
 				}
 
-				cond = cfg_eval_condition(args + 1, &errmsg);
+				cond = cfg_eval_condition(args + 1, &errmsg, &errptr);
 				if (cond < 0) {
-					ha_alert("parsing [%s:%d]: %s in '.if'\n", file, linenum, errmsg);
+					size_t newpos = sanitize_for_printing(args[1], errptr - args[1], 76);
+
+					ha_alert("parsing [%s:%d]: %s in '.if' at position %d:\n  .if %s\n  %*s\n",
+						 file, linenum, errmsg,
+					         (int)(errptr-args[1]+1), args[1], (int)(newpos+5), "^");
+
 					free(errmsg);
 					err_code |= ERR_ALERT | ERR_FATAL | ERR_ABORT;
 					goto err;
@@ -1907,6 +1916,7 @@
 				goto next_line;
 			}
 			else if (strcmp(args[0], ".elif") == 0) {
+				const char *errptr = NULL;
 				char *errmsg = NULL;
 				int cond;
 
@@ -1931,9 +1941,14 @@
 					goto next_line;
 				}
 
-				cond = cfg_eval_condition(args + 1, &errmsg);
+				cond = cfg_eval_condition(args + 1, &errmsg, &errptr);
 				if (cond < 0) {
-					ha_alert("parsing [%s:%d]: %s in '.elif'\n", file, linenum, errmsg);
+					size_t newpos = sanitize_for_printing(args[1], errptr - args[1], 74);
+
+					ha_alert("parsing [%s:%d]: %s in '.elif' at position %d:\n  .elif %s\n  %*s\n",
+						 file, linenum, errmsg,
+					         (int)(errptr-args[1]+1), args[1], (int)(newpos+7), "^");
+
 					free(errmsg);
 					err_code |= ERR_ALERT | ERR_FATAL | ERR_ABORT;
 					goto err;