cfengine  3.15.4
About: CFEngine is a configuration management system for configuring and maintaining Unix-like computers (using an own high level policy language). Community version.
  Fossies Dox: cfengine-3.15.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

iteration.c File Reference
#include <iteration.h>
#include <scope.h>
#include <vars.h>
#include <fncall.h>
#include <eval_context.h>
#include <misc_lib.h>
#include <string_lib.h>
#include <assoc.h>
#include <expand.h>
#include <conversion.h>
Include dependency graph for iteration.c:

Go to the source code of this file.

Data Structures

struct  Wheel
struct  PromiseIterator_


static WheelWheelNew (const char *varname, size_t varname_len)
static void WheelValuesSeqDestroy (Wheel *w)
static void WheelDestroy (void *wheel)
static int WheelCompareUnexpanded (const void *wheel1, const void *wheel2, void *user_data)
PromiseIteratorPromiseIteratorNew (const Promise *pp)
void PromiseIteratorDestroy (PromiseIterator *iterctx)
size_t PromiseIteratorIndex (const PromiseIterator *iter_ctx)
static size_t FindDollarParen (const char *s, size_t max)
static char opposite (char c)
static char * FindClosingParen (char *s, char c)
static bool IsMangled (const char *s)
static void MangleVarRefString (char *ref_str, size_t len)
static const void * IterVariableGet (const PromiseIterator *iterctx, const EvalContext *evalctx, const char *varname, DataType *type)
static bool VarIsSpecial (const char *s)
static bool ShouldAddVariableAsIterationWheel (const PromiseIterator *iterctx, const EvalContext *evalctx, char *varname, size_t varname_len)
static char * ProcessVar (PromiseIterator *iterctx, const EvalContext *evalctx, char *s, char c)
void PromiseIteratorPrepare (PromiseIterator *iterctx, const EvalContext *evalctx, char *s)
 Fills up the wheels of the iterator according to the variables found in #s. Also mangles all namespaced/scoped variables in #s. More...
static void IterListElementVariablePut (EvalContext *evalctx, const char *varname, DataType listtype, void *value)
static void SeqAppendContainerPrimitive (Seq *seq, const JsonElement *primitive)
static SeqContainerToSeq (const JsonElement *container)
static SeqRlistToSeq (const Rlist *p)
static SeqIterableToSeq (const void *v, DataType t)
static void ExpandAndPutWheelVariablesAfter (const PromiseIterator *iterctx, EvalContext *evalctx, size_t wheel_idx)
static bool IteratorHasEmptyWheel (const PromiseIterator *iterctx)
static size_t WheelRightmostIncrement (PromiseIterator *iterctx)
static bool RunOnlyOnce (PromiseIterator *iterctx)
bool PromiseIteratorNext (PromiseIterator *iterctx, EvalContext *evalctx)

Function Documentation

◆ ContainerToSeq()

◆ ExpandAndPutWheelVariablesAfter()

static void ExpandAndPutWheelVariablesAfter ( const PromiseIterator iterctx,
EvalContext evalctx,
size_t  wheel_idx 

For each of the wheels to the right of wheel_idx (including this one)

  1. varname_exp = expand the variable name
    • if it's same with previous varname_exp, skip steps 2-4
  2. values = VariableGet(varname_exp);
  3. if the value is an iterable (slist/container), set the wheel size.
  4. reset the wheel in order to re-iterate over all combinations.
  5. Put(varname_exp:first_value) in the EvalContext

Definition at line 802 of file iteration.c.

References BufferClear(), BufferDestroy(), BufferNew(), CF_DATA_TYPE_NONE, DataTypeIsIterable(), EvalContextVariablePutSpecial(), ExpandScalar(), free(), IsMangled(), Wheel::iter_index, IterableToSeq(), IterListElementVariablePut(), IterVariableGet(), Log(), LOG_LEVEL_VERBOSE, NULL, PromiseIterator_::pp, PromiseGetNamespace(), SeqAt(), SeqLength(), SPECIAL_SCOPE_THIS, Wheel::values, Wheel::varname_exp, Wheel::varname_unexp, Wheel::vartype, PromiseIterator_::wheels, WheelValuesSeqDestroy(), and xstrdup().

Referenced by PromiseIteratorNext().

◆ FindClosingParen()

static char* FindClosingParen ( char *  s,
char  c 

Find the closing parenthesis for #c in #s. #c is considered to not be part of #s (IOW, #s is considered to be a string after #c).

A closing parenthesis for #c in #s or NULL if not found

Definition at line 262 of file iteration.c.

References NULL, and opposite().

Referenced by ProcessVar().

◆ FindDollarParen()

static size_t FindDollarParen ( const char *  s,
size_t  max 

Returns offset to "$(" or "${" in the string. Reads bytes up to s[max-1], s[max] is NOT read. If a '\0' is encountered before the pattern, return offset to \0 byte If no '\0' byte or pattern is found within max bytes, max is returned

Definition at line 229 of file iteration.c.

Referenced by IsMangled(), MangleVarRefString(), ProcessVar(), PromiseIteratorPrepare(), and ShouldAddVariableAsIterationWheel().

◆ IsMangled()

static bool IsMangled ( const char *  s)

Check if variable reference is mangled, while avoiding going into the inner variables that are being expanded, or into array indexes.

@NOTE variable name is naked, i.e. shouldn't start with dollar-paren.

Definition at line 290 of file iteration.c.

References CF_MANGLED_NS, CF_MANGLED_SCOPE, FindDollarParen(), MIN, NULL, and strchrnul().

Referenced by ExpandAndPutWheelVariablesAfter(), and IterVariableGet().

◆ IterableToSeq()

◆ IteratorHasEmptyWheel()

static bool IteratorHasEmptyWheel ( const PromiseIterator iterctx)

◆ IterListElementVariablePut()

◆ IterVariableGet()

static const void* IterVariableGet ( const PromiseIterator iterctx,
const EvalContext evalctx,
const char *  varname,
DataType type 

Lookup a variable within iteration context. Since the scoped or namespaced variable names may be mangled, we have to look them up using special separators CF_MANGLED_NS and CF_MANGLED_SCOPE.

Definition at line 362 of file iteration.c.

References CF_DATA_TYPE_NONE, CF_MANGLED_NS, CF_MANGLED_SCOPE, EvalContextVariableGet(), IsMangled(), Bundle_::name, Bundle_::ns, NULL, PromiseIterator_::pp, PromiseGetBundle(), VarRefDestroy(), VarRefParse(), and VarRefParseFromNamespaceAndScope().

Referenced by ExpandAndPutWheelVariablesAfter().

◆ MangleVarRefString()

static void MangleVarRefString ( char *  ref_str,
size_t  len 

Mangle namespace and scope separators, up to '$(', '${', '[', '\0', whichever comes first.

"this" scope is never mangled, no need to VariablePut() a mangled reference in THIS scope, since the non-manled one already exists.

Definition at line 318 of file iteration.c.


Referenced by ProcessVar().

◆ opposite()

static char opposite ( char  c)

Definition at line 245 of file iteration.c.

References ProgrammingError.

Referenced by FindClosingParen(), and ProcessVar().

◆ ProcessVar()

static char* ProcessVar ( PromiseIterator iterctx,
const EvalContext evalctx,
char *  s,
char  c 

Recursive function that adds wheels to the iteration engine, according to the variable (and possibly its inner variables) in #s.

Another important thing it does, is modify the string #s, mangling all scoped or namespaced variable names. Mangling is done in order to iterate over foreign variables, without modifying the foreign value. For example if "test.var" is an slist, then we mangle it as "test#var" and on each iteration we just VariablePut(test::var) in the local scope. Mangling is skipped for variables that do not resolve, since they are not to be iterated over.

sis the start of a variable name, right after "$(" or "${".
cis the character after '$', i.e. must be either '(' or '{'.
pointer to the closing parenthesis or brace of the variable, or if not found, returns a pointer to terminating '\0' of #s.

Definition at line 515 of file iteration.c.

References FindClosingParen(), FindDollarParen(), Log(), LOG_LEVEL_ERR, LOG_MOD_ITERATIONS, LogDebug, MangleVarRefString(), NULL, opposite(), SeqAppend(), SeqLength(), SeqLookup(), ShouldAddVariableAsIterationWheel(), Wheel::varname_unexp, WheelCompareUnexpanded(), WheelDestroy(), WheelNew(), and PromiseIterator_::wheels.

Referenced by PromiseIteratorPrepare().

◆ PromiseIteratorDestroy()

void PromiseIteratorDestroy ( PromiseIterator iterctx)

Definition at line 211 of file iteration.c.

References free(), SeqDestroy(), and PromiseIterator_::wheels.

Referenced by ExpandPromise().

◆ PromiseIteratorIndex()

size_t PromiseIteratorIndex ( const PromiseIterator iter_ctx)

Definition at line 217 of file iteration.c.

References PromiseIterator_::count.

Referenced by EvalContextStackPath().

◆ PromiseIteratorNew()

PromiseIterator* PromiseIteratorNew ( const Promise pp)

Definition at line 201 of file iteration.c.

References SeqNew(), WheelDestroy(), PromiseIterator_::wheels, and xmemdup().

Referenced by ExpandPromise().

◆ PromiseIteratorNext()

◆ PromiseIteratorPrepare()

void PromiseIteratorPrepare ( PromiseIterator iterctx,
const EvalContext evalctx,
char *  s 

Fills up the wheels of the iterator according to the variables found in #s. Also mangles all namespaced/scoped variables in #s.

@EXAMPLE Have a look in iteration_test.c:test_PromiseIteratorPrepare()

@NOTE the wheel numbers can't change once iteration started, so make sure you call WheelIteratorPrepare() in advance, as many times it's needed.

Definition at line 632 of file iteration.c.

References FindDollarParen(), LOG_MOD_ITERATIONS, LogDebug, NULL, and ProcessVar().

Referenced by MapIteratorsFromRval().

◆ RlistToSeq()

static Seq* RlistToSeq ( const Rlist p)

Definition at line 757 of file iteration.c.

References Rval::item, Rlist_::next, NULL, SeqAppend(), SeqNew(), and Rlist_::val.

Referenced by IterableToSeq().

◆ RunOnlyOnce()

static bool RunOnlyOnce ( PromiseIterator iterctx)

Definition at line 976 of file iteration.c.

References PromiseIterator_::count, SeqLength(), and PromiseIterator_::wheels.

Referenced by PromiseIteratorNext().

◆ SeqAppendContainerPrimitive()

◆ ShouldAddVariableAsIterationWheel()

static bool ShouldAddVariableAsIterationWheel ( const PromiseIterator iterctx,
const EvalContext evalctx,
char *  varname,
size_t  varname_len 

Decide whether to mangle varname and add wheel to the iteration engine.

If variable contains inner expansions -> mangle and add wheel (because you don't know if it will be an iterable or not - you will know after inner variable is iterated and the variable is looked up)

else if it resolves to iterable -> mangle and add wheel

else if it resolves to empty iterable -> mangle and add wheel (see comments in code)

else if the variable name is special for some functions (this.k etc) -> mangle and add wheel

else if it resolves to non-iterable -> no mangle, no wheel

else if it doesn't resolve -> no mangle, no wheel

@NOTE Important special scopes (e.g. "connection.ip" for cf-serverd) must not be mangled to work correctly. This is auto-OK because such variables do not resolve usually.

Definition at line 440 of file iteration.c.

References ARG_UNUSED, DataTypeIsIterable(), EvalContextVariableGet(), FindDollarParen(), PromiseIterator_::pp, PromiseGetBundle(), VarIsSpecial(), VarRefDestroy(), and VarRefParseFromBundle().

Referenced by ProcessVar().

◆ VarIsSpecial()

static bool VarIsSpecial ( const char *  s)

Definition at line 401 of file iteration.c.

Referenced by IteratorHasEmptyWheel(), and ShouldAddVariableAsIterationWheel().

◆ WheelCompareUnexpanded()

static int WheelCompareUnexpanded ( const void *  wheel1,
const void *  wheel2,
void *  user_data 

Definition at line 193 of file iteration.c.

References Wheel::varname_unexp.

Referenced by ProcessVar().

◆ WheelDestroy()

static void WheelDestroy ( void *  wheel)

Definition at line 183 of file iteration.c.

References free(), Wheel::varname_exp, Wheel::varname_unexp, and WheelValuesSeqDestroy().

Referenced by ProcessVar(), and PromiseIteratorNew().

◆ WheelNew()

static Wheel* WheelNew ( const char *  varname,
size_t  varname_len 

@NOTE #varname doesn't need to be '\0'-terminated, since the length is provided.

Definition at line 149 of file iteration.c.

References NULL, Wheel::varname_unexp, xmemdup(), and xstrndup().

Referenced by ProcessVar().

◆ WheelRightmostIncrement()

static size_t WheelRightmostIncrement ( PromiseIterator iterctx)

◆ WheelValuesSeqDestroy()

static void WheelValuesSeqDestroy ( Wheel w)