changeset 1527:b4d37b562772

Remove auval and dmeval stuff.
author Matti Hamalainen <ccr@tnsp.org>
date Fri, 11 May 2018 23:58:08 +0300
parents e0cd0fc8c753
children 239dc13123fd
files Makefile.gen src/dmeval.c src/dmeval.h src/dmevalw.c tests/evaltest.c tools/auval.c
diffstat 6 files changed, 1 insertions(+), 2240 deletions(-) [+]
line wrap: on
line diff
--- a/Makefile.gen	Fri May 11 23:44:53 2018 +0300
+++ b/Makefile.gen	Fri May 11 23:58:08 2018 +0300
@@ -142,14 +142,6 @@
 DM_CFLAGS += -DDM_GFX_TTF_TEXT
 DMLIB_OBJS += dmtext_ttf.o
 
-ifeq ($(DM_BUILD_TOOLS),yes)
-ifeq ($(DM_GFX_BLITS),yes)
-ifeq ($(DM_GFX_BM_TEXT),yes)
-TOOL_BINARIES += auval
-endif
-endif
-endif
-
 ifeq ($(DM_BUILD_TESTS),yes)
 ifeq ($(DM_GFX_BLITS),yes)
 ifeq ($(DM_USE_STDIO),yes)
@@ -280,7 +272,7 @@
 
 ### What tests to build?
 ifeq ($(DM_BUILD_TESTS),yes)
-TESTS_BINARIES += vecmattest fptest evaltest dzlib
+TESTS_BINARIES += vecmattest fptest dzlib
 endif
 
 FONTCONV_BIN=fontconv
@@ -454,10 +446,6 @@
 	@echo " LINK $+"
 	@$(CC) -o $@ $(filter %.o %.a,$+) $(DM_LDFLAGS) $(SDL_LDFLAGS) $(SDL_TTF_LDFLAGS) -lm
 
-$(TESTS_BINPATH)evaltest$(EXEEXT): $(OBJPATH)evaltest.o $(OBJPATH)dmeval.o $(OBJPATH)dmevalw.o $(DMLIB_A)
-	@echo " LINK $+"
-	@$(CC) -o $@ $(filter %.o %.a,$+) $(DM_LDFLAGS) $(TOOL_LDFLAGS) -lm
-
 $(TESTS_BINPATH)%test$(EXEEXT): $(OBJPATH)%test.o $(DMLIB_A)
 	@echo " LINK $+"
 	@$(CC) -o $@ $(filter %.o %.a,$+) $(DM_LDFLAGS) $(TOOL_LDFLAGS) -lm
@@ -518,10 +506,6 @@
 	@echo " LINK $+"
 	@$(CC) -o $@ $(filter %.o %.a,$+) $(DM_LDFLAGS) $(TOOL_LDFLAGS) -lm
 
-$(TOOL_BINPATH)auval$(EXEEXT): $(OBJPATH)auval.o $(OBJPATH)dmeval.o $(OBJPATH)dmevalw.o $(OBJPATH)libgutil.o $(DMLIB_A)
-	@echo " LINK $+"
-	@$(CC) -o $@ $(filter %.o %.a,$+) $(DM_LDFLAGS) $(SDL_LDFLAGS) $(SDL_TTF_LDFLAGS) -lm
-
 
 ###
 ### Demo binary
--- a/src/dmeval.c	Fri May 11 23:44:53 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,765 +0,0 @@
-#include "dmeval.h"
-#include <math.h>
-
-#define DM_MAX_BUF     512
-
-
-/* Operators
- */
-const DMEvalOper dmEvalOpers[OP_NOPERS] =
-{
-    { "-"      , OT_UNARY , FALSE },
-    { "~"      , OT_UNARY , TRUE },
-
-    { "+"      , OT_LEFT  , TRUE },
-    { "-"      , OT_LEFT  , TRUE },
-    { "*"      , OT_LEFT  , TRUE },
-    { "/"      , OT_LEFT  , TRUE },
-    { "%"      , OT_LEFT  , TRUE },
-
-
-    { "<<"     , OT_LEFT  , TRUE },
-    { ">>"     , OT_LEFT  , TRUE },
-
-    { "&"      , OT_LEFT  , TRUE },
-    { "|"      , OT_LEFT  , TRUE },
-    { "^"      , OT_LEFT  , TRUE },
-
-    { ">="     , OT_LEFT  , TRUE },
-    { "<="     , OT_LEFT  , TRUE },
-    { ">"      , OT_LEFT  , TRUE },
-    { "<"      , OT_LEFT  , TRUE },
-
-    { "FUNC"   , OT_NONE  , FALSE },
-    { "VAR"    , OT_NONE  , FALSE },
-    { "CONST"  , OT_NONE  , FALSE },
-
-    { "SUBEXPR", OT_NONE  , FALSE },
-};
-
-
-/* Function definitions
- */
-static DMValue func_int_clip(DMValue *v)
-{
-    return (*v < -1.0f) ? -1.0f : ((*v > 1.0f) ? 1.0f : *v);
-}
-
-
-static DMValue func_sin(DMValue *v)
-{
-    return sin(*v);
-}
-
-
-static DMValue func_cos(DMValue *v)
-{
-    return cos(*v);
-}
-
-
-static DMValue func_pow(DMValue *v)
-{
-    return pow(v[0], v[1]);
-}
-
-
-/* Some basic functions
- */
-static const DMEvalSymbol dmEvalBasicFuncs[] =
-{
-    { "sin",  SYM_FUNC , 1, func_sin, NULL, 0 },
-    { "cos",  SYM_FUNC , 1, func_cos, NULL, 0 },
-    { "clip", SYM_FUNC , 1, func_int_clip, NULL, 0 },
-    { "pow",  SYM_FUNC , 2, func_pow, NULL, 0 },
-
-    { "pi",   SYM_CONST, 0, NULL, NULL, DM_PI },
-    { "e",    SYM_CONST, 0, NULL, NULL, DM_E },
-};
-
-static const int ndmEvalBasicFuncs = sizeof(dmEvalBasicFuncs) / sizeof(dmEvalBasicFuncs[0]);
-
-
-void dmEvalErrorV(DMEvalContext *ev, const char *fmt, va_list ap)
-{
-    char *tmp = dm_strdup_vprintf(fmt, ap);
-
-    ev->err = TRUE;
-
-    if (ev->errStr != NULL)
-    {
-        ev->errStr = dm_strdup_printf("%s%s", ev->errStr, tmp);
-        dmFree(tmp);
-    }
-    else
-        ev->errStr = tmp;
-}
-
-
-void dmEvalError(DMEvalContext *ev, const char *fmt, ...)
-{
-    va_list ap;
-    va_start(ap, fmt);
-    dmEvalErrorV(ev, fmt, ap);
-    va_end(ap);
-}
-
-
-DMEvalSymbol *dmEvalContextFindSymbol(DMEvalContext *ev, const char *name)
-{
-    int i;
-    if (ev->symbols == NULL)
-        return NULL;
-
-    for (i = 0; i < ev->nsymbols; i++)
-    {
-        if (strcmp(ev->symbols[i].name, name) == 0)
-            return &(ev->symbols[i]);
-    }
-
-    return NULL;
-}
-
-
-// Add a new symbol to the evaluation context.
-// Return pointer to newly allocated symbol struct if successful.
-// If the symbol already exists or there was a memory allocation
-// error, NULL is returned.
-static DMEvalSymbol * dmEvalContextAddSymbol(DMEvalContext *ev, const char *name, const int type)
-{
-    DMEvalSymbol *symbol = dmEvalContextFindSymbol(ev, name);
-    if (symbol != NULL)
-        return NULL;
-
-    ev->symbols = dmRealloc(ev->symbols, sizeof(DMEvalSymbol) * (ev->nsymbols + 1));
-    if (ev->symbols == NULL)
-    {
-        dmEvalError(ev,
-            "Could not reallocate eval symbols array (#%d). Fatal error.\n",
-            ev->nsymbols + 1);
-        return NULL;
-    }
-
-    symbol = &(ev->symbols[ev->nsymbols]);
-    ev->nsymbols++;
-
-    dmMemset(symbol, 0, sizeof(DMEvalSymbol));
-    symbol->name = dm_strdup(name);
-    symbol->type = type;
-
-    return symbol;
-}
-
-
-DMEvalSymbol *dmEvalContextAddVar(DMEvalContext *ev, const char *name, DMValue *var)
-{
-    DMEvalSymbol *symbol = dmEvalContextAddSymbol(ev, name, SYM_VAR);
-    if (symbol == NULL)
-        return NULL;
-
-    symbol->var = var;
-    return symbol;
-}
-
-
-DMEvalSymbol *dmEvalContextAddConst(DMEvalContext *ev, const char *name, DMValue value)
-{
-    DMEvalSymbol *symbol = dmEvalContextAddSymbol(ev, name, SYM_CONST);
-    if (symbol == NULL)
-        return NULL;
-
-    symbol->cvalue = value;
-    return symbol;
-}
-
-
-DMEvalSymbol *dmEvalContextAddFunc(DMEvalContext *ev, const char *name, DMValue (*func)(DMValue *), int nargs)
-{
-    DMEvalSymbol *symbol = dmEvalContextAddSymbol(ev, name, SYM_VAR);
-    if (symbol == NULL)
-        return NULL;
-
-    symbol->func  = func;
-    symbol->nargs = nargs;
-
-    return DMERR_OK;
-}
-
-
-DMEvalContext *dmEvalContextNew(void)
-{
-    int i;
-    DMEvalContext *ev = dmCalloc(1, sizeof(DMEvalContext));
-
-    if (ev == NULL)
-        return NULL;
-
-    for (i = 0; i < ndmEvalBasicFuncs; i++)
-    {
-        const DMEvalSymbol *symbol= &dmEvalBasicFuncs[i];
-        DMEvalSymbol *nsymbol = dmEvalContextAddSymbol(ev, symbol->name, symbol->type);
-        if (nsymbol != NULL)
-        {
-            nsymbol->nargs    = symbol->nargs;
-            nsymbol->func     = symbol->func;
-            nsymbol->var      = symbol->var;
-            nsymbol->cvalue   = symbol->cvalue;
-        }
-    }
-
-    return ev;
-}
-
-
-void dmEvalTreeFree(DMEvalNode *node)
-{
-    while (node != NULL)
-    {
-        DMEvalNode *next = node->next;
-        int i;
-
-        for (i = 0; i < DM_EVAL_MAX_ARGS; i++)
-        {
-            dmEvalTreeFree(node->args[i]);
-            node->args[i] = NULL;
-        }
-
-        dmEvalTreeFree(node->subexpr);
-        node->subexpr = NULL;
-        dmFree(node);
-        node = next;
-    }
-}
-
-
-void dmEvalContextClear(DMEvalContext *ev)
-{
-    if (ev == NULL)
-        return;
-
-    dmFree(ev->errStr);
-    ev->err = FALSE;
-    ev->errStr = NULL;
-}
-
-
-void dmEvalContextClose(DMEvalContext *ev)
-{
-    int i;
-
-    if (ev == NULL)
-        return;
-
-    for (i = 0; i < ev->nsymbols; i++)
-        dmFree(ev->symbols[i].name);
-
-    dmFree(ev->symbols);
-    dmEvalContextClear(ev);
-    dmFree(ev);
-}
-
-
-static DMEvalNode *dmEvalInsertNode(DMEvalNode **list, DMEvalNode *node)
-{
-    if (*list != NULL)
-    {
-        node->prev = (*list)->prev;
-        (*list)->prev->next = node;
-        (*list)->prev = node;
-    }
-    else
-    {
-        *list = node;
-        node->prev = *list;
-    }
-
-    node->next = NULL;
-    return node;
-}
-
-
-static DMEvalNode *dmEvalAddNode(DMEvalNode **list, const int op)
-{
-    DMEvalNode *node = dmCalloc(1, sizeof(DMEvalNode));
-    if (node == NULL)
-        return NULL;
-
-    node->op = op;
-
-    return dmEvalInsertNode(list, node);
-}
-
-
-enum
-{
-    PARSE_NONE          = 0x0000,
-    PARSE_START         = 0x1000,
-    PARSE_END           = 0x2000,
-    PARSE_ERROR         = 0x8000,
-
-    PARSE_IDENT         = 0x0001, // Any identifier (variable, function name)
-    PARSE_CONST         = 0x0002, // Constant value (n, n.nnn, etc)
-    PARSE_OPER          = 0x0004, // All operators
-    PARSE_OPER_UNARY    = 0x0008, // Unary operators ~, -
-    PARSE_SUBEXPR_START = 0x0010, // ( ...
-    PARSE_SUBEXPR_END   = 0x0020, // )
-    PARSE_ARGS          = 0x0040, // function args: (xxx[, yyy ...])
-
-    PARSE_NORMAL        = PARSE_CONST | PARSE_IDENT | PARSE_SUBEXPR_START | PARSE_OPER_UNARY,
-};
-
-#define DM_CHECK(x) { if (mode & PARSE_ ## x ) { if (str[0]) strcat(str, " or "); strcat(str, # x ); } }
-
-static char *dmEvalGetMode(int mode)
-{
-    char str[128] = "";
-
-    DM_CHECK(START);
-    DM_CHECK(END);
-    DM_CHECK(IDENT);
-    DM_CHECK(CONST);
-    DM_CHECK(OPER);
-    DM_CHECK(OPER_UNARY);
-    DM_CHECK(SUBEXPR_START);
-    DM_CHECK(SUBEXPR_END);
-    DM_CHECK(ARGS);
-
-    return dm_strdup(str);
-}
-
-
-static void dmEvalSetMode(DMEvalContext *ev, const int mode)
-{
-    if (mode != PARSE_ERROR &&
-        mode != PARSE_START &&
-        ev->expect != PARSE_NONE &&
-        (mode & ev->expect) == 0)
-    {
-        char *tmp1 = dmEvalGetMode(ev->expect),
-             *tmp2 = dmEvalGetMode(mode);
-
-        dmEvalError(ev, "Expected [%s], got %s.\n", tmp1, tmp2);
-        dmFree(tmp1);
-        dmFree(tmp2);
-    }
-
-    ev->prev = ev->mode;
-    ev->mode = mode;
-}
-
-
-static BOOL dmEvalTokenizeExpr(DMEvalContext *ev, DMEvalNode **list, char **str, int depth)
-{
-    char *c = *str;
-    char tmpStr[DM_MAX_BUF + 2], *tmp;
-    int tmpStrLen = 0, argIndex, op;
-    DMEvalNode *node = NULL, *func = NULL;
-    BOOL first = FALSE, decimal = FALSE;
-
-    ev->expect = PARSE_NORMAL;
-    ev->mode = PARSE_START;
-
-    while (ev->mode != PARSE_ERROR && ev->mode != PARSE_END)
-    switch (ev->mode)
-    {
-        case PARSE_START:
-            // Start
-            if (*c == 0)
-                dmEvalSetMode(ev, PARSE_END);
-
-            // Skip whitespace
-            else if (isspace(*c))
-                c++;
-
-            else if (*c == ')' || *c == ',')
-            {
-                if (depth > 0)
-                    dmEvalSetMode(ev, PARSE_END);
-                else
-                {
-                    dmEvalError(ev, "Invalid nesting near '%s' (depth %d).\n", c, depth);
-                    dmEvalSetMode(ev, PARSE_ERROR);
-                }
-                c++;
-            }
-
-            else if (*c == '(')
-                dmEvalSetMode(ev, func != NULL ? PARSE_ARGS : PARSE_SUBEXPR_START);
-
-            else if (*c == '-')
-                dmEvalSetMode(ev, (ev->prev == PARSE_START || ev->prev == PARSE_OPER || ev->prev == PARSE_OPER_UNARY) ? PARSE_OPER_UNARY : PARSE_OPER);
-
-            else if (*c == '~')
-                dmEvalSetMode(ev, PARSE_OPER_UNARY);
-
-            else if (strchr("+*/<>%&|!^", *c))
-                dmEvalSetMode(ev, PARSE_OPER);
-
-            else if (isdigit(*c) || *c == '.')
-                dmEvalSetMode(ev, PARSE_CONST);
-
-            else if (isalpha(*c) || *c == '_')
-                dmEvalSetMode(ev, PARSE_IDENT);
-
-            else
-            {
-                dmEvalError(ev, "Syntax error near '%s' (depth %d).\n", c, depth);
-                dmEvalSetMode(ev, PARSE_ERROR);
-            }
-
-            first = TRUE;
-            break;
-
-        case PARSE_SUBEXPR_START:
-            tmp = c + 1;
-
-            ev->expect = PARSE_NORMAL;
-
-            if ((node = dmEvalAddNode(list, OP_SUBEXPR)) == NULL)
-                dmEvalSetMode(ev, PARSE_ERROR);
-            else
-            if (dmEvalTokenizeExpr(ev, &(node->subexpr), &tmp, depth + 1) != 0)
-            {
-                dmEvalError(ev, "Subexpression starting at '%s' contained errors.\n", c);
-                dmEvalSetMode(ev, PARSE_ERROR);
-            }
-
-            if (ev->mode != PARSE_ERROR)
-            {
-                dmEvalSetMode(ev, PARSE_START);
-                ev->expect = PARSE_OPER | PARSE_SUBEXPR_END;
-                c = tmp;
-            }
-            break;
-
-        case PARSE_ARGS:
-            tmp = c + 1;
-
-            for (argIndex = 0; argIndex < func->symbol->nargs; argIndex++)
-            {
-                if (dmEvalTokenizeExpr(ev, &(func->args[argIndex]), &tmp, depth + 1) != 0)
-                {
-                    dmEvalError(ev, "Function argument subexpression starting at '%s' contained errors.\n", c);
-                    dmEvalSetMode(ev, PARSE_ERROR);
-                }
-            }
-
-            func = NULL;
-
-            if (ev->mode != PARSE_ERROR)
-            {
-                dmEvalSetMode(ev, PARSE_START);
-                ev->expect = PARSE_OPER | PARSE_END;
-                c = tmp;
-            }
-            break;
-
-        case PARSE_CONST:
-            if (first)
-            {
-                first = FALSE;
-                decimal = FALSE;
-                tmpStrLen = 0;
-
-                if (isdigit(*c) || *c == '-' || *c == '+' || *c == '.')
-                {
-                    if (*c == '.')
-                        decimal = TRUE;
-                    tmpStr[tmpStrLen++] = *c++;
-                }
-                else
-                {
-                    dmEvalError(ev, "Invalid constant expression near '%s'.\n", c);
-                    dmEvalSetMode(ev, PARSE_ERROR);
-                }
-            }
-            else
-            {
-                if (isdigit(*c))
-                {
-                    tmpStr[tmpStrLen++] = *c++;
-                }
-                else
-                if (*c == '.')
-                {
-                    if (!decimal)
-                    {
-                        tmpStr[tmpStrLen++] = *c++;
-                        decimal = TRUE;
-                    }
-                    else
-                    {
-                        dmEvalError(ev, "Invalid constant expression near '%s'.\n", c);
-                        dmEvalSetMode(ev, PARSE_ERROR);
-                    }
-                }
-                else
-                {
-                    tmpStr[tmpStrLen] = 0;
-
-                    if ((node = dmEvalAddNode(list, OP_VALUE)) == NULL)
-                    {
-                        dmEvalSetMode(ev, PARSE_ERROR);
-                    }
-                    else
-                    {
-                        node->val = atof(tmpStr);
-                        dmEvalSetMode(ev, PARSE_START);
-                        ev->expect = PARSE_OPER | PARSE_END;
-                    }
-                }
-            }
-            break;
-
-        case PARSE_OPER_UNARY:
-            {
-                int op = OP_INVALID;
-
-                switch (*c)
-                {
-                    case '-': op = OP_SUB_UNARY; c++; break;
-                    case '~': op = OP_BIT_COMPLEMENT; c++; break;
-                }
-
-                if (op != OP_INVALID)
-                {
-                    if ((node = dmEvalAddNode(list, op)) != NULL)
-                    {
-                        ev->expect = PARSE_NORMAL;
-                        dmEvalSetMode(ev, PARSE_START);
-                    }
-                    else
-                        dmEvalSetMode(ev, PARSE_ERROR);
-                }
-            }
-            break;
-
-        case PARSE_OPER:
-            op = OP_INVALID;
-
-            switch (*c)
-            {
-                case '+': op = OP_ADD; c++; break;
-                case '-': op = OP_SUB; c++; break;
-                case '*': op = OP_MUL; c++; break;
-                case '/': op = OP_DIV; c++; break;
-                case '%': op = OP_MOD; c++; break;
-                case '&': op = OP_BIT_AND; c++; break;
-                case '^': op = OP_BIT_XOR; c++; break;
-                case '|': op = OP_BIT_OR; c++; break;
-
-                case '>':
-                    if (c[1] == '>')
-                    {
-                        c += 2;
-                        op = OP_BIT_RSHIFT;
-                    }
-                    else
-                    {
-                        op = (c[1] == '=') ? OP_GT_EQ : OP_GT;
-                        c++;
-                    }
-                    break;
-
-                case '<':
-                    if (c[1] == '<')
-                    {
-                        c += 2;
-                        op = OP_BIT_LSHIFT;
-                    }
-                    else
-                    {
-                        op = (c[1] == '=') ? OP_LT_EQ : OP_LT;
-                        c++;
-                    }
-                    break;
-
-                default:
-                    dmEvalError(ev, "Unknown operator '%c' at %s\n", *c, c);
-                    dmEvalSetMode(ev, PARSE_ERROR);
-            }
-
-            if (op != OP_INVALID)
-            {
-                if ((node = dmEvalAddNode(list, op)) != NULL)
-                {
-                    ev->expect = PARSE_NORMAL | PARSE_OPER_UNARY;
-                    dmEvalSetMode(ev, PARSE_START);
-                }
-                else
-                    dmEvalSetMode(ev, PARSE_ERROR);
-            }
-            break;
-
-        case PARSE_IDENT:
-            if (isalnum(*c) || *c == '_')
-            {
-                if (first)
-                {
-                    tmpStrLen = 0;
-                    first = FALSE;
-                }
-
-                if (tmpStrLen < DM_MAX_BUF)
-                    tmpStr[tmpStrLen++] = *c++;
-                else
-                {
-                    tmpStr[tmpStrLen] = 0;
-                    dmEvalError(ev, "Identifier too long! ('%s') near %s\n", tmpStr, c);
-                }
-            }
-            else
-            {
-                tmpStr[tmpStrLen] = 0;
-                DMEvalSymbol *symbol = dmEvalContextFindSymbol(ev, tmpStr);
-                if (symbol != NULL)
-                {
-                    if ((node = dmEvalAddNode(list, symbol->type == SYM_FUNC ? OP_FUNC : OP_VAR)) != NULL)
-                    {
-                        node->symbol = symbol;
-                        if (symbol->type == SYM_FUNC)
-                        {
-                            func = node;
-                            ev->expect = PARSE_ARGS;
-                        }
-                        else
-                            ev->expect = PARSE_END | PARSE_OPER;
-
-                        dmEvalSetMode(ev, PARSE_START);
-                    }
-                    else
-                        dmEvalSetMode(ev, PARSE_ERROR);
-                }
-                else
-                {
-                    dmEvalError(ev, "No such identifier '%s'.\n", tmpStr);
-                    dmEvalSetMode(ev, PARSE_ERROR);
-                }
-            }
-            break;
-    }
-
-    *str = c;
-
-    return (ev->mode == PARSE_ERROR);
-}
-
-
-int dmEvalParseExpr(DMEvalContext *ev, char *expr, DMEvalNode **result)
-{
-    int ret;
-
-    if (ev == NULL || result == NULL)
-        return DMERR_NULLPTR;
-
-    ev->prev = PARSE_START;
-    ret = dmEvalTokenizeExpr(ev, result, &expr, 0);
-
-    return ret;
-}
-
-
-
-
-BOOL dmEvalTreeExecute(DMEvalContext *ev, DMEvalNode *node, DMValue *presult)
-{
-    DMValue val1, val2;
-
-    if (node == NULL)
-        return FALSE;
-
-    switch (node->op)
-    {
-        case OP_VAR:
-            switch (node->symbol->type)
-            {
-                case SYM_CONST: *presult = node->symbol->cvalue; return TRUE;
-                case SYM_VAR  : *presult = *(node->symbol->var); return TRUE;
-            }
-            return FALSE;
-
-        case OP_VALUE:
-            *presult = node->val;
-            return TRUE;
-
-        case OP_FUNC:
-
-            return TRUE;
-
-        case OP_SUBEXPR:
-            return dmEvalTreeExecute(ev, node->subexpr, presult);
-
-        // Binary operators
-        case OP_BIT_LSHIFT:
-        case OP_BIT_RSHIFT:
-
-        case OP_BIT_AND:
-        case OP_BIT_XOR:
-        case OP_BIT_OR:
-
-        case OP_ADD:
-        case OP_SUB:
-        case OP_MUL:
-        case OP_DIV:
-        case OP_MOD:
-            if (!dmEvalTreeExecute(ev, node->left, &val1) ||
-                !dmEvalTreeExecute(ev, node->right, &val2))
-                return FALSE;
-
-            switch (node->op)
-            {
-                case OP_DIV:
-                    if (val2 == 0)
-                    {
-                        dmEvalError(ev, "Division by zero.\n");
-                        return FALSE;
-                    }
-                    *presult = val1 / val2;
-                    break;
-
-
-                case OP_MOD:
-                    if (val2 == 0)
-                    {
-                        dmEvalError(ev, "Division by zero.\n");
-                        return FALSE;
-                    }
-                    *presult = DMCONVTYPE val1 % DMCONVTYPE val2;
-                    break;
-
-                case OP_BIT_LSHIFT:
-                    if (val2 > 31)
-                        dmEvalError(ev, "Left shift count >= width of type (%d << %d)\n", val1, val2);
-                    *presult = DMCONVTYPE val1 << DMCONVTYPE val2; break;
-
-                case OP_BIT_RSHIFT:
-                    if (val2 > 31)
-                        dmEvalError(ev, "Right shift count >= width of type (%d >> %d)\n", val1, val2);
-                    *presult = DMCONVTYPE val1 >> DMCONVTYPE val2; break;
-
-                case OP_MUL     : *presult = val1 * val2; break;
-                case OP_ADD     : *presult = val1 + val2; break;
-                case OP_SUB     : *presult = val1 - val2; break;
-                case OP_BIT_AND : *presult = DMCONVTYPE val1 & DMCONVTYPE val2; break;
-                case OP_BIT_OR  : *presult = DMCONVTYPE val1 | DMCONVTYPE val2; break;
-                case OP_BIT_XOR : *presult = DMCONVTYPE val1 ^ DMCONVTYPE val2; break;
-            }
-            return TRUE;
-
-        // Unary operators
-        case OP_SUB_UNARY:
-        case OP_BIT_COMPLEMENT:
-/*
-            switch (node->op)
-            {
-                case OP_SUB_UNARY: *presult -= tmp; break;
-                case OP_BIT_COMPLEMENT: *presult = DMCONVTYPE ~(DMCONVTYPE tmp); break;
-            }
-*/
-            return TRUE;
-
-        default:
-            dmEvalError(ev, "Invalid opcode %d in node %p.\n", node->op, node);
-            return FALSE;
-    }
-}
--- a/src/dmeval.h	Fri May 11 23:44:53 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,136 +0,0 @@
-#ifndef DMEVAL_H
-#define DMEVAL_H
-
-#include "dmlib.h"
-#include <stdio.h>
-
-
-typedef double DMValue;
-#define DMCONVTYPE       (int)
-#define DM_EVAL_MAX_ARGS      4
-
-
-enum
-{
-    OP_SUB_UNARY,
-    OP_BIT_COMPLEMENT,
-
-    OP_ADD,
-    OP_SUB,
-    OP_MUL,
-    OP_DIV,
-    OP_MOD,
-
-    OP_BIT_LSHIFT,
-    OP_BIT_RSHIFT,
-
-    OP_BIT_AND,
-    OP_BIT_OR,
-    OP_BIT_XOR,
-
-    OP_GT_EQ,
-    OP_LT_EQ,
-    OP_GT,
-    OP_LT,
-
-    // Special ops
-    OP_FUNC,
-    OP_VAR,
-    OP_VALUE,
-    OP_SUBEXPR,
-
-    // Total number of operators
-    OP_NOPERS,
-
-    OP_INVALID
-} DMEvalOperId;
-
-
-enum
-{
-    OT_NONE,
-
-    OT_LEFT,      // Left-associative
-    OT_RIGHT,     // Right-associative
-    OT_UNARY,
-} DMEvalOperAssoc;
-
-
-typedef struct
-{
-    char *name;     // Token
-    int   assoc;    // Associativity type (DMEvalOperAssoc)
-    BOOL  tokenize; // Automatically tokenize?
-} DMEvalOper;
-
-
-enum
-{
-    SYM_FUNC,
-    SYM_VAR,
-    SYM_CONST,
-} DMEvalSymbolType;
-
-
-typedef struct
-{
-    char *name;     // Name of the symbol
-    int type;       // Type (SYM_*)
-    int nargs;      // Number of arguments, if SYM_FUNC
-
-    DMValue (*func)(DMValue arg[DM_EVAL_MAX_ARGS]);
-
-    DMValue *var;   // Pointer to variable value if SYM_VAR
-    DMValue cvalue; // Const value, if SYM_CVAR
-} DMEvalSymbol;
-
-
-typedef struct DMEvalNode
-{
-    int op;               // Operator/token type
-    DMValue val;          // Value, if immediate constant
-    DMEvalSymbol *symbol; // Symbol pointer, if function/variable/constvar
-
-    struct DMEvalNode *args[DM_EVAL_MAX_ARGS]; // Arguments, if function
-
-    struct DMEvalNode *subexpr, *left, *right, *next, *prev;
-} DMEvalNode;
-
-
-typedef struct
-{
-    BOOL err;
-    char *errStr;
-
-    int nsymbols;
-    DMEvalSymbol *symbols;
-
-    int mode, prev, expect;
-} DMEvalContext;
-
-
-// Evaluation context management
-DMEvalContext * dmEvalContextNew(void);
-void            dmEvalContextClose(DMEvalContext *ev);
-void            dmEvalContextClear(DMEvalContext *ev);
-
-
-// Symbol management
-DMEvalSymbol *  dmEvalContextFindSymbol(DMEvalContext *ev, const char *name);
-DMEvalSymbol *  dmEvalContextAddVar(DMEvalContext *ev, const char *name, DMValue *var);
-DMEvalSymbol *  dmEvalContextAddConst(DMEvalContext *ev, const char *name, DMValue value);
-DMEvalSymbol *  dmEvalContextAddFunc(DMEvalContext *ev, const char *name, DMValue (*func)(DMValue *), int nargs);
-
-
-// Evaluation trees, tokenization, parsing
-int   dmEvalParseExpr(DMEvalContext *ev, char *expr, DMEvalNode **plist);
-int   dmEvalTreeExecute(DMEvalContext *ev, DMEvalNode *tree, DMValue *presult);
-void  dmEvalTreeFree(DMEvalNode *node);
-
-
-void dmEvalPrintOpTree(FILE *out, DMEvalContext *ev, DMEvalNode *node);
-
-
-extern const DMEvalOper dmEvalOpers[OP_NOPERS];
-
-#endif // DMEVAL_H
--- a/src/dmevalw.c	Fri May 11 23:44:53 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,55 +0,0 @@
-#include "dmeval.h"
-
-
-void dmDoEvalPrintOpTree(FILE *out, DMEvalContext *ev, DMEvalNode *node, int level)
-{
-    int i;
-    while (node != NULL)
-    {
-        switch (node->op)
-        {
-            case OP_FUNC:
-                fprintf(out, "%s(", node->symbol != NULL ? node->symbol->name : "?ERROR");
-                for (i = 0; i < node->symbol->nargs; i++)
-                {
-                    dmDoEvalPrintOpTree(out, ev, node->args[i], level + 1);
-                    if (i < node->symbol->nargs - 1)
-                        fprintf(out, ",");
-                }
-                fprintf(out, ")");
-                break;
-
-            case OP_VAR:
-                fprintf(out, "%s", node->symbol != NULL ? node->symbol->name : "?ERROR");
-                break;
-
-            case OP_VALUE:
-                fprintf(out, "%.1f", node->val);
-                break;
-
-            case OP_SUBEXPR:
-                fprintf(out, "(");
-                if (node->subexpr != NULL)
-                    dmDoEvalPrintOpTree(out, ev, node->subexpr, level + 1);
-                else
-                    fprintf(out, "?ERROR");
-                fprintf(out, ")");
-                break;
-
-            default:
-                if (node->op >= 0 && node->op < OP_NOPERS)
-                    fprintf(out, "%s", dmEvalOpers[node->op].name);
-                else
-                    fprintf(out, "ERROR!");
-                break;
-        }
-        node = node->next;
-    }
-}
-
-
-void dmEvalPrintOpTree(FILE *out, DMEvalContext *ev, DMEvalNode *node)
-{
-    dmDoEvalPrintOpTree(out, ev, node, 0);
-    fprintf(out, "\n");
-}
--- a/tests/evaltest.c	Fri May 11 23:44:53 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,125 +0,0 @@
-#include "dmtool.h"
-#include "dmlib.h"
-#include "dmeval.h"
-#include "dmargs.h"
-
-
-BOOL    optBenchmark = FALSE,
-        optFloor = FALSE;
-char *  optExpression = "";
-
-
-static const DMOptArg optList[] =
-{
-    { 0, '?', "help",       "Show this help", OPT_NONE },
-    { 1, 'v', "verbose",    "Be more verbose", OPT_NONE },
-    { 2, 'b', "benchmark",  "Run in benchmark mode", OPT_NONE },
-    { 3, 'e', "expression", "Next argument is the expression", OPT_ARGREQ },
-    { 4, 'f', "floor",      "Clamp/floor the result value", OPT_NONE },
-};
-
-const int optListN = sizeof(optList) / sizeof(optList[0]);
-
-
-void argShowHelp()
-{
-    dmPrintBanner(stdout, dmProgName, "[options] [-e] '<expression>'");
-    dmArgsPrintHelp(stdout, optList, optListN, 0);
-}
-
-
-BOOL argHandleOpt(const int optN, char *optArg, char *currArg)
-{
-    switch (optN)
-    {
-    case 0:
-        argShowHelp();
-        exit(0);
-        break;
-
-    case 1:
-        dmVerbosity++;
-        break;
-    
-    case 2:
-        optBenchmark = TRUE;
-        break;
-
-    case 3:
-        optExpression = optArg;
-        break; 
-
-    case 4:
-        optFloor = TRUE;
-        break;
-
-    default:
-        dmErrorMsg("Unknown option '%s'.\n", currArg);
-        return FALSE;
-    }
-    
-    return TRUE;
-}
-
-
-BOOL argHandleNonOpt(char *currArg)
-{
-    optExpression = currArg;
-    return TRUE;
-}
-
-
-int main(int argc, char *argv[])
-{
-    DMEvalContext *ev = dmEvalContextNew();
-    DMEvalNode *expr = NULL;
-    DMValue result, t, f = 44100.0f;
-    int ret;
-
-    dmInitProg("evaltest", "evaltest", "0.1", NULL, NULL);
-
-    // Parse arguments
-    if (!dmArgsProcess(argc, argv, optList, optListN,
-        argHandleOpt, argHandleNonOpt, OPTH_BAILOUT))
-        exit(1);
-
-
-    // Register some variables
-    dmEvalContextAddVar(ev, "t", &t);
-    dmEvalContextAddVar(ev, "f", &f);
-
-
-    // Parse expression
-    ret = dmEvalParseExpr(ev, optExpression, &expr);
-    dmMsg(1, "parse ret=%d\n", ret);
-    if (ev->err)
-        dmErrorMsg("%s\n", ev->errStr);
-
-    if (dmVerbosity > 0)
-        dmEvalPrintOpTree(stdout, ev, expr);
-    
-    if (ret != 0)
-        return -1;
-    
-    // Benchmark or execute
-    dmEvalContextClear(ev);
-
-    if (optBenchmark)
-    {
-        dmMsg(0, "Benchmarking ...\n");
-        for (t = 0; t < 12500000; t++)
-            ret = dmEvalTreeExecute(ev, expr, &result);
-    }
-    else
-    {
-        ret = dmEvalTreeExecute(ev, expr, &result);
-        printf("%1.5f\n", optFloor ? (int) result : result);
-    }
-
-    dmMsg(1, "eval ret=%d\n", ret);
-
-    dmEvalContextClose(ev);
-    dmEvalTreeFree(expr);
-
-    return 0;
-}
--- a/tools/auval.c	Fri May 11 23:44:53 2018 +0300
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,1142 +0,0 @@
-#include "dmlib.h"
-#include "libgutil.h"
-#include "dmargs.h"
-#include "dmeval.h"
-#include "dmtext.h"
-#include <math.h>
-
-
-#define AUVAL_NAME           "AuVal"
-#define AUVAL_VERSION        "0.6"
-#define AUVAL_TMPBUF_SIZE    (4096)
-#define AUVAL_HISTORY_FILE   "history.txt"
-#define AUVAL_HISTORY_USER   "formulas.txt"
-#define SDL_NCOLORS           256
-
-
-enum
-{
-    REDRAW_VISUALIZER = 0x00000001,
-    REDRAW_EDITOR     = 0x00000002,
-    REDRAW_INFO       = 0x00000004,
-    REDRAW_ALL        = 0x0fffffff,
-};
-
-
-typedef struct
-{
-    DMEvalNode *expr;
-    DMEvalContext *ctx;
-
-    double varTime, varFreq, varKeyTime,
-           varKeyTimeRev, varKeyFreq, varUnit;
-
-    int avail, bufsize, pos, oldpos;
-    Uint8 *buf;
-
-    DMMutex *mutex;
-} AUAudioData;
-
-
-char *optFontFile = "font.ttf";
-
-int optVFlags      = SDL_SWSURFACE | SDL_HWPALETTE,
-    optScrWidth    = 640,
-    optScrHeight   = 480,
-    optScrDepth    = 32,
-    optFontSize    = 20,
-    optAudioFreq   = 44100,
-    optBMPSize     = 32,
-    optHistoryLen  = 64;
-
-BOOL optClipping = TRUE,
-     optScale = TRUE;
-
-
-static const DMOptArg optList[] =
-{
-    { 0, '?', "help",       "Show this help", OPT_NONE },
-    { 2, 'v', "verbose",    "Be more verbose", OPT_NONE },
-    { 3,   0, "fs",         "Fullscreen", OPT_NONE },
-    { 5, 's', "size",       "Initial window size/resolution -s 640x480", OPT_ARGREQ },
-    { 6, 'd', "depth",      "Color depth of mode/window in bits (8/15/16/32)", OPT_ARGREQ },
-    { 7, 'f', "freq",       "Audio output frequency", OPT_ARGREQ },
-    { 8, 'b', "bmpsize",    "Bitmap size", OPT_ARGREQ },
-
-    {10, 'n', "noclip",     "Disable clipping by default", OPT_NONE },
-    {11, 'r', "range",      "Use range [0, 255] instead of [0.0, 1.0]", OPT_NONE },
-};
-
-const int optListN = sizeof(optList) / sizeof(optList[0]);
-
-
-void argShowHelp()
-{
-    printf("%s v%s\n(C) Copyright 2011 ccr/TNSP\n", AUVAL_NAME, AUVAL_VERSION);
-    dmArgsPrintHelp(stdout, optList, optListN, 0);
-}
-
-
-BOOL argHandleOpt(const int optN, char *optArg, char *currArg)
-{
-    switch (optN) {
-    case 0:
-        argShowHelp();
-        exit(0);
-        break;
-
-    case 2:
-        dmVerbosity++;
-        break;
-
-    case 3:
-        optVFlags |= SDL_FULLSCREEN;
-        break;
-
-    case 5:
-        if (optArg)
-        {
-            int w, h;
-            if (sscanf(optArg, "%dx%d", &w, &h) == 2)
-            {
-                if (w < 320 || h < 200 || w > 3200 || h > 3200)
-                {
-                    dmErrorMsg("Invalid width or height: %d x %d\n", w, h);
-                    return FALSE;
-                }
-                optScrWidth = w;
-                optScrHeight = h;
-            }
-            else
-            {
-                dmErrorMsg("Invalid size argument '%s'.\n", optArg);
-                return FALSE;
-            }
-        }
-        else
-        {
-            dmErrorMsg("Dimensions option %s requires an argument.\n", currArg);
-        }
-        break;
-
-    case 6:
-        optScrDepth = atoi(optArg);
-        break;
-
-    case 7:
-        {
-            int tmp = atoi(optArg);
-            if (tmp < 4000 || tmp > 96000)
-            {
-                dmErrorMsg("Invalid audio frequency '%s'.\n", optArg);
-                return FALSE;
-            }
-            optAudioFreq = tmp;
-        }
-        break;
-
-    case 8:
-        {
-            int tmp = atoi(optArg);
-            if (tmp < 32 || tmp > 512)
-            {
-                dmErrorMsg("Invalid bitmap size '%s'.\n", optArg);
-                return FALSE;
-            }
-            optBMPSize = tmp;
-        }
-        break;
-
-    case 10:
-        optClipping = FALSE;
-        break;
-
-    case 11:
-        optScale = FALSE;
-        break;
-
-    default:
-        dmErrorMsg("Unknown option '%s'.\n", currArg);
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-
-typedef struct
-{
-    ssize_t pos, len, size;
-    char *data;
-    BOOL dirty;
-} AUEditBuf;
-
-
-int au_editbuf_write(AUEditBuf *buf, ssize_t pos, int ch)
-{
-    if (buf->len+1 >= buf->size) return -3;
-
-    if (pos < 0)
-        return -1;
-    else
-    if (pos >= buf->len)
-        buf->data[buf->len++] = ch;
-    else
-        buf->data[pos] = ch;
-
-    buf->dirty = TRUE;
-    return 0;
-}
-
-
-int au_editbuf_insert(AUEditBuf *buf, ssize_t pos, int ch)
-{
-    if (buf->len+1 >= buf->size) return -3;
-
-    if (pos < 0)
-        return -1;
-    else if (pos >= buf->len) {
-        buf->data[buf->len] = ch;
-    }
-    else
-    {
-        memmove(&(buf->data[pos+1]), &(buf->data[pos]), buf->len - pos + 1);
-        buf->data[pos] = ch;
-    }
-    buf->len++;
-    buf->dirty = TRUE;
-    return 0;
-}
-
-
-int au_editbuf_delete(AUEditBuf *buf, ssize_t pos)
-{
-    if (pos < 0)
-        return -1;
-    else
-    if (pos < buf->len)
-    {
-        memmove(&(buf->data[pos]), &(buf->data[pos+1]), buf->len - pos);
-        buf->len--;
-        buf->dirty = TRUE;
-        return 0;
-    } else
-        return -2;
-}
-
-
-void au_editbuf_clear(AUEditBuf *buf)
-{
-    buf->len = 0;
-    buf->pos = 0;
-    buf->dirty = TRUE;
-}
-
-
-AUEditBuf * au_editbuf_new(ssize_t n)
-{
-    AUEditBuf *res = dmCalloc(1, sizeof(AUEditBuf));
-
-    res->data = (char *) dmMalloc(n);
-    res->size = n;
-    res->dirty = TRUE;
-
-    return res;
-}
-
-AUEditBuf * au_editbuf_new_str(ssize_t n, const char *str)
-{
-    AUEditBuf *res = au_editbuf_new(n);
-    strncpy(res->data, str, res->size);
-    res->data[res->size - 1] = 0;
-    res->pos = res->len = strlen(res->data);
-    return res;
-}
-
-
-void au_editbuf_free(AUEditBuf *buf)
-{
-    if (buf != NULL)
-    {
-        dmFree(buf->data);
-        dmFree(buf);
-    }
-}
-
-
-AUEditBuf * au_editbuf_copy(AUEditBuf *src)
-{
-    AUEditBuf *res;
-
-    if (src == NULL) return NULL;
-
-    if ((res = au_editbuf_new(src->size)) == NULL)
-        return NULL;
-
-    memcpy(res->data, src->data, src->size);
-    res->pos = res->len = src->len;
-    res->dirty = TRUE;
-
-    return res;
-}
-
-
-char * au_editbuf_get_string(AUEditBuf *buf, ssize_t start, ssize_t end)
-{
-    char *str;
-    ssize_t siz;
-
-    if (buf == NULL)
-        return NULL;
-
-    if (start < 0 || end > buf->len || start >= buf->len)
-        return NULL;
-
-    if (end < 0) {
-        siz = buf->len - start + 1;
-    } else if (start <= end) {
-        siz = end - start + 1;
-    } else
-        return NULL;
-
-    if ((str = dmMalloc(siz + 1)) == NULL)
-        return NULL;
-
-    memcpy(str, buf->data + start, siz);
-    str[siz] = 0;
-
-    return str;
-}
-
-
-void au_editbuf_setpos(AUEditBuf *buf, ssize_t pos)
-{
-    if (pos < 0)
-        buf->pos = 0;
-    else if (pos >= buf->len)
-        buf->pos = buf->len;
-    else
-        buf->pos = pos;
-}
-
-
-BOOL au_init_video(SDL_Surface **screen)
-{
-    *screen = SDL_SetVideoMode(optScrWidth, optScrHeight, optScrDepth, optVFlags | SDL_RESIZABLE);
-    if (*screen == NULL)
-    {
-        dmErrorMsg("Can't SDL_SetVideoMode(): %s\n", SDL_GetError());
-        return FALSE;
-    }
-
-    return TRUE;
-}
-
-
-void au_draw_editbuf(SDL_Surface *screen, TTF_Font *font, SDL_Color col,
-    int xc, int yc, int w, int h, AUEditBuf *buf, int curcol)
-{
-    ssize_t left, maxlen, pos;
-    int strw, strh, y1 = yc + h;
-    char *line = NULL, *ptr;
-
-    if (buf == NULL)
-        return;
-
-    if (TTF_SizeText(font, "X", &strw, &strh) != 0)
-        goto error;
-
-    maxlen = w / strw;
-    line = dmMalloc(maxlen + 2);
-    pos = 0;
-    left = buf->len;
-    ptr = buf->data;
-
-    do
-    {
-        ssize_t ppos = buf->pos - pos;
-        if (ppos >= 0 && ppos < maxlen)
-        {
-            int x0 = xc + ppos * strw;
-            dmFillRect(screen, x0, yc, x0 + strw, yc + strh, curcol);
-        }
-        else
-        if ((buf->pos % maxlen) == 0)
-        {
-            dmFillRect(screen, xc, yc + strh, xc + strw, yc + strh + strh, curcol);
-        }
-
-        ssize_t len = left > maxlen ? maxlen : left;
-        strncpy(line, ptr, len);
-        line[len] = 0;
-
-        dmDrawTTFTextConst(screen, font, col, xc, yc, line);
-
-        left -= len;
-        ptr += len;
-        pos += len;
-
-        yc += strh;
-    }
-    while (left > 0 && yc < y1);
-
-
-error:
-    dmFree(line);
-}
-
-
-void au_vis_wave(SDL_Surface *screen, int x0, int y0, int x1, int y1, AUAudioData *data)
-{
-    int x, offs;
-    const int height = y1 - y0, center = y0 + (height / 2);
-    const int pitch = screen->pitch, bpp = screen->format->BytesPerPixel;
-    const int xend = x1 * bpp;
-    const float scale = 128.0f / (float) height;
-
-    dmMutexLock(data->mutex);
-
-    Uint8 *dp = data->buf,
-          *sp = screen->pixels;
-
-    for (offs = 0, x = x0 * bpp; x < xend && offs < data->avail; x += bpp, offs++)
-    {
-        const int curr = center + ((dp[offs] - 128) * scale);
-        sp[x + curr * pitch] = 255;
-    }
-
-    dmMutexUnlock(data->mutex);
-}
-
-
-void au_vis_image(SDL_Surface *screen, AUAudioData *data)
-{
-    int y;
-    Uint8 *p = (Uint8 *) screen->pixels;
-
-    dmMutexLock(data->mutex);
-
-    Uint8 *dp = data->buf;
-
-    for (y = 0; y < screen->h; y++)
-    {
-        int x;
-        for (x = 0; x < screen->w; x++)
-            *p++ = *dp++;
-
-        p += screen->pitch - screen->w;
-    }
-
-    dmMutexUnlock(data->mutex);
-}
-
-
-int au_get_note_from_key(SDL_keysym *key, int octave)
-{
-    int note;
-
-    switch (key->sym)
-    {
-        case SDLK_z: note = 1; break;
-        case SDLK_s: note = 2; break;
-        case SDLK_x: note = 3; break;
-        case SDLK_d: note = 4; break;
-        case SDLK_c: note = 5; break;
-        case SDLK_v: note = 6; break;
-        case SDLK_g: note = 7; break;
-        case SDLK_b: note = 8; break;
-        case SDLK_h: note = 9; break;
-        case SDLK_n: note = 10; break;
-        case SDLK_j: note = 11; break;
-        case SDLK_m: note = 12; break;
-
-        case SDLK_q: note = 13; break;
-        case SDLK_2: note = 14; break;
-        case SDLK_w: note = 15; break;
-        case SDLK_3: note = 16; break;
-        case SDLK_e: note = 17; break;
-        case SDLK_r: note = 18; break;
-        case SDLK_5: note = 19; break;
-        case SDLK_t: note = 20; break;
-        case SDLK_6: note = 21; break;
-        case SDLK_y: note = 22; break;
-        case SDLK_7: note = 23; break;
-        case SDLK_u: note = 24; break;
-        case SDLK_i: note = 25; break;
-        case SDLK_9: note = 26; break;
-        case SDLK_o: note = 27; break;
-        case SDLK_0: note = 28; break;
-        case SDLK_p: note = 29; break;
-
-        default: return -1;
-    }
-
-    note += 12 * octave;
-    return (note < 1) ? 1 : (note > 120 ? 120 : note);
-}
-
-
-void au_adjust_value(int *val, int min, int max, int delta)
-{
-    *val += delta;
-    if (*val < min) *val = min;
-    else if (*val > max) *val = max;
-}
-
-
-int au_read_history(const char *filename, AUEditBuf **history, int maxHistory, int *histMax)
-{
-    char tmpStr[1024];
-    int i;
-
-    FILE *f = fopen(filename, "r");
-    if (f == NULL)
-    {
-        dmErrorMsg("Could not open input file '%s'.\n", filename);
-        return -1;
-    }
-
-    while (fgets(tmpStr, sizeof(tmpStr), f) != NULL)
-    {
-        /* Strip the string end from linefeeds etc. */
-        for (i = 0; tmpStr[i] != 0 && i < 512; i++);
-        while (--i >= 0 && (tmpStr[i] == '\n' || tmpStr[i] == '\r' || isspace(tmpStr[i])))
-            tmpStr[i] = 0;
-
-        /* Add to history only if it's not an empty line */
-        if (tmpStr[0] != 0)
-        {
-            au_editbuf_free(history[maxHistory + 1]);
-            history[maxHistory + 1] = NULL;
-            memmove(&history[2], &history[1], maxHistory * sizeof(history[0]));
-
-            history[1] = au_editbuf_new_str(AUVAL_TMPBUF_SIZE, tmpStr);
-
-            if (*histMax < maxHistory)
-                (*histMax)++;
-        }
-    }
-
-    fclose(f);
-    return 0;
-}
-
-
-int au_save_history(const char *filename, AUEditBuf **history, int histMax)
-{
-    int i;
-
-    FILE *f = fopen(filename, "w");
-    if (f == NULL)
-    {
-        dmErrorMsg("Could not create output file '%s'.\n", filename);
-        return -1;
-    }
-
-    for (i = histMax; i >= 0; i--)
-    {
-        AUEditBuf *buf = history[i];
-        if (buf != NULL)
-        {
-            buf->data[buf->len] = 0;
-            fprintf(f, "%s\n", buf->data);
-        }
-    }
-
-    fclose(f);
-    return 0;
-}
-
-
-/* SDL audio callback. We do the actual rendering here, by setting
- * Lua variables and calling Lua evaluation function to generate samples.
- *
- * Mutex locking is used to ensure that the variables are not improperly
- * accessed.
- */
-void au_sdl_audio_fill(void *udata, Uint8 *buf, int len)
-{
-    AUAudioData *data = (AUAudioData *) udata;
-
-    dmMutexLock(data->mutex);
-
-    data->avail = 0;
-
-    if (!data->ctx->err)
-    {
-        while (data->avail < len && data->avail < data->bufsize)
-        {
-            double value;
-
-            data->varKeyTimeRev = 1.0f - data->varKeyTime;
-
-            if (dmEvalTreeExecute(data->ctx, data->expr, &value) != 0)
-                break;
-
-            if (optScale)
-            {
-                if (optClipping)
-                    value = ((value < -1.0f) ? -1.0f : ((value > 1.0f) ? 1.0f : value));
-
-                value = 128 + (value * 126);
-            }
-            else
-            {
-                if (optClipping)
-                    value = ((value < 0) ? 0 : ((value > 255) ? 255 : value));
-            }
-
-            data->buf[data->avail++] = value;
-
-            data->varTime += data->varFreq;
-            data->varUnit += data->varKeyFreq;
-
-            data->varKeyTime += data->varKeyFreq;
-            if (data->varKeyTime > 1.0f)
-                data->varKeyTime = 1.0f;
-        }
-
-        if (data->avail >= len && !data->ctx->err)
-        {
-            memcpy(buf, data->buf, len);
-            data->pos += len;
-        }
-        else
-            dmMemset(buf, 0, len);
-    }
-
-    dmMutexUnlock(data->mutex);
-}
-
-
-int main(int argc, char *argv[])
-{
-    AUEditBuf *editBuf = au_editbuf_new(AUVAL_TMPBUF_SIZE);
-    AUEditBuf **histBuf = NULL;
-    int histPos = 0, histMax = 0, viewMode;
-    SDL_Surface *screen = NULL, *bmp = NULL;
-    TTF_Font *font = NULL;
-    SDL_Color fontcol = {255,255,255, 0};
-    SDL_Event event;
-    SDL_AudioSpec fmt;
-    AUAudioData audata;
-    int needRedraw;
-    BOOL initSDL = FALSE, initTTF = FALSE, exitFlag,
-         insertMode, audioPlaying = FALSE, jazzMode;
-
-    dmMemset(&audata, 0, sizeof(audata));
-
-    /* Parse arguments */
-    if (!dmArgsProcess(argc, argv, optList, optListN,
-        argHandleOpt, NULL, 0))
-        exit(1);
-
-
-    /* Allocate edit history buffers */
-    histBuf = dmCalloc(sizeof(histBuf[0]), optHistoryLen + 2);
-    if (histBuf == NULL)
-    {
-        dmErrorMsg("Could not allocate memory for edit history buffer!\n");
-        goto error_exit;
-    }
-
-
-    /* Read in history file, if any exists */
-    au_read_history(AUVAL_HISTORY_FILE, histBuf, optHistoryLen, &histMax);
-
-
-    /* Initialize evaluator ctx */
-    audata.ctx = dmEvalContextNew();
-    audata.expr = NULL;
-
-    dmEvalContextAddVar(audata.ctx, "t", &audata.varTime);
-    dmEvalContextAddVar(audata.ctx, "k", &audata.varKeyTime);
-    dmEvalContextAddVar(audata.ctx, "q", &audata.varKeyTimeRev);
-    dmEvalContextAddVar(audata.ctx, "f", &audata.varUnit);
-
-
-    /* Initialize SDL */
-    if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER | SDL_INIT_AUDIO) != 0)
-    {
-        dmErrorMsg("Could not initialize SDL: %s\n", SDL_GetError());
-        goto error_exit;
-    }
-    initSDL = TRUE;
-
-    if (TTF_Init() < 0)
-    {
-        dmErrorMsg("Could not initialize FreeType/TTF: %s\n", SDL_GetError());
-        goto error_exit;
-    }
-    initTTF = TRUE;
-
-    font = TTF_OpenFont(optFontFile, optFontSize);
-    if (font == NULL)
-    {
-        dmErrorMsg("Could not load TTF font '%s' (%d): %s\n",
-            optFontFile, optFontSize, SDL_GetError());
-        goto error_exit;
-    }
-    TTF_SetFontStyle(font, TTF_STYLE_NORMAL);
-
-    if (!au_init_video(&screen))
-        goto error_exit;
-
-    SDL_WM_SetCaption(AUVAL_NAME " v" AUVAL_VERSION, AUVAL_NAME);
-
-    SDL_EnableUNICODE(1);
-    SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL);
-
-
-    /* Initialize audio */
-    fmt.freq = optAudioFreq;
-    fmt.format = AUDIO_U8;
-    fmt.channels = 1;
-    fmt.samples = 512;
-    fmt.callback = au_sdl_audio_fill;
-    fmt.userdata = &audata;
-
-    if (SDL_OpenAudio(&fmt, NULL) < 0)
-    {
-        dmErrorMsg("Could not initialize SDL audio.\n");
-        goto error_exit;
-    }
-
-    audata.bufsize = optAudioFreq;
-    audata.buf = dmMalloc(audata.bufsize * sizeof(*audata.buf));
-    audata.mutex = dmCreateMutex();
-    audata.varTime = 0;
-    audata.varKeyFreq = 1.0f / (double) optAudioFreq;
-
-    SDL_PauseAudio(0);
-    SDL_PauseAudio(1);
-
-
-    /* Create visualizer bitmap surface */
-    bmp = SDL_CreateRGBSurface(SDL_SWSURFACE, optBMPSize, optBMPSize, 8, 0, 0, 0, 0);
-    SDL_Color pal[SDL_NCOLORS];
-    int n;
-    for (n = 0; n < SDL_NCOLORS; n++)
-    {
-        pal[n].r = n;
-        pal[n].g = n;
-        pal[n].b = n;
-    }
-    SDL_SetColors(bmp, pal, 0, SDL_NCOLORS);
-
-    /* Misc inits */
-    au_editbuf_clear(editBuf);
-    needRedraw = REDRAW_ALL;
-    exitFlag = FALSE;
-    insertMode = TRUE;
-    jazzMode = FALSE;
-    viewMode = 0;
-
-    /* Enter mainloop */
-    while (!exitFlag)
-    {
-        /* Handle events */
-        while (SDL_PollEvent(&event))
-        switch (event.type)
-        {
-            case SDL_KEYDOWN:
-                {
-                /* Get key event modifiers into handy booleans */
-                BOOL modCtrl  = event.key.keysym.mod & KMOD_CTRL,
-                     modShift = event.key.keysym.mod & KMOD_SHIFT;
-
-                switch (event.key.keysym.sym)
-                {
-                    case SDLK_F1:
-                        audioPlaying = !audioPlaying;
-                        SDL_PauseAudio(!audioPlaying);
-                        needRedraw |= REDRAW_ALL;
-                        break;
-
-                    case SDLK_F2:
-                        audata.varTime = 0;
-                        audata.varKeyTime = 0;
-                        needRedraw |= REDRAW_ALL;
-                        break;
-
-                    case SDLK_F4:
-                        optClipping = !optClipping;
-                        needRedraw |= REDRAW_VISUALIZER;
-                        break;
-
-                    case SDLK_F5:
-                        /* Toggle audio scaling / range between [0.0, 1.0] and [0, 255] */
-                        optScale = !optScale;
-                        needRedraw |= REDRAW_VISUALIZER;
-                        break;
-
-
-                    case SDLK_F6:
-                        viewMode = (viewMode + 1) % 2;
-                        needRedraw |= REDRAW_VISUALIZER;
-                        break;
-
-                    case SDLK_F8:
-                        /* Toggle keyboard jazz mode */
-                        jazzMode = !jazzMode;
-                        needRedraw |= REDRAW_VISUALIZER;
-                        break;
-
-                    case SDLK_F9:
-                        /* Save history to file */
-                        au_save_history(AUVAL_HISTORY_USER, histBuf, histMax);
-                        break;
-
-                    case SDLK_ESCAPE:
-                        exitFlag = TRUE;
-                        break;
-
-                    case SDLK_RETURN:
-                        /* Add to history buffer */
-                        if (!jazzMode && editBuf->len > 0)
-                        {
-                            if (histMax > 0)
-                            {
-                                au_editbuf_free(histBuf[optHistoryLen+1]);
-                                histBuf[optHistoryLen+1] = NULL;
-                                memmove(&histBuf[2], &histBuf[1], histMax * sizeof(histBuf[0]));
-                            }
-
-                            histPos = 0;
-                            histBuf[1] = au_editbuf_copy(editBuf);
-                            if (histMax < optHistoryLen) histMax++;
-
-                            au_editbuf_insert(editBuf, editBuf->len, 0);
-
-                            /* You could do something here with the data ... */
-                            //result = handleUserInput(conn, editBuf->data, editBuf->len);
-
-                            au_editbuf_clear(editBuf);
-                        }
-                        break;
-
-                    case SDLK_UP: /* Backwards in input history */
-                        if (jazzMode)
-                            break;
-
-                        if (histPos == 0)
-                        {
-                            au_editbuf_free(histBuf[0]);
-                            histBuf[0] = au_editbuf_copy(editBuf);
-                        }
-                        if (histPos < histMax)
-                        {
-                            histPos++;
-                            au_editbuf_free(editBuf);
-                            editBuf = au_editbuf_copy(histBuf[histPos]);
-                        }
-                        break;
-
-                    case SDLK_DOWN: /* Forwards in input history */
-                        if (jazzMode)
-                            break;
-
-                        if (histPos > 0)
-                        {
-                            histPos--;
-                            au_editbuf_free(editBuf);
-                            editBuf = au_editbuf_copy(histBuf[histPos]);
-                        }
-                        break;
-
-                    case SDLK_LEFT:
-                        if (jazzMode)
-                            break;
-
-                        /* ctrl+left arrow = Skip words left */
-                        if (modCtrl)
-                        {
-                            while (editBuf->pos > 0 && isspace((int) editBuf->data[editBuf->pos - 1]))
-                                editBuf->pos--;
-                            while (editBuf->pos > 0 && !isspace((int) editBuf->data[editBuf->pos - 1]))
-                                editBuf->pos--;
-                        }
-                        else
-                        {
-                            au_editbuf_setpos(editBuf, editBuf->pos - 1);
-                        }
-                        break;
-
-                    case SDLK_RIGHT:
-                        if (jazzMode)
-                            break;
-
-                        /* ctrl+right arrow = Skip words right */
-                        if (modCtrl)
-                        {
-                            while (editBuf->pos < editBuf->len && isspace((int) editBuf->data[editBuf->pos]))
-                                editBuf->pos++;
-                            while (editBuf->pos < editBuf->len && !isspace((int) editBuf->data[editBuf->pos]))
-                                editBuf->pos++;
-                        }
-                        else
-                        {
-                            au_editbuf_setpos(editBuf, editBuf->pos + 1);
-                        }
-                        break;
-
-                    case SDLK_HOME:
-                        if (jazzMode)
-                            break;
-
-                        au_editbuf_setpos(editBuf, 0);
-                        break;
-
-                    case SDLK_END:
-                        if (jazzMode)
-                            break;
-
-                        au_editbuf_setpos(editBuf, editBuf->len);
-                        break;
-
-                    case SDLK_BACKSPACE:
-                        if (jazzMode)
-                            break;
-
-                        au_editbuf_delete(editBuf, editBuf->pos - 1);
-                        au_editbuf_setpos(editBuf, editBuf->pos - 1);
-                        break;
-
-                    case SDLK_DELETE: /* Delete character */
-                        if (jazzMode)
-                            break;
-
-                        au_editbuf_delete(editBuf, editBuf->pos);
-                        break;
-
-                    case SDLK_INSERT: /* Ins = Toggle insert / overwrite mode */
-                        if (jazzMode)
-                            break;
-
-                        insertMode = !insertMode;
-                        break;
-
-                    default:
-                        if (jazzMode)
-                        {
-                            int key = event.key.keysym.unicode;
-                            /* In keyboard jazz-mode, space stops playing */
-                            if (key == SDLK_SPACE)
-                            {
-                                dmMutexLock(audata.mutex);
-                                audata.varFreq = 1.0f;
-                                audata.pos = 0;
-                                audata.varTime = 0;
-                                audata.varKeyTime = 0;
-                                audata.varUnit = 0;
-                                dmMutexUnlock(audata.mutex);
-
-                                audioPlaying = FALSE;
-                                SDL_PauseAudio(!audioPlaying);
-                                break;
-                            }
-                            else
-                            {
-                                /* Calculate note based on key */
-                                int period, note = au_get_note_from_key(&event.key.keysym, 4);
-                                if (note > 0)
-                                {
-                                    period = 7680 - (note * 64) - (/* finetune */ 128 / 2);
-                                    if (period < 1) period = 1;
-
-                                    dmMutexLock(audata.mutex);
-                                    audata.varFreq = 8363.0f * pow(2.0f, (4608.0f - (double) period) / 768.0f) / optAudioFreq ;
-                                    audata.pos = 0;
-                                    audata.varTime = 0;
-                                    audata.varKeyTime = 0;
-                                    audata.varUnit = 0;
-                                    dmMutexUnlock(audata.mutex);
-
-                                    audioPlaying = TRUE;
-                                    SDL_PauseAudio(!audioPlaying);
-                                }
-                            }
-
-                            needRedraw |= REDRAW_VISUALIZER;
-                        }
-                        else
-                        {
-                            int key = event.key.keysym.unicode;
-                            if (isprint(key))
-                            {
-                                if (insertMode)
-                                    au_editbuf_insert(editBuf, editBuf->pos, key);
-                                else
-                                    au_editbuf_write(editBuf, editBuf->pos, key);
-                                au_editbuf_setpos(editBuf, editBuf->pos + 1);
-                            }
-                        }
-                        break;
-                }
-                }
-                needRedraw |= REDRAW_EDITOR | REDRAW_INFO;
-                break;
-
-            case SDL_VIDEORESIZE:
-                /* Window resized, reinit video etc */
-                optScrWidth = event.resize.w;
-                optScrHeight = event.resize.h;
-
-                if (!au_init_video(&screen))
-                    goto error_exit;
-
-                needRedraw = REDRAW_ALL;
-                break;
-
-            case SDL_VIDEOEXPOSE:
-                /* Window exposed, redraw everything just to be sure */
-                needRedraw = REDRAW_ALL;
-                break;
-
-            case SDL_QUIT:
-                goto error_exit;
-        }
-
-
-        /* If formula has changed, update evaluation variables and load the
-         * expression into Lua. Check for errors. The actual expression
-         * evaluation is done in the audio rendering callback.
-         */
-        if (!jazzMode && editBuf->len > 0 && editBuf->dirty)
-        {
-            editBuf->dirty = FALSE;
-            editBuf->data[editBuf->len] = 0;
-
-            dmMutexLock(audata.mutex);
-
-            dmEvalTreeFree(audata.expr);
-            audata.expr = NULL;
-            audata.ctx->err = dmEvalParseExpr(audata.ctx, editBuf->data, &audata.expr);
-            dmEvalPrintOpTree(stdout, audata.ctx, audata.expr);
-            printf("--\n");
-
-            audata.pos        = 0;
-            audata.varTime    = 0;
-            audata.varFreq    = 1.0f;
-            audata.varKeyTime = 0;
-            audata.varUnit    = 0;
-
-            dmMutexUnlock(audata.mutex);
-        }
-
-        /* Check if visualizer needs redrawing
-         */
-        if (audata.pos != audata.oldpos)
-        {
-            audata.oldpos = audata.pos;
-            needRedraw |= REDRAW_VISUALIZER;
-        }
-
-        /* Redraw screen, if needed */
-        if (needRedraw)
-        {
-            if (SDL_MUSTLOCK(screen) != 0 && SDL_LockSurface(screen) != 0)
-            {
-                dmErrorMsg("Can't lock surface");
-                goto error_exit;
-            }
-
-            /* Clear the surface, draw copyright etc */
-            int fh = TTF_FontHeight(font);
-            int eh = screen->h - fh * 4;
-
-            if (needRedraw & REDRAW_INFO)
-            {
-                dmFillBox3D(screen, 0, 0, screen->w - 1, fh + 5, dmMapRGB(screen, 50, 50, 150),
-                    dmMapRGB(screen, 150,150,250), dmMapRGB(screen, 25,25,50));
-
-                dmDrawTTFTextConst(screen, font, fontcol, 5, 2,
-                    AUVAL_NAME " v" AUVAL_VERSION " (C) Copyright 2013 ccr/TNSP");
-
-
-                dmFillBox3D(screen, 0, eh - 25 - fh, screen->w - 1, eh - 16, dmMapRGB(screen, 50, 50, 150),
-                    dmMapRGB(screen, 150,150,250), dmMapRGB(screen, 25,25,50));
-
-                dmDrawTTFText(screen, font, fontcol, 5, eh - fh - 20, "%s | [%-8s] | %s",
-                    optClipping ? "CLIPPED" : "WRAPPED",
-                    optScale ? "0.0-1.0" : "0 - 255",
-                    jazzMode ? "jazz" : "edit");
-            }
-
-            /* Draw the visualizer, based on the current mode*/
-            if (needRedraw & REDRAW_VISUALIZER)
-            {
-                char *vms;
-                dmFillRect(screen, 0, fh + 6, screen->w - 1, eh - fh - 27, dmMapRGB(screen, 15, 15, 15));
-
-                switch (viewMode)
-                {
-                    case 0:
-                        au_vis_wave(screen, 5, fh * 2 + 15, screen->w - 5, eh - 20, &audata);
-                        vms = "scope";
-                        break;
-
-                    case 1:
-                        au_vis_image(bmp, &audata);
-                        dmScaledBlitSurfaceAny(bmp, 5, fh * 2 + 15, screen->w - 10, eh - fh * 2 - 30, screen, DMD_NONE);
-                        vms = "bitmap";
-                        break;
-
-                    default:
-                        vms = "?";
-                }
-
-                dmDrawTTFText(screen, font, fontcol, 5, fh + 10, "%s | %s | f=%dHz | t=%-8.1f",
-                    audioPlaying ? "PLAYING" : "STOPPED",
-                    vms, optAudioFreq, audata.varTime
-                    );
-            }
-
-            /* Draw the function editor box */
-            if (needRedraw & REDRAW_EDITOR)
-            {
-                dmMutexLock(audata.mutex);
-
-                dmFillBox3D(screen, 0, eh - 15, screen->w - 1, screen->h - 1,
-                    audata.ctx->err ? dmMapRGB(screen, 255, 0, 0) : dmMapRGB(screen, 0, 128, 64),
-                    dmMapRGB(screen, 200, 255, 200), 100);
-
-                au_draw_editbuf(screen, font, fontcol, 5, eh - 10, screen->w - 10, eh - 15, editBuf,
-                    dmMapRGB(screen, 0, 0, 150));
-
-                if (audata.ctx->err && audata.ctx->errStr != NULL)
-                    dmDrawTTFTextConst(screen, font, fontcol, 5, screen->h - fh, audata.ctx->errStr);
-
-                dmMutexUnlock(audata.mutex);
-            }
-
-            if (SDL_MUSTLOCK(screen) != 0)
-                SDL_UnlockSurface(screen);
-
-            SDL_Flip(screen);
-            needRedraw = 0;
-        }
-
-        SDL_Delay(50);
-    }
-
-    /* Save history */
-    au_save_history(AUVAL_HISTORY_FILE, histBuf, histMax);
-
-error_exit:
-    if (font)
-        TTF_CloseFont(font);
-
-    if (audioPlaying)
-        SDL_PauseAudio(1);
-
-    dmDestroyMutex(audata.mutex);
-
-    if (initSDL)
-        SDL_Quit();
-
-    if (initTTF)
-        TTF_Quit();
-
-    return 0;
-}