Get rid of the depth argument to dfilter_macro_apply(); have an internal
routine that does all the work and that takes a depth argumen, and an external routine that calls that internal routine with a depth argument of 0. The depth is only of use internally, to avoid infinite recursion. When recursing with that routine, pass depth+1 as the depth value, rather than passing depth and incrementing it afterwards; the latter doesn't prevent infinite recursion. (Thanks and a tip of the hat to Clang Cat for catching this.) Squelch some other (harmless) warnings from Clang Cat. Clean up indentation. svn path=/trunk/; revision=39838
This commit is contained in:
parent
91398db56b
commit
70a8b27948
|
@ -217,7 +217,7 @@ static gchar* dfilter_macro_resolve(gchar* name, gchar** args, const gchar** err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
gchar* dfilter_macro_apply(const gchar* text, guint depth, const gchar** error) {
|
static gchar* dfilter_macro_apply_recurse(const gchar* text, guint depth, const gchar** error) {
|
||||||
enum { OUTSIDE, STARTING, NAME, ARGS } state = OUTSIDE;
|
enum { OUTSIDE, STARTING, NAME, ARGS } state = OUTSIDE;
|
||||||
GString* out;
|
GString* out;
|
||||||
GString* name = NULL;
|
GString* name = NULL;
|
||||||
|
@ -241,62 +241,113 @@ gchar* dfilter_macro_apply(const gchar* text, guint depth, const gchar** error)
|
||||||
if (args) { \
|
if (args) { \
|
||||||
while(args->len) { void* p = g_ptr_array_remove_index_fast(args,0); if (p) g_free(p); } \
|
while(args->len) { void* p = g_ptr_array_remove_index_fast(args,0); if (p) g_free(p); } \
|
||||||
g_ptr_array_free(args,TRUE); \
|
g_ptr_array_free(args,TRUE); \
|
||||||
args = NULL; } } while(0)
|
args = NULL; \
|
||||||
|
} \
|
||||||
|
} while(0)
|
||||||
|
|
||||||
*error = NULL;
|
*error = NULL;
|
||||||
out = g_string_sized_new(64);
|
out = g_string_sized_new(64);
|
||||||
|
|
||||||
while(1) {
|
while(1) {
|
||||||
c = *r++;
|
c = *r++;
|
||||||
|
|
||||||
switch(state) {
|
switch(state) {
|
||||||
case OUTSIDE: {
|
case OUTSIDE: {
|
||||||
switch(c) {
|
switch(c) {
|
||||||
case '\0': {
|
case '\0': {
|
||||||
goto finish;
|
goto finish;
|
||||||
} case '$': {
|
} case '$': {
|
||||||
state = STARTING;
|
state = STARTING;
|
||||||
break;
|
break;
|
||||||
} default: {
|
} default: {
|
||||||
g_string_append_c(out,c);
|
g_string_append_c(out,c);
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
} case STARTING: {
|
break;
|
||||||
switch (c) {
|
} case STARTING: {
|
||||||
case '{': {
|
switch (c) {
|
||||||
args = g_ptr_array_new();
|
case '{': {
|
||||||
arg = g_string_sized_new(32);
|
args = g_ptr_array_new();
|
||||||
name = g_string_sized_new(32);
|
arg = g_string_sized_new(32);
|
||||||
|
name = g_string_sized_new(32);
|
||||||
|
|
||||||
state = NAME;
|
state = NAME;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
} case '\0': {
|
} case '\0': {
|
||||||
g_string_append_c(out,'$');
|
g_string_append_c(out,'$');
|
||||||
|
|
||||||
goto finish;
|
goto finish;
|
||||||
} default: {
|
} default: {
|
||||||
g_string_append_c(out,'$');
|
g_string_append_c(out,'$');
|
||||||
g_string_append_c(out,c);
|
g_string_append_c(out,c);
|
||||||
|
|
||||||
state = OUTSIDE;
|
state = OUTSIDE;
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
} case NAME: {
|
break;
|
||||||
if ( isalnum((int)c) || c == '_' || c == '-' || c == '.' ) {
|
} case NAME: {
|
||||||
g_string_append_c(name,c);
|
if ( isalnum((int)c) || c == '_' || c == '-' || c == '.' ) {
|
||||||
} else if ( c == ':') {
|
g_string_append_c(name,c);
|
||||||
state = ARGS;
|
} else if ( c == ':') {
|
||||||
} else if ( c == '}') {
|
state = ARGS;
|
||||||
|
} else if ( c == '}') {
|
||||||
|
gchar* resolved;
|
||||||
|
|
||||||
|
g_ptr_array_add(args,NULL);
|
||||||
|
|
||||||
|
resolved = dfilter_macro_resolve(name->str, (gchar**)args->pdata, error);
|
||||||
|
if (*error) goto on_error;
|
||||||
|
|
||||||
|
changed = TRUE;
|
||||||
|
|
||||||
|
g_string_append(out,resolved);
|
||||||
|
|
||||||
|
FREE_ALL();
|
||||||
|
|
||||||
|
state = OUTSIDE;
|
||||||
|
} else if ( c == '\0') {
|
||||||
|
*error = "end of filter in the middle of a macro expression";
|
||||||
|
goto on_error;
|
||||||
|
} else {
|
||||||
|
*error = "invalid char in macro name";
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
} case ARGS: {
|
||||||
|
switch(c) {
|
||||||
|
case '\0': {
|
||||||
|
*error = "end of filter in the middle of a macro expression";
|
||||||
|
goto on_error;
|
||||||
|
} case ';': {
|
||||||
|
g_ptr_array_add(args,arg->str);
|
||||||
|
g_string_free(arg,FALSE);
|
||||||
|
|
||||||
|
arg = g_string_sized_new(32);
|
||||||
|
break;
|
||||||
|
} case '\\': {
|
||||||
|
c = *r++;
|
||||||
|
if (c) {
|
||||||
|
g_string_append_c(arg,c);
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
*error = "end of filter in the middle of a macro expression";
|
||||||
|
goto on_error;
|
||||||
|
}
|
||||||
|
} default: {
|
||||||
|
g_string_append_c(arg,c);
|
||||||
|
break;
|
||||||
|
} case '}': {
|
||||||
gchar* resolved;
|
gchar* resolved;
|
||||||
|
g_ptr_array_add(args,arg->str);
|
||||||
g_ptr_array_add(args,NULL);
|
g_ptr_array_add(args,NULL);
|
||||||
|
|
||||||
|
g_string_free(arg,FALSE);
|
||||||
|
arg = NULL;
|
||||||
|
|
||||||
resolved = dfilter_macro_resolve(name->str, (gchar**)args->pdata, error);
|
resolved = dfilter_macro_resolve(name->str, (gchar**)args->pdata, error);
|
||||||
if (*error) goto on_error;
|
if (*error) goto on_error;
|
||||||
|
|
||||||
|
@ -307,84 +358,39 @@ gchar* dfilter_macro_apply(const gchar* text, guint depth, const gchar** error)
|
||||||
FREE_ALL();
|
FREE_ALL();
|
||||||
|
|
||||||
state = OUTSIDE;
|
state = OUTSIDE;
|
||||||
} else if ( c == '\0') {
|
break;
|
||||||
*error = "end of filter in the middle of a macro expression";
|
|
||||||
goto on_error;
|
|
||||||
} else {
|
|
||||||
*error = "invalid char in macro name";
|
|
||||||
goto on_error;
|
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
} case ARGS: {
|
|
||||||
switch(c) {
|
|
||||||
case '\0': {
|
|
||||||
*error = "end of filter in the middle of a macro expression";
|
|
||||||
goto on_error;
|
|
||||||
} case ';': {
|
|
||||||
g_ptr_array_add(args,arg->str);
|
|
||||||
g_string_free(arg,FALSE);
|
|
||||||
|
|
||||||
arg = g_string_sized_new(32);
|
|
||||||
break;
|
|
||||||
} case '\\': {
|
|
||||||
c = *r++;
|
|
||||||
if (c) {
|
|
||||||
g_string_append_c(arg,c);
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
*error = "end of filter in the middle of a macro expression";
|
|
||||||
goto on_error;
|
|
||||||
}
|
|
||||||
} default: {
|
|
||||||
g_string_append_c(arg,c);
|
|
||||||
break;
|
|
||||||
} case '}': {
|
|
||||||
gchar* resolved;
|
|
||||||
g_ptr_array_add(args,arg->str);
|
|
||||||
g_ptr_array_add(args,NULL);
|
|
||||||
|
|
||||||
g_string_free(arg,FALSE);
|
|
||||||
arg = NULL;
|
|
||||||
|
|
||||||
resolved = dfilter_macro_resolve(name->str, (gchar**)args->pdata, error);
|
|
||||||
if (*error) goto on_error;
|
|
||||||
|
|
||||||
changed = TRUE;
|
|
||||||
|
|
||||||
g_string_append(out,resolved);
|
|
||||||
|
|
||||||
FREE_ALL();
|
|
||||||
|
|
||||||
state = OUTSIDE;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
finish:
|
finish:
|
||||||
{
|
{
|
||||||
FREE_ALL();
|
FREE_ALL();
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
gchar* resolved = dfilter_macro_apply(out->str, depth++, error);
|
gchar* resolved = dfilter_macro_apply_recurse(out->str, depth + 1, error);
|
||||||
g_string_free(out,TRUE);
|
|
||||||
return (*error) ? NULL : resolved;
|
|
||||||
} else {
|
|
||||||
gchar* out_str = ep_strdup(out->str);
|
|
||||||
g_string_free(out,TRUE);
|
|
||||||
return out_str;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
on_error:
|
|
||||||
{
|
|
||||||
FREE_ALL();
|
|
||||||
if (! *error) *error = "unknown error in macro expression";
|
|
||||||
g_string_free(out,TRUE);
|
g_string_free(out,TRUE);
|
||||||
return NULL;
|
return (*error) ? NULL : resolved;
|
||||||
|
} else {
|
||||||
|
gchar* out_str = ep_strdup(out->str);
|
||||||
|
g_string_free(out,TRUE);
|
||||||
|
return out_str;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
on_error:
|
||||||
|
{
|
||||||
|
FREE_ALL();
|
||||||
|
if (! *error) *error = "unknown error in macro expression";
|
||||||
|
g_string_free(out,TRUE);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gchar* dfilter_macro_apply(const gchar* text, const gchar** error) {
|
||||||
|
return dfilter_macro_apply_recurse(text, 0, error);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void macro_update(void* mp, const gchar** error) {
|
static void macro_update(void* mp, const gchar** error) {
|
||||||
|
@ -429,7 +435,7 @@ static void macro_update(void* mp, const gchar** error) {
|
||||||
*(w++) = *(r++);
|
*(w++) = *(r++);
|
||||||
break;
|
break;
|
||||||
case '\0':
|
case '\0':
|
||||||
*(w++) = *(r++);
|
*w = *r;
|
||||||
goto done;
|
goto done;
|
||||||
case '\\':
|
case '\\':
|
||||||
*(w++) = *(++r);
|
*(w++) = *(++r);
|
||||||
|
|
|
@ -48,7 +48,7 @@ void dfilter_macro_save(const gchar*, gchar**);
|
||||||
void dfilter_macro_dump(void);
|
void dfilter_macro_dump(void);
|
||||||
|
|
||||||
/* applies all macros to the given text and returns the resulting string or NULL on failure */
|
/* applies all macros to the given text and returns the resulting string or NULL on failure */
|
||||||
gchar* dfilter_macro_apply(const gchar* text, guint depth, const gchar** error);
|
gchar* dfilter_macro_apply(const gchar* text, const gchar** error);
|
||||||
|
|
||||||
void dfilter_macro_init(void);
|
void dfilter_macro_init(void);
|
||||||
|
|
||||||
|
|
|
@ -230,7 +230,7 @@ dfilter_compile(const gchar *text, dfilter_t **dfp)
|
||||||
|
|
||||||
dfilter_error_msg = NULL;
|
dfilter_error_msg = NULL;
|
||||||
|
|
||||||
if ( !( text = dfilter_macro_apply(text, 0, &dfilter_error_msg) ) ) {
|
if ( !( text = dfilter_macro_apply(text, &dfilter_error_msg) ) ) {
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue