#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <ctype.h>
#if HAVE_STRING_H || !defined(HAVE_CONFIG_H)
# include <string.h>
#endif
#include "number.h"
#include "calculator.h" /* for report_error */
#include "list.h"
#include "variables.h"
#ifdef MEMWATCH
#include "memwatch.h"
#endif
#define THE_VALUE 0
#define THE_STRUCTURE 2
#define THE_EXPRESSION 4
#define HASH_LENGTH = 101
List them = NULL;
/* Hidden, internal functions */
static void *getvar_core(const char *key, const int all_or_nothing);
void initvar(void)
{ /*{{{ */
} /*}}} */
/* This function deletes all the variables and frees all the memory. */
void cleanupvar(void)
{ /*{{{ */
struct variable *freeme;
while ((freeme = (struct variable *)getHeadOfList(them)) != NULL) {
free(freeme->key);
if (freeme->exp == 1) {
free(freeme->expression);
} else {
num_free(freeme->value);
}
if (freeme->description) {
free(freeme->description);
}
free(freeme);
}
} /*}}} */
/* Returns the number of variables */
size_t numvars()
{ /*{{{ */
return listLen(them);
} /*}}} */
/* prints out all the variables */
void printvariables(void)
{/*{{{*/
ListIterator li = NULL;
struct variable *cursor = NULL;
if (!them || listLen(them) == 0)
return;
li = getListIterator(them);
while ((cursor = (struct variable *)nextListElement(li)) != NULL) {
printf("%s = ", cursor->key);
if (cursor->exp) {
printf("%s\n", cursor->expression);
} else {
printf("%g\n", num_get_d(cursor->value));
}
}
freeListIterator(li);
}/*}}}*/
/* returns a list of variables (only the base array is malloc'd, the rest must
* NOT be freed */
char **listvarnames(void)
{/*{{{*/
size_t i;
char **ret = calloc(listLen(them) + 1, sizeof(char *));
ListIterator li = NULL;
struct variable *cursor = NULL;
if (!them || listLen(them) == 0)
return ret;
li = getListIterator(them);
i = 0;
while ((cursor = (struct variable *)nextListElement(li)) != NULL) {
ret[i++] = cursor->key;
}
freeListIterator(li);
return ret;
/*}}}*/}
void delnvar(const size_t i)
{ /*{{{ */
struct variable *freeme;
freeme = (struct variable *)getListElement(them, i);
if (freeme) {
free(freeme->key);
if (freeme->exp == 1) {
free(freeme->expression);
} else {
num_free(freeme->value);
}
free(freeme);
}
} /*}}} */
struct variable *getrealnvar(const size_t i)
{ /*{{{ */
return (struct variable *)peekListElement(them, i);
} /*}}} */
struct answer getvar(const char *key)
{ /*{{{ */
struct answer ans;
Number *t = getvar_core(key, THE_VALUE);
if (t) {
num_init_set(ans.val, *t);
ans.err = 0;
ans.exp = NULL;
} else {
/* it's an error.
* if you access ans.val, you deserve what you get */
ans.exp = NULL;
ans.err = 1;
}
return ans;
} /*}}} */
void getvarval(Number out, const char *key)
{ /*{{{ */
Number *t = getvar_core(key, THE_VALUE);
if (t) {
num_set(out, *t);
}
} /*}}} */
struct answer getvar_full(const char *key)
{ /*{{{ */
struct answer ans;
struct variable *var;
var = getvar_core(key, THE_STRUCTURE);
if (var && !var->exp) {
num_init_set(ans.val, var->value);
ans.err = 0;
ans.exp = NULL;
ans.desc = var->description;
} else if (var && var->exp) {
ans.exp = var->expression;
ans.desc = var->description;
ans.err = 0;
} else {
ans.exp = NULL;
ans.err = 1;
}
return ans;
} /*}}} */
/* This function returns 1 if a variable by that key has already been created
* and returns 0 if a variable by that key has not been created yet */
int varexists(const char *key)
{ /*{{{ */
struct variable *cursor = NULL;
ListIterator li = NULL;
if (!them || !strlen(key) || listLen(them) == 0)
return 0;
li = getListIterator(them);
while ((cursor = (struct variable *)nextListElement(li)) != NULL) {
if (!strncmp(cursor->key, key, strlen(cursor->key) + 1))
break;
else
cursor = NULL;
}
freeListIterator(li);
return cursor ? 1 : 0;
} /*}}} */
static void *getvar_core(const char *key, const int all_or_nothing)
{ /*{{{ */
struct variable *cursor = NULL;
ListIterator li = NULL;
if (!them || key == NULL || *key == 0 || listLen(them) == 0) {
return NULL;
}
li = getListIterator(them);
while ((cursor = (struct variable *)nextListElement(li)) != NULL) {
if (!strncmp(cursor->key, key, strlen(cursor->key) + 1))
break;
else
cursor = NULL;
}
freeListIterator(li);
if (cursor) {
switch (all_or_nothing) {
case THE_VALUE:
if (cursor->exp) {
return NULL;
} else {
return &(cursor->value);
}
case THE_STRUCTURE:
return cursor;
case THE_EXPRESSION:
return cursor->expression;
}
}
return NULL;
} /*}}} */
/* this adds the key-expression pair to the list.
* if the key already exists, change the value to this */
int putexp(const char *key, const char *value, const char *desc)
{ /*{{{ */
struct variable *cursor = NULL;
if (*key == 0)
return -1;
cursor = getvar_core(key, THE_STRUCTURE);
if (!cursor) {
// variable named "key" doesn't exist yet, so allocate memory
cursor = calloc(sizeof(struct variable), 1);
addToList(&them, cursor);
}
// by this point, we have a variable (cursor) in the list (them)
if (cursor->key) {
if (cursor->expression) {
free(cursor->expression);
} else {
num_free(cursor->value);
}
if (cursor->description) {
free(cursor->description);
}
} else {
cursor->key = (char *)strdup(key);
}
// by this point, the cursor has been prepared to accept the exp/desc
cursor->expression = (char *)strdup(value);
if (desc != NULL) {
cursor->description = (char *)strdup(desc);
} else {
cursor->description = NULL;
}
cursor->exp = 1;
return 0;
} /*}}} */
/* this adds the key-value pair to the list.
* if the key already exists, change the value to this */
int putval(const char *key, const Number value, const char *desc)
{ /*{{{ */
struct variable *cursor = NULL;
if (key == NULL || *key == 0) {
return -1;
}
cursor = getvar_core(key, THE_STRUCTURE);
if (!cursor) {
// variable named "key" doesn't exist yet, so allocate memory
cursor = calloc(1, sizeof(struct variable));
addToList(&them, cursor);
}
// by this point, we have a variable (cursor) in the list (them)
// but key may not exist, and value may not be properly initialized
if (!cursor->key) {
cursor->key = (char *)strdup(key);
num_init(cursor->value);
} else if (cursor->expression) {
free(cursor->expression);
cursor->expression = NULL;
num_init(cursor->value);
}
if (cursor->description) {
free(cursor->description);
}
cursor->exp = 0;
// by this point, the variable has a key, and an initialized value,
// and is ready to receive the correct value/desc
if (desc != NULL) {
cursor->description = (char *)strdup(desc);
} else {
cursor->description = NULL;
}
num_set(cursor->value, value);
return 0;
} /*}}} */
syntax highlighted by Code2HTML, v. 0.9.1