Mercurial > audlegacy-plugins
view src/paranormal/pn/pnscript.c @ 65:d54fa96988b3 trunk
[svn] - correct formatting issue
author | nenolod |
---|---|
date | Sat, 30 Sep 2006 22:05:07 -0700 |
parents | 3da1b8942b8b |
children |
line wrap: on
line source
/* Paranormal - A highly customizable audio visualization library * Copyright (C) 2001 Jamie Gennis <jgennis@mindspring.com> * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library 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 * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the Free * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include <config.h> #include <math.h> #include "pnscript.h" /* Initialization */ static void pn_script_class_init (PnScriptClass *class); /* Internal parser */ gboolean pn_script_internal_parse_string (PnScript *script, const gchar *string); static GObjectClass *parent_class = NULL; GType pn_script_get_type (void) { static GType script_type = 0; if (! script_type) { static const GTypeInfo script_info = { sizeof (PnScriptClass), NULL, /* base_init */ NULL, /* base_finalize */ (GClassInitFunc) pn_script_class_init, NULL, /* class_finalize */ NULL, /* class_data */ sizeof (PnScript), 0, /* n_preallocs */ NULL /* instance_init */ }; /* FIXME: should this be dynamic? */ script_type = g_type_register_static (PN_TYPE_OBJECT, "PnScript", &script_info, 0); } return script_type; } static void pn_script_class_init (PnScriptClass *class) { GObjectClass *gobject_class; PnObjectClass *object_class; gobject_class = (GObjectClass *) class; object_class = (PnObjectClass *) class; parent_class = g_type_class_peek_parent (class); } static void pn_script_unref_variables (PnScript *script) { g_return_if_fail (script != NULL); g_return_if_fail (PN_IS_SCRIPT (script)); if (script->code && script->symbol_table) { guint *op; for (op = script->code; *op != PN_OP_END; op++) switch (*op) { case PN_OP_PUSHC: op++; break; case PN_OP_PUSHV: pn_symbol_table_unref_variable (script->symbol_table, PN_VARIABLE (*(++op))); break; case PN_OP_SET: pn_symbol_table_unref_variable (script->symbol_table, PN_VARIABLE (*(++op))); break; } } } /** * pn_script_new * * Creates a new #PnScript object. * * Returns: The newly created #PnScript object */ PnScript* pn_script_new (void) { return (PnScript *) g_object_new (PN_TYPE_SCRIPT, NULL); } /** * pn_script_parse_string * @script: A #PnScript * @symbol_table: the #PnSymbolTable to associate with the script * @string: a string containing the script * * Parses a script, compiling it to a bytecode that is stored within the script object. * All in-script variables within the script are added to the specified symbol table (if * they are not already in it). If errors are encountered while parsing the script, * they are output using pn_error(). * * Returns: %TRUE on success; %FALSE otherwise */ gboolean pn_script_parse_string (PnScript *script, PnSymbolTable *symbol_table, const gchar *string) { g_return_val_if_fail (script != NULL, FALSE); g_return_val_if_fail (PN_IS_SCRIPT (script), FALSE); g_return_val_if_fail (symbol_table != NULL, FALSE); g_return_val_if_fail (PN_IS_SYMBOL_TABLE (symbol_table), FALSE); g_return_val_if_fail (string != NULL, FALSE); /* Make sure if it's the same symbol table, we don't destroy it */ pn_object_ref (PN_OBJECT (symbol_table)); pn_object_sink (PN_OBJECT (symbol_table)); /* get rid of the old script */ if (script->symbol_table) { pn_script_unref_variables (script); pn_object_unref (PN_OBJECT (script->symbol_table)); } if (script->stack) { g_free (script->stack); script->stack = NULL; } if (script->code) { g_free (script->code); script->code = NULL; } if (script->constant_table) { g_free (script->constant_table); script->constant_table = NULL; } /* Set our new symbol table */ script->symbol_table = symbol_table; return pn_script_internal_parse_string (script, string); } /** * pn_script_execute * @script: a #PnScript * * Executes a script, updating all variabes in the associated symbol * table as the script dictates. */ void pn_script_execute (PnScript *script) { guint *op; gdouble stack[64]; guint stack_top = 0; gdouble temp; g_return_if_fail (script != NULL); g_return_if_fail (PN_IS_SCRIPT (script)); if (! script->code) return; for (op = script->code; *op != PN_OP_END; op++) switch (*op) { #define PUSH(f) stack[stack_top++] = f; #define POP stack_top--; #define POPV (stack[--stack_top]) #define PEEK (stack[stack_top-1]) #define PEEKN(n) (stack[stack_top-n]) case PN_OP_PUSHC: case PN_OP_PUSHV: PUSH (* (gdouble *)(*(++op))); break; case PN_OP_POP: POP; break; case PN_OP_SET: *(gdouble *)(*(++op)) = PEEK; break; case PN_OP_ADD: /* PEEKN (2) += POPV; */ temp = POPV; PEEKN(1) += temp; break; case PN_OP_SUB: /* PEEKN (2) -= POPV; */ temp = POPV; PEEKN(1) -= temp; break; case PN_OP_MUL: /* PEEKN (2) *= POPV; */ temp = POPV; PEEKN(1) *= temp; break; case PN_OP_DIV: if (PEEK != 0) PEEKN (2) /= PEEK; else PEEK = 0; POP; break; case PN_OP_NEG: PEEK = -PEEK; break; case PN_OP_POW: PEEKN (2) = pow (PEEKN (2), PEEK); POP; break; case PN_OP_ABS: PEEK = ABS (PEEK); break; case PN_OP_MAX: PEEKN (2) = MAX (PEEK, PEEKN (2)); POP; break; case PN_OP_MIN: PEEKN (2) = MIN (PEEK, PEEKN (2)); POP; break; case PN_OP_SIN: PEEK = sin (PEEK); break; case PN_OP_COS: PEEK = cos (PEEK); break; case PN_OP_TAN: PEEK = tan (PEEK); break; case PN_OP_ASIN: PEEK = asin (PEEK); break; case PN_OP_ACOS: PEEK = acos (PEEK); break; case PN_OP_ATAN: PEEK = atan (PEEK); break; } }