]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
double-check and fix flags.
authorAlan T. DeKok <aland@freeradius.org>
Thu, 19 May 2022 15:38:07 +0000 (11:38 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Thu, 19 May 2022 15:40:48 +0000 (11:40 -0400)
We now have a "can_purify" flag.  This is set to "true" for
pure functions which have pure arguments.  And for alternations
which have pure arguments.

%% is set to pure.  XLAT_BOX and XLAT_LITERAL are pure, but
they are not "can_purify".

The result is that we tell if there are portions of the tree
which need additional work for purification.

src/lib/unlang/xlat.h
src/lib/unlang/xlat_priv.h
src/lib/unlang/xlat_tokenize.c

index 18cd8ea6825c4068e3290ef1ce591b5adc03e089..c61773369e8294ac427984acb10a645527eb7f3a 100644 (file)
@@ -106,8 +106,8 @@ typedef struct {
        bool                    needs_resolving;//!< Needs pass2 resolution.
        bool                    needs_async;    //!< Node and all child nodes are guaranteed to not
                                                ///< require asynchronous expansion.
-       bool                    pure;           //!< has no external side effects
-       bool                    has_pure_children; //!< as the sticker says
+       bool                    pure;           //!< has no external side effects, true for BOX, LITERAL, and some functions
+       bool                    can_purify;     //!< if the xlat has a pure function with pure arguments.
 } xlat_flags_t;
 
 /*
index 67581289bc1670a3cdc3a6f49ca056bb10f8271f..4ce34148576c13ca3279ec7249fbb850d1c6c73e 100644 (file)
@@ -178,7 +178,7 @@ static inline CC_HINT(nonnull) void xlat_flags_merge(xlat_flags_t *parent, xlat_
        parent->needs_resolving |= child->needs_resolving;
        parent->pure &= child->pure; /* purity can only be removed, never added */
        parent->pure &= !parent->needs_async; /* things needing async cannot be pure */
-       parent->has_pure_children |= child->pure | child->has_pure_children;
+       parent->can_purify |= child->can_purify;
 }
 
 /** Set the type of an xlat node
index a39c7f2e19b95bf77eff9ea4253184730416b948..2885cdecdcb7c569f041bd21b24d26ed40f42057 100644 (file)
@@ -128,6 +128,12 @@ xlat_exp_t *xlat_exp_func_alloc(TALLOC_CTX *ctx, xlat_t *func, xlat_exp_head_t c
        node->flags = func->flags;
        xlat_flags_merge(&node->flags, &args->flags);
 
+       /*
+        *      If the function is pure, AND it's arguments are pure,
+        *      then remember that we need to call a pure function.
+        */
+       node->flags.can_purify = func->flags.pure && args->flags.pure;
+
        return node;
 }
 
@@ -175,6 +181,14 @@ static inline int xlat_tokenize_alternation(xlat_exp_head_t *head, fr_sbuff_t *i
        }
        node->flags = node->alternate[0]->flags;
 
+       /*
+        *      If the first argument is pure, then we can purify this
+        *      node.  If the first argument isn't pure, but the
+        *      second one is, then we can still purify the second
+        *      argument.
+        */
+       node->flags.can_purify |= node->alternate[0]->flags.pure;
+
        /*
         *      Allow the RHS to be empty as a special case.
         */
@@ -197,6 +211,7 @@ static inline int xlat_tokenize_alternation(xlat_exp_head_t *head, fr_sbuff_t *i
                goto error;
        }
        xlat_flags_merge(&node->flags, &node->alternate[1]->flags);
+       node->flags.can_purify |= node->alternate[1]->flags.pure;
 
 done:
        xlat_exp_insert_tail(head, node);
@@ -498,7 +513,11 @@ int xlat_tokenize_function_args(xlat_exp_head_t *head, fr_sbuff_t *in,
        /*
         *      Check we have all the required arguments
         */
-       if ((node->type == XLAT_FUNC) && (xlat_validate_function_args(node) < 0)) goto error;
+       if (node->type == XLAT_FUNC) {
+               if (xlat_validate_function_args(node) < 0) goto error;
+
+               node->flags.can_purify = node->call.func->flags.pure && node->call.args->flags.pure;
+       }
 
        if (!fr_sbuff_next_if_char(in, ')')) {
                fr_strerror_const("Missing closing brace");
@@ -931,8 +950,11 @@ static int xlat_tokenize_string(xlat_exp_head_t *head,
                        xlat_exp_set_type(node, XLAT_ONE_LETTER);
                        xlat_exp_set_name_buffer_shallow(node, str);
 
-                       node->flags.pure = true;         /* value boxes are always pure */
-                       node->flags.needs_async = false; /* value boxes are always non-async */
+                       /*
+                        *      %% is pure.  Everything else is not.
+                        */
+                       node->flags.pure = (node->fmt[0] == '%');
+                       node->flags.needs_async = false;
 
                        xlat_exp_insert_tail(head, node);
                        continue;
@@ -1633,6 +1655,8 @@ int xlat_resolve(xlat_exp_head_t *head, xlat_res_rules_t const *xr_rules)
                        if (xlat_resolve(node->call.args, xr_rules) < 0) return -1;
                        node->flags = node->call.func->flags;
                        xlat_flags_merge(&node->flags, &node->call.args->flags);
+
+                       node->flags.can_purify = node->call.func->flags.pure && node->call.args->flags.pure;
                        break;
 
                /*
@@ -1706,6 +1730,8 @@ int xlat_resolve(xlat_exp_head_t *head, xlat_res_rules_t const *xr_rules)
                         */
                        xlat_flags_merge(&node->flags, &node->call.args->flags);
 
+                       node->flags.can_purify = node->call.func->flags.pure && node->call.args->flags.pure;
+
                        /*
                         *      Add the freshly resolved function
                         *      to the bootstrap tree.