# HG changeset patch # User nenolod # Date 1164057969 28800 # Node ID 3e160f6c04d2476ac9c2060b75ac3b86611062d4 # Parent 65c4d8591b4a0dbf5e7396e0c3e827592d977c16 [svn] - add libcalc from xvs and link to build diff -r 65c4d8591b4a -r 3e160f6c04d2 ChangeLog --- a/ChangeLog Mon Nov 20 13:06:08 2006 -0800 +++ b/ChangeLog Mon Nov 20 13:26:09 2006 -0800 @@ -1,3 +1,11 @@ +2006-11-20 21:06:08 +0000 William Pitcock + revision [598] + - pinch xvs's beat detection algorithm. + + trunk/src/paranormal/beatdetect.c | 31 +++++++++++++++++++++++-------- + 1 file changed, 23 insertions(+), 8 deletions(-) + + 2006-11-20 17:06:45 +0000 Derek Pomery revision [594] typo diff -r 65c4d8591b4a -r 3e160f6c04d2 src/paranormal/Makefile --- a/src/paranormal/Makefile Mon Nov 20 13:06:08 2006 -0800 +++ b/src/paranormal/Makefile Mon Nov 20 13:26:09 2006 -0800 @@ -3,11 +3,11 @@ OBJECTIVE_LIBS = libparanormal$(SHARED_SUFFIX) -SUBDIRS = presets +SUBDIRS = libcalc presets LIBDIR = $(plugindir)/$(VISUALIZATION_PLUGIN_DIR) -LIBADD = $(GTK_LIBS) $(XML_LIBS) $(SDL_LIBS) +LIBADD = $(GTK_LIBS) $(XML_LIBS) $(SDL_LIBS) libcalc/libcalc.a SOURCES = \ actuators.c \ diff -r 65c4d8591b4a -r 3e160f6c04d2 src/paranormal/libcalc/Makefile --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/paranormal/libcalc/Makefile Mon Nov 20 13:26:09 2006 -0800 @@ -0,0 +1,19 @@ +include ../../../mk/rules.mk +include ../../../mk/init.mk + +OBJECTIVE_LIBS_NOINST = libcalc.a + +LIBDIR = $(plugindir)/$(VISUALIZATION_PLUGIN_DIR) + +LIBADD = $(GTK_LIBS) $(XML_LIBS) $(SDL_LIBS) + +SOURCES = dict.c execute.c function.c parser.c storage.c + +OBJECTS = ${SOURCES:.c=.o} + +CFLAGS += $(PICFLAGS) $(GTK_CFLAGS) $(ARCH_DEFINES) $(XML_CPPFLAGS) $(SDL_CFLAGS) -I../../intl -I../.. + +include ../../../mk/objective.mk + +libcalc.a: $(OBJECTS) + $(AR) cq $@ $(OBJECTS) diff -r 65c4d8591b4a -r 3e160f6c04d2 src/paranormal/libcalc/calc.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/paranormal/libcalc/calc.h Mon Nov 20 13:26:09 2006 -0800 @@ -0,0 +1,30 @@ +/* calc.h -- an all-in-one include file for libcalc + * + * Copyright (C) 2001 Janusz Gregorczyk + * + * This file is part of xvs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef Included_CALC_H +#define Included_CALC_H + +#include "dict.h" +#include "execute.h" +#include "parser.h" +#include "storage.h" + +#endif /* Included_CALC_H */ diff -r 65c4d8591b4a -r 3e160f6c04d2 src/paranormal/libcalc/dict.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/paranormal/libcalc/dict.c Mon Nov 20 13:26:09 2006 -0800 @@ -0,0 +1,99 @@ +/* dict.c -- symbol dictionary structures + * + * Copyright (C) 2001 Janusz Gregorczyk + * + * This file is part of xvs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#define V_SPACE_INIT 8 +#define V_SPACE_INCR 8 + +#include +#include + +#include "dict.h" + +static void more_variables (symbol_dict_t *dict) { + var_t *new_var; + + dict->v_space += V_SPACE_INCR; + + new_var = (var_t *)g_malloc (dict->v_space * sizeof(var_t)); + + memcpy (new_var, dict->variables, dict->v_count * sizeof(var_t)); + g_free (dict->variables); + + dict->variables = new_var; +} + +symbol_dict_t *dict_new (void) { + symbol_dict_t *dict; + + dict = (symbol_dict_t *) g_malloc (sizeof(symbol_dict_t)); + + /* Allocate space for variables. */ + dict->v_count = 0; + dict->v_space = V_SPACE_INIT; + dict->variables = (var_t *)g_malloc (dict->v_space * sizeof(var_t)); + + return dict; +} + +void dict_free (symbol_dict_t *dict) { + int i; + + if (!dict) + return; + + /* Free memory used by variables. */ + for (i = 0; i < dict->v_count; i++) + g_free (dict->variables[i].name); + g_free (dict->variables); + + g_free (dict); +} + +static int dict_define_variable (symbol_dict_t *dict, const char *name) { + var_t *var; + + if (dict->v_count >= dict->v_space) + more_variables (dict); + + var = &dict->variables[dict->v_count]; + + var->value = 0.0; + var->name = g_strdup (name); + + return dict->v_count++; +} + +int dict_lookup (symbol_dict_t *dict, const char *name) { + int i; + + for (i = 0; i < dict->v_count; i++) { + if (strcmp (dict->variables[i].name, name) == 0) + return i; + } + + /* Not defined -- define a new variable. */ + return dict_define_variable (dict, name); +} + +double *dict_variable (symbol_dict_t *dict, const char *var_name) { + int id = dict_lookup (dict, var_name); + return &dict->variables[id].value; +} diff -r 65c4d8591b4a -r 3e160f6c04d2 src/paranormal/libcalc/dict.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/paranormal/libcalc/dict.h Mon Nov 20 13:26:09 2006 -0800 @@ -0,0 +1,46 @@ +/* dict.h -- symbol dictionary structures + * + * Copyright (C) 2001 Janusz Gregorczyk + * + * This file is part of xvs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef Included_DICT_H +#define Included_DICT_H + +/* A variable. */ +typedef struct { + char *name; + double value; +} var_t; + +/* A symbol dictionary. */ +typedef struct { + /* Variables. */ + var_t *variables; + int v_count; + int v_space; +} symbol_dict_t; + +/* Prototypes. */ +symbol_dict_t *dict_new (void); +void dict_free (symbol_dict_t *dict); + +int dict_lookup (symbol_dict_t *calc, const char *name); +double* dict_variable (symbol_dict_t *calc, const char *var_name); + +#endif /* Included_DICT_H */ diff -r 65c4d8591b4a -r 3e160f6c04d2 src/paranormal/libcalc/execute.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/paranormal/libcalc/execute.c Mon Nov 20 13:26:09 2006 -0800 @@ -0,0 +1,121 @@ +/* execute.c -- execute precompiled expression expr + * + * Copyright (C) 2001 Janusz Gregorczyk + * + * This file is part of xvs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include + +#include "execute.h" +#include "function.h" + +/* Execution stack. */ + +gboolean check_stack (ex_stack *stack, int depth) { + if (stack->sp < depth) { + g_warning ("Stack error"); + return FALSE; + } + + return TRUE; +} + +void push (ex_stack *stack, double value) { + g_assert (stack); + + if (stack->sp < STACK_DEPTH) { + stack->value[stack->sp++] = value; + } else { + g_warning ("Stack overflow"); + } +} + +double pop (ex_stack *stack) { + g_assert (stack); + + if (stack->sp > 0) { + return stack->value[--stack->sp]; + } else { + g_warning ("Stack error (stack empty)"); + return 0.0; + } +} + +/* */ + +void expr_execute (expression_t *expr, symbol_dict_t *dict) { + char op, *str = expr->data->str; + ex_stack stack = { 0, { 0.0 }}; + + while ((op = *str++)) { + switch (op) { + case 'l': /* Load a variable. */ + push (&stack, dict->variables[load_int (str)].value); + str += sizeof (int); + break; + + case 's': /* Store to a variable. */ + dict->variables[load_int (str)].value = pop (&stack); + str += sizeof (int); + break; + + case 'f': /* Call a function. */ + function_call (load_int (str), &stack); + str += sizeof (int); + break; + + case 'c': /* Load a constant. */ + push (&stack, load_double (str)); + str += sizeof (double); + break; + + case 'n': /* Do a negation. */ + push (&stack, -pop (&stack)); + break; + + case '+': /* Do an addition. */ + push (&stack, pop (&stack) + pop (&stack)); + break; + case '-': /* Do a subtraction. */ + push (&stack, pop (&stack) - pop (&stack)); + break; + case '*': /* Do a multiplication. */ + push (&stack, pop (&stack) * pop (&stack)); + break; + case '/': /* Do a division. */ + if (check_stack (&stack, 2)) { + double y = stack.value[stack.sp - 2] / stack.value[stack.sp - 1]; + stack.sp -= 2; + push (&stack, y); + } + break; + case '^': /* Do an exponentiation. */ + if (check_stack (&stack, 2)) { + double y = pow (stack.value[stack.sp - 2], stack.value[stack.sp - 1]); + stack.sp -= 2; + push (&stack, y); + } + break; + + default: + g_warning ("Invalid opcode: %c", op); + return; + } + } +} diff -r 65c4d8591b4a -r 3e160f6c04d2 src/paranormal/libcalc/execute.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/paranormal/libcalc/execute.h Mon Nov 20 13:26:09 2006 -0800 @@ -0,0 +1,46 @@ +/* execute.h -- execute precompiled expression code + * + * Copyright (C) 2001 Janusz Gregorczyk + * + * This file is part of xvs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef Included_EXECUTE_H +#define Included_EXECUTE_H + +#include + +#include "dict.h" +#include "storage.h" + +/* Execution stack. */ + +typedef struct { +#define STACK_DEPTH 64 + int sp; /* stack pointer */ + double value[STACK_DEPTH]; +} ex_stack; + +/* Prototypes. */ + +gboolean check_stack (ex_stack *stack, int depth); +void push (ex_stack *stack, double value); +double pop (ex_stack *stack); + +void expr_execute (expression_t *expr, symbol_dict_t *dict); + +#endif /* Included_EXECUTE_H */ diff -r 65c4d8591b4a -r 3e160f6c04d2 src/paranormal/libcalc/function.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/paranormal/libcalc/function.c Mon Nov 20 13:26:09 2006 -0800 @@ -0,0 +1,81 @@ +/* function.c -- + * + * Copyright (C) 2001 Janusz Gregorczyk + * + * This file is part of xvs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include +#include + +#include "function.h" + +/* Function pointer type. */ +typedef struct { + char *name; + double (*funcptr)(ex_stack *stack); +} func_t; + +/* */ + +static double f_sin (ex_stack *stack) { + return sin (pop (stack)); +} + +static double f_cos (ex_stack *stack) { + return cos (pop (stack)); +} + +static double f_if (ex_stack *stack) { + double a = pop (stack); + double b = pop (stack); + return (pop (stack) != 0.0) ? a : b; +} + +static double f_div (ex_stack *stack) { + int y = (int)pop (stack); + int x = (int)pop (stack); + return (y == 0) ? 0 : (x / y); +} + +/* */ + +static const func_t init[] = { + { "sin", f_sin }, + { "cos", f_cos }, + { "if", f_if }, + { "div", f_div } +}; + +int function_lookup (const char *name) { + int i; + + for (i = 0; i < sizeof (init) / sizeof (init[0]); i++) + if (strcmp (init[i].name, name) == 0) + return i; + + g_warning ("Unknown function: %s\n", name); + return -1; +} + +void function_call (int func_id, ex_stack *stack) { + g_assert (func_id >= 0); + g_assert (func_id < sizeof (init) / sizeof (init[0])); + + push (stack, (*init[func_id].funcptr)(stack)); +} diff -r 65c4d8591b4a -r 3e160f6c04d2 src/paranormal/libcalc/function.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/paranormal/libcalc/function.h Mon Nov 20 13:26:09 2006 -0800 @@ -0,0 +1,32 @@ +/* function.h -- + * + * Copyright (C) 2001 Janusz Gregorczyk + * + * This file is part of xvs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef Included_FUNCTION +#define Included_FUNCTION + +#include "execute.h" + +/* Prototypes. */ + +int function_lookup (const char *name); +void function_call (int func_id, ex_stack *stack); + +#endif /* Included_FUNCTION */ diff -r 65c4d8591b4a -r 3e160f6c04d2 src/paranormal/libcalc/parser.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/paranormal/libcalc/parser.c Mon Nov 20 13:26:09 2006 -0800 @@ -0,0 +1,1178 @@ + +/* A Bison parser, made from parser.y + by GNU Bison version 1.28 */ + +#define YYBISON 1 /* Identify Bison output. */ + +#define NAME 257 +#define NUMBER 258 +#define NEG 259 + +#line 23 "parser.y" + +#include +#include +#include +#include +#include +#include + +#include "dict.h" +#include "execute.h" +#include "function.h" +#include "parser.h" +#include "storage.h" + +#define YYPARSE_PARAM yyparam +#define YYLEX_PARAM yyparam + +static gboolean expr_add_compile (expression_t *expr, symbol_dict_t *dict, + char *str); + +#define GENERATE(str) if (!expr_add_compile (((parser_control *)yyparam)->expr, \ + ((parser_control *)yyparam)->dict, str)) \ + YYABORT; + +#line 51 "parser.y" +typedef union { +char *s_value; +char c_value; +double d_value; +int i_value; +} YYSTYPE; +#include + +#ifndef __cplusplus +#ifndef __STDC__ +#define const +#endif +#endif + + + +#define YYFINAL 37 +#define YYFLAG -32768 +#define YYNTBASE 18 + +#define YYTRANSLATE(x) ((unsigned)(x) <= 259 ? yytranslate[x] : 22) + +static const char yytranslate[] = { 0, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 14, + 15, 8, 7, 13, 6, 2, 9, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 12, 17, + 5, 16, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 11, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 1, 3, 4, 10 +}; + +#if YYDEBUG != 0 +static const short yyprhs[] = { 0, + 0, 1, 4, 5, 7, 10, 13, 15, 19, 21, + 23, 27, 32, 36, 40, 44, 48, 52, 56, 59, + 63 +}; + +static const short yyrhs[] = { -1, + 18, 19, 0, 0, 21, 0, 19, 12, 0, 1, + 12, 0, 21, 0, 20, 13, 21, 0, 4, 0, + 3, 0, 3, 5, 21, 0, 3, 14, 20, 15, + 0, 21, 16, 21, 0, 21, 17, 21, 0, 21, + 7, 21, 0, 21, 6, 21, 0, 21, 8, 21, + 0, 21, 9, 21, 0, 6, 21, 0, 21, 11, + 21, 0, 14, 21, 15, 0 +}; + +#endif + +#if YYDEBUG != 0 +static const short yyrline[] = { 0, + 73, 74, 78, 79, 81, 82, 86, 90, 95, 101, + 107, 113, 120, 122, 125, 127, 129, 131, 133, 135, + 137 +}; +#endif + + +#if YYDEBUG != 0 || defined (YYERROR_VERBOSE) + +static const char * const yytname[] = { "$","error","$undefined.","NAME","NUMBER", +"'='","'-'","'+'","'*'","'/'","NEG","'^'","';'","','","'('","')'","'>'","'<'", +"input","expression_list","argument_list","expression", NULL +}; +#endif + +static const short yyr1[] = { 0, + 18, 18, 19, 19, 19, 19, 20, 20, 21, 21, + 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, + 21 +}; + +static const short yyr2[] = { 0, + 0, 2, 0, 1, 2, 2, 1, 3, 1, 1, + 3, 4, 3, 3, 3, 3, 3, 3, 2, 3, + 3 +}; + +static const short yydefact[] = { 1, + 0, 0, 10, 9, 0, 0, 2, 4, 6, 0, + 0, 19, 0, 5, 0, 0, 0, 0, 0, 0, + 0, 11, 0, 7, 21, 16, 15, 17, 18, 20, + 13, 14, 0, 12, 8, 0, 0 +}; + +static const short yydefgoto[] = { 1, + 7, 23, 8 +}; + +static const short yypact[] = {-32768, + 17, -8, 22,-32768, 47, 47, -3, 38,-32768, 47, + 47, -9, 26,-32768, 47, 47, 47, 47, 47, 47, + 47, 38, 9, 38,-32768, 48, 48, -9, -9, -9, + 38, 38, 47,-32768, 38, 3,-32768 +}; + +static const short yypgoto[] = {-32768, +-32768,-32768, -5 +}; + + +#define YYLAST 65 + + +static const short yytable[] = { 12, + 13, 19, 37, 9, 22, 24, 20, 21, 14, 26, + 27, 28, 29, 30, 31, 32, 36, 2, 0, 3, + 4, 33, 5, 34, 0, 0, 10, 35, -3, 0, + 6, 15, 16, 17, 18, 11, 19, 0, 0, 0, + 25, 20, 21, 15, 16, 17, 18, 0, 19, 3, + 4, 0, 5, 20, 21, 17, 18, 0, 19, 0, + 6, 0, 0, 20, 21 +}; + +static const short yycheck[] = { 5, + 6, 11, 0, 12, 10, 11, 16, 17, 12, 15, + 16, 17, 18, 19, 20, 21, 0, 1, -1, 3, + 4, 13, 6, 15, -1, -1, 5, 33, 12, -1, + 14, 6, 7, 8, 9, 14, 11, -1, -1, -1, + 15, 16, 17, 6, 7, 8, 9, -1, 11, 3, + 4, -1, 6, 16, 17, 8, 9, -1, 11, -1, + 14, -1, -1, 16, 17 +}; +#define YYPURE 1 + +/* -*-C-*- Note some compilers choke on comments on `#line' lines. */ +#line 3 "/usr/share/misc/bison.simple" +/* This file comes from bison-1.28. */ + +/* Skeleton output parser for bison, + Copyright (C) 1984, 1989, 1990 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2, or (at your option) + any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place - Suite 330, + Boston, MA 02111-1307, USA. */ + +/* As a special exception, when this file is copied by Bison into a + Bison output file, you may use that output file without restriction. + This special exception was added by the Free Software Foundation + in version 1.24 of Bison. */ + +/* This is the parser code that is written into each bison parser + when the %semantic_parser declaration is not specified in the grammar. + It was written by Richard Stallman by simplifying the hairy parser + used when %semantic_parser is specified. */ + +#ifndef YYSTACK_USE_ALLOCA +#ifdef alloca +#define YYSTACK_USE_ALLOCA +#else /* alloca not defined */ +#ifdef __GNUC__ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#else /* not GNU C. */ +#if (!defined (__STDC__) && defined (sparc)) || defined (__sparc__) || defined (__sparc) || defined (__sgi) || (defined (__sun) && defined (__i386)) +#define YYSTACK_USE_ALLOCA +#include +#else /* not sparc */ +/* We think this test detects Watcom and Microsoft C. */ +/* This used to test MSDOS, but that is a bad idea + since that symbol is in the user namespace. */ +#if (defined (_MSDOS) || defined (_MSDOS_)) && !defined (__TURBOC__) +#if 0 /* No need for malloc.h, which pollutes the namespace; + instead, just don't use alloca. */ +#include +#endif +#else /* not MSDOS, or __TURBOC__ */ +#if defined(_AIX) +/* I don't know what this was needed for, but it pollutes the namespace. + So I turned it off. rms, 2 May 1997. */ +/* #include */ + #pragma alloca +#define YYSTACK_USE_ALLOCA +#else /* not MSDOS, or __TURBOC__, or _AIX */ +#if 0 +#ifdef __hpux /* haible@ilog.fr says this works for HPUX 9.05 and up, + and on HPUX 10. Eventually we can turn this on. */ +#define YYSTACK_USE_ALLOCA +#define alloca __builtin_alloca +#endif /* __hpux */ +#endif +#endif /* not _AIX */ +#endif /* not MSDOS, or __TURBOC__ */ +#endif /* not sparc */ +#endif /* not GNU C */ +#endif /* alloca not defined */ +#endif /* YYSTACK_USE_ALLOCA not defined */ + +#ifdef YYSTACK_USE_ALLOCA +#define YYSTACK_ALLOC alloca +#else +#define YYSTACK_ALLOC malloc +#endif + +/* Note: there must be only one dollar sign in this file. + It is replaced by the list of actions, each action + as one case of the switch. */ + +#define yyerrok (yyerrstatus = 0) +#define yyclearin (yychar = YYEMPTY) +#define YYEMPTY -2 +#define YYEOF 0 +#define YYACCEPT goto yyacceptlab +#define YYABORT goto yyabortlab +#define YYERROR goto yyerrlab1 +/* Like YYERROR except do call yyerror. + This remains here temporarily to ease the + transition to the new meaning of YYERROR, for GCC. + Once GCC version 2 has supplanted version 1, this can go. */ +#define YYFAIL goto yyerrlab +#define YYRECOVERING() (!!yyerrstatus) +#define YYBACKUP(token, value) \ +do \ + if (yychar == YYEMPTY && yylen == 1) \ + { yychar = (token), yylval = (value); \ + yychar1 = YYTRANSLATE (yychar); \ + YYPOPSTACK; \ + goto yybackup; \ + } \ + else \ + { yyerror ("syntax error: cannot back up"); YYERROR; } \ +while (0) + +#define YYTERROR 1 +#define YYERRCODE 256 + +#ifndef YYPURE +#define YYLEX yylex() +#endif + +#ifdef YYPURE +#ifdef YYLSP_NEEDED +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, &yylloc, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval, &yylloc) +#endif +#else /* not YYLSP_NEEDED */ +#ifdef YYLEX_PARAM +#define YYLEX yylex(&yylval, YYLEX_PARAM) +#else +#define YYLEX yylex(&yylval) +#endif +#endif /* not YYLSP_NEEDED */ +#endif + +/* If nonreentrant, generate the variables here */ + +#ifndef YYPURE + +int yychar; /* the lookahead symbol */ +YYSTYPE yylval; /* the semantic value of the */ + /* lookahead symbol */ + +#ifdef YYLSP_NEEDED +YYLTYPE yylloc; /* location data for the lookahead */ + /* symbol */ +#endif + +int yynerrs; /* number of parse errors so far */ +#endif /* not YYPURE */ + +#if YYDEBUG != 0 +int yydebug; /* nonzero means print parse trace */ +/* Since this is uninitialized, it does not stop multiple parsers + from coexisting. */ +#endif + +/* YYINITDEPTH indicates the initial size of the parser's stacks */ + +#ifndef YYINITDEPTH +#define YYINITDEPTH 200 +#endif + +/* YYMAXDEPTH is the maximum size the stacks can grow to + (effective only if the built-in stack extension method is used). */ + +#if YYMAXDEPTH == 0 +#undef YYMAXDEPTH +#endif + +#ifndef YYMAXDEPTH +#define YYMAXDEPTH 10000 +#endif + +/* Define __yy_memcpy. Note that the size argument + should be passed with type unsigned int, because that is what the non-GCC + definitions require. With GCC, __builtin_memcpy takes an arg + of type size_t, but it can handle unsigned int. */ + +#if __GNUC__ > 1 /* GNU C and GNU C++ define this. */ +#define __yy_memcpy(TO,FROM,COUNT) __builtin_memcpy(TO,FROM,COUNT) +#else /* not GNU C or C++ */ +#ifndef __cplusplus + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (to, from, count) + char *to; + char *from; + unsigned int count; +{ + register char *f = from; + register char *t = to; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#else /* __cplusplus */ + +/* This is the most reliable way to avoid incompatibilities + in available built-in functions on various systems. */ +static void +__yy_memcpy (char *to, char *from, unsigned int count) +{ + register char *t = to; + register char *f = from; + register int i = count; + + while (i-- > 0) + *t++ = *f++; +} + +#endif +#endif + +#line 217 "/usr/share/misc/bison.simple" + +/* The user can define YYPARSE_PARAM as the name of an argument to be passed + into yyparse. The argument should have type void *. + It should actually point to an object. + Grammar actions can access the variable by casting it + to the proper pointer type. */ + +#ifdef YYPARSE_PARAM +#ifdef __cplusplus +#define YYPARSE_PARAM_ARG void *YYPARSE_PARAM +#define YYPARSE_PARAM_DECL +#else /* not __cplusplus */ +#define YYPARSE_PARAM_ARG YYPARSE_PARAM +#define YYPARSE_PARAM_DECL void *YYPARSE_PARAM; +#endif /* not __cplusplus */ +#else /* not YYPARSE_PARAM */ +#define YYPARSE_PARAM_ARG +#define YYPARSE_PARAM_DECL +#endif /* not YYPARSE_PARAM */ + +/* Prevent warning if -Wstrict-prototypes. */ +#ifdef __GNUC__ +#ifdef YYPARSE_PARAM +int yyparse (void *); +#else +int yyparse (void); +#endif +#endif + +int +yyparse(YYPARSE_PARAM_ARG) + YYPARSE_PARAM_DECL +{ + register int yystate; + register int yyn; + register short *yyssp; + register YYSTYPE *yyvsp; + int yyerrstatus; /* number of tokens to shift before error messages enabled */ + int yychar1 = 0; /* lookahead token as an internal (translated) token number */ + + short yyssa[YYINITDEPTH]; /* the state stack */ + YYSTYPE yyvsa[YYINITDEPTH]; /* the semantic value stack */ + + short *yyss = yyssa; /* refer to the stacks thru separate pointers */ + YYSTYPE *yyvs = yyvsa; /* to allow yyoverflow to reallocate them elsewhere */ + +#ifdef YYLSP_NEEDED + YYLTYPE yylsa[YYINITDEPTH]; /* the location stack */ + YYLTYPE *yyls = yylsa; + YYLTYPE *yylsp; + +#define YYPOPSTACK (yyvsp--, yyssp--, yylsp--) +#else +#define YYPOPSTACK (yyvsp--, yyssp--) +#endif + + int yystacksize = YYINITDEPTH; + int yyfree_stacks = 0; + +#ifdef YYPURE + int yychar; + YYSTYPE yylval; + int yynerrs; +#ifdef YYLSP_NEEDED + YYLTYPE yylloc; +#endif +#endif + + YYSTYPE yyval; /* the variable used to return */ + /* semantic values from the action */ + /* routines */ + + int yylen; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Starting parse\n"); +#endif + + yystate = 0; + yyerrstatus = 0; + yynerrs = 0; + yychar = YYEMPTY; /* Cause a token to be read. */ + + /* Initialize stack pointers. + Waste one element of value and location stack + so that they stay on the same level as the state stack. + The wasted elements are never initialized. */ + + yyssp = yyss - 1; + yyvsp = yyvs; +#ifdef YYLSP_NEEDED + yylsp = yyls; +#endif + +/* Push a new state, which is found in yystate . */ +/* In all cases, when you get here, the value and location stacks + have just been pushed. so pushing a state here evens the stacks. */ +yynewstate: + + *++yyssp = yystate; + + if (yyssp >= yyss + yystacksize - 1) + { + /* Give user a chance to reallocate the stack */ + /* Use copies of these so that the &'s don't force the real ones into memory. */ + YYSTYPE *yyvs1 = yyvs; + short *yyss1 = yyss; +#ifdef YYLSP_NEEDED + YYLTYPE *yyls1 = yyls; +#endif + + /* Get the current used size of the three stacks, in elements. */ + int size = yyssp - yyss + 1; + +#ifdef yyoverflow + /* Each stack pointer address is followed by the size of + the data in use in that stack, in bytes. */ +#ifdef YYLSP_NEEDED + /* This used to be a conditional around just the two extra args, + but that might be undefined if yyoverflow is a macro. */ + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yyls1, size * sizeof (*yylsp), + &yystacksize); +#else + yyoverflow("parser stack overflow", + &yyss1, size * sizeof (*yyssp), + &yyvs1, size * sizeof (*yyvsp), + &yystacksize); +#endif + + yyss = yyss1; yyvs = yyvs1; +#ifdef YYLSP_NEEDED + yyls = yyls1; +#endif +#else /* no yyoverflow */ + /* Extend the stack our own way. */ + if (yystacksize >= YYMAXDEPTH) + { + yyerror("parser stack overflow"); + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 2; + } + yystacksize *= 2; + if (yystacksize > YYMAXDEPTH) + yystacksize = YYMAXDEPTH; +#ifndef YYSTACK_USE_ALLOCA + yyfree_stacks = 1; +#endif + yyss = (short *) YYSTACK_ALLOC (yystacksize * sizeof (*yyssp)); + __yy_memcpy ((char *)yyss, (char *)yyss1, + size * (unsigned int) sizeof (*yyssp)); + yyvs = (YYSTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yyvsp)); + __yy_memcpy ((char *)yyvs, (char *)yyvs1, + size * (unsigned int) sizeof (*yyvsp)); +#ifdef YYLSP_NEEDED + yyls = (YYLTYPE *) YYSTACK_ALLOC (yystacksize * sizeof (*yylsp)); + __yy_memcpy ((char *)yyls, (char *)yyls1, + size * (unsigned int) sizeof (*yylsp)); +#endif +#endif /* no yyoverflow */ + + yyssp = yyss + size - 1; + yyvsp = yyvs + size - 1; +#ifdef YYLSP_NEEDED + yylsp = yyls + size - 1; +#endif + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Stack size increased to %d\n", yystacksize); +#endif + + if (yyssp >= yyss + yystacksize - 1) + YYABORT; + } + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Entering state %d\n", yystate); +#endif + + goto yybackup; + yybackup: + +/* Do appropriate processing given the current state. */ +/* Read a lookahead token if we need one and don't already have one. */ +/* yyresume: */ + + /* First try to decide what to do without reference to lookahead token. */ + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yydefault; + + /* Not known => get a lookahead token if don't already have one. */ + + /* yychar is either YYEMPTY or YYEOF + or a valid token in external form. */ + + if (yychar == YYEMPTY) + { +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Reading a token: "); +#endif + yychar = YYLEX; + } + + /* Convert token to internal form (in yychar1) for indexing tables with */ + + if (yychar <= 0) /* This means end of input. */ + { + yychar1 = 0; + yychar = YYEOF; /* Don't call YYLEX any more */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Now at end of input.\n"); +#endif + } + else + { + yychar1 = YYTRANSLATE(yychar); + +#if YYDEBUG != 0 + if (yydebug) + { + fprintf (stderr, "Next token is %d (%s", yychar, yytname[yychar1]); + /* Give the individual parser a way to print the precise meaning + of a token, for further debugging info. */ +#ifdef YYPRINT + YYPRINT (stderr, yychar, yylval); +#endif + fprintf (stderr, ")\n"); + } +#endif + } + + yyn += yychar1; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != yychar1) + goto yydefault; + + yyn = yytable[yyn]; + + /* yyn is what to do for this token type in this state. + Negative => reduce, -yyn is rule number. + Positive => shift, yyn is new state. + New state is final state => don't bother to shift, + just return success. + 0, or most negative number => error. */ + + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrlab; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrlab; + + if (yyn == YYFINAL) + YYACCEPT; + + /* Shift the lookahead token. */ + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting token %d (%s), ", yychar, yytname[yychar1]); +#endif + + /* Discard the token being shifted unless it is eof. */ + if (yychar != YYEOF) + yychar = YYEMPTY; + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + /* count tokens shifted since error; after three, turn off error status. */ + if (yyerrstatus) yyerrstatus--; + + yystate = yyn; + goto yynewstate; + +/* Do the default action for the current state. */ +yydefault: + + yyn = yydefact[yystate]; + if (yyn == 0) + goto yyerrlab; + +/* Do a reduction. yyn is the number of a rule to reduce with. */ +yyreduce: + yylen = yyr2[yyn]; + if (yylen > 0) + yyval = yyvsp[1-yylen]; /* implement default value of the action */ + +#if YYDEBUG != 0 + if (yydebug) + { + int i; + + fprintf (stderr, "Reducing via rule %d (line %d), ", + yyn, yyrline[yyn]); + + /* Print the symbols being reduced, and their result. */ + for (i = yyprhs[yyn]; yyrhs[i] > 0; i++) + fprintf (stderr, "%s ", yytname[yyrhs[i]]); + fprintf (stderr, " -> %s\n", yytname[yyr1[yyn]]); + } +#endif + + + switch (yyn) { + +case 4: +#line 80 "parser.y" +{ ; + break;} +case 6: +#line 83 "parser.y" +{ yyerrok; ; + break;} +case 7: +#line 88 "parser.y" +{ + ; + break;} +case 8: +#line 91 "parser.y" +{ + ; + break;} +case 9: +#line 96 "parser.y" +{ + char *buf = g_strdup_printf ("c%f:", yyvsp[0].d_value); + GENERATE (buf); + g_free (buf); + ; + break;} +case 10: +#line 102 "parser.y" +{ + char *buf = g_strdup_printf ("l%s:", yyvsp[0].s_value); + GENERATE (buf); + g_free (buf); + ; + break;} +case 11: +#line 108 "parser.y" +{ + char *buf = g_strdup_printf ("s%s:", yyvsp[-2].s_value); + GENERATE (buf); + g_free (buf); + ; + break;} +case 12: +#line 114 "parser.y" +{ + char *buf = g_strdup_printf ("f%s:", yyvsp[-3].s_value); + GENERATE (buf); + g_free (buf); + ; + break;} +case 13: +#line 121 "parser.y" +{ GENERATE (">"); ; + break;} +case 14: +#line 123 "parser.y" +{ GENERATE ("<"); ; + break;} +case 15: +#line 126 "parser.y" +{ GENERATE ("+"); ; + break;} +case 16: +#line 128 "parser.y" +{ GENERATE ("-"); ; + break;} +case 17: +#line 130 "parser.y" +{ GENERATE ("*"); ; + break;} +case 18: +#line 132 "parser.y" +{ GENERATE ("/"); ; + break;} +case 19: +#line 134 "parser.y" +{ GENERATE ("n"); ; + break;} +case 20: +#line 136 "parser.y" +{ GENERATE ("^"); ; + break;} +case 21: +#line 138 "parser.y" +{ ; + break;} +} + /* the action file gets copied in in place of this dollarsign */ +#line 543 "/usr/share/misc/bison.simple" + + yyvsp -= yylen; + yyssp -= yylen; +#ifdef YYLSP_NEEDED + yylsp -= yylen; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + + *++yyvsp = yyval; + +#ifdef YYLSP_NEEDED + yylsp++; + if (yylen == 0) + { + yylsp->first_line = yylloc.first_line; + yylsp->first_column = yylloc.first_column; + yylsp->last_line = (yylsp-1)->last_line; + yylsp->last_column = (yylsp-1)->last_column; + yylsp->text = 0; + } + else + { + yylsp->last_line = (yylsp+yylen-1)->last_line; + yylsp->last_column = (yylsp+yylen-1)->last_column; + } +#endif + + /* Now "shift" the result of the reduction. + Determine what state that goes to, + based on the state we popped back to + and the rule number reduced by. */ + + yyn = yyr1[yyn]; + + yystate = yypgoto[yyn - YYNTBASE] + *yyssp; + if (yystate >= 0 && yystate <= YYLAST && yycheck[yystate] == *yyssp) + yystate = yytable[yystate]; + else + yystate = yydefgoto[yyn - YYNTBASE]; + + goto yynewstate; + +yyerrlab: /* here on detecting error */ + + if (! yyerrstatus) + /* If not already recovering from an error, report this error. */ + { + ++yynerrs; + +#ifdef YYERROR_VERBOSE + yyn = yypact[yystate]; + + if (yyn > YYFLAG && yyn < YYLAST) + { + int size = 0; + char *msg; + int x, count; + + count = 0; + /* Start X at -yyn if nec to avoid negative indexes in yycheck. */ + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + size += strlen(yytname[x]) + 15, count++; + msg = (char *) malloc(size + 15); + if (msg != 0) + { + strcpy(msg, "parse error"); + + if (count < 5) + { + count = 0; + for (x = (yyn < 0 ? -yyn : 0); + x < (sizeof(yytname) / sizeof(char *)); x++) + if (yycheck[x + yyn] == x) + { + strcat(msg, count == 0 ? ", expecting `" : " or `"); + strcat(msg, yytname[x]); + strcat(msg, "'"); + count++; + } + } + yyerror(msg); + free(msg); + } + else + yyerror ("parse error; also virtual memory exceeded"); + } + else +#endif /* YYERROR_VERBOSE */ + yyerror("parse error"); + } + + goto yyerrlab1; +yyerrlab1: /* here on error raised explicitly by an action */ + + if (yyerrstatus == 3) + { + /* if just tried and failed to reuse lookahead token after an error, discard it. */ + + /* return failure if at end of input */ + if (yychar == YYEOF) + YYABORT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Discarding token %d (%s).\n", yychar, yytname[yychar1]); +#endif + + yychar = YYEMPTY; + } + + /* Else will try to reuse lookahead token + after shifting the error token. */ + + yyerrstatus = 3; /* Each real token shifted decrements this */ + + goto yyerrhandle; + +yyerrdefault: /* current state does not do anything special for the error token. */ + +#if 0 + /* This is wrong; only states that explicitly want error tokens + should shift them. */ + yyn = yydefact[yystate]; /* If its default is to accept any token, ok. Otherwise pop it.*/ + if (yyn) goto yydefault; +#endif + +yyerrpop: /* pop the current state because it cannot handle the error token */ + + if (yyssp == yyss) YYABORT; + yyvsp--; + yystate = *--yyssp; +#ifdef YYLSP_NEEDED + yylsp--; +#endif + +#if YYDEBUG != 0 + if (yydebug) + { + short *ssp1 = yyss - 1; + fprintf (stderr, "Error: state stack now"); + while (ssp1 != yyssp) + fprintf (stderr, " %d", *++ssp1); + fprintf (stderr, "\n"); + } +#endif + +yyerrhandle: + + yyn = yypact[yystate]; + if (yyn == YYFLAG) + goto yyerrdefault; + + yyn += YYTERROR; + if (yyn < 0 || yyn > YYLAST || yycheck[yyn] != YYTERROR) + goto yyerrdefault; + + yyn = yytable[yyn]; + if (yyn < 0) + { + if (yyn == YYFLAG) + goto yyerrpop; + yyn = -yyn; + goto yyreduce; + } + else if (yyn == 0) + goto yyerrpop; + + if (yyn == YYFINAL) + YYACCEPT; + +#if YYDEBUG != 0 + if (yydebug) + fprintf(stderr, "Shifting error token, "); +#endif + + *++yyvsp = yylval; +#ifdef YYLSP_NEEDED + *++yylsp = yylloc; +#endif + + yystate = yyn; + goto yynewstate; + + yyacceptlab: + /* YYACCEPT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 0; + + yyabortlab: + /* YYABORT comes here. */ + if (yyfree_stacks) + { + free (yyss); + free (yyvs); +#ifdef YYLSP_NEEDED + free (yyls); +#endif + } + return 1; +} +#line 141 "parser.y" + +/* End of grammar */ + +/* Called by yyparse on error. */ +int yyerror (char *s) { + /* Ignore errors, just print a warning. */ + g_warning ("%s\n", s); + return 0; +} + +int yylex (YYSTYPE *yylval, void *yyparam) { + int c; + parser_control *pc = (parser_control *) yyparam; + + /* Ignore whitespace, get first nonwhite character. */ + while ((c = fgetc (pc->input)) == ' ' || c == '\t' || c == '\n'); + + /* End of input ? */ + if (c == EOF) + return 0; + + /* Char starts a number => parse the number. */ + if (isdigit (c)) { + ungetc (c, pc->input);/* Put the char back. */ + { + char *old_locale, *saved_locale; + + old_locale = setlocale (LC_ALL, NULL); + saved_locale = g_strdup (old_locale); + setlocale (LC_ALL, "C"); + fscanf (pc->input, "%lf", &yylval->d_value); + setlocale (LC_ALL, saved_locale); + g_free (saved_locale); + } + return NUMBER; + } + + /* Char starts an identifier => read the name. */ + if (isalpha (c)) { + GString *sym_name; + + sym_name = g_string_new (NULL); + + do { + sym_name = g_string_append_c (sym_name, c); + + /* Get another character. */ + c = fgetc (pc->input); + } while (c != EOF && isalnum (c)); + + ungetc (c, pc->input); + + yylval->s_value = sym_name->str; + + g_string_free (sym_name, FALSE); + + return NAME; + } + + /* Any other character is a token by itself. */ + return c; +} + +static int load_name (char *str, char **name) { + int count = 0; + GString *new = g_string_new (NULL); + + while (*str != 0 && *str != ':') { + g_string_append_c (new, *str++); + count++; + } + + *name = new->str; + g_string_free (new, FALSE); + + return count; +} + +static gboolean expr_add_compile (expression_t *expr, symbol_dict_t *dict, + char *str) { + char op; + double dval; + int i; + char *name; + + while ((op = *str++)) { + switch (op) { + case 'c': /* A constant. */ + store_byte (expr, 'c'); + sscanf (str, "%lf%n", &dval, &i); + str += i; + store_double (expr, dval); + str++; /* Skip ';' */ + break; + + case 'f': /* A function call. */ + store_byte (expr, 'f'); + str += load_name (str, &name); + i = function_lookup (name); + if (i < 0) return FALSE; /* Fail on error. */ + store_int (expr, i); + g_free (name); + str++; /* Skip ';' */ + break; + + case 'l': /* Load a variable. */ + case 's': /* Store a variable. */ + store_byte (expr, op); + str += load_name (str, &name); + i = dict_lookup (dict, name); + store_int (expr, i); + g_free (name); + str++; /* Skip ';' */ + break; + + default: /* Copy verbatim. */ + store_byte (expr, op); + break; + } + } + + return TRUE; +} + +expression_t *expr_compile_string (const char* str, symbol_dict_t *dict) { + parser_control pc; + FILE *stream; + + stream = fmemopen (str, strlen (str), "r"); + + pc.input = stream; + pc.expr = expr_new (); + pc.dict = dict; + + if (yyparse (&pc) != 0) { + /* Check for error. */ + expr_free (pc.expr); + pc.expr = NULL; + } + + fclose (stream); + + return pc.expr; +} diff -r 65c4d8591b4a -r 3e160f6c04d2 src/paranormal/libcalc/parser.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/paranormal/libcalc/parser.h Mon Nov 20 13:26:09 2006 -0800 @@ -0,0 +1,40 @@ +/* parser.h -- header file for libexp + * + * Copyright (C) 2001 Janusz Gregorczyk + * + * This file is part of xvs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef Included_PARSER_H +#define Included_PARSER_H + +#include +#include + +#include "execute.h" + +/* Structure passed do yyparse. */ +typedef struct { + FILE *input; + expression_t *expr; + symbol_dict_t *dict; +} parser_control; + +/* Prototypes. */ +expression_t *expr_compile_string (const char *str, symbol_dict_t *dict); + +#endif /* Included_PARSER_H */ diff -r 65c4d8591b4a -r 3e160f6c04d2 src/paranormal/libcalc/parser.y --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/paranormal/libcalc/parser.y Mon Nov 20 13:26:09 2006 -0800 @@ -0,0 +1,284 @@ +/* parser.y -- Bison parser for libexp + * + * Copyright (C) 2001 Janusz Gregorczyk + * + * This file is part of xvs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +/* C declarations. */ +%{ +#include +#include +#include +#include +#include +#include + +#include "dict.h" +#include "execute.h" +#include "function.h" +#include "parser.h" +#include "storage.h" + +#define YYPARSE_PARAM yyparam +#define YYLEX_PARAM yyparam + +static gboolean expr_add_compile (expression_t *expr, symbol_dict_t *dict, + char *str); + +#define GENERATE(str) if (!expr_add_compile (((parser_control *)yyparam)->expr, \ + ((parser_control *)yyparam)->dict, str)) \ + YYABORT; +%} + +%pure_parser + +/* Data types. */ +%union { +char *s_value; +char c_value; +double d_value; +int i_value; +} + +/* Terminal symbols. */ +%token NAME +%token NUMBER + +/* Precedence rules. */ +%right '=' +%left '-' '+' +%left '*' '/' +%left NEG +%right '^' + +/* Grammar follows */ +%% + +/* Input consits of a (possibly empty) list of expressions. */ +input: /* empty */ + | input expression_list +; + +/* expression_list is a ';' separated list of expressions. */ +expression_list: /* empty */ + | expression + { } + | expression_list ';' + | error ';' + { yyerrok; } + +/* argument list is a comma separated list od expressions */ +argument_list: + expression + { + } + | argument_list ',' expression + { + } + +/* expression is a C-like expression. */ +expression: NUMBER + { + char *buf = g_strdup_printf ("c%f:", $1); + GENERATE (buf); + g_free (buf); + } + | NAME + { + char *buf = g_strdup_printf ("l%s:", $1); + GENERATE (buf); + g_free (buf); + } + | NAME '=' expression + { + char *buf = g_strdup_printf ("s%s:", $1); + GENERATE (buf); + g_free (buf); + } + | NAME '(' argument_list ')' + { + char *buf = g_strdup_printf ("f%s:", $1); + GENERATE (buf); + g_free (buf); + } + + | expression '>' expression + { GENERATE (">"); } + | expression '<' expression + { GENERATE ("<"); } + + | expression '+' expression + { GENERATE ("+"); } + | expression '-' expression + { GENERATE ("-"); } + | expression '*' expression + { GENERATE ("*"); } + | expression '/' expression + { GENERATE ("/"); } + | '-' expression %prec NEG + { GENERATE ("n"); } + | expression '^' expression + { GENERATE ("^"); } + | '(' expression ')' + { } +; + +%% +/* End of grammar */ + +/* Called by yyparse on error. */ +int yyerror (char *s) { + /* Ignore errors, just print a warning. */ + g_warning ("%s\n", s); + return 0; +} + +int yylex (YYSTYPE *yylval, void *yyparam) { + int c; + parser_control *pc = (parser_control *) yyparam; + + /* Ignore whitespace, get first nonwhite character. */ + while ((c = fgetc (pc->input)) == ' ' || c == '\t' || c == '\n'); + + /* End of input ? */ + if (c == EOF) + return 0; + + /* Char starts a number => parse the number. */ + if (isdigit (c)) { + ungetc (c, pc->input);/* Put the char back. */ + { + char *old_locale, *saved_locale; + + old_locale = setlocale (LC_ALL, NULL); + saved_locale = g_strdup (old_locale); + setlocale (LC_ALL, "C"); + fscanf (pc->input, "%lf", &yylval->d_value); + setlocale (LC_ALL, saved_locale); + g_free (saved_locale); + } + return NUMBER; + } + + /* Char starts an identifier => read the name. */ + if (isalpha (c)) { + GString *sym_name; + + sym_name = g_string_new (NULL); + + do { + sym_name = g_string_append_c (sym_name, c); + + /* Get another character. */ + c = fgetc (pc->input); + } while (c != EOF && isalnum (c)); + + ungetc (c, pc->input); + + yylval->s_value = sym_name->str; + + g_string_free (sym_name, FALSE); + + return NAME; + } + + /* Any other character is a token by itself. */ + return c; +} + +static int load_name (char *str, char **name) { + int count = 0; + GString *new = g_string_new (NULL); + + while (*str != 0 && *str != ':') { + g_string_append_c (new, *str++); + count++; + } + + *name = new->str; + g_string_free (new, FALSE); + + return count; +} + +static gboolean expr_add_compile (expression_t *expr, symbol_dict_t *dict, + char *str) { + char op; + double dval; + int i; + char *name; + + while ((op = *str++)) { + switch (op) { + case 'c': /* A constant. */ + store_byte (expr, 'c'); + sscanf (str, "%lf%n", &dval, &i); + str += i; + store_double (expr, dval); + str++; /* Skip ';' */ + break; + + case 'f': /* A function call. */ + store_byte (expr, 'f'); + str += load_name (str, &name); + i = function_lookup (name); + if (i < 0) return FALSE; /* Fail on error. */ + store_int (expr, i); + g_free (name); + str++; /* Skip ';' */ + break; + + case 'l': /* Load a variable. */ + case 's': /* Store a variable. */ + store_byte (expr, op); + str += load_name (str, &name); + i = dict_lookup (dict, name); + store_int (expr, i); + g_free (name); + str++; /* Skip ';' */ + break; + + default: /* Copy verbatim. */ + store_byte (expr, op); + break; + } + } + + return TRUE; +} + +expression_t *expr_compile_string (const char* str, symbol_dict_t *dict) { + parser_control pc; + FILE *stream; + + stream = fmemopen (str, strlen (str), "r"); + + pc.input = stream; + pc.expr = expr_new (); + pc.dict = dict; + + if (yyparse (&pc) != 0) { + /* Check for error. */ + expr_free (pc.expr); + pc.expr = NULL; + } + + fclose (stream); + + return pc.expr; +} diff -r 65c4d8591b4a -r 3e160f6c04d2 src/paranormal/libcalc/storage.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/paranormal/libcalc/storage.c Mon Nov 20 13:26:09 2006 -0800 @@ -0,0 +1,79 @@ +/* storage.c -- + * + * Copyright (C) 2001 Janusz Gregorczyk + * + * This file is part of xvs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#include +#include + +#include "storage.h" + +/* Code block. */ + +expression_t *expr_new (void) { + expression_t *new_expr; + + new_expr = (expression_t *)g_malloc (sizeof(expression_t)); + new_expr->data = g_string_new (NULL); + return new_expr; +} + +void expr_free (expression_t *expr) { + if (!expr) + return; + + g_string_free (expr->data, TRUE); + g_free (expr); +} + +static void load_data (char *str, void *dest, size_t size) { + char *ch = (char *)dest; + while (size--) + *ch++ = *str++; +} + +int load_int (char *str) { + int val; + load_data (str, &val, sizeof(val)); + return val; +} + +double load_double (char *str) { + double val; + load_data (str, &val, sizeof(val)); + return val; +} + +static void store_data (expression_t *expr, void *src, size_t size) { + char *ch = (char *)src; + while (size--) + store_byte (expr, *ch++); +} + +void store_byte (expression_t *expr, char byte) { + g_string_append_c (expr->data, byte); +} + +void store_int (expression_t *expr, int val) { + store_data (expr, &val, sizeof(val)); +} + +void store_double (expression_t *expr, double val) { + store_data (expr, &val, sizeof(val)); +} diff -r 65c4d8591b4a -r 3e160f6c04d2 src/paranormal/libcalc/storage.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/paranormal/libcalc/storage.h Mon Nov 20 13:26:09 2006 -0800 @@ -0,0 +1,42 @@ +/* storage.h -- + * + * Copyright (C) 2001 Janusz Gregorczyk + * + * This file is part of xvs. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef Included_STORAGE_H +#define Included_STORAGE_H + +#include + +typedef struct { + GString *data; +} expression_t; + +/* Expr block. */ +expression_t *expr_new (void); +void expr_free (expression_t *expr); + +int load_int (char *str); +double load_double (char *str); + +void store_byte (expression_t *expr, char byte); +void store_int (expression_t *expr, int val); +void store_double (expression_t *expr, double val); + +#endif /* Included_STORAGE_H */