1 /*****************************************************************************
3 *****************************************************************************
4 * Copyright (C) 2004 the VideoLAN team
7 * Authors: Cyril Deguet <asmax@videolan.org>
8 * code from projectM http://xmms-projectm.sourceforge.net
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
23 *****************************************************************************/
36 #include "splaytree_types.h"
37 #include "splaytree.h"
38 #include "tree_types.h"
40 #include "expr_types.h"
43 #include "param_types.h"
46 #include "func_types.h"
49 #include "preset_types.h"
50 #include "builtin_funcs.h"
52 #include "per_pixel_eqn_types.h"
53 #include "per_pixel_eqn.h"
55 #include "init_cond_types.h"
56 #include "init_cond.h"
58 #include "per_frame_eqn_types.h"
59 #include "per_frame_eqn.h"
62 #include "engine_vars.h"
64 #include "custom_wave_types.h"
65 #include "custom_wave.h"
67 #include "custom_shape_types.h"
68 #include "custom_shape.h"
70 /* Strings that prefix (and denote the type of) equations */
73 #define PER_FRAME_STRING "per_frame_"
74 #define PER_FRAME_STRING_LENGTH 10
76 #define PER_PIXEL_STRING "per_pixel_"
77 #define PER_PIXEL_STRING_LENGTH 10
79 #define PER_FRAME_INIT_STRING "per_frame_init_"
80 #define PER_FRAME_INIT_STRING_LENGTH 15
82 #define WAVECODE_STRING "wavecode_"
83 #define WAVECODE_STRING_LENGTH 9
85 #define WAVE_STRING "wave_"
86 #define WAVE_STRING_LENGTH 5
88 #define PER_POINT_STRING "per_point"
89 #define PER_POINT_STRING_LENGTH 9
91 #define PER_FRAME_STRING_NO_UNDERSCORE "per_frame"
92 #define PER_FRAME_STRING_NO_UNDERSCORE_LENGTH 9
94 #define SHAPECODE_STRING "shapecode_"
95 #define SHAPECODE_STRING_LENGTH 10
97 #define SHAPE_STRING "shape_"
98 #define SHAPE_STRING_LENGTH 6
100 #define SHAPE_INIT_STRING "init"
101 #define SHAPE_INIT_STRING_LENGTH 4
103 #define WAVE_INIT_STRING "init"
104 #define WAVE_INIT_STRING_LENGTH 4
106 /* Stores a line of a file as its being parsed */
107 char string_line_buffer[STRING_LINE_SIZE];
109 /* The current position of the string line buffer (see above) */
110 int string_line_buffer_index = 0;
112 /* All infix operators (except '=') are prototyped here */
113 extern infix_op_t * infix_add, * infix_minus, * infix_div, * infix_mult,
114 * infix_or, * infix_and, * infix_mod, * infix_positive, * infix_negative;
116 /* If the parser reads a line with a custom wave, this pointer is set to
117 the custom wave of concern */
118 custom_wave_t * current_wave = NULL;
119 custom_shape_t * current_shape = NULL;
120 /* Counts the number of lines parsed */
121 unsigned int line_count = 1;
122 int per_frame_eqn_count = 0;
123 int per_frame_init_eqn_count = 0;
130 CUSTOM_WAVE_PER_POINT_LINE_MODE,
131 CUSTOM_WAVE_PER_FRAME_LINE_MODE,
132 CUSTOM_WAVE_WAVECODE_LINE_MODE,
133 CUSTOM_SHAPE_SHAPECODE_LINE_MODE,
136 line_mode_t line_mode = NORMAL_LINE_MODE;
138 /* Token enumeration type */
141 tEOL, /* end of a line, usually a '/n' or '/r' */
142 tEOF, /* end of file */
156 tPositive, /* + as a prefix operator */
157 tNegative, /* - as a prefix operator */
159 tStringTooLong, /* special token to indicate an invalid string length */
160 tStringBufferFilled /* the string buffer for this line is maxed out */
164 int get_string_prefix_len(char * string);
165 tree_expr_t * insert_gen_expr(gen_expr_t * gen_expr, tree_expr_t ** root);
166 tree_expr_t * insert_infix_op(infix_op_t * infix_op, tree_expr_t ** root);
167 token_t parseToken(FILE * fs, char * string);
168 gen_expr_t ** parse_prefix_args(FILE * fs, int num_args, struct PRESET_T * preset);
169 gen_expr_t * parse_infix_op(FILE * fs, token_t token, tree_expr_t * tree_expr, struct PRESET_T * preset);
170 gen_expr_t * parse_sign_arg(FILE * fs);
171 int parse_float(FILE * fs, double * float_ptr);
172 int parse_int(FILE * fs, int * int_ptr);
173 int insert_gen_rec(gen_expr_t * gen_expr, tree_expr_t * root);
174 int insert_infix_rec(infix_op_t * infix_op, tree_expr_t * root);
175 gen_expr_t * parse_gen_expr(FILE * fs, tree_expr_t * tree_expr, struct PRESET_T * preset);
176 per_frame_eqn_t * parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, struct PRESET_T * preset);
177 init_cond_t * parse_per_frame_init_eqn(FILE * fs, struct PRESET_T * preset, splaytree_t * database);
178 int parse_wavecode_prefix(char * token, int * id, char ** var_string);
179 int parse_wavecode(char * token, FILE * fs, preset_t * preset);
180 int parse_wave_prefix(char * token, int * id, char ** eqn_string);
182 int parse_shapecode(char * eqn_string, FILE * fs, preset_t * preset);
183 int parse_shapecode_prefix(char * token, int * id, char ** var_string);
185 int parse_wave(char * eqn_string, FILE * fs, preset_t * preset);
186 int parse_shape(char * eqn_string, FILE * fs, preset_t * preset);
187 int parse_shape_prefix(char * token, int * id, char ** eqn_string);
189 int update_string_buffer(char * buffer, int * index);
190 int string_to_float(char * string, double * float_ptr);
192 /* Grabs the next token from the file. The second argument points
195 token_t parseToken(FILE * fs, char * string) {
201 memset(string, 0, MAX_TOKEN_SIZE);
203 /* Loop until a delimiter is found, or the maximum string size is found */
204 for (i = 0; i < MAX_TOKEN_SIZE;i++) {
207 /* If the string line buffer is full, quit */
208 if (string_line_buffer_index == (STRING_LINE_SIZE - 1))
209 return tStringBufferFilled;
211 /* Otherwise add this character to the string line buffer */
212 string_line_buffer[string_line_buffer_index++] = c;
213 /* Now interpret the character */
224 /* check for line comment here */
225 if ((c = fgetc(fs)) == '/') {
229 line_mode = NORMAL_LINE_MODE;
233 line_mode = NORMAL_LINE_MODE;
240 /* Otherwise, just a regular division operator */
264 line_mode = NORMAL_LINE_MODE;
270 case ' ': /* space, skip the character */
275 line_mode = NORMAL_LINE_MODE;
285 /* String reached maximum length, return special token error */
286 return tStringTooLong;
290 /* Parse input in the form of "exp, exp, exp, ...)"
291 Returns a general expression list */
293 gen_expr_t ** parse_prefix_args(FILE * fs, int num_args, struct PRESET_T * preset) {
296 gen_expr_t ** expr_list; /* List of arguments to function */
297 gen_expr_t * gen_expr;
299 /* Malloc the expression list */
300 expr_list = (gen_expr_t**)malloc(sizeof(gen_expr_t*)*num_args);
303 if (expr_list == NULL)
309 while (i < num_args) {
310 //if (PARSE_DEBUG) printf("parse_prefix_args: parsing argument %d...\n", i+1);
311 /* Parse the ith expression in the list */
312 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
313 //if (PARSE_DEBUG) printf("parse_prefix_args: failed to get parameter # %d for function (LINE %d)\n", i+1, line_count);
314 for (j = 0; j < i; j++)
315 free_gen_expr(expr_list[j]);
319 /* Assign entry in expression list */
320 expr_list[i++] = gen_expr;
323 //if (PARSE_DEBUG) printf("parse_prefix_args: finished parsing %d arguments (LINE %d)\n", num_args, line_count);
324 /* Finally, return the resulting expression list */
329 /* Parses a comment at the top of the file. Stops when left bracket is found */
330 int parse_top_comment(FILE * fs) {
332 char string[MAX_TOKEN_SIZE];
335 /* Process tokens until left bracket is found */
336 while ((token = parseToken(fs, string)) != tLBr) {
341 /* Done, return success */
345 /* Right Bracket is parsed by this function.
346 puts a new string into name */
347 int parse_preset_name(FILE * fs, char * name) {
354 if ((token = parseToken(fs, name)) != tRBr)
357 //if (PARSE_DEBUG) printf("parse_preset_name: parsed preset (name = \"%s\")\n", name);
363 /* Parses per pixel equations */
364 int parse_per_pixel_eqn(FILE * fs, preset_t * preset) {
367 char string[MAX_TOKEN_SIZE];
368 gen_expr_t * gen_expr;
370 if (PARSE_DEBUG) printf("parse_per_pixel: per_pixel equation parsing start...(LINE %d)\n", line_count);
372 if (parseToken(fs, string) != tEq) { /* parse per pixel operator name */
373 if (PARSE_DEBUG) printf("parse_per_pixel: equal operator expected after per pixel operator \"%s\", but not found (LINE %d)\n",
378 /* Parse right side of equation as an expression */
379 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
380 if (PARSE_DEBUG) printf("parse_per_pixel: equation evaluated to null? (LINE %d)\n", line_count);
384 /* Add the per pixel equation */
385 if (add_per_pixel_eqn(string, gen_expr, preset) < 0) {
386 free_gen_expr(gen_expr);
393 /* Parses an equation line, this function is way too big, should add some helper functions */
394 int parse_line(FILE * fs, struct PRESET_T * preset) {
396 char eqn_string[MAX_TOKEN_SIZE];
398 init_cond_t * init_cond;
399 per_frame_eqn_t * per_frame_eqn;
401 /* Clear the string line buffer */
402 memset(string_line_buffer, 0, STRING_LINE_SIZE);
403 string_line_buffer_index = 0;
406 switch (token = parseToken(fs, eqn_string)) {
422 // if (PARSE_DEBUG) printf("parse_line: invalid token found at start of line (LINE %d)\n", line_count);
423 /* Invalid token found, return a parse error */
427 case tEOL: /* Empty line */
428 line_mode = NORMAL_LINE_MODE;
431 case tEOF: /* End of File */
432 line_mode = NORMAL_LINE_MODE;
436 case tSemiColon: /* Indicates end of expression */
439 /* Valid Case, either an initial condition or equation should follow */
442 /* CASE: PER FRAME INIT EQUATION */
443 if (!strncmp(eqn_string, PER_FRAME_INIT_STRING, PER_FRAME_INIT_STRING_LENGTH)) {
445 //if (PARSE_DEBUG) printf("parse_line: per frame init equation found...(LINE %d)\n", line_count);
447 /* Set the line mode to normal */
448 line_mode = NORMAL_LINE_MODE;
450 /* Parse the per frame equation */
451 if ((init_cond = parse_per_frame_init_eqn(fs, preset, NULL)) == NULL) {
452 //if (PARSE_DEBUG) printf("parse_line: per frame init equation parsing failed (LINE %d)\n", line_count);
456 /* Insert the equation in the per frame equation tree */
457 if (splay_insert(init_cond, init_cond->param->name, preset->per_frame_init_eqn_tree) < 0) {
458 //if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
459 free_init_cond(init_cond); /* will free the gen expr too */
464 if (update_string_buffer(preset->per_frame_init_eqn_string_buffer,
465 &preset->per_frame_init_eqn_string_index) < 0)
472 /* Per frame equation case */
473 if (!strncmp(eqn_string, PER_FRAME_STRING, PER_FRAME_STRING_LENGTH)) {
475 /* Sometimes per frame equations are implicitly defined without the
476 per_frame_ prefix. This informs the parser that one could follow */
477 line_mode = PER_FRAME_LINE_MODE;
479 //if (PARSE_DEBUG) printf("parse_line: per frame equation found...(LINE %d)\n", line_count);
481 /* Parse the per frame equation */
482 if ((per_frame_eqn = parse_per_frame_eqn(fs, ++per_frame_eqn_count, preset)) == NULL) {
483 if (PARSE_DEBUG) printf("parse_line: per frame equation parsing failed (LINE %d)\n", line_count);
487 /* Insert the equation in the per frame equation tree */
488 if (splay_insert(per_frame_eqn, &per_frame_eqn_count, preset->per_frame_eqn_tree) < 0) {
489 if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
490 free_per_frame_eqn(per_frame_eqn); /* will free the gen expr too */
494 if (update_string_buffer(preset->per_frame_eqn_string_buffer,
495 &preset->per_frame_eqn_string_index) < 0)
504 /* Wavecode initial condition case */
505 if (!strncmp(eqn_string, WAVECODE_STRING, WAVECODE_STRING_LENGTH)) {
507 line_mode = CUSTOM_WAVE_WAVECODE_LINE_MODE;
510 // printf("parse_line: wavecode prefix found: \"%s\"\n", eqn_string);
512 // printf("string:%d\n", 5);
514 //SUPER MYSTERIO-BUG - Don't Remove
517 return parse_wavecode(eqn_string, fs, preset);
520 /* Custom Wave Prefix */
521 if ((!strncmp(eqn_string, WAVE_STRING, WAVE_STRING_LENGTH)) &&
522 ((eqn_string[5] >= 48) && (eqn_string[5] <= 57))) {
524 // if (PARSE_DEBUG) printf("parse_line wave prefix found: \"%s\"\n", eqn_string);
526 return parse_wave(eqn_string, fs, preset);
531 /* Shapecode initial condition case */
532 if (!strncmp(eqn_string, SHAPECODE_STRING, SHAPECODE_STRING_LENGTH)) {
534 line_mode = CUSTOM_SHAPE_SHAPECODE_LINE_MODE;
536 if (PARSE_DEBUG) printf("parse_line: shapecode prefix found: \"%s\"\n", eqn_string);
538 return parse_shapecode(eqn_string, fs, preset);
541 /* Custom Shape Prefix */
542 if ((!strncmp(eqn_string, SHAPE_STRING, SHAPE_STRING_LENGTH)) &&
543 ((eqn_string[6] >= 48) && (eqn_string[6] <= 57))) {
545 if (PARSE_DEBUG) printf("parse_line shape prefix found: \"%s\"\n", eqn_string);
546 return parse_shape(eqn_string, fs, preset);
550 /* Per pixel equation case */
551 if (!strncmp(eqn_string, PER_PIXEL_STRING, PER_PIXEL_STRING_LENGTH)) {
552 line_mode = PER_PIXEL_LINE_MODE;
554 if (parse_per_pixel_eqn(fs, preset) < 0)
558 if (update_string_buffer(preset->per_pixel_eqn_string_buffer,
559 &preset->per_pixel_eqn_string_index) < 0)
562 if (PARSE_DEBUG) printf("parse_line: finished parsing per pixel equation (LINE %d)\n", line_count);
566 /* Sometimes equations are written implicitly in milkdrop files, in the form
568 per_frame_1 = p1 = eqn1; p2 = eqn2; p3 = eqn3;..;
570 which is analagous to:
572 per_frame_1 = p1 = eqn1; per_frame_2 = p2 = eqn2; per_frame_3 = p3 = eqn3; ...;
574 The following line mode hack allows such implicit declaration of the
575 prefix that specifies the equation type. An alternative method
576 may be to associate each equation line as list of equations separated
577 by semicolons (and a new line ends the list). Instead, however, a global
578 variable called "line_mode" specifies the last type of equation found,
579 and bases any implicitly typed input on this fact
581 Note added by Carmelo Piccione (cep@andrew.cmu.edu) 10/19/03
584 /* Per frame line mode previously, try to parse the equation implicitly */
585 if (line_mode == PER_FRAME_LINE_MODE) {
586 if ((per_frame_eqn = parse_implicit_per_frame_eqn(fs, eqn_string, ++per_frame_eqn_count, preset)) == NULL)
589 /* Insert the equation in the per frame equation tree */
590 if (splay_insert(per_frame_eqn, &per_frame_eqn_count, preset->per_frame_eqn_tree) < 0) {
591 if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
592 free_per_frame_eqn(per_frame_eqn); /* will free the gen expr too */
597 if (update_string_buffer(preset->per_frame_eqn_string_buffer,
598 &preset->per_frame_eqn_string_index) < 0)
606 //if (PARSE_DEBUG) printf("parse_line: found initial condition: name = \"%s\" (LINE %d)\n", eqn_string, line_count);
608 /* Evaluate the initial condition */
609 if ((init_cond = parse_init_cond(fs, eqn_string, preset)) == NULL) {
610 if (PARSE_DEBUG) printf("parse_line: failed to parse initial condition (LINE %d)\n", line_count);
614 /* Add equation to initial condition tree */
615 if (splay_insert(init_cond, init_cond->param->name, preset->init_cond_tree) < 0) {
616 if (PARSE_DEBUG) printf("parse_line: failed to add initial condition \"%s\" to equation tree (LINE %d)\n",
617 init_cond->param->name, line_count);
618 free_init_cond(init_cond);
622 /* Finished with initial condition line */
623 // if (PARSE_DEBUG) printf("parse_line: initial condition parsed successfully\n");
627 /* END INITIAL CONDITIONING PARSING */
630 default: /* an uncaught type or an error has occurred */
631 if (PARSE_DEBUG) printf("parse_line: uncaught case, token val = %d\n", token);
635 /* Because of the default in the case statement,
636 control flow should never actually reach here */
642 /* Parses a general expression, this function is the meat of the parser */
643 gen_expr_t * parse_gen_expr (FILE * fs, tree_expr_t * tree_expr, struct PRESET_T * preset) {
646 char string[MAX_TOKEN_SIZE];
648 gen_expr_t * gen_expr;
650 param_t * param = NULL;
652 gen_expr_t ** expr_list;
654 switch (token = parseToken(fs,string)) {
655 /* Left Parentice Case */
658 /* CASE 1 (Left Parentice): See if the previous string before this parentice is a function name */
659 if ((func = find_func(string)) != NULL) {
660 if (PARSE_DEBUG) printf("parse_gen_expr: found prefix function (name = %s) (LINE %d)\n", func->name, line_count);
662 /* Parse the functions arguments */
663 if ((expr_list = parse_prefix_args(fs, func->num_args, preset)) == NULL) {
664 if (PARSE_DEBUG) printf("parse_prefix_args: failed to generate an expresion list! (LINE %d) \n", line_count);
665 free_tree_expr(tree_expr);
669 /* Convert function to expression */
670 if ((gen_expr = prefun_to_expr((void*)func->func_ptr, expr_list, func->num_args)) == NULL) {
671 if (PARSE_DEBUG) printf("parse_prefix_args: failed to convert prefix function to general expression (LINE %d) \n",
673 free_tree_expr(tree_expr);
674 for (i = 0; i < func->num_args;i++)
675 free_gen_expr(expr_list[i]);
682 token = parseToken(fs, string);
685 if (PARSE_DEBUG) printf("parse_prefix_args: empty string expected, but not found...(LINE %d)\n", line_count);
686 /* continue anyway for now, could be implicit multiplication */
689 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
693 /* Case 2: (Left Parentice), a string coupled with a left parentice. Either an error or implicit
694 multiplication operator. For now treat it as an error */
696 if (PARSE_DEBUG) printf("parse_gen_expr: implicit multiplication case unimplemented!\n");
697 free_tree_expr(tree_expr);
701 /* CASE 3 (Left Parentice): the following is enclosed parentices to change order
702 of operations. So we create a new expression tree */
704 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
705 //if (PARSE_DEBUG) printf("parse_gen_expr: found left parentice, but failed to create new expression tree \n");
706 free_tree_expr(tree_expr);
710 if (PARSE_DEBUG) printf("parse_gen_expr: finished enclosed expression tree...\n");
711 token = parseToken(fs, string);
712 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
714 /* Plus is a prefix operator check */
718 //if (PARSE_DEBUG) printf("parse_gen_expr: plus used as prefix (LINE %d)\n", line_count);
720 /* Treat prefix plus as implict 0 preceding operator */
721 gen_expr = const_to_expr(0);
723 return parse_infix_op(fs, tPositive, insert_gen_expr(gen_expr, &tree_expr), preset);
726 /* Minus is a prefix operator check */
730 /* Use the negative infix operator, but first add an implicit zero to the operator tree */
731 gen_expr = const_to_expr(0);
732 //return parse_gen_expr(fs, insert_gen_expr(gen_expr, &tree_expr), preset);
733 return parse_infix_op(fs, tNegative, insert_gen_expr(gen_expr, &tree_expr), preset);
736 /* All the following cases are strings followed by an infix operator or terminal */
743 /* CASE 1 (terminal): string is empty, but not null. Not sure if this will actually happen
746 //if (PARSE_DEBUG) printf("parse_gen_expr: empty string coupled with terminal (LINE %d) \n", line_count);
747 return parse_infix_op(fs, token, tree_expr, preset);
753 /* CASE 0: Empty string, parse error */
755 if (PARSE_DEBUG) printf("parse_gen_expr: empty string coupled with infix op (ERROR!) (LINE %d) \n", line_count);
756 free_tree_expr(tree_expr);
760 /* CASE 1: Check if string is a just a floating point number */
761 if (string_to_float(string, &val) != PARSE_ERROR) {
762 if ((gen_expr = const_to_expr(val)) == NULL) {
763 free_tree_expr(tree_expr);
767 /* Parse the rest of the line */
768 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
773 /* CASE 4: custom shape variable */
774 if (current_shape != NULL) {
775 if ((param = find_param_db(string, current_shape->param_tree, FALSE)) == NULL) {
776 if ((param = find_builtin_param(string)) == NULL)
777 if ((param = find_param_db(string, current_shape->param_tree, TRUE)) == NULL) {
778 free_tree_expr(tree_expr);
784 printf("parse_gen_expr: custom shape parameter (name = %s)... ", param->name);
788 /* Convert parameter to an expression */
789 if ((gen_expr = param_to_expr(param)) == NULL) {
790 free_tree_expr(tree_expr);
794 //if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
796 /* Parse the rest of the line */
797 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
800 /* CASE 5: custom wave variable */
801 if (current_wave != NULL) {
802 if ((param = find_param_db(string, current_wave->param_tree, FALSE)) == NULL) {
803 if ((param = find_builtin_param(string)) == NULL)
804 if ((param = find_param_db(string, current_wave->param_tree, TRUE)) == NULL) {
805 free_tree_expr(tree_expr);
812 printf("parse_gen_expr: custom wave parameter (name = %s)... ", param->name);
816 /* Convert parameter to an expression */
817 if ((gen_expr = param_to_expr(param)) == NULL) {
818 free_tree_expr(tree_expr);
822 if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
824 /* Parse the rest of the line */
825 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
829 /* CASE 6: regular parameter. Will be created if necessary and the string has no invalid characters */
830 if ((param = find_param(string, preset, P_CREATE)) != NULL) {
833 printf("parse_gen_expr: parameter (name = %s)... ", param->name);
837 /* Convert parameter to an expression */
838 if ((gen_expr = param_to_expr(param)) == NULL) {
839 free_tree_expr(tree_expr);
843 if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
845 /* Parse the rest of the line */
846 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
850 /* CASE 7: Bad string, give up */
851 if (PARSE_DEBUG) printf("parse_gen_expr: syntax error [string = \"%s\"] (LINE %d)\n", string, line_count);
852 free_tree_expr(tree_expr);
859 /* Inserts expressions into tree according to operator precedence.
860 If root is null, a new tree is created, with gen_expr as only element */
862 tree_expr_t * insert_infix_op(infix_op_t * infix_op, tree_expr_t **root) {
864 tree_expr_t * new_root;
867 if (infix_op == NULL)
870 /* The root is null, so make this operator
874 new_root = new_tree_expr(infix_op, NULL, NULL, NULL);
879 /* The root node is not an infix function,
880 so we make this infix operator the new root */
882 if ((*root)->infix_op == NULL) {
883 new_root = new_tree_expr(infix_op, NULL, *root, NULL);
888 /* The root is an infix function. If the precedence
889 of the item to be inserted is greater than the root's
890 precedence, then make gen_expr the root */
892 if (infix_op->precedence > (*root)->infix_op->precedence) {
893 new_root = new_tree_expr(infix_op, NULL, *root, NULL);
898 /* If control flow reaches here, use a recursive helper
899 with the knowledge that the root is higher precedence
900 than the item to be inserted */
902 insert_infix_rec(infix_op, *root);
908 tree_expr_t * insert_gen_expr(gen_expr_t * gen_expr, tree_expr_t ** root) {
910 tree_expr_t * new_root;
912 /* If someone foolishly passes a null
913 pointer to insert, return the original tree */
915 if (gen_expr == NULL) {
919 /* If the root is null, generate a new expression tree,
920 using the passed expression as the root element */
923 new_root = new_tree_expr(NULL, gen_expr, NULL, NULL);
929 /* Otherwise. the new element definitely will not replace the current root.
930 Use a recursive helper function to do insertion */
932 insert_gen_rec(gen_expr, *root);
936 /* A recursive helper function to insert general expression elements into the operator tree */
937 int insert_gen_rec(gen_expr_t * gen_expr, tree_expr_t * root) {
939 /* Trivial Case: root is null */
942 ////if (PARSE_DEBUG) printf("insert_gen_rec: root is null, returning failure\n");
947 /* The current node's left pointer is null, and this
948 current node is an infix operator, so insert the
949 general expression at the left pointer */
951 if ((root->left == NULL) && (root->infix_op != NULL)) {
952 root->left = new_tree_expr(NULL, gen_expr, NULL, NULL);
956 /* The current node's right pointer is null, and this
957 current node is an infix operator, so insert the
958 general expression at the right pointer */
960 if ((root->right == NULL) && (root->infix_op != NULL)) {
961 root->right = new_tree_expr(NULL, gen_expr, NULL, NULL);
965 /* Otherwise recurse down to the left. If
966 this succeeds then return. If it fails, try
967 recursing down to the right */
969 if (insert_gen_rec(gen_expr, root->left) == FAILURE)
970 return insert_gen_rec(gen_expr, root->right);
972 /* Impossible for control flow to reach here, but in
973 the world of C programming, who knows... */
974 //if (PARSE_DEBUG) printf("insert_gen_rec: should never reach here!\n");
979 /* A recursive helper function to insert infix arguments by operator precedence */
980 int insert_infix_rec(infix_op_t * infix_op, tree_expr_t * root) {
982 /* Shouldn't happen, implies a parse error */
987 /* Also shouldn't happen, also implies a (different) parse error */
989 if (root->infix_op == NULL)
992 /* Left tree is empty, attach this operator to it.
993 I don't think this will ever happen */
994 if (root->left == NULL) {
995 root->left = new_tree_expr(infix_op, NULL, root->left, NULL);
999 /* Right tree is empty, attach this operator to it */
1000 if (root->right == NULL) {
1001 root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
1005 /* The left element can now be ignored, since there is no way for this
1006 operator to use those expressions */
1008 /* If the right element is not an infix operator,
1009 then insert the expression here, attaching the old right branch
1010 to the left of the new expression */
1012 if (root->right->infix_op == NULL) {
1013 root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
1017 /* Traverse deeper if the inserting operator precedence is less than the
1018 the root's right operator precedence */
1019 if (infix_op->precedence < root->right->infix_op->precedence)
1020 return insert_infix_rec(infix_op, root->right);
1022 /* Otherwise, insert the operator here */
1024 root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
1029 /* Parses an infix operator */
1030 gen_expr_t * parse_infix_op(FILE * fs, token_t token, tree_expr_t * tree_expr, struct PRESET_T * preset) {
1032 gen_expr_t * gen_expr;
1035 /* All the infix operators */
1037 //if (PARSE_DEBUG) printf("parse_infix_op: found addition operator (LINE %d)\n", line_count);
1038 return parse_gen_expr(fs, insert_infix_op(infix_add, &tree_expr), preset);
1040 //if (PARSE_DEBUG) printf("parse_infix_op: found subtraction operator (LINE %d)\n", line_count);
1041 return parse_gen_expr(fs, insert_infix_op(infix_minus, &tree_expr), preset);
1043 //if (PARSE_DEBUG) printf("parse_infix_op: found multiplication operator (LINE %d)\n", line_count);
1044 return parse_gen_expr(fs, insert_infix_op(infix_mult, &tree_expr), preset);
1046 //if (PARSE_DEBUG) printf("parse_infix_op: found division operator (LINE %d)\n", line_count);
1047 return parse_gen_expr(fs, insert_infix_op(infix_div, &tree_expr), preset);
1049 //if (PARSE_DEBUG) printf("parse_infix_op: found modulo operator (LINE %d)\n", line_count);
1050 return parse_gen_expr(fs, insert_infix_op(infix_mod, &tree_expr), preset);
1052 //if (PARSE_DEBUG) printf("parse_infix_op: found bitwise or operator (LINE %d)\n", line_count);
1053 return parse_gen_expr(fs, insert_infix_op(infix_or, &tree_expr), preset);
1055 //if (PARSE_DEBUG) printf("parse_infix_op: found bitwise and operator (LINE %d)\n", line_count);
1056 return parse_gen_expr(fs, insert_infix_op(infix_and, &tree_expr), preset);
1058 //if (PARSE_DEBUG) printf("parse_infix_op: found positive operator (LINE %d)\n", line_count);
1059 return parse_gen_expr(fs, insert_infix_op(infix_positive, &tree_expr), preset);
1061 //if (PARSE_DEBUG) printf("parse_infix_op: found negative operator (LINE %d)\n", line_count);
1062 return parse_gen_expr(fs, insert_infix_op(infix_negative, &tree_expr), preset);
1069 //if (PARSE_DEBUG) printf("parse_infix_op: terminal found (LINE %d)\n", line_count);
1070 gen_expr = new_gen_expr(TREE_T, (void*)tree_expr);
1073 //if (PARSE_DEBUG) printf("parse_infix_op: operator or terminal expected, but not found (LINE %d)\n", line_count);
1074 free_tree_expr(tree_expr);
1078 /* Will never happen */
1083 /* Parses an integer, checks for +/- prefix */
1084 int parse_int(FILE * fs, int * int_ptr) {
1086 char string[MAX_TOKEN_SIZE];
1089 char * end_ptr = " ";
1091 token = parseToken(fs, string);
1097 token = parseToken(fs, string);
1101 token = parseToken(fs, string);
1112 /* Convert the string to an integer. *end_ptr
1113 should end up pointing to null terminator of 'string'
1114 if the conversion was successful. */
1115 // printf("STRING: \"%s\"\n", string);
1117 (*int_ptr) = sign*strtol(string, &end_ptr, 10);
1119 /* If end pointer is a return character or null terminator, all is well */
1120 if ((*end_ptr == '\r') || (*end_ptr == '\0'))
1126 /* Parses a floating point number */
1127 int string_to_float(char * string, double * float_ptr) {
1134 error_ptr = malloc(sizeof(char**));
1136 (*float_ptr) = strtod(string, error_ptr);
1138 /* These imply a succesful parse of the string */
1139 if ((**error_ptr == '\0') || (**error_ptr == '\r')) {
1149 /* Parses a floating point number */
1150 int parse_float(FILE * fs, double * float_ptr) {
1152 char string[MAX_TOKEN_SIZE];
1157 error_ptr = malloc(sizeof(char**));
1159 token = parseToken(fs, string);
1164 token = parseToken(fs, string);
1168 token = parseToken(fs, string);
1174 if (string[0] == 0) {
1179 (*float_ptr) = sign*strtod(string, error_ptr);
1181 /* No conversion was performed */
1182 if ((**error_ptr == '\0') || (**error_ptr == '\r')) {
1187 //if (PARSE_DEBUG) printf("parse_float: double conversion failed for string \"%s\"\n", string);
1197 /* Parses a per frame equation. That is, interprets a stream of data as a per frame equation */
1198 per_frame_eqn_t * parse_per_frame_eqn(FILE * fs, int index, struct PRESET_T * preset) {
1200 char string[MAX_TOKEN_SIZE];
1202 per_frame_eqn_t * per_frame_eqn;
1203 gen_expr_t * gen_expr;
1205 if (parseToken(fs, string) != tEq) {
1206 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
1210 /* Find the parameter associated with the string, create one if necessary */
1211 if ((param = find_param(string, preset, P_CREATE)) == NULL) {
1215 /* Make sure parameter is writable */
1216 if (param->flags & P_FLAG_READONLY) {
1217 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1221 /* Parse right side of equation as an expression */
1222 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1223 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: equation evaluated to null (LINE %d)\n", line_count);
1227 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: finished per frame equation evaluation (LINE %d)\n", line_count);
1229 /* Create a new per frame equation */
1230 if ((per_frame_eqn = new_per_frame_eqn(index, param, gen_expr)) == NULL) {
1231 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: failed to create a new per frame eqn, out of memory?\n");
1232 free_gen_expr(gen_expr);
1236 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: per_frame eqn parsed succesfully\n");
1238 return per_frame_eqn;
1241 /* Parses an 'implicit' per frame equation. That is, interprets a stream of data as a per frame equation without a prefix */
1242 per_frame_eqn_t * parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, struct PRESET_T * preset) {
1245 per_frame_eqn_t * per_frame_eqn;
1246 gen_expr_t * gen_expr;
1250 if (param_string == NULL)
1255 //rintf("param string: %s\n", param_string);
1256 /* Find the parameter associated with the string, create one if necessary */
1257 if ((param = find_param(param_string, preset, P_CREATE)) == NULL) {
1261 //printf("parse_implicit_per_frame_eqn: param is %s\n", param->name);
1263 /* Make sure parameter is writable */
1264 if (param->flags & P_FLAG_READONLY) {
1265 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1269 /* Parse right side of equation as an expression */
1270 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1271 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: equation evaluated to null (LINE %d)\n", line_count);
1275 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: finished per frame equation evaluation (LINE %d)\n", line_count);
1277 /* Create a new per frame equation */
1278 if ((per_frame_eqn = new_per_frame_eqn(index, param, gen_expr)) == NULL) {
1279 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: failed to create a new per frame eqn, out of memory?\n");
1280 free_gen_expr(gen_expr);
1284 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: per_frame eqn parsed succesfully\n");
1286 return per_frame_eqn;
1289 /* Parses an initial condition */
1290 init_cond_t * parse_init_cond(FILE * fs, char * name, struct PRESET_T * preset) {
1294 init_cond_t * init_cond;
1301 /* Search for the paramater in the database, creating it if necessary */
1302 if ((param = find_param(name, preset, P_CREATE)) == NULL) {
1306 //if (PARSE_DEBUG) printf("parse_init_cond: parameter = \"%s\" (LINE %d)\n", param->name, line_count);
1308 if (param->flags & P_FLAG_READONLY) {
1309 //if (PARSE_DEBUG) printf("parse_init_cond: builtin parameter \"%s\" marked as read only!\n", param->name);
1313 /* At this point, a parameter has been created or was found
1316 //if (PARSE_DEBUG) printf("parse_init_cond: parsing initial condition value... (LINE %d)\n", line_count);
1318 /* integer value (boolean is an integer in C) */
1319 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1320 if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {
1321 //if (PARSE_DEBUG) printf("parse_init_cond: error parsing integer!\n");
1327 else if (param->type == P_TYPE_DOUBLE) {
1328 if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
1329 //if (PARSE_DEBUG) printf("parse_init_cond: error parsing double!\n");
1336 //if (PARSE_DEBUG) printf("parse_init_cond: unknown parameter type!\n");
1340 /* Create new initial condition */
1341 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1342 //if (PARSE_DEBUG) printf("parse_init_cond: new_init_cond failed!\n");
1350 /* Parses a per frame init equation, not sure if this works right now */
1351 init_cond_t * parse_per_frame_init_eqn(FILE * fs, struct PRESET_T * preset, splaytree_t * database) {
1353 char name[MAX_TOKEN_SIZE];
1354 param_t * param = NULL;
1356 init_cond_t * init_cond;
1357 gen_expr_t * gen_expr;
1367 if ((token = parseToken(fs, name)) != tEq)
1371 /* If a database was specified,then use find_param_db instead */
1372 if ((database != NULL) && ((param = find_param_db(name, database, TRUE)) == NULL)) {
1376 /* Otherwise use the builtin parameter and user databases. This is confusing. Sorry. */
1377 if ((param == NULL) && ((param = find_param(name, preset, P_CREATE)) == NULL)) {
1381 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: parameter = \"%s\" (LINE %d)\n", param->name, line_count);
1383 if (param->flags & P_FLAG_READONLY) {
1384 //if (PARSE_DEBUG) printf("pars_per_frame_init_eqn: builtin parameter \"%s\" marked as read only!\n", param->name);
1388 /* At this point, a parameter has been created or was found
1391 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: parsing right hand side of per frame init equation.. (LINE %d)\n", line_count);
1393 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1394 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: failed to parse general expresion!\n");
1398 /* Compute initial condition value */
1399 val = eval_gen_expr(gen_expr);
1401 /* Free the general expression now that we are done with it */
1402 free_gen_expr(gen_expr);
1404 /* integer value (boolean is an integer in C) */
1405 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1406 init_val.int_val = (int)val;
1410 else if (param->type == P_TYPE_DOUBLE) {
1411 init_val.double_val = val;
1416 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: unknown parameter type!\n");
1421 /* Create new initial condition */
1422 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1423 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: new_init_cond failed!\n");
1432 int parse_wavecode(char * token, FILE * fs, preset_t * preset) {
1435 init_cond_t * init_cond;
1436 custom_wave_t * custom_wave;
1441 /* Null argument checks */
1449 /* token should be in the form wavecode_N_var, such as wavecode_1_samples */
1451 /* Get id and variable name from token string */
1452 if (parse_wavecode_prefix(token, &id, &var_string) < 0)
1455 //if (PARSE_DEBUG) printf("parse_wavecode: wavecode id = %d, parameter = \"%s\"\n", id, var_string);
1457 /* Retrieve custom wave information from preset. The 3rd argument
1458 if true creates a custom wave if one does not exist */
1459 if ((custom_wave = find_custom_wave(id, preset, TRUE)) == NULL) {
1460 //if (PARSE_DEBUG) printf("parse_wavecode: failed to load (or create) custom wave (id = %d)!\n", id);
1463 //if (PARSE_DEBUG) printf("parse_wavecode: custom wave found (id = %d)\n", custom_wave->id);
1465 /* Retrieve parameter from this custom waves parameter db */
1466 if ((param = find_param_db(var_string, custom_wave->param_tree, TRUE)) == NULL)
1469 //if (PARSE_DEBUG) printf("parse_wavecode: custom wave parameter found (name = %s)\n", param->name);
1471 /* integer value (boolean is an integer in C) */
1472 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1473 if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {
1474 //if (PARSE_DEBUG) printf("parse_wavecode: error parsing integer!\n");
1480 else if (param->type == P_TYPE_DOUBLE) {
1481 if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
1482 //if (PARSE_DEBUG) printf("parse_wavecode: error parsing double!\n");
1489 //if (PARSE_DEBUG) printf("parse_wavecode: unknown parameter type!\n");
1493 /* Create new initial condition */
1494 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1495 //if (PARSE_DEBUG) printf("parse_wavecode: new_init_cond failed!\n");
1499 if (splay_insert(init_cond, param->name, custom_wave->init_cond_tree) < 0) {
1500 free_init_cond(init_cond);
1504 //if (PARSE_DEBUG) printf("parse_wavecode: [success]\n");
1508 int parse_shapecode(char * token, FILE * fs, preset_t * preset) {
1511 init_cond_t * init_cond;
1512 custom_shape_t * custom_shape;
1517 /* Null argument checks */
1525 /* token should be in the form shapecode_N_var, such as shapecode_1_samples */
1527 /* Get id and variable name from token string */
1528 if (parse_shapecode_prefix(token, &id, &var_string) < 0)
1531 //if (PARSE_DEBUG) printf("parse_shapecode: shapecode id = %d, parameter = \"%s\"\n", id, var_string);
1533 /* Retrieve custom shape information from preset. The 3rd argument
1534 if true creates a custom shape if one does not exist */
1535 if ((custom_shape = find_custom_shape(id, preset, TRUE)) == NULL) {
1536 //if (PARSE_DEBUG) printf("parse_shapecode: failed to load (or create) custom shape (id = %d)!\n", id);
1539 //if (PARSE_DEBUG) printf("parse_shapecode: custom shape found (id = %d)\n", custom_shape->id);
1541 /* Retrieve parameter from this custom shapes parameter db */
1542 if ((param = find_param_db(var_string, custom_shape->param_tree, TRUE)) == NULL) {
1543 //if (PARSE_DEBUG) printf("parse_shapecode: failed to create parameter.\n");
1546 //if (PARSE_DEBUG) printf("parse_shapecode: custom shape parameter found (name = %s)\n", param->name);
1548 /* integer value (boolean is an integer in C) */
1549 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1550 if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {
1551 //if (PARSE_DEBUG) printf("parse_shapecode: error parsing integer!\n");
1557 else if (param->type == P_TYPE_DOUBLE) {
1558 if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
1559 //if (PARSE_DEBUG) printf("parse_shapecode: error parsing double!\n");
1566 //if (PARSE_DEBUG) printf("parse_shapecode: unknown parameter type!\n");
1570 /* Create new initial condition */
1571 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1572 //if (PARSE_DEBUG) printf("parse_shapecode: new_init_cond failed!\n");
1576 if (splay_insert(init_cond, param->name, custom_shape->init_cond_tree) < 0) {
1577 free_init_cond(init_cond);
1578 //if (PARSE_DEBUG) printf("parse_shapecode: initial condition already set, not reinserting it (param = \"%s\")\n", param->name);
1582 //if (PARSE_DEBUG) printf("parse_shapecode: [success]\n");
1587 int parse_wavecode_prefix(char * token, int * id, char ** var_string) {
1593 if (*var_string == NULL)
1598 len = strlen(token);
1600 /* Move pointer passed "wavecode_" prefix */
1601 if (len <= WAVECODE_STRING_LENGTH)
1603 i = WAVECODE_STRING_LENGTH;
1607 /* This loop grabs the integer id for this custom wave */
1608 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1609 if (j >= MAX_TOKEN_SIZE)
1612 (*id) = 10*(*id) + (token[i]-48);
1621 *var_string = token + i + 1;
1628 int parse_shapecode_prefix(char * token, int * id, char ** var_string) {
1634 if (*var_string == NULL)
1639 len = strlen(token);
1641 /* Move pointer passed "shapecode_" prefix */
1642 if (len <= SHAPECODE_STRING_LENGTH)
1644 i = SHAPECODE_STRING_LENGTH;
1648 /* This loop grabs the integer id for this custom shape */
1649 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1650 if (j >= MAX_TOKEN_SIZE)
1653 (*id) = 10*(*id) + (token[i]-48);
1662 *var_string = token + i + 1;
1668 int parse_wave_prefix(char * token, int * id, char ** eqn_string) {
1674 if (eqn_string == NULL)
1679 len = strlen(token);
1681 if (len <= WAVE_STRING_LENGTH)
1685 i = WAVE_STRING_LENGTH;
1689 /* This loop grabs the integer id for this custom wave */
1690 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1691 if (j >= MAX_TOKEN_SIZE)
1694 (*id) = 10*(*id) + (token[i]-48);
1702 *eqn_string = token + i + 1;
1708 int parse_shape_prefix(char * token, int * id, char ** eqn_string) {
1714 if (eqn_string == NULL)
1719 len = strlen(token);
1721 if (len <= SHAPE_STRING_LENGTH)
1725 i = SHAPE_STRING_LENGTH;
1729 /* This loop grabs the integer id for this custom wave */
1730 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1731 if (j >= MAX_TOKEN_SIZE)
1734 (*id) = 10*(*id) + (token[i]-48);
1742 *eqn_string = token + i + 1;
1748 /* Parses custom wave equations */
1749 int parse_wave(char * token, FILE * fs, preset_t * preset) {
1753 char string[MAX_TOKEN_SIZE];
1755 per_frame_eqn_t * per_frame_eqn;
1756 gen_expr_t * gen_expr;
1757 custom_wave_t * custom_wave;
1758 init_cond_t * init_cond;
1767 /* Grab custom wave id and equation type (per frame or per point) from string token */
1768 if (parse_wave_prefix(token, &id, &eqn_type) < 0) {
1769 //if (PARSE_DEBUG) printf("parse_wave: syntax error in custom wave prefix!\n");
1772 /* Retrieve custom wave associated with this id */
1773 if ((custom_wave = find_custom_wave(id, preset, TRUE)) == NULL)
1777 /* per frame init equation case */
1778 if (!strncmp(eqn_type, WAVE_INIT_STRING, WAVE_INIT_STRING_LENGTH)) {
1780 //if (PARSE_DEBUG) printf("parse_wave (per frame init): [begin] (LINE %d)\n", line_count);
1782 /* Parse the per frame equation */
1783 if ((init_cond = parse_per_frame_init_eqn(fs, preset, custom_wave->param_tree)) == NULL) {
1784 //if (PARSE_DEBUG) printf("parse_wave (per frame init): equation parsing failed (LINE %d)\n", line_count);
1788 /* Insert the equation in the per frame equation tree */
1789 if (splay_insert(init_cond, init_cond->param->name, custom_wave->per_frame_init_eqn_tree) < 0) {
1790 //if (PARSE_DEBUG) printf("parse_wave (per frame init): failed to add equation (ERROR)\n");
1791 free_init_cond(init_cond); /* will free the gen expr too */
1795 if (update_string_buffer(custom_wave->per_frame_init_eqn_string_buffer,
1796 &custom_wave->per_frame_init_eqn_string_index) < 0)
1803 /* per frame equation case */
1804 if (!strncmp(eqn_type, PER_FRAME_STRING_NO_UNDERSCORE, PER_FRAME_STRING_NO_UNDERSCORE_LENGTH)) {
1806 //if (PARSE_DEBUG) printf("parse_wave (per_frame): [start] (custom wave id = %d)\n", custom_wave->id);
1808 if (parseToken(fs, string) != tEq) {
1809 //if (PARSE_DEBUG) printf("parse_wave (per_frame): no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
1813 /* Find the parameter associated with the string in the custom wave database */
1814 if ((param = find_param_db(string, custom_wave->param_tree, TRUE)) == NULL) {
1815 //if (PARSE_DEBUG) printf("parse_wave (per_frame): parameter \"%s\" not found or cannot be malloc'ed!!\n", string);
1820 /* Make sure parameter is writable */
1821 if (param->flags & P_FLAG_READONLY) {
1822 //if (PARSE_DEBUG) printf("parse_wave (per_frame): parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1826 /* Parse right side of equation as an expression */
1828 current_wave = custom_wave;
1829 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1830 //if (PARSE_DEBUG) printf("parse_wave (per_frame): equation evaluated to null (LINE %d)\n", line_count);
1831 current_wave = NULL;
1835 current_wave = NULL;
1837 //if (PARSE_DEBUG) printf("parse_wave (per_frame): [finished parsing equation] (LINE %d)\n", line_count);
1839 /* Create a new per frame equation */
1840 if ((per_frame_eqn = new_per_frame_eqn(custom_wave->per_frame_count++, param, gen_expr)) == NULL) {
1841 //if (PARSE_DEBUG) printf("parse_wave (per_frame): failed to create a new per frame eqn, out of memory?\n");
1842 free_gen_expr(gen_expr);
1846 if (splay_insert(per_frame_eqn, &per_frame_eqn->index, custom_wave->per_frame_eqn_tree) < 0) {
1847 free_per_frame_eqn(per_frame_eqn);
1851 //if (PARSE_DEBUG) printf("parse_wave (per_frame): equation %d associated with custom wave %d [success]\n",
1852 // per_frame_eqn->index, custom_wave->id);
1855 /* Need to add stuff to string buffer so the editor can read the equations.
1856 Why not make a nice little helper function for this? - here it is: */
1859 if (update_string_buffer(custom_wave->per_frame_eqn_string_buffer, &custom_wave->per_frame_eqn_string_index) < 0)
1867 /* per point equation case */
1868 if (!strncmp(eqn_type, PER_POINT_STRING, PER_POINT_STRING_LENGTH)) {
1870 //if (PARSE_DEBUG) printf("parse_wave (per_point): per_pixel equation parsing start...(LINE %d)\n", line_count);
1872 if (parseToken(fs, string) != tEq) { /* parse per pixel operator name */
1873 //if (PARSE_DEBUG) printf("parse_wave (per_point): equal operator missing after per pixel operator! (LINE %d)\n", line_count);
1877 /* Parse right side of equation as an expression */
1878 current_wave = custom_wave;
1879 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1880 //if (PARSE_DEBUG) printf("parse_wave (per_point): equation evaluated to null? (LINE %d)\n", line_count);
1883 current_wave = NULL;
1885 /* Add the per point equation */
1886 if (add_per_point_eqn(string, gen_expr, custom_wave) < 0) {
1887 free_gen_expr(gen_expr);
1892 if (update_string_buffer(custom_wave->per_point_eqn_string_buffer, &custom_wave->per_point_eqn_string_index) < 0)
1895 //if (PARSE_DEBUG) printf("parse_wave (per_point): [finished] (custom wave id = %d)\n", custom_wave->id);
1900 /* Syntax error, return parse error */
1906 /* Parses custom shape equations */
1907 int parse_shape(char * token, FILE * fs, preset_t * preset) {
1911 char string[MAX_TOKEN_SIZE];
1913 per_frame_eqn_t * per_frame_eqn;
1914 gen_expr_t * gen_expr;
1915 custom_shape_t * custom_shape;
1916 init_cond_t * init_cond;
1926 /* Grab custom shape id and equation type (per frame or per point) from string token */
1927 if (parse_shape_prefix(token, &id, &eqn_type) < 0) {
1928 //if (PARSE_DEBUG) printf("parse_shape: syntax error in custom shape prefix!\n");
1931 /* Retrieve custom shape associated with this id */
1932 if ((custom_shape = find_custom_shape(id, preset, TRUE)) == NULL)
1936 /* per frame init equation case */
1937 if (!strncmp(eqn_type, SHAPE_INIT_STRING, SHAPE_INIT_STRING_LENGTH)) {
1939 //if (PARSE_DEBUG) printf("parse_shape (per frame init): [begin] (LINE %d)\n", line_count);
1941 /* Parse the per frame equation */
1942 if ((init_cond = parse_per_frame_init_eqn(fs, preset, custom_shape->param_tree)) == NULL) {
1943 //if (PARSE_DEBUG) printf("parse_shape (per frame init): equation parsing failed (LINE %d)\n", line_count);
1947 /* Insert the equation in the per frame equation tree */
1948 if (splay_insert(init_cond, init_cond->param->name, custom_shape->per_frame_init_eqn_tree) < 0) {
1949 //if (PARSE_DEBUG) printf("parse_shape (per frame init): failed to add equation (ERROR)\n");
1950 free_init_cond(init_cond); /* will free the gen expr too */
1954 if (update_string_buffer(custom_shape->per_frame_init_eqn_string_buffer,
1955 &custom_shape->per_frame_init_eqn_string_index) < 0)
1962 /* per frame equation case */
1963 if (!strncmp(eqn_type, PER_FRAME_STRING_NO_UNDERSCORE, PER_FRAME_STRING_NO_UNDERSCORE_LENGTH)) {
1965 //if (PARSE_DEBUG) printf("parse_shape (per_frame): [start] (custom shape id = %d)\n", custom_shape->id);
1967 if (parseToken(fs, string) != tEq) {
1968 //if (PARSE_DEBUG) printf("parse_shape (per_frame): no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
1972 /* Find the parameter associated with the string in the custom shape database */
1973 if ((param = find_param_db(string, custom_shape->param_tree, TRUE)) == NULL) {
1974 //if (PARSE_DEBUG) printf("parse_shape (per_frame): parameter \"%s\" not found or cannot be malloc'ed!!\n", string);
1979 /* Make sure parameter is writable */
1980 if (param->flags & P_FLAG_READONLY) {
1981 //if (PARSE_DEBUG) printf("parse_shape (per_frame): parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1985 /* Parse right side of equation as an expression */
1987 current_shape = custom_shape;
1988 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1989 //if (PARSE_DEBUG) printf("parse_shape (per_frame): equation evaluated to null (LINE %d)\n", line_count);
1990 current_shape = NULL;
1994 current_shape = NULL;
1996 //if (PARSE_DEBUG) printf("parse_shape (per_frame): [finished parsing equation] (LINE %d)\n", line_count);
1998 /* Create a new per frame equation */
1999 if ((per_frame_eqn = new_per_frame_eqn(custom_shape->per_frame_count++, param, gen_expr)) == NULL) {
2000 //if (PARSE_DEBUG) printf("parse_shape (per_frame): failed to create a new per frame eqn, out of memory?\n");
2001 free_gen_expr(gen_expr);
2005 if (splay_insert(per_frame_eqn, &per_frame_eqn->index, custom_shape->per_frame_eqn_tree) < 0) {
2006 free_per_frame_eqn(per_frame_eqn);
2010 //if (PARSE_DEBUG) printf("parse_shape (per_frame): equation %d associated with custom shape %d [success]\n",
2011 // per_frame_eqn->index, custom_shape->id);
2014 /* Need to add stuff to string buffer so the editor can read the equations.
2015 Why not make a nice little helper function for this? - here it is: */
2017 if (update_string_buffer(custom_shape->per_frame_eqn_string_buffer, &custom_shape->per_frame_eqn_string_index) < 0)
2025 /* Syntax error, return parse error */
2029 /* Helper function to update the string buffers used by the editor */
2030 int update_string_buffer(char * buffer, int * index) {
2041 /* If the string line buffer used by the parser is already full then quit */
2042 if (string_line_buffer_index == (STRING_LINE_SIZE-1))
2045 if ((skip_size = get_string_prefix_len(string_line_buffer)) == FAILURE)
2048 string_line_buffer[string_line_buffer_index++] = '\n';
2050 // string_length = strlen(string_line_buffer + strlen(eqn_string)+1);
2051 if (skip_size >= STRING_LINE_SIZE)
2054 string_length = strlen(string_line_buffer + skip_size);
2056 if (skip_size > (STRING_LINE_SIZE-1))
2059 /* Add line to string buffer */
2060 strncpy(buffer + (*index),
2061 string_line_buffer + skip_size, string_length);
2063 /* Buffer full, quit */
2064 if ((*index) > (STRING_BUFFER_SIZE - 1)) {
2065 //if (PARSE_DEBUG) printf("update_string_buffer: string buffer full!\n");
2069 /* Otherwise, increment string index by the added string length */
2070 (*index)+=string_length;
2077 /* Helper function: returns the length of the prefix portion in the line
2078 buffer (the passed string here). In other words, given
2079 the string 'per_frame_1 = x = ....', return the length of 'per_frame_1 = '
2080 Returns -1 if syntax error
2083 int get_string_prefix_len(char * string) {
2087 /* Null argument check */
2092 /* First find the equal sign */
2093 while (string[i] != '=') {
2099 /* If the string already ends at the next char then give up */
2100 if (string[i+1] == 0)
2103 /* Move past the equal sign */
2106 /* Now found the start of the LHS variable, ie skip the spaces */
2107 while(string[i] == ' ') {
2111 /* If this is the end of the string then its a syntax error */
2115 /* Finished succesfully, return the length */