Example 3. A Symbol Lookup Table
The following example illustrates how to use the eval module with a symbol table to evaluate a simple arithmetic expression from the commandline.
#include <stdlib.h> #include <stdio.h> #include <mba/eval.h> #include <mba/msgno.h> struct { const tchar *name; const unsigned long val; } symtab[] = { { _T("N"), 3 }, { _T("MAXVALUES"), 0xFFFF }, { _T("whatever"), 100 } }; int symbol_lookup(const tchar *name, unsigned long *val, void *context) { int i; for (i = 0; symtab[i].name; i++) { if (tcscmp(symtab[i].name, name) == 0) { *val = symtab[i].val; return 0; } } return -1; } int main(int argc, char *argv[]) { unsigned long result; struct eval *eval = eval_new(&symbol_lookup, NULL); if (eval_expression(eval, argv[1], argv[1] + strlen(argv[1]), &result) == -1) { MSG(""); return EXIT_FAILURE; } printf("%s = %ld\n", argv[1], result); return EXIT_SUCCESS; } output: $ ./eval '(5 + 3) * N' (5 + 3) * N = 24Large tables should be generated with a program that sorts the identifiers so the the symlook_fn can perform a binary search (see end of wcwidth.c).
The eval_new function
Description
#include <mba/eval.h> struct eval *eval_new(symlook_fn symlook, void *context);
typedef int (*symlook_fn)(const tchar *name, unsigned long *val, void *context);The symlook_fn function will be called to resolve any non-numeric symbols and should place the value identified by name into val and return 0. If the symbol is not found -1 should be returned.
The eval_new function can be used repeatedly to evaluate any number of expressions before being destroyed with the eval_del function. The context parameter is passed uninterpreted to the symlook_fn (e.g. a hashmap perhaps).
The eval_del function
Description
#include <mba/eval.h> void eval_del(void *eval);
The eval_eval_expression function
Description
#include <mba/eval.h> int eval_expression(struct eval *eval, const tchar *expr, const tchar *elim, unsigned long *result);