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:
Guy Harris 2011-11-15 04:26:38 +00:00
parent 91398db56b
commit 70a8b27948
3 changed files with 122 additions and 116 deletions

View File

@ -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;
GString* out;
GString* name = NULL;
@ -241,62 +241,113 @@ gchar* dfilter_macro_apply(const gchar* text, guint depth, const gchar** error)
if (args) { \
while(args->len) { void* p = g_ptr_array_remove_index_fast(args,0); if (p) g_free(p); } \
g_ptr_array_free(args,TRUE); \
args = NULL; } } while(0)
args = NULL; \
} \
} while(0)
*error = NULL;
out = g_string_sized_new(64);
*error = NULL;
out = g_string_sized_new(64);
while(1) {
c = *r++;
while(1) {
c = *r++;
switch(state) {
case OUTSIDE: {
switch(c) {
case '\0': {
goto finish;
} case '$': {
state = STARTING;
break;
} default: {
g_string_append_c(out,c);
break;
}
switch(state) {
case OUTSIDE: {
switch(c) {
case '\0': {
goto finish;
} case '$': {
state = STARTING;
break;
} default: {
g_string_append_c(out,c);
break;
}
break;
} case STARTING: {
switch (c) {
case '{': {
args = g_ptr_array_new();
arg = g_string_sized_new(32);
name = g_string_sized_new(32);
}
break;
} case STARTING: {
switch (c) {
case '{': {
args = g_ptr_array_new();
arg = g_string_sized_new(32);
name = g_string_sized_new(32);
state = NAME;
state = NAME;
break;
} case '\0': {
g_string_append_c(out,'$');
break;
} case '\0': {
g_string_append_c(out,'$');
goto finish;
} default: {
g_string_append_c(out,'$');
g_string_append_c(out,c);
goto finish;
} default: {
g_string_append_c(out,'$');
g_string_append_c(out,c);
state = OUTSIDE;
state = OUTSIDE;
break;
}
break;
}
break;
} case NAME: {
if ( isalnum((int)c) || c == '_' || c == '-' || c == '.' ) {
g_string_append_c(name,c);
} else if ( c == ':') {
state = ARGS;
} else if ( c == '}') {
}
break;
} case NAME: {
if ( isalnum((int)c) || c == '_' || c == '-' || c == '.' ) {
g_string_append_c(name,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;
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;
@ -307,84 +358,39 @@ gchar* dfilter_macro_apply(const gchar* text, guint depth, const gchar** error)
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;
}
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:
{
FREE_ALL();
{
FREE_ALL();
if (changed) {
gchar* resolved = dfilter_macro_apply(out->str, depth++, 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";
if (changed) {
gchar* resolved = dfilter_macro_apply_recurse(out->str, depth + 1, error);
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) {
@ -429,7 +435,7 @@ static void macro_update(void* mp, const gchar** error) {
*(w++) = *(r++);
break;
case '\0':
*(w++) = *(r++);
*w = *r;
goto done;
case '\\':
*(w++) = *(++r);

View File

@ -48,7 +48,7 @@ void dfilter_macro_save(const gchar*, gchar**);
void dfilter_macro_dump(void);
/* 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);

View File

@ -230,7 +230,7 @@ dfilter_compile(const gchar *text, dfilter_t **dfp)
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;
}