static void test_zeroBuffer(void) { char *element0 = xstrdup("element0"); unsigned int element0size = strlen(element0); const char *element0pointer = NULL; Buffer *buffer = BufferNew(); assert_int_equal(element0size, BufferSet(buffer, element0, element0size)); element0pointer = buffer->buffer; assert_int_equal(element0size, buffer->used); assert_int_equal(element0size, BufferSize(buffer)); BufferZero(buffer); assert_int_equal(DEFAULT_BUFFER_SIZE, buffer->capacity); assert_int_equal(0, buffer->used); assert_int_equal(0, BufferSize(buffer)); const char *data = BufferData(buffer); assert_string_equal(data, ""); assert_true(element0pointer == buffer->buffer); BufferZero(NULL); assert_int_equal(0, BufferDestroy(&buffer)); /* * Release the resources */ BufferDestroy(&buffer); free (element0); }
static void test_zeroBuffer(void **state) { char element0[] = "element0"; unsigned int element0size = strlen(element0); const char *element0pointer = NULL; Buffer *buffer = NULL; assert_int_equal(0, BufferNew(&buffer)); assert_int_equal(element0size, BufferSet(buffer, element0, element0size)); element0pointer = buffer->buffer; assert_int_equal(element0size, buffer->used); assert_int_equal(element0size, BufferSize(buffer)); BufferZero(buffer); assert_int_equal(DEFAULT_BUFFER_SIZE, buffer->capacity); assert_int_equal(0, buffer->used); assert_int_equal(0, BufferSize(buffer)); assert_true(element0pointer == buffer->buffer); BufferZero(NULL); assert_int_equal(0, BufferDestroy(&buffer)); }
static PromiseResult ExpandPromiseAndDo(EvalContext *ctx, const Promise *pp, Rlist *lists, Rlist *containers, PromiseActuator *ActOnPromise, void *param) { const char *handle = PromiseGetHandle(pp); EvalContextStackPushPromiseFrame(ctx, pp, true); PromiseIterator *iter_ctx = NULL; size_t i = 0; PromiseResult result = PROMISE_RESULT_NOOP; Buffer *expbuf = BufferNew(); for (iter_ctx = PromiseIteratorNew(ctx, pp, lists, containers); PromiseIteratorHasMore(iter_ctx); i++, PromiseIteratorNext(iter_ctx)) { if (handle) { // This ordering is necessary to get automated canonification BufferZero(expbuf); ExpandScalar(ctx, NULL, "this", handle, expbuf); CanonifyNameInPlace(BufferGet(expbuf)); EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "handle", BufferData(expbuf), CF_DATA_TYPE_STRING, "source=promise"); } else { EvalContextVariablePutSpecial(ctx, SPECIAL_SCOPE_THIS, "handle", PromiseID(pp), CF_DATA_TYPE_STRING, "source=promise"); } const Promise *pexp = EvalContextStackPushPromiseIterationFrame(ctx, i, iter_ctx); PromiseResult iteration_result = ActOnPromise(ctx, pexp, param); result = PromiseResultUpdate(result, iteration_result); if (strcmp(pp->parent_promise_type->name, "vars") == 0 || strcmp(pp->parent_promise_type->name, "meta") == 0) { VerifyVarPromise(ctx, pexp, true); } EvalContextStackPopFrame(ctx); } BufferDestroy(expbuf); PromiseIteratorDestroy(iter_ctx); EvalContextStackPopFrame(ctx); return result; }
static void test_vprintf(void) { char *char0 = xstrdup("char0"); unsigned int char0size = strlen(char0); const char *char0pointer = NULL; char *char1 = xstrdup("char1"); unsigned int char1size = strlen(char1); const char *char1pointer = NULL; char *char2 = (char *)xmalloc(2 * DEFAULT_BUFFER_SIZE + 2); unsigned int char2size = 2 * DEFAULT_BUFFER_SIZE + 1; int int0 = 123456789; char *int0char = xstrdup("123456789"); unsigned int int0charsize = strlen(int0char); double double0 = 3.1415; char *double0char = xstrdup("3.1415"); unsigned int double0charsize = strlen(double0char); char *char0int0char1double0 = xstrdup("char0 123456789 char1 3.1415"); unsigned int char0int0char1double0size = strlen(char0int0char1double0); char *element3 = (char *)xmalloc(DEFAULT_MEMORY_CAP * 2); unsigned int element3size = 2 * DEFAULT_MEMORY_CAP; Buffer *buffer = BufferNew(); assert_true(buffer != NULL); /* * Print the first char and compare the result */ assert_int_equal(char0size, test_vprintf_helper(buffer, "%s", char0)); char0pointer = buffer->buffer; assert_string_equal(char0, buffer->buffer); assert_string_equal(char0, BufferData(buffer)); assert_int_equal(char0size, buffer->used); assert_int_equal(char0size, BufferSize(buffer)); /* * Overwrite the first char with the second one */ assert_int_equal(char1size, test_vprintf_helper(buffer, "%s", char1)); char1pointer = buffer->buffer; assert_string_equal(char1, buffer->buffer); assert_string_equal(char1, BufferData(buffer)); assert_int_equal(char1size, buffer->used); assert_int_equal(char1size, BufferSize(buffer)); assert_true(char0pointer == char1pointer); /* * Try the int now */ assert_int_equal(int0charsize, test_vprintf_helper(buffer, "%d", int0)); assert_string_equal(int0char, buffer->buffer); assert_string_equal(int0char, BufferData(buffer)); assert_int_equal(int0charsize, buffer->used); assert_int_equal(int0charsize, BufferSize(buffer)); /* * Try the double now */ assert_int_equal(double0charsize, test_vprintf_helper(buffer, "%.4f", double0)); assert_string_equal(double0char, buffer->buffer); assert_string_equal(double0char, BufferData(buffer)); assert_int_equal(double0charsize, buffer->used); assert_int_equal(double0charsize, BufferSize(buffer)); /* * Try the combination now */ assert_int_equal(char0int0char1double0size, test_vprintf_helper(buffer, "%s %d %s %.4f", char0, int0, char1, double0)); assert_string_equal(char0int0char1double0, buffer->buffer); assert_string_equal(char0int0char1double0, BufferData(buffer)); assert_int_equal(char0int0char1double0size, buffer->used); assert_int_equal(char0int0char1double0size, BufferSize(buffer)); /* * Finally, try something larger than the default buffer and see if we get the right return value. */ unsigned int i = 0; for (i = 0; i < char2size; ++i) char2[i] = 'a'; char2[char2size] = '\0'; // The buffer should resize itself assert_int_equal(char2size, test_vprintf_helper(buffer, "%s", char2)); assert_string_equal(char2, buffer->buffer); assert_string_equal(char2, BufferData(buffer)); assert_int_equal(char2size, buffer->used); assert_int_equal(char2size, BufferSize(buffer)); /* * A buffer that is so large that it will get rejected by our memory cap */ BufferZero(buffer); for (i = 0; i < element3size; ++i) { element3[i] = 'b'; } element3[element3size - 1] = '\0'; assert_int_equal(-1, test_vprintf_helper(buffer, "%s", element3)); /* * Boundary checks, BUFFER_SIZE-1, BUFFER_SIZE and BUFFER_SIZE+1 */ Buffer *bm1 = BufferNew(); Buffer *be = BufferNew(); Buffer *bp1 = BufferNew(); /* * The sizes are different for printf. If we have a size of X, then the string * is of length X-1, and so forth. */ char buffer_m1[DEFAULT_BUFFER_SIZE]; char buffer_0[DEFAULT_BUFFER_SIZE + 1]; char buffer_p1[DEFAULT_BUFFER_SIZE + 2]; unsigned int bm1_size = DEFAULT_BUFFER_SIZE - 1; unsigned int be_size = DEFAULT_BUFFER_SIZE; unsigned int bp1_size = DEFAULT_BUFFER_SIZE + 1; /* * Make sure the buffers are filled with 0. */ memset(buffer_m1, '\0', DEFAULT_BUFFER_SIZE); memset(buffer_0, '\0', DEFAULT_BUFFER_SIZE + 1); memset(buffer_p1, '\0', DEFAULT_BUFFER_SIZE + 2); /* * Write something to the buffers */ memset(buffer_m1, 'c', DEFAULT_BUFFER_SIZE); memset(buffer_0, 'd', DEFAULT_BUFFER_SIZE + 1); memset(buffer_p1, 'e', DEFAULT_BUFFER_SIZE + 2); /* * One shorter, that means the buffer remains the same size as before. */ buffer_m1[DEFAULT_BUFFER_SIZE - 1] = '\0'; assert_int_equal(bm1_size, test_vprintf_helper(bm1, "%s", buffer_m1)); assert_string_equal(buffer_m1, bm1->buffer); assert_int_equal(bm1->capacity, DEFAULT_BUFFER_SIZE); /* * Same size, it should allocate one more block. * This means retrying the operation. */ buffer_0[DEFAULT_BUFFER_SIZE] = '\0'; assert_int_equal(be_size, test_vprintf_helper(be, "%s", buffer_0)); assert_string_equal(buffer_0, be->buffer); assert_int_equal(be->capacity, 2 * DEFAULT_BUFFER_SIZE); /* * 1 more, it should allocate one more block * This means retrying the operation. */ buffer_p1[DEFAULT_BUFFER_SIZE + 1] = '\0'; assert_int_equal(bp1_size, test_vprintf_helper(bp1, "%s", buffer_p1)); assert_string_equal(buffer_p1, bp1->buffer); assert_int_equal(bp1->capacity, 2 * DEFAULT_BUFFER_SIZE); /* * Release the resources */ BufferDestroy(&buffer); BufferDestroy(&bm1); BufferDestroy(&be); BufferDestroy(&bp1); free (char0); free (char1); free (char2); free (int0char); free (double0char); free (char0int0char1double0); free (element3); }
static void test_setBuffer(void) { char *element0 = xstrdup("element0"); unsigned int element0size = strlen(element0); char *element1 = (char *)xmalloc(2 * DEFAULT_BUFFER_SIZE + 2); unsigned int element1size = 2 * DEFAULT_BUFFER_SIZE + 1; char *element2 = (char *)xmalloc(DEFAULT_MEMORY_CAP * 2); unsigned int element2size = 2 * DEFAULT_MEMORY_CAP; Buffer *buffer = BufferNew(); assert_true(buffer != NULL); // Smaller than the allocated buffer assert_int_equal(element0size, BufferSet(buffer, element0, element0size)); assert_int_equal(element0size, buffer->used); assert_int_equal(element0size, BufferSize(buffer)); assert_string_equal(element0, buffer->buffer); assert_string_equal(element0, BufferData(buffer)); assert_int_equal(DEFAULT_BUFFER_SIZE, buffer->capacity); // Larger than the allocated buffer int i = 0; for (i = 0; i < element1size; ++i) element1[i] = 'a'; element1[element1size] = '\0'; assert_int_equal(element1size, BufferSet(buffer, element1, element1size)); assert_int_equal(element1size, buffer->used); assert_string_equal(element1, buffer->buffer); assert_string_equal(element1, BufferData(buffer)); assert_int_equal(DEFAULT_BUFFER_SIZE * 3, buffer->capacity); /* * A buffer that is so large that it will get rejected by our memory cap */ BufferZero(buffer); for (i = 0; i < element2size; ++i) { element2[i] = 'b'; } element2[element2size - 1] = '\0'; assert_int_equal(-1, BufferSet(buffer, element2, element2size)); /* * Boundary checks, BUFFER_SIZE-1, BUFFER_SIZE and BUFFER_SIZE+1 */ Buffer *bm1 = BufferNew(); Buffer *be = BufferNew(); Buffer *bp1 = BufferNew(); char buffer_m1[DEFAULT_BUFFER_SIZE - 1]; char buffer_0[DEFAULT_BUFFER_SIZE]; char buffer_p1[DEFAULT_BUFFER_SIZE + 1]; unsigned int bm1_size = DEFAULT_BUFFER_SIZE - 1; unsigned int be_size = DEFAULT_BUFFER_SIZE; unsigned int bp1_size = DEFAULT_BUFFER_SIZE + 1; for (i = 0; i < DEFAULT_BUFFER_SIZE - 1; ++i) { buffer_m1[i] = 'c'; buffer_0[i] = 'd'; buffer_p1[i] = 'e'; } /* * One shorter, that means the buffer remains the same size as before. */ buffer_m1[DEFAULT_BUFFER_SIZE - 2] = '\0'; assert_int_equal(bm1_size, BufferSet(bm1, buffer_m1, bm1_size)); assert_int_equal(bm1->capacity, DEFAULT_BUFFER_SIZE); /* * Same size, it should allocate one more block */ buffer_0[DEFAULT_BUFFER_SIZE - 1] = '\0'; assert_int_equal(be_size, BufferSet(be, buffer_0, be_size)); assert_int_equal(be->capacity, 2 * DEFAULT_BUFFER_SIZE); /* * 1 more, it should allocate one more block */ buffer_p1[DEFAULT_BUFFER_SIZE] = '\0'; assert_int_equal(bp1_size, BufferSet(bp1, buffer_p1, bp1_size)); assert_int_equal(bp1->capacity, 2 * DEFAULT_BUFFER_SIZE); // Negative cases assert_int_equal(-1, BufferSet(NULL, element0, element0size)); assert_int_equal(-1, BufferSet(NULL, NULL, element0size)); assert_int_equal(-1, BufferSet(buffer, NULL, element0size)); assert_int_equal(0, BufferSet(buffer, element0, 0)); /* * Destroy the buffer and good night. */ assert_int_equal(0, BufferDestroy(&buffer)); assert_true(buffer == NULL); BufferDestroy(&bm1); BufferDestroy(&be); BufferDestroy(&bp1); free (element0); free (element1); free (element2); }
static void test_appendBuffer(void) { char *element0 = xstrdup("element0"); unsigned int element0size = strlen(element0); const char *element0pointer = NULL; char *element1 = xstrdup("element1"); unsigned int element1size = strlen(element1); const char *element1pointer = NULL; char *element2 = (char *)xmalloc(2 * DEFAULT_BUFFER_SIZE + 2); unsigned int element2size = 2 * DEFAULT_BUFFER_SIZE + 1; char *element3 = (char *)xmalloc(DEFAULT_MEMORY_CAP * 2); unsigned int element3size = 2 * DEFAULT_MEMORY_CAP; Buffer *buffer = BufferNew(); assert_true(buffer != NULL); // Initialize the buffer with a small string assert_int_equal(element0size, BufferAppend(buffer, element0, element0size)); element0pointer = buffer->buffer; assert_int_equal(element0size, buffer->used); assert_int_equal(element0size, BufferSize(buffer)); assert_string_equal(element0, buffer->buffer); assert_string_equal(element0, BufferData(buffer)); assert_int_equal(DEFAULT_BUFFER_SIZE, buffer->capacity); // Attach a small string to it assert_int_equal(element0size + element1size, BufferAppend(buffer, element1, element1size)); element1pointer = buffer->buffer; assert_true(element0pointer == element1pointer); assert_int_equal(buffer->used, element0size + element1size); assert_int_equal(BufferSize(buffer), element0size + element1size); char *shortAppend = NULL; shortAppend = (char *)xmalloc(element0size + element1size + 1); strcpy(shortAppend, element0); strcat(shortAppend, element1); assert_string_equal(shortAppend, buffer->buffer); assert_string_equal(shortAppend, BufferData(buffer)); /* * Zero the string and start again. */ BufferZero(buffer); assert_int_equal(element0size, BufferAppend(buffer, element0, element0size)); element0pointer = buffer->buffer; assert_int_equal(element0size, buffer->used); assert_int_equal(element0size, BufferSize(buffer)); assert_string_equal(element0, buffer->buffer); assert_string_equal(element0, BufferData(buffer)); /* * Larger than the allocated buffer, this means we will allocate more memory * copy stuff into the new buffer and all that. */ int i = 0; for (i = 0; i < element2size; ++i) element2[i] = 'a'; element2[element2size] = '\0'; assert_int_equal(element0size + element2size, BufferAppend(buffer, element2, element2size)); assert_int_equal(buffer->used, element0size + element2size); assert_int_equal(BufferSize(buffer), element0size + element2size); char *longAppend = NULL; longAppend = (char *)xmalloc(element0size + element2size + 1); strcpy(longAppend, element0); strcat(longAppend, element2); assert_string_equal(longAppend, buffer->buffer); assert_string_equal(longAppend, BufferData(buffer)); /* * A buffer that is so large that it will get rejected by our memory cap */ BufferZero(buffer); for (i = 0; i < element3size; ++i) { element3[i] = 'b'; } element3[element3size - 1] = '\0'; assert_int_equal(-1, BufferAppend(buffer, element3, element3size)); /* * Boundary checks, BUFFER_SIZE-1, BUFFER_SIZE and BUFFER_SIZE+1 */ Buffer *bm1 = BufferNew(); Buffer *be = BufferNew(); Buffer *bp1 = BufferNew(); char buffer_m1[DEFAULT_BUFFER_SIZE - 1]; char buffer_0[DEFAULT_BUFFER_SIZE]; char buffer_p1[DEFAULT_BUFFER_SIZE + 1]; unsigned int bm1_size = DEFAULT_BUFFER_SIZE - 1; unsigned int be_size = DEFAULT_BUFFER_SIZE; unsigned int bp1_size = DEFAULT_BUFFER_SIZE + 1; for (i = 0; i < DEFAULT_BUFFER_SIZE - 1; ++i) { buffer_m1[i] = 'c'; buffer_0[i] = 'd'; buffer_p1[i] = 'e'; } /* * One shorter, that means the buffer remains the same size as before. */ buffer_m1[DEFAULT_BUFFER_SIZE - 2] = '\0'; assert_int_equal(bm1_size, BufferAppend(bm1, buffer_m1, bm1_size)); assert_int_equal(bm1->capacity, DEFAULT_BUFFER_SIZE); /* * Same size, it should allocate one more block */ buffer_0[DEFAULT_BUFFER_SIZE - 1] = '\0'; assert_int_equal(be_size, BufferAppend(be, buffer_0, be_size)); assert_int_equal(be->capacity, 2 * DEFAULT_BUFFER_SIZE); /* * 1 more, it should allocate one more block */ buffer_p1[DEFAULT_BUFFER_SIZE] = '\0'; assert_int_equal(bp1_size, BufferAppend(bp1, buffer_p1, bp1_size)); assert_int_equal(bp1->capacity, 2 * DEFAULT_BUFFER_SIZE); /* * Destroy the buffer and good night. */ free(shortAppend); free(longAppend); assert_int_equal(0, BufferDestroy(&buffer)); assert_int_equal(0, BufferDestroy(&bm1)); assert_int_equal(0, BufferDestroy(&be)); assert_int_equal(0, BufferDestroy(&bp1)); free (element0); free (element1); free (element2); free (element3); }
bool ExpandScalar(const EvalContext *ctx, const char *ns, const char *scope, const char *string, Buffer *out) { assert(string); bool returnval = true; if (strlen(string) == 0) { return false; } // TODO: cleanup, optimize this mess Buffer *var = BufferNew(); Buffer *current_item = BufferNew(); Buffer *temp = BufferNew(); for (const char *sp = string; /* No exit */ ; sp++) /* check for varitems */ { char varstring = false; size_t increment = 0; if (*sp == '\0') { break; } BufferZero(current_item); ExtractScalarPrefix(current_item, sp, strlen(sp)); BufferAppend(out, BufferData(current_item), BufferSize(current_item)); sp += BufferSize(current_item); if (*sp == '\0') { break; } BufferZero(var); if (*sp == '$') { switch (*(sp + 1)) { case '(': varstring = ')'; ExtractScalarReference(var, sp, strlen(sp), false); if (BufferSize(var) == 0) { BufferAppendChar(out, '$'); continue; } break; case '{': varstring = '}'; ExtractScalarReference(var, sp, strlen(sp), false); if (BufferSize(var) == 0) { BufferAppendChar(out, '$'); continue; } break; default: BufferAppendChar(out, '$'); continue; } } BufferZero(current_item); { BufferZero(temp); ExtractScalarReference(temp, sp, strlen(sp), true); if (IsCf3VarString(BufferData(temp))) { ExpandScalar(ctx, ns, scope, BufferData(temp), current_item); } else { BufferAppend(current_item, BufferData(temp), BufferSize(temp)); } } increment = BufferSize(var) - 1; char name[CF_MAXVARSIZE] = ""; if (!IsExpandable(BufferData(current_item))) { DataType type = DATA_TYPE_NONE; const void *value = NULL; { VarRef *ref = VarRefParseFromNamespaceAndScope(BufferData(current_item), ns, scope, CF_NS, '.'); value = EvalContextVariableGet(ctx, ref, &type); VarRefDestroy(ref); } if (value) { switch (type) { case DATA_TYPE_STRING: case DATA_TYPE_INT: case DATA_TYPE_REAL: BufferAppend(out, value, strlen(value)); break; case DATA_TYPE_STRING_LIST: case DATA_TYPE_INT_LIST: case DATA_TYPE_REAL_LIST: case DATA_TYPE_NONE: if (varstring == '}') { snprintf(name, CF_MAXVARSIZE, "${%s}", BufferData(current_item)); } else { snprintf(name, CF_MAXVARSIZE, "$(%s)", BufferData(current_item)); } BufferAppend(out, name, strlen(name)); returnval = false; break; default: Log(LOG_LEVEL_DEBUG, "Returning Unknown Scalar ('%s' => '%s')", string, BufferData(out)); BufferDestroy(var); BufferDestroy(current_item); BufferDestroy(temp); return false; } } else { if (varstring == '}') { snprintf(name, CF_MAXVARSIZE, "${%s}", BufferData(current_item)); } else { snprintf(name, CF_MAXVARSIZE, "$(%s)", BufferData(current_item)); } BufferAppend(out, name, strlen(name)); returnval = false; } } sp += increment; BufferZero(current_item); } BufferDestroy(var); BufferDestroy(current_item); BufferDestroy(temp); return returnval; }
static void ExpandAndMapIteratorsFromScalar(EvalContext *ctx, const Bundle *bundle, char *string, size_t length, int level, Rlist **scalars, Rlist **lists, Rlist **containers, Rlist **full_expansion) { assert(string); if (!string) { return; } Buffer *value = BufferNew(); for (size_t i = 0; i < length; i++) { const char *sp = string + i; Rlist *tmp_list = NULL; BufferZero(value); if (ExtractScalarPrefix(value, sp, length - i)) { if (full_expansion) { RlistConcatInto(&tmp_list, *full_expansion, BufferData(value)); RlistDestroy(*full_expansion); *full_expansion = tmp_list; tmp_list = NULL; } sp += BufferSize(value); i += BufferSize(value); BufferZero(value); if (i >= length) { break; } } if (*sp == '$') { BufferZero(value); ExtractScalarReference(value, sp, length - i, true); if (BufferSize(value) > 0) { Rlist *inner_expansion = NULL; Rlist *exp = NULL; int success = 0; VarRef *ref = VarRefParse(BufferData(value)); int increment = BufferSize(value) - 1 + 3; // Handle any embedded variables char *substring = string + i + 2; ExpandAndMapIteratorsFromScalar(ctx, bundle, substring, BufferSize(value), level+1, scalars, lists, containers, &inner_expansion); for (exp = inner_expansion; exp != NULL; exp = exp->next) { // If a list is non-local, i.e. $(bundle.var), map it to local $(bundle#var) // NB without modifying variables as we map them, it's not // possible to handle remote lists referenced by a variable // scope. For example: // scope => "test."; var => "somelist"; $($(scope)$(var)) fails // varname => "test.somelist"; $($(varname)) also fails // TODO Unless the consumer handles it? const char *inner_ref_str = RlistScalarValue(exp); VarRef *inner_ref = VarRefParseFromBundle(inner_ref_str, bundle); // var is the expanded name of the variable in its native context // finalname will be the mapped name in the local context "this." DataType value_type = DATA_TYPE_NONE; const void *value = EvalContextVariableGet(ctx, inner_ref, &value_type); if (value) { char *mangled_inner_ref = xstrdup(inner_ref_str); MangleVarRefString(mangled_inner_ref, strlen(mangled_inner_ref)); success++; switch (DataTypeToRvalType(value_type)) { case RVAL_TYPE_LIST: if (level > 0) { RlistPrependScalarIdemp(lists, mangled_inner_ref); } else { RlistAppendScalarIdemp(lists, mangled_inner_ref); } if (full_expansion) { for (const Rlist *rp = value; rp != NULL; rp = rp->next) { // append each slist item to each of full_expansion RlistConcatInto(&tmp_list, *full_expansion, RlistScalarValue(rp)); } } break; case RVAL_TYPE_SCALAR: RlistAppendScalarIdemp(scalars, mangled_inner_ref); if (full_expansion) { // append the scalar value to each of full_expansion RlistConcatInto(&tmp_list, *full_expansion, value); } break; case RVAL_TYPE_CONTAINER: if (level > 0) { RlistPrependScalarIdemp(containers, mangled_inner_ref); } else { RlistAppendScalarIdemp(containers, mangled_inner_ref); } break; case RVAL_TYPE_FNCALL: case RVAL_TYPE_NOPROMISEE: break; } free(mangled_inner_ref); } VarRefDestroy(inner_ref); } RlistDestroy(inner_expansion); if (full_expansion) { RlistDestroy(*full_expansion); *full_expansion = tmp_list; tmp_list = NULL; } // No need to map this.* even though it's technically qualified if (success && IsQualifiedVariable(BufferData(value)) && strcmp(ref->scope, "this") != 0) { char *dotpos = strchr(substring, '.'); if (dotpos) { *dotpos = CF_MAPPEDLIST; // replace '.' with '#' } if (strchr(BufferData(value), ':')) { char *colonpos = strchr(substring, ':'); if (colonpos) { *colonpos = '*'; } } } VarRefDestroy(ref); sp += increment; i += increment; } } } BufferDestroy(value); }
int LoadFileAsItemList(Item **liststart, const char *file, EditDefaults edits) { { struct stat statbuf; if (stat(file, &statbuf) == -1) { Log(LOG_LEVEL_VERBOSE, "The proposed file '%s' could not be loaded. (stat: %s)", file, GetErrorStr()); return false; } if (edits.maxfilesize != 0 && statbuf.st_size > edits.maxfilesize) { Log(LOG_LEVEL_INFO, "File '%s' is bigger than the limit edit.max_file_size = %jd > %d bytes", file, (intmax_t) statbuf.st_size, edits.maxfilesize); return (false); } if (!S_ISREG(statbuf.st_mode)) { Log(LOG_LEVEL_INFO, "%s is not a plain file", file); return false; } } FILE *fp = safe_fopen(file, "r"); if (!fp) { Log(LOG_LEVEL_INFO, "Couldn't read file '%s' for editing. (fopen: %s)", file, GetErrorStr()); return false; } Buffer *concat = BufferNew(); size_t line_size = CF_BUFSIZE; char *line = xmalloc(line_size); bool result = true; for (;;) { ssize_t num_read = CfReadLine(&line, &line_size, fp); if (num_read == -1) { if (!feof(fp)) { Log(LOG_LEVEL_ERR, "Unable to read contents of '%s'. (fread: %s)", file, GetErrorStr()); result = false; } break; } if (edits.joinlines && *(line + strlen(line) - 1) == '\\') { *(line + strlen(line) - 1) = '\0'; BufferAppend(concat, line, num_read); } else { BufferAppend(concat, line, num_read); if (!feof(fp) || (BufferSize(concat) > 0)) { AppendItem(liststart, BufferData(concat), NULL); } } BufferZero(concat); } free(line); BufferDestroy(concat); fclose(fp); return result; }
VarRef *VarRefParseFromNamespaceAndScope(const char *qualified_name, const char *_ns, const char *_scope, char ns_separator, char scope_separator) { char *ns = NULL; const char *indices_start = strchr(qualified_name, '['); const char *scope_start = strchr(qualified_name, ns_separator); if (scope_start && (!indices_start || scope_start < indices_start)) { ns = xstrndup(qualified_name, scope_start - qualified_name); scope_start++; } else { scope_start = qualified_name; } char *scope = NULL; const char *lval_start = strchr(scope_start, scope_separator); if (lval_start && (!indices_start || lval_start < indices_start)) { lval_start++; scope = xstrndup(scope_start, lval_start - scope_start - 1); } else { lval_start = scope_start; } char *lval = NULL; char **indices = NULL; size_t num_indices = 0; if (indices_start) { indices_start++; lval = xstrndup(lval_start, indices_start - lval_start - 1); assert("Index brackets in variable expression did not balance" && IndexBracketsBalance(indices_start - 1)); num_indices = IndexCount(indices_start - 1); indices = xmalloc(num_indices * sizeof(char *)); Buffer *buf = BufferNew(); size_t cur_index = 0; for (const char *c = indices_start; *c != '\0'; c++) { if (*c == '[') { cur_index++; } else if (*c == ']') { indices[cur_index] = xstrdup(BufferData(buf)); BufferZero(buf); } else { BufferAppend(buf, c, sizeof(char)); } } BufferDestroy(&buf); } else { lval = xstrdup(lval_start); } assert(lval); if (!scope && !_scope) { assert(ns == NULL && "A variable missing a scope should not have a namespace"); } VarRef *ref = xmalloc(sizeof(VarRef)); ref->ns = ns ? ns : (_ns ? xstrdup(_ns) : NULL); ref->scope = scope ? scope : (_scope ? xstrdup(_scope) : NULL); ref->lval = lval; ref->indices = indices; ref->num_indices = num_indices; ref->hash = VarRefHash(ref); return ref; }