MINOR: config: support some pseudo-variables for file/line/section

The new pseudo-variables ".FILE", ".LINE" and ".SECTION" will be resolved
on the fly by the config parser and will respectively retrieve the current
configuration file name, the current line number and the current section
being parsed. This may help emit logs, errors, and debugging information
(e.g. which rule matched).

The '.' in the first char was reserved for such pseudo-variables and no
other variable is permitted. This will allow to add support for new ones
in the future if they prove to be useful (e.g. randoms/uuid for secret
keying or automatic naming of configuration objects).
diff --git a/src/tools.c b/src/tools.c
index 056c9ca..c453585 100644
--- a/src/tools.c
+++ b/src/tools.c
@@ -5300,14 +5300,14 @@
 			 */
 			char *var_name;
 			char save_char;
-			char *value;
+			const char *value;
 
 			in++;
 
 			if (*in == '{')
 				brace = in++;
 
-			if (!isalpha((unsigned char)*in) && *in != '_') {
+			if (!isalpha((unsigned char)*in) && *in != '_' && *in != '.') {
 				/* unacceptable character in variable name */
 				err |= PARSE_ERR_VARNAME;
 				if (errptr)
@@ -5316,12 +5316,31 @@
 			}
 
 			var_name = in;
+			if (*in == '.')
+				in++;
 			while (isalnum((unsigned char)*in) || *in == '_')
 				in++;
 
 			save_char = *in;
 			*in = '\0';
-			value = getenv(var_name);
+			if (unlikely(*var_name == '.')) {
+				/* internal pseudo-variables */
+				if (strcmp(var_name, ".LINE") == 0)
+					value = ultoa(global.cfg_curr_line);
+				else if (strcmp(var_name, ".FILE") == 0)
+					value = global.cfg_curr_file;
+				else if (strcmp(var_name, ".SECTION") == 0)
+					value = global.cfg_curr_section;
+				else {
+					/* unsupported internal variable name */
+					err |= PARSE_ERR_VARNAME;
+					if (errptr)
+						*errptr = var_name;
+					goto leave;
+				}
+			} else {
+				value = getenv(var_name);
+			}
 			*in = save_char;
 
 			/* support for '[*]' sequence to force word expansion,