void symClose(sym_fd_t sd) { sym_tabent_t *tp; sym_t *sp, *forw; int i; a_assert(0 <= sd && sd < symMax); tp = sym[sd]; a_assert(tp); /* * Free all symbols in the hash table, then the hash table itself. */ for (i = 0; i < tp->hash_size; i++) { for (sp = tp->hash_table[i]; sp; sp = forw) { forw = sp->forw; valueFree(&sp->name); valueFree(&sp->content); bfree(B_L, (void*) sp); sp = forw; } } bfree(B_L, (void*) tp->hash_table); symMax = hFree((void***) &sym, sd); bfree(B_L, (void*) tp); }
/** * @param state expression parser state */ static Value doAddSubtract(ParseState state) { Value v1, v2 = NULL; DEBUG(printf("doAddSubtract()\n")); v1 = doMultiplyDivide(state); if (v1 == NULL) return NULL; while (state->nextToken == TOK_ADD || state->nextToken == TOK_MINUS) { int op = state->nextToken; if (rdToken(state)) return NULL; if (v2) valueFree(v2); v2 = doMultiplyDivide(state); if (v2 == NULL) return NULL; if (! valueSameType(v1, v2)) { rpmlog(RPMLOG_ERR, _("types must match\n")); return NULL; } if (valueIsInteger(v1)) { int i1 = v1->data.i, i2 = v2->data.i; valueFree(v1); if (op == TOK_ADD) v1 = valueMakeInteger(i1 + i2); else v1 = valueMakeInteger(i1 - i2); } else { char *copy; if (op == TOK_MINUS) { rpmlog(RPMLOG_ERR, _("- not suported for strings\n")); return NULL; } copy = xmalloc(strlen(v1->data.s) + strlen(v2->data.s) + 1); (void) stpcpy( stpcpy(copy, v1->data.s), v2->data.s); valueFree(v1); v1 = valueMakeString(copy); } } if (v2) valueFree(v2); return v1; }
int symDelete(sym_fd_t sd, char_t *name) { sym_tabent_t *tp; sym_t *sp, *last; char_t *cp; int hindex; a_assert(name && *name); a_assert(0 <= sd && sd < symMax); tp = sym[sd]; a_assert(tp); /* * Calculate the first daisy-chain from the hash table. If non-zero, then * we have daisy-chain, so scan it and look for the symbol. */ last = NULL; hindex = hashIndex(tp, name); if ((sp = tp->hash_table[hindex]) != NULL) { for ( ; sp; sp = sp->forw) { cp = sp->name.value.string; if (cp[0] == name[0] && gstrcmp(cp, name) == 0) { break; } last = sp; } } if (sp == (sym_t*) NULL) { /* Not Found */ return -1; } /* * Unlink and free the symbol. Last will be set if the element to be deleted * is not first in the chain. */ if (last) { last->forw = sp->forw; } else { tp->hash_table[hindex] = sp->forw; } valueFree(&sp->name); valueFree(&sp->content); bfree(B_L, (void*) sp); return 0; }
/** * @param state expression parser state */ static Value doLogical(ParseState state) { Value v1, v2 = NULL; DEBUG(printf("doLogical()\n")); v1 = doRelational(state); if (v1 == NULL) return NULL; while (state->nextToken == TOK_LOGICAL_AND || state->nextToken == TOK_LOGICAL_OR) { int op = state->nextToken; if (rdToken(state)) return NULL; if (v2) valueFree(v2); v2 = doRelational(state); if (v2 == NULL) return NULL; if (! valueSameType(v1, v2)) { rpmlog(RPMLOG_ERR, _("types must match\n")); return NULL; } if (valueIsInteger(v1)) { int i1 = v1->data.i, i2 = v2->data.i; valueFree(v1); if (op == TOK_LOGICAL_AND) v1 = valueMakeInteger(i1 && i2); else v1 = valueMakeInteger(i1 || i2); } else { rpmlog(RPMLOG_ERR, _("&& and || not suported for strings\n")); return NULL; } } if (v2) valueFree(v2); return v1; }
/** * @param state expression parser state */ static Value doMultiplyDivide(ParseState state) { Value v1, v2 = NULL; DEBUG(printf("doMultiplyDivide()\n")); v1 = doPrimary(state); if (v1 == NULL) return NULL; while (state->nextToken == TOK_MULTIPLY || state->nextToken == TOK_DIVIDE) { int op = state->nextToken; if (rdToken(state)) return NULL; if (v2) valueFree(v2); v2 = doPrimary(state); if (v2 == NULL) return NULL; if (! valueSameType(v1, v2)) { rpmlog(RPMLOG_ERR, _("types must match\n")); return NULL; } if (valueIsInteger(v1)) { int i1 = v1->data.i, i2 = v2->data.i; valueFree(v1); if (op == TOK_MULTIPLY) v1 = valueMakeInteger(i1 * i2); else v1 = valueMakeInteger(i1 / i2); } else { rpmlog(RPMLOG_ERR, _("* / not suported for strings\n")); return NULL; } } if (v2) valueFree(v2); return v1; }
int parseExpressionBoolean(rpmSpec spec, const char *expr) { struct _parseState state; int result = -1; Value v; DEBUG(printf("parseExprBoolean(?, '%s')\n", expr)); /* Initialize the expression parser state. */ state.p = state.str = xstrdup(expr); state.spec = spec; state.nextToken = 0; state.tokenValue = NULL; (void) rdToken(&state); /* Parse the expression. */ v = doLogical(&state); if (!v) { state.str = _free(state.str); return -1; } /* If the next token is not TOK_EOF, we have a syntax error. */ if (state.nextToken != TOK_EOF) { rpmlog(RPMLOG_ERR, _("syntax error in expression\n")); state.str = _free(state.str); return -1; } DEBUG(valueDump("parseExprBoolean:", v, stdout)); switch (v->type) { case VALUE_TYPE_INTEGER: result = v->data.i != 0; break; case VALUE_TYPE_STRING: result = v->data.s[0] != '\0'; break; default: break; } state.str = _free(state.str); valueFree(v); return result; }
LONGBOW_TEST_CASE(Global, PARC_TreeRedBlack_Remove) { PARCTreeRedBlack *tree1; PARCTreeRedBlack *tree2; tree1 = parcTreeRedBlack_Create(intComp, keyFree, NULL, intEquals, valueFree, NULL); tree2 = parcTreeRedBlack_Create(intComp, keyFree, NULL, intEquals, valueFree, NULL); for (int i = 31; i < 40; i++) { // Add some elements to the tree parcTreeRedBlack_Insert(tree1, keyNewInt(i), valueNewInt(i << 8)); parcTreeRedBlack_Insert(tree2, keyNewInt(i), valueNewInt(i << 8)); } parcTreeRedBlack_Insert(tree1, keyNewInt(30), valueNewInt(31 << 8)); for (int i = 2; i < 10; i++) { // Add some elements to the tree parcTreeRedBlack_Insert(tree1, keyNewInt(i), valueNewInt(i << 8)); parcTreeRedBlack_Insert(tree2, keyNewInt(i), valueNewInt(i << 8)); } for (int i = 20; i < 30; i++) { // Add some elements to the tree parcTreeRedBlack_Insert(tree1, keyNewInt(i), valueNewInt(i << 8)); parcTreeRedBlack_Insert(tree2, keyNewInt(i), valueNewInt(i << 8)); } int searchKey = 30; void *data = parcTreeRedBlack_Remove(tree1, &searchKey); valueFree(&data); assertTrue(parcTreeRedBlack_Equals(tree1, tree2), "Trees dont match after remove"); parcTreeRedBlack_Destroy(&tree1); parcTreeRedBlack_Destroy(&tree2); }
sym_t *symEnter(sym_fd_t sd, char_t *name, value_t v, int arg) { sym_tabent_t *tp; sym_t *sp, *last; char_t *cp; int hindex; a_assert(name); a_assert(0 <= sd && sd < symMax); tp = sym[sd]; a_assert(tp); /* * Calculate the first daisy-chain from the hash table. If non-zero, then * we have daisy-chain, so scan it and look for the symbol. */ last = NULL; hindex = hashIndex(tp, name); if ((sp = tp->hash_table[hindex]) != NULL) { for (; sp; sp = sp->forw) { cp = sp->name.value.string; if (cp[0] == name[0] && gstrcmp(cp, name) == 0) { break; } last = sp; } if (sp) { /* * Found, so update the value * If the caller stores handles which require freeing, they * will be lost here. It is the callers responsibility to free * resources before overwriting existing contents. We will here * free allocated strings which occur due to value_instring(). * We should consider providing the cleanup function on the open rather * than the close and then we could call it here and solve the problem. */ if (sp->content.valid) { valueFree(&sp->content); } sp->content = v; sp->arg = arg; return sp; } /* * Not found so allocate and append to the daisy-chain */ sp = (sym_t*) balloc(B_L, sizeof(sym_t)); if (sp == NULL) { return NULL; } sp->name = valueString(name, VALUE_ALLOCATE); sp->content = v; sp->forw = (sym_t*) NULL; sp->arg = arg; last->forw = sp; } else { /* * Daisy chain is empty so we need to start the chain */ sp = (sym_t*) balloc(B_L, sizeof(sym_t)); if (sp == NULL) { return NULL; } tp->hash_table[hindex] = sp; tp->hash_table[hashIndex(tp, name)] = sp; sp->forw = (sym_t*) NULL; sp->content = v; sp->arg = arg; sp->name = valueString(name, VALUE_ALLOCATE); } return sp; }
/** * @param state expression parser state */ static Value doRelational(ParseState state) { Value v1, v2 = NULL; DEBUG(printf("doRelational()\n")); v1 = doAddSubtract(state); if (v1 == NULL) return NULL; while (state->nextToken >= TOK_EQ && state->nextToken <= TOK_GE) { int op = state->nextToken; if (rdToken(state)) return NULL; if (v2) valueFree(v2); v2 = doAddSubtract(state); if (v2 == NULL) return NULL; if (! valueSameType(v1, v2)) { rpmlog(RPMLOG_ERR, _("types must match\n")); return NULL; } if (valueIsInteger(v1)) { int i1 = v1->data.i, i2 = v2->data.i, r = 0; switch (op) { case TOK_EQ: r = (i1 == i2); break; case TOK_NEQ: r = (i1 != i2); break; case TOK_LT: r = (i1 < i2); break; case TOK_LE: r = (i1 <= i2); break; case TOK_GT: r = (i1 > i2); break; case TOK_GE: r = (i1 >= i2); break; default: break; } valueFree(v1); v1 = valueMakeInteger(r); } else { const char * s1 = v1->data.s; const char * s2 = v2->data.s; int r = 0; switch (op) { case TOK_EQ: r = (strcmp(s1,s2) == 0); break; case TOK_NEQ: r = (strcmp(s1,s2) != 0); break; case TOK_LT: r = (strcmp(s1,s2) < 0); break; case TOK_LE: r = (strcmp(s1,s2) <= 0); break; case TOK_GT: r = (strcmp(s1,s2) > 0); break; case TOK_GE: r = (strcmp(s1,s2) >= 0); break; default: break; } valueFree(v1); v1 = valueMakeInteger(r); } } if (v2) valueFree(v2); return v1; }