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; 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);

View File

@ -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);

View File

@ -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;
} }