Skip to content

Commit

Permalink
Make "break" jump out of the "foreach" loop
Browse files Browse the repository at this point in the history
and add a test to that effect!
  • Loading branch information
alandekok committed Nov 26, 2013
1 parent d3c1098 commit e3efcd1
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 2 deletions.
35 changes: 33 additions & 2 deletions src/main/modcall.c
Expand Up @@ -382,6 +382,7 @@ static char const *modcall_spaces = "
typedef struct modcall_stack_entry_t {
int result;
int priority;
int unwind; /* unwind to this one if it exists */
modcallable *c;
} modcall_stack_entry_t;

Expand Down Expand Up @@ -410,13 +411,21 @@ static void modcall_child(REQUEST *request, rlm_components_t component, int dept
next->c = c;
next->result = entry->result;
next->priority = 0;
next->unwind = 0;

if (!modcall_recurse(request, component,
depth, next)) {
*result = RLM_MODULE_FAIL;
return;
}

/*
* Unwind back up the stack
*/
if (next->unwind != 0) {
entry->unwind = next->unwind;
}

*result = next->result;

return;
Expand Down Expand Up @@ -696,11 +705,11 @@ static bool modcall_recurse(REQUEST *request, rlm_components_t component, int de
next->c = g->children;
next->result = entry->result;
next->priority = 0;
next->unwind = 0;

if (!modcall_recurse(request, component, depth + 1, next)) {
request_data_get(request, radius_get_vp, foreach_depth);
pairfree(&copy);

break;
}

Expand All @@ -715,6 +724,15 @@ static bool modcall_recurse(REQUEST *request, rlm_components_t component, int de
} else {
break;
}

/*
* If we've been told to stop processing
* it, do so.
*/
if (entry->unwind == MOD_FOREACH) {
entry->unwind = 0;
break;
}
} /* loop over VPs */

result = next->result;
Expand All @@ -734,7 +752,7 @@ static bool modcall_recurse(REQUEST *request, rlm_components_t component, int de
copy_p = request_data_get(request,
radius_get_vp, i);
if (copy_p) {
RDEBUG2("%.*s # BREAK Foreach-Variable-%d", depth + 1,
RDEBUG2("%.*s # break Foreach-Variable-%d", depth + 1,
modcall_spaces, i);
pairfree(copy_p);
break;
Expand All @@ -744,6 +762,7 @@ static bool modcall_recurse(REQUEST *request, rlm_components_t component, int de
/*
* Leave result / priority on the stack, and stop processing the section.
*/
entry->unwind = MOD_FOREACH;
return true;
} /* MOD_BREAK */

Expand Down Expand Up @@ -984,6 +1003,17 @@ static bool modcall_recurse(REQUEST *request, rlm_components_t component, int de
*/
if (c->type == MOD_CASE) return true;

/*
* If we've been told to stop processing
* it, do so.
*/
if (entry->unwind != 0) {
RDEBUG2("%.*s # unwind to enclosing %s", depth + 1, modcall_spaces,
group_name[entry->unwind]);
entry->unwind = 0;
return true;
}

next_sibling:
entry->c = entry->c->next;

Expand All @@ -1010,6 +1040,7 @@ int modcall(rlm_components_t component, modcallable *c, REQUEST *request)
stack[0].c = c;
stack[0].result = default_component_results[component];
stack[0].priority = 0;
stack[0].unwind = 0;

/*
* Call the main handler.
Expand Down
23 changes: 23 additions & 0 deletions src/tests/keywords/foreach-break
@@ -0,0 +1,23 @@
# PRE: foreach
#

#
# We DON'T want to see this one.
#
update request {
Filter-Id += "broken"
}

foreach Filter-Id {
#
# If we see this one, "break" out of the
# foreach loop.
#
if ("%{Foreach-Variable-0}" == "broken") {
break
}

update reply {
Called-Station-Id += "%{Foreach-Variable-0}"
}
}
17 changes: 17 additions & 0 deletions src/tests/keywords/foreach-break.attrs
@@ -0,0 +1,17 @@
#
# Input packet
#
User-Name = "bob"
User-Password = "hello"
Filter-Id = "1"
Filter-Id += "2"
Filter-Id += "3"
Filter-Id += "4"

#
# Expected answer
#
Called-Station-Id == "1"
Called-Station-Id == "2"
Called-Station-Id == "3"
Called-Station-Id == "4"

0 comments on commit e3efcd1

Please sign in to comment.