MINOR: tools: make parse_line() always terminate the args list

parse_line() as added in commit c8d167bcf ("MINOR: tools: add a new
configurable line parse, parse_line()") presents an difficult usage
because it's up to the caller to determine the last written argument
based on what was passed to it. In practice the only way to safely
use it is for the caller to always pass nbarg-1 and make that last
entry point to the last arg + its strlen. This is annoying because
it makes it as painful to use as the infamous strncpy() while it has
all the information the caller needs.

This patch changes its behavior so that it guarantees that at least
one argument will point to the trailing zero at the end of the output
string, as long as there is at least one argument. The caller just
has to pass +1 to the arg count to make sure at least a last one is
empty.
diff --git a/src/tools.c b/src/tools.c
index 10c9737..9641700 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -4738,7 +4738,9 @@
  * extraneous ones are not emitted but <outlen> is updated so that the caller
  * knows how much to realloc. Similarly, <args> are not updated beyond <nbargs>
  * but the returned <nbargs> indicates how many were found. All trailing args
- * up to <nbargs> point to the trailing zero.
+ * up to <nbargs> point to the trailing zero, and as long as <nbargs> is > 0,
+ * it is guaranteed that at least one arg will point to the zero. It is safe
+ * to call it with a NULL <args> if <nbargs> is 0.
  *
  * <out> may overlap with <in> provided that it never goes further, in which
  * case the parser will accept to perform in-place parsing and unquoting/
@@ -4761,7 +4763,7 @@
 	char *brace = NULL;
 	unsigned char hex1, hex2;
 	size_t outmax = *outlen;
-	int argsmax = *nbargs;
+	int argsmax = *nbargs - 1;
 	size_t outpos = 0;
 	int squote = 0;
 	int dquote = 0;
@@ -4771,7 +4773,10 @@
 	*nbargs = 0;
 	*outlen = 0;
 
-	args[arg] = out;
+	/* argsmax may be -1 here, protecting args[] from any write */
+	if (arg < argsmax)
+		args[arg] = out;
+
 	while (1) {
 		if (*in >= '-' && *in != '\\') {
 			/* speedup: directly send all regular chars starting
@@ -4972,8 +4977,13 @@
 	*nbargs = arg;
 	*outlen = outpos;
 
-	/* empty all trailing args by making them point to the trailing zero */
-	while (arg < argsmax)
+	/* empty all trailing args by making them point to the trailing zero,
+	 * at least the last one in any case.
+	 */
+	if (arg > argsmax)
+		arg = argsmax;
+
+	while (arg >= 0 && arg <= argsmax)
 		args[arg++] = out + outpos - 1;
 
 	return err;