# HG changeset patch # User Matti Hamalainen # Date 1526072288 -10800 # Node ID b4d37b5627725b5af5b06bbc542ca88bd85b1d32 # Parent e0cd0fc8c7536abf082686bfe360841ace0769ce Remove auval and dmeval stuff. diff -r e0cd0fc8c753 -r b4d37b562772 Makefile.gen --- 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 diff -r e0cd0fc8c753 -r b4d37b562772 src/dmeval.c --- 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 - -#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; - } -} diff -r e0cd0fc8c753 -r b4d37b562772 src/dmeval.h --- 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 - - -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 diff -r e0cd0fc8c753 -r b4d37b562772 src/dmevalw.c --- 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"); -} diff -r e0cd0fc8c753 -r b4d37b562772 tests/evaltest.c --- 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] ''"); - 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; -} diff -r e0cd0fc8c753 -r b4d37b562772 tools/auval.c --- 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 - - -#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; -}