Page MenuHomePhorge

grammar.c
No OneTemporary

Authored By
Unknown
Size
5 KB
Referenced Files
None
Subscribers
None

grammar.c

/*
* grammar.c
*
* Created on: Nov 6, 2014
* Author: James Cassell
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include "grammar.h"
#include "xmalloc.h"
EXPORTED int is_identifier(char *s)
{
/* identifier = (ALPHA / "_") *(ALPHA / DIGIT / "_") */
int i = 0;
while (s && s[i]) {
if (s[i] == '_' || (s[i] >= 'a' && s[i] <= 'z')
|| (s[i] >= 'A' && s[i] <= 'Z')
|| (i && (s[i] >= '0' && s[i] <= '9'))) {
i++;
} else {
return 0;
}
}
return 1;
}
EXPORTED int is_number(char *s)
{
char *tail;
if (s && *s && (strtol(s, &tail, 10) || !*tail) && !*tail) {
return 1;
}
return 0;
}
/* TODO: implement parse_string() with a proper yacc/bison lexer/parser */
EXPORTED char *parse_string(const char *s, variable_list_t *vars)
{
/* protect against being called with no string - this is possible in some places */
if (!s) return NULL;
/*
* variable-ref = "${" [namespace] variable-name "}"
* namespace = identifier "." *sub-namespace
* sub-namespace = variable-name "."
* variable-name = num-variable / identifier
* num-variable = 1*DIGIT
* identifier = (ALPHA / "_") *(ALPHA / DIGIT / "_")
*/
strarray_t stringparts = STRARRAY_INITIALIZER;
variable_list_t *variable = NULL;
char *test_str;
int is_match_var;
int match_var;
int fail = 0;
strarray_append(&stringparts, s);
test_str = stringparts.data[stringparts.count-1];
while (test_str && *test_str) {
char *variable_ref_begin, *variable_ref_end;
/* find the beginning of a variable-ref */
while (*test_str && *(test_str+1)
&& !('$' == *test_str && '{' == *(test_str+1))) {
test_str++;
}
/* if we've reached the end of the string, we're done */
if (!(*test_str && *(test_str+1))) {
break;
}
/* save the beginning of the variable-ref */
variable_ref_begin = variable_ref_end = test_str;
test_str += 2;
variable_ref_end += 2;
/* find the end of the variable-ref */
while (*variable_ref_end && !('}' == *variable_ref_end)) {
variable_ref_end++;
}
/* if we've reached the end of the string, we're done */
if (!*variable_ref_end) {
break;
}
/* create a null-terminated string for comparison */
*variable_ref_end = '\0';
/* check if the string is a number */
is_match_var = is_number(test_str);
/* if we've found a valid variable, add its value to stringparts */
if (is_identifier(test_str) || is_match_var) {
/* capture the match_var variable number */
match_var = strtol(test_str, NULL, 10);
/* NULL-terminate the previous stringpart */
*variable_ref_begin = '\0';
/* attempt to find the variable */
if (is_match_var) {
variable = varlist_select(vars, VL_MATCH_VARS);
if (match_var >= variable->var->count) {
variable = NULL;
}
} else {
variable = varlist_select(vars, test_str);
}
/* add the value of the requested variable to stringparts if
* the variable is found
*/
if (variable) {
char *temp;
if (is_match_var) {
temp = xstrdup(variable->var->data[match_var]);
} else {
temp = strarray_join(variable->var, " ");
}
if (temp) {
strarray_append(&stringparts, temp);
free (temp);
}
}
/* continue search for variable-ref's after the current one */
test_str = variable_ref_end + 1;
/* add the remainder of the original string to stringparts */
if (*test_str) {
strarray_append(&stringparts, test_str);
test_str = stringparts.data[stringparts.count-1];
}
} else {
/* first check if this is a namespace, which we don't yet support.
RFC 5229, Sieve: Variables Extension, Section 3. Interpretation of Strings:
References to namespaces without a prior require statement for the
relevant extension MUST cause an error.
*/
{
char *dot;
if ((dot = strchr(test_str, '.'))) {
*dot = '\0';
if (is_identifier(test_str)) {
fail = 1;
} else {
*dot = '.';
}
}
}
/* if we haven't found a valid variable, restore the overwritten
* character
*/
*variable_ref_end = '}';
/* continue the search after the non-valid identifier */
test_str = variable_ref_begin + 2;
}
}
if ((test_str = strarray_join(&stringparts, ""))) {
strarray_appendm(varlist_select(vars, VL_PARSED_STRINGS)->var, test_str);
} else {
test_str = xstrdup("");
strarray_appendm(varlist_select(vars, VL_PARSED_STRINGS)->var, test_str);
}
strarray_fini(&stringparts);
/* TODO: test this in the sieve parser, not at script runtime */
if (0 && fail) {
free(test_str);
test_str = NULL;
}
return test_str;
}

File Metadata

Mime Type
text/x-c
Expires
Sat, Apr 4, 3:22 AM (1 d, 12 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18822391
Default Alt Text
grammar.c (5 KB)

Event Timeline