From 83b1f62e0bf6226c396466183b1033bfb97ee5db Mon Sep 17 00:00:00 2001
From: Stephan Bosch <stephan@rename-it.nl>
Date: Thu, 28 Feb 2008 22:10:44 +0100
Subject: [PATCH] Variables: exported namespace+variable parsing to separate
 file.

---
 src/lib-sieve/plugins/variables/Makefile.am   |   4 +-
 .../plugins/variables/ext-variables-common.c  | 110 +-----------------
 .../plugins/variables/ext-variables-name.c    |  80 +++++++++++++
 .../plugins/variables/ext-variables-name.h    |  48 ++++++++
 .../plugins/variables/variables-nspace.sieve  |   5 +
 5 files changed, 142 insertions(+), 105 deletions(-)
 create mode 100644 src/lib-sieve/plugins/variables/ext-variables-name.c
 create mode 100644 src/lib-sieve/plugins/variables/ext-variables-name.h
 create mode 100644 src/lib-sieve/plugins/variables/variables-nspace.sieve

diff --git a/src/lib-sieve/plugins/variables/Makefile.am b/src/lib-sieve/plugins/variables/Makefile.am
index f3457b799..413a0b170 100644
--- a/src/lib-sieve/plugins/variables/Makefile.am
+++ b/src/lib-sieve/plugins/variables/Makefile.am
@@ -15,11 +15,13 @@ tsts = \
 
 libsieve_ext_variables_la_SOURCES = \
 	ext-variables-common.c \
+	ext-variables-name.c \
 	$(cmds) \
 	$(tsts) \
 	ext-variables.c
 
 noinst_HEADERS = \
-	ext-variables-common.h
+	ext-variables-common.h \
+	ext-variables-name.h
 
 
diff --git a/src/lib-sieve/plugins/variables/ext-variables-common.c b/src/lib-sieve/plugins/variables/ext-variables-common.c
index 6ce43f9dd..a7c43358a 100644
--- a/src/lib-sieve/plugins/variables/ext-variables-common.c
+++ b/src/lib-sieve/plugins/variables/ext-variables-common.c
@@ -1,6 +1,7 @@
 #include "lib.h"
 #include "hash.h"
 #include "str.h"
+#include "array.h"
 
 #include "sieve-common.h"
 
@@ -15,6 +16,7 @@
 #include "sieve-interpreter.h"
 
 #include "ext-variables-common.h"
+#include "ext-variables-name.h"
 
 #include <ctype.h>
 
@@ -338,106 +340,6 @@ inline static struct sieve_ast_argument *_add_string_element
 	return strarg;
 }
 
-/* Variable Substitution
- * ---------------------
- * 
- * The variable strings are preprocessed into an AST list consisting of variable 
- * substitutions and constant parts of the string. The variables to which
- * the substitutions link are looked up and their index in their scope storage
- * is what is added to the list and eventually emitted as byte code. So in byte
- * code a variable string will look as a series of substrings interrupted by
- * integer operands that refer to variables. During execution the strings and 
- * the looked-up variables are concatenated to obtain the desired result. The 
- * the variable references are simple indexes into an array of variables, so
- * looking these up during execution is a trivial process.
- * 
- * However (RFC 5229):
- *   Tests or actions in future extensions may need to access the
- *   unexpanded version of the string argument and, e.g., do the expansion
- *   after setting variables in its namespace.  The design of the
- *   implementation should allow this.
- *
- * Various options exist to provide this feature. If the extension is entirely
- * namespace-based there is actually not very much of a problem. The variable
- * list can easily be extended with new argument-types that refer to a variable
- * identifier in stead of an index in the variable's storage. 
- */
- 
-struct variable_name {
-	string_t *identifier;
-	int num_variable;
-};
-
-ARRAY_DEFINE_TYPE(variable_name, struct variable_name);
- 
-static int arg_variable_parse
-(ARRAY_TYPE(variable_name) *vname, const char **str, const char *strend)
-{
-	const char *p = *str;
-	int nspace_used = 0;
-				
-	for (;;) { 
-		struct variable_name *cur_element;
-		string_t *cur_ident;
-
-		/* Acquire current position in the substitution structure or allocate 
-		 * a new one if this substitution consists of more elements than before.
-		 */
-		if ( nspace_used < (int) array_count(vname) ) {
-			cur_element = array_idx_modifiable
-				(vname, (unsigned int) nspace_used);
-			cur_ident = cur_element->identifier;
-		} else {
-			cur_element = array_append_space(vname);
-			cur_ident = cur_element->identifier = t_str_new(32);
-		}
-
-		/* Identifier */
-		if ( *p == '_' || isalpha(*p) ) {
-			cur_element->num_variable = -1;
-			str_truncate(cur_ident, 0);
-			str_append_c(cur_ident, *p);
-			p++;
-		
-			while ( p < strend && (*p == '_' || isalnum(*p)) ) {
-				str_append_c(cur_ident, *p);
-				p++;
-			}
-		
-		/* Num-variable */
-		} else if ( isdigit(*p) ) {
-			cur_element->num_variable = *p - '0';
-			p++;
-			
-			while ( p < strend && isdigit(*p) ) {
-				cur_element->num_variable = cur_element->num_variable*10 + (*p - '0');
-				p++;
-			} 
-
-			/* If a num-variable is first, no more elements can follow because no
-			 * namespace is specified.
-			 */
-			if ( nspace_used == 0 ) {
-				*str = p;
-				return 1;
-			}
-		} else {
-			*str = p;
-			return -1;
-		}
-		
-		nspace_used++;
-		
-		if ( p < strend && *p == '.' ) 
-			p++;
-		else
-			break;
-	}
-	
-	*str = p;
-	return nspace_used;
-} 
- 
 static bool arg_variable_string_validate
 (struct sieve_validator *validator, struct sieve_ast_argument **arg, 
 		struct sieve_command_context *cmd)
@@ -452,7 +354,7 @@ static bool arg_variable_string_validate
 	struct _variable_string_data *strdata;
 	bool result = TRUE;
 	
-	ARRAY_TYPE(variable_name) substitution;	
+	ARRAY_TYPE(ext_variable_name) substitution;	
 	int nelements = 0;
 	
 	t_push();
@@ -482,7 +384,7 @@ static bool arg_variable_string_validate
 			break;
 		/* Got '${' */ 
 		case ST_VARIABLE:
-			nelements = arg_variable_parse(&substitution, &p, strend);
+			nelements = ext_variable_name_parse(&substitution, &p, strend);
 			
 			if ( nelements < 0 )
 				state = ST_NONE;
@@ -519,7 +421,7 @@ static bool arg_variable_string_validate
 				
 				/* Find the variable */
 				if ( nelements == 1 ) {
-					const struct variable_name *cur_element = 
+					const struct ext_variable_name *cur_element = 
 						array_idx(&substitution, 0);
 						
 					if ( cur_element->num_variable == -1 ) {
@@ -539,7 +441,7 @@ static bool arg_variable_string_validate
 					
 					printf("NS_VARIABLE: ");
 					for ( i = 0; i < nelements; i++ ) {
-						const struct variable_name *cur_element = 
+						const struct ext_variable_name *cur_element = 
 							array_idx(&substitution, (unsigned int) i);
 							
 						if ( cur_element->num_variable == -1 ) {
diff --git a/src/lib-sieve/plugins/variables/ext-variables-name.c b/src/lib-sieve/plugins/variables/ext-variables-name.c
new file mode 100644
index 000000000..e4b2675fb
--- /dev/null
+++ b/src/lib-sieve/plugins/variables/ext-variables-name.c
@@ -0,0 +1,80 @@
+#include "lib.h"
+#include "str.h"
+#include "array.h"
+
+#include "sieve-common.h"
+
+#include "ext-variables-common.h"
+#include "ext-variables-name.h"
+
+#include <ctype.h>
+  
+int ext_variable_name_parse
+(ARRAY_TYPE(ext_variable_name) *vname, const char **str, const char *strend)
+{
+	const char *p = *str;
+	int nspace_used = 0;
+				
+	for (;;) { 
+		struct ext_variable_name *cur_element;
+		string_t *cur_ident;
+
+		/* Acquire current position in the substitution structure or allocate 
+		 * a new one if this substitution consists of more elements than before.
+		 */
+		if ( nspace_used < (int) array_count(vname) ) {
+			cur_element = array_idx_modifiable
+				(vname, (unsigned int) nspace_used);
+			cur_ident = cur_element->identifier;
+		} else {
+			cur_element = array_append_space(vname);
+			cur_ident = cur_element->identifier = t_str_new(32);
+		}
+
+		/* Identifier */
+		if ( *p == '_' || isalpha(*p) ) {
+			cur_element->num_variable = -1;
+			str_truncate(cur_ident, 0);
+			str_append_c(cur_ident, *p);
+			p++;
+		
+			while ( p < strend && (*p == '_' || isalnum(*p)) ) {
+				str_append_c(cur_ident, *p);
+				p++;
+			}
+		
+		/* Num-variable */
+		} else if ( isdigit(*p) ) {
+			cur_element->num_variable = *p - '0';
+			p++;
+			
+			while ( p < strend && isdigit(*p) ) {
+				cur_element->num_variable = cur_element->num_variable*10 + (*p - '0');
+				p++;
+			} 
+
+			/* If a num-variable is first, no more elements can follow because no
+			 * namespace is specified.
+			 */
+			if ( nspace_used == 0 ) {
+				*str = p;
+				return 1;
+			}
+		} else {
+			*str = p;
+			return -1;
+		}
+		
+		nspace_used++;
+		
+		if ( p < strend && *p == '.' ) 
+			p++;
+		else
+			break;
+	}
+	
+	*str = p;
+	return nspace_used;
+} 
+ 
+
diff --git a/src/lib-sieve/plugins/variables/ext-variables-name.h b/src/lib-sieve/plugins/variables/ext-variables-name.h
new file mode 100644
index 000000000..efc00a54a
--- /dev/null
+++ b/src/lib-sieve/plugins/variables/ext-variables-name.h
@@ -0,0 +1,48 @@
+#ifndef __EXT_VARIABLES_NAME
+#define __EXT_VARIABLES_NAME
+
+/* Variable Substitution
+ * ---------------------
+ * 
+ * The variable strings are preprocessed into an AST list consisting of variable 
+ * substitutions and constant parts of the string. The variables to which
+ * the substitutions link are looked up and their index in their scope storage
+ * is what is added to the list and eventually emitted as byte code. So in byte
+ * code a variable string will look as a series of substrings interrupted by
+ * integer operands that refer to variables. During execution the strings and 
+ * the looked-up variables are concatenated to obtain the desired result. The 
+ * the variable references are simple indexes into an array of variables, so
+ * looking these up during execution is a trivial process.
+ * 
+ * However (RFC 5229):
+ *   Tests or actions in future extensions may need to access the
+ *   unexpanded version of the string argument and, e.g., do the expansion
+ *   after setting variables in its namespace.  The design of the
+ *   implementation should allow this.
+ *
+ * Various options exist to provide this feature. If the extension is entirely
+ * namespace-based there is actually not very much of a problem. The variable
+ * list can easily be extended with new argument-types that refer to a variable
+ * identifier in stead of an index in the variable's storage. 
+ */
+
+#include "lib.h"
+#include "array.h"
+
+#include "sieve-common.h"
+
+#include "ext-variables-common.h"
+
+#include <ctype.h>
+ 
+struct ext_variable_name {
+	string_t *identifier;
+	int num_variable;
+};
+
+ARRAY_DEFINE_TYPE(ext_variable_name, struct ext_variable_name);
+ 
+int ext_variable_name_parse
+	(ARRAY_TYPE(ext_variable_name) *vname, const char **str, const char *strend);
+
+#endif /* __EXT_VARIABLES_NAME */
diff --git a/src/lib-sieve/plugins/variables/variables-nspace.sieve b/src/lib-sieve/plugins/variables/variables-nspace.sieve
new file mode 100644
index 000000000..32502cb5a
--- /dev/null
+++ b/src/lib-sieve/plugins/variables/variables-nspace.sieve
@@ -0,0 +1,5 @@
+require "variables";
+require "fileinto";
+
+fileinto "This is ${dovecot.program_name} version ${dovecot.program_version}.";
+
-- 
GitLab