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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23 *****************************************************************************/
35 #include "splaytree_types.h"
36 #include "splaytree.h"
37 #include "tree_types.h"
39 #include "expr_types.h"
42 #include "param_types.h"
45 #include "func_types.h"
48 #include "preset_types.h"
49 #include "builtin_funcs.h"
51 #include "per_pixel_eqn_types.h"
52 #include "per_pixel_eqn.h"
54 #include "init_cond_types.h"
55 #include "init_cond.h"
57 #include "per_frame_eqn_types.h"
58 #include "per_frame_eqn.h"
61 #include "engine_vars.h"
63 #include "custom_wave_types.h"
64 #include "custom_wave.h"
66 #include "custom_shape_types.h"
67 #include "custom_shape.h"
69 /* Strings that prefix (and denote the type of) equations */
72 #define PER_FRAME_STRING "per_frame_"
73 #define PER_FRAME_STRING_LENGTH 10
75 #define PER_PIXEL_STRING "per_pixel_"
76 #define PER_PIXEL_STRING_LENGTH 10
78 #define PER_FRAME_INIT_STRING "per_frame_init_"
79 #define PER_FRAME_INIT_STRING_LENGTH 15
81 #define WAVECODE_STRING "wavecode_"
82 #define WAVECODE_STRING_LENGTH 9
84 #define WAVE_STRING "wave_"
85 #define WAVE_STRING_LENGTH 5
87 #define PER_POINT_STRING "per_point"
88 #define PER_POINT_STRING_LENGTH 9
90 #define PER_FRAME_STRING_NO_UNDERSCORE "per_frame"
91 #define PER_FRAME_STRING_NO_UNDERSCORE_LENGTH 9
93 #define SHAPECODE_STRING "shapecode_"
94 #define SHAPECODE_STRING_LENGTH 10
96 #define SHAPE_STRING "shape_"
97 #define SHAPE_STRING_LENGTH 6
99 #define SHAPE_INIT_STRING "init"
100 #define SHAPE_INIT_STRING_LENGTH 4
102 #define WAVE_INIT_STRING "init"
103 #define WAVE_INIT_STRING_LENGTH 4
105 /* Stores a line of a file as its being parsed */
106 char string_line_buffer[STRING_LINE_SIZE];
108 /* The current position of the string line buffer (see above) */
109 int string_line_buffer_index = 0;
111 /* All infix operators (except '=') are prototyped here */
112 extern infix_op_t * infix_add, * infix_minus, * infix_div, * infix_mult,
113 * infix_or, * infix_and, * infix_mod, * infix_positive, * infix_negative;
115 /* If the parser reads a line with a custom wave, this pointer is set to
116 the custom wave of concern */
117 custom_wave_t * current_wave = NULL;
118 custom_shape_t * current_shape = NULL;
119 /* Counts the number of lines parsed */
120 unsigned int line_count = 1;
121 int per_frame_eqn_count = 0;
122 int per_frame_init_eqn_count = 0;
129 CUSTOM_WAVE_PER_POINT_LINE_MODE,
130 CUSTOM_WAVE_PER_FRAME_LINE_MODE,
131 CUSTOM_WAVE_WAVECODE_LINE_MODE,
132 CUSTOM_SHAPE_SHAPECODE_LINE_MODE,
135 line_mode_t line_mode = NORMAL_LINE_MODE;
137 /* Token enumeration type */
140 tEOL, /* end of a line, usually a '/n' or '/r' */
141 tEOF, /* end of file */
155 tPositive, /* + as a prefix operator */
156 tNegative, /* - as a prefix operator */
158 tStringTooLong, /* special token to indicate an invalid string length */
159 tStringBufferFilled /* the string buffer for this line is maxed out */
163 int get_string_prefix_len(char * string);
164 tree_expr_t * insert_gen_expr(gen_expr_t * gen_expr, tree_expr_t ** root);
165 tree_expr_t * insert_infix_op(infix_op_t * infix_op, tree_expr_t ** root);
166 token_t parseToken(FILE * fs, char * string);
167 gen_expr_t ** parse_prefix_args(FILE * fs, int num_args, struct PRESET_T * preset);
168 gen_expr_t * parse_infix_op(FILE * fs, token_t token, tree_expr_t * tree_expr, struct PRESET_T * preset);
169 gen_expr_t * parse_sign_arg(FILE * fs);
170 int parse_float(FILE * fs, double * float_ptr);
171 int parse_int(FILE * fs, int * int_ptr);
172 int insert_gen_rec(gen_expr_t * gen_expr, tree_expr_t * root);
173 int insert_infix_rec(infix_op_t * infix_op, tree_expr_t * root);
174 gen_expr_t * parse_gen_expr(FILE * fs, tree_expr_t * tree_expr, struct PRESET_T * preset);
175 per_frame_eqn_t * parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, struct PRESET_T * preset);
176 init_cond_t * parse_per_frame_init_eqn(FILE * fs, struct PRESET_T * preset, splaytree_t * database);
177 int parse_wavecode_prefix(char * token, int * id, char ** var_string);
178 int parse_wavecode(char * token, FILE * fs, preset_t * preset);
179 int parse_wave_prefix(char * token, int * id, char ** eqn_string);
181 int parse_shapecode(char * eqn_string, FILE * fs, preset_t * preset);
182 int parse_shapecode_prefix(char * token, int * id, char ** var_string);
184 int parse_wave(char * eqn_string, FILE * fs, preset_t * preset);
185 int parse_shape(char * eqn_string, FILE * fs, preset_t * preset);
186 int parse_shape_prefix(char * token, int * id, char ** eqn_string);
188 int update_string_buffer(char * buffer, int * index);
189 int string_to_float(char * string, double * float_ptr);
191 /* Grabs the next token from the file. The second argument points
194 token_t parseToken(FILE * fs, char * string) {
200 memset(string, 0, MAX_TOKEN_SIZE);
202 /* Loop until a delimiter is found, or the maximum string size is found */
203 for (i = 0; i < MAX_TOKEN_SIZE;i++) {
206 /* If the string line buffer is full, quit */
207 if (string_line_buffer_index == (STRING_LINE_SIZE - 1))
208 return tStringBufferFilled;
210 /* Otherwise add this character to the string line buffer */
211 string_line_buffer[string_line_buffer_index++] = c;
212 /* Now interpret the character */
223 /* check for line comment here */
224 if ((c = fgetc(fs)) == '/') {
228 line_mode = NORMAL_LINE_MODE;
232 line_mode = NORMAL_LINE_MODE;
239 /* Otherwise, just a regular division operator */
263 line_mode = NORMAL_LINE_MODE;
269 case ' ': /* space, skip the character */
274 line_mode = NORMAL_LINE_MODE;
284 /* String reached maximum length, return special token error */
285 return tStringTooLong;
289 /* Parse input in the form of "exp, exp, exp, ...)"
290 Returns a general expression list */
292 gen_expr_t ** parse_prefix_args(FILE * fs, int num_args, struct PRESET_T * preset) {
295 gen_expr_t ** expr_list; /* List of arguments to function */
296 gen_expr_t * gen_expr;
298 /* Malloc the expression list */
299 expr_list = (gen_expr_t**)malloc(sizeof(gen_expr_t*)*num_args);
302 if (expr_list == NULL)
308 while (i < num_args) {
309 //if (PARSE_DEBUG) printf("parse_prefix_args: parsing argument %d...\n", i+1);
310 /* Parse the ith expression in the list */
311 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
312 //if (PARSE_DEBUG) printf("parse_prefix_args: failed to get parameter # %d for function (LINE %d)\n", i+1, line_count);
313 for (j = 0; j < i; j++)
314 free_gen_expr(expr_list[j]);
318 /* Assign entry in expression list */
319 expr_list[i++] = gen_expr;
322 //if (PARSE_DEBUG) printf("parse_prefix_args: finished parsing %d arguments (LINE %d)\n", num_args, line_count);
323 /* Finally, return the resulting expression list */
328 /* Parses a comment at the top of the file. Stops when left bracket is found */
329 int parse_top_comment(FILE * fs) {
331 char string[MAX_TOKEN_SIZE];
334 /* Process tokens until left bracket is found */
335 while ((token = parseToken(fs, string)) != tLBr) {
340 /* Done, return success */
344 /* Right Bracket is parsed by this function.
345 puts a new string into name */
346 int parse_preset_name(FILE * fs, char * name) {
353 if ((token = parseToken(fs, name)) != tRBr)
356 //if (PARSE_DEBUG) printf("parse_preset_name: parsed preset (name = \"%s\")\n", name);
362 /* Parses per pixel equations */
363 int parse_per_pixel_eqn(FILE * fs, preset_t * preset) {
366 char string[MAX_TOKEN_SIZE];
367 gen_expr_t * gen_expr;
369 if (PARSE_DEBUG) printf("parse_per_pixel: per_pixel equation parsing start...(LINE %d)\n", line_count);
371 if (parseToken(fs, string) != tEq) { /* parse per pixel operator name */
372 if (PARSE_DEBUG) printf("parse_per_pixel: equal operator expected after per pixel operator \"%s\", but not found (LINE %d)\n",
377 /* Parse right side of equation as an expression */
378 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
379 if (PARSE_DEBUG) printf("parse_per_pixel: equation evaluated to null? (LINE %d)\n", line_count);
383 /* Add the per pixel equation */
384 if (add_per_pixel_eqn(string, gen_expr, preset) < 0) {
385 free_gen_expr(gen_expr);
392 /* Parses an equation line, this function is way too big, should add some helper functions */
393 int parse_line(FILE * fs, struct PRESET_T * preset) {
395 char eqn_string[MAX_TOKEN_SIZE];
397 init_cond_t * init_cond;
398 per_frame_eqn_t * per_frame_eqn;
400 /* Clear the string line buffer */
401 memset(string_line_buffer, 0, STRING_LINE_SIZE);
402 string_line_buffer_index = 0;
405 switch (token = parseToken(fs, eqn_string)) {
421 // if (PARSE_DEBUG) printf("parse_line: invalid token found at start of line (LINE %d)\n", line_count);
422 /* Invalid token found, return a parse error */
426 case tEOL: /* Empty line */
427 line_mode = NORMAL_LINE_MODE;
430 case tEOF: /* End of File */
431 line_mode = NORMAL_LINE_MODE;
435 case tSemiColon: /* Indicates end of expression */
438 /* Valid Case, either an initial condition or equation should follow */
441 /* CASE: PER FRAME INIT EQUATION */
442 if (!strncmp(eqn_string, PER_FRAME_INIT_STRING, PER_FRAME_INIT_STRING_LENGTH)) {
444 //if (PARSE_DEBUG) printf("parse_line: per frame init equation found...(LINE %d)\n", line_count);
446 /* Set the line mode to normal */
447 line_mode = NORMAL_LINE_MODE;
449 /* Parse the per frame equation */
450 if ((init_cond = parse_per_frame_init_eqn(fs, preset, NULL)) == NULL) {
451 //if (PARSE_DEBUG) printf("parse_line: per frame init equation parsing failed (LINE %d)\n", line_count);
455 /* Insert the equation in the per frame equation tree */
456 if (splay_insert(init_cond, init_cond->param->name, preset->per_frame_init_eqn_tree) < 0) {
457 //if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
458 free_init_cond(init_cond); /* will free the gen expr too */
463 if (update_string_buffer(preset->per_frame_init_eqn_string_buffer,
464 &preset->per_frame_init_eqn_string_index) < 0)
471 /* Per frame equation case */
472 if (!strncmp(eqn_string, PER_FRAME_STRING, PER_FRAME_STRING_LENGTH)) {
474 /* Sometimes per frame equations are implicitly defined without the
475 per_frame_ prefix. This informs the parser that one could follow */
476 line_mode = PER_FRAME_LINE_MODE;
478 //if (PARSE_DEBUG) printf("parse_line: per frame equation found...(LINE %d)\n", line_count);
480 /* Parse the per frame equation */
481 if ((per_frame_eqn = parse_per_frame_eqn(fs, ++per_frame_eqn_count, preset)) == NULL) {
482 if (PARSE_DEBUG) printf("parse_line: per frame equation parsing failed (LINE %d)\n", line_count);
486 /* Insert the equation in the per frame equation tree */
487 if (splay_insert(per_frame_eqn, &per_frame_eqn_count, preset->per_frame_eqn_tree) < 0) {
488 if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
489 free_per_frame_eqn(per_frame_eqn); /* will free the gen expr too */
493 if (update_string_buffer(preset->per_frame_eqn_string_buffer,
494 &preset->per_frame_eqn_string_index) < 0)
503 /* Wavecode initial condition case */
504 if (!strncmp(eqn_string, WAVECODE_STRING, WAVECODE_STRING_LENGTH)) {
506 line_mode = CUSTOM_WAVE_WAVECODE_LINE_MODE;
509 // printf("parse_line: wavecode prefix found: \"%s\"\n", eqn_string);
511 // printf("string:%d\n", 5);
513 //SUPER MYSTERIO-BUG - Don't Remove
516 return parse_wavecode(eqn_string, fs, preset);
519 /* Custom Wave Prefix */
520 if ((!strncmp(eqn_string, WAVE_STRING, WAVE_STRING_LENGTH)) &&
521 ((eqn_string[5] >= 48) && (eqn_string[5] <= 57))) {
523 // if (PARSE_DEBUG) printf("parse_line wave prefix found: \"%s\"\n", eqn_string);
525 return parse_wave(eqn_string, fs, preset);
530 /* Shapecode initial condition case */
531 if (!strncmp(eqn_string, SHAPECODE_STRING, SHAPECODE_STRING_LENGTH)) {
533 line_mode = CUSTOM_SHAPE_SHAPECODE_LINE_MODE;
535 if (PARSE_DEBUG) printf("parse_line: shapecode prefix found: \"%s\"\n", eqn_string);
537 return parse_shapecode(eqn_string, fs, preset);
540 /* Custom Shape Prefix */
541 if ((!strncmp(eqn_string, SHAPE_STRING, SHAPE_STRING_LENGTH)) &&
542 ((eqn_string[6] >= 48) && (eqn_string[6] <= 57))) {
544 if (PARSE_DEBUG) printf("parse_line shape prefix found: \"%s\"\n", eqn_string);
545 return parse_shape(eqn_string, fs, preset);
549 /* Per pixel equation case */
550 if (!strncmp(eqn_string, PER_PIXEL_STRING, PER_PIXEL_STRING_LENGTH)) {
551 line_mode = PER_PIXEL_LINE_MODE;
553 if (parse_per_pixel_eqn(fs, preset) < 0)
557 if (update_string_buffer(preset->per_pixel_eqn_string_buffer,
558 &preset->per_pixel_eqn_string_index) < 0)
561 if (PARSE_DEBUG) printf("parse_line: finished parsing per pixel equation (LINE %d)\n", line_count);
565 /* Sometimes equations are written implicitly in milkdrop files, in the form
567 per_frame_1 = p1 = eqn1; p2 = eqn2; p3 = eqn3;..;
569 which is analagous to:
571 per_frame_1 = p1 = eqn1; per_frame_2 = p2 = eqn2; per_frame_3 = p3 = eqn3; ...;
573 The following line mode hack allows such implicit declaration of the
574 prefix that specifies the equation type. An alternative method
575 may be to associate each equation line as list of equations separated
576 by semicolons (and a new line ends the list). Instead, however, a global
577 variable called "line_mode" specifies the last type of equation found,
578 and bases any implicitly typed input on this fact
580 Note added by Carmelo Piccione (cep@andrew.cmu.edu) 10/19/03
583 /* Per frame line mode previously, try to parse the equation implicitly */
584 if (line_mode == PER_FRAME_LINE_MODE) {
585 if ((per_frame_eqn = parse_implicit_per_frame_eqn(fs, eqn_string, ++per_frame_eqn_count, preset)) == NULL)
588 /* Insert the equation in the per frame equation tree */
589 if (splay_insert(per_frame_eqn, &per_frame_eqn_count, preset->per_frame_eqn_tree) < 0) {
590 if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
591 free_per_frame_eqn(per_frame_eqn); /* will free the gen expr too */
596 if (update_string_buffer(preset->per_frame_eqn_string_buffer,
597 &preset->per_frame_eqn_string_index) < 0)
605 //if (PARSE_DEBUG) printf("parse_line: found initial condition: name = \"%s\" (LINE %d)\n", eqn_string, line_count);
607 /* Evaluate the initial condition */
608 if ((init_cond = parse_init_cond(fs, eqn_string, preset)) == NULL) {
609 if (PARSE_DEBUG) printf("parse_line: failed to parse initial condition (LINE %d)\n", line_count);
613 /* Add equation to initial condition tree */
614 if (splay_insert(init_cond, init_cond->param->name, preset->init_cond_tree) < 0) {
615 if (PARSE_DEBUG) printf("parse_line: failed to add initial condition \"%s\" to equation tree (LINE %d)\n",
616 init_cond->param->name, line_count);
617 free_init_cond(init_cond);
621 /* Finished with initial condition line */
622 // if (PARSE_DEBUG) printf("parse_line: initial condition parsed successfully\n");
626 /* END INITIAL CONDITIONING PARSING */
629 default: /* an uncaught type or an error has occurred */
630 if (PARSE_DEBUG) printf("parse_line: uncaught case, token val = %d\n", token);
634 /* Because of the default in the case statement,
635 control flow should never actually reach here */
641 /* Parses a general expression, this function is the meat of the parser */
642 gen_expr_t * parse_gen_expr (FILE * fs, tree_expr_t * tree_expr, struct PRESET_T * preset) {
645 char string[MAX_TOKEN_SIZE];
647 gen_expr_t * gen_expr;
649 param_t * param = NULL;
651 gen_expr_t ** expr_list;
653 switch (token = parseToken(fs,string)) {
654 /* Left Parentice Case */
657 /* CASE 1 (Left Parentice): See if the previous string before this parentice is a function name */
658 if ((func = find_func(string)) != NULL) {
659 if (PARSE_DEBUG) printf("parse_gen_expr: found prefix function (name = %s) (LINE %d)\n", func->name, line_count);
661 /* Parse the functions arguments */
662 if ((expr_list = parse_prefix_args(fs, func->num_args, preset)) == NULL) {
663 if (PARSE_DEBUG) printf("parse_prefix_args: failed to generate an expresion list! (LINE %d) \n", line_count);
664 free_tree_expr(tree_expr);
668 /* Convert function to expression */
669 if ((gen_expr = prefun_to_expr((void*)func->func_ptr, expr_list, func->num_args)) == NULL) {
670 if (PARSE_DEBUG) printf("parse_prefix_args: failed to convert prefix function to general expression (LINE %d) \n",
672 free_tree_expr(tree_expr);
673 for (i = 0; i < func->num_args;i++)
674 free_gen_expr(expr_list[i]);
681 token = parseToken(fs, string);
684 if (PARSE_DEBUG) printf("parse_prefix_args: empty string expected, but not found...(LINE %d)\n", line_count);
685 /* continue anyway for now, could be implicit multiplication */
688 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
692 /* Case 2: (Left Parentice), a string coupled with a left parentice. Either an error or implicit
693 multiplication operator. For now treat it as an error */
695 if (PARSE_DEBUG) printf("parse_gen_expr: implicit multiplication case unimplemented!\n");
696 free_tree_expr(tree_expr);
700 /* CASE 3 (Left Parentice): the following is enclosed parentices to change order
701 of operations. So we create a new expression tree */
703 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
704 //if (PARSE_DEBUG) printf("parse_gen_expr: found left parentice, but failed to create new expression tree \n");
705 free_tree_expr(tree_expr);
709 if (PARSE_DEBUG) printf("parse_gen_expr: finished enclosed expression tree...\n");
710 token = parseToken(fs, string);
711 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
713 /* Plus is a prefix operator check */
717 //if (PARSE_DEBUG) printf("parse_gen_expr: plus used as prefix (LINE %d)\n", line_count);
719 /* Treat prefix plus as implict 0 preceding operator */
720 gen_expr = const_to_expr(0);
722 return parse_infix_op(fs, tPositive, insert_gen_expr(gen_expr, &tree_expr), preset);
725 /* Minus is a prefix operator check */
729 /* Use the negative infix operator, but first add an implicit zero to the operator tree */
730 gen_expr = const_to_expr(0);
731 //return parse_gen_expr(fs, insert_gen_expr(gen_expr, &tree_expr), preset);
732 return parse_infix_op(fs, tNegative, insert_gen_expr(gen_expr, &tree_expr), preset);
735 /* All the following cases are strings followed by an infix operator or terminal */
742 /* CASE 1 (terminal): string is empty, but not null. Not sure if this will actually happen
745 //if (PARSE_DEBUG) printf("parse_gen_expr: empty string coupled with terminal (LINE %d) \n", line_count);
746 return parse_infix_op(fs, token, tree_expr, preset);
752 /* CASE 0: Empty string, parse error */
754 if (PARSE_DEBUG) printf("parse_gen_expr: empty string coupled with infix op (ERROR!) (LINE %d) \n", line_count);
755 free_tree_expr(tree_expr);
759 /* CASE 1: Check if string is a just a floating point number */
760 if (string_to_float(string, &val) != PARSE_ERROR) {
761 if ((gen_expr = const_to_expr(val)) == NULL) {
762 free_tree_expr(tree_expr);
766 /* Parse the rest of the line */
767 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
772 /* CASE 4: custom shape variable */
773 if (current_shape != NULL) {
774 if ((param = find_param_db(string, current_shape->param_tree, FALSE)) == NULL) {
775 if ((param = find_builtin_param(string)) == NULL)
776 if ((param = find_param_db(string, current_shape->param_tree, TRUE)) == NULL) {
777 free_tree_expr(tree_expr);
783 printf("parse_gen_expr: custom shape parameter (name = %s)... ", param->name);
787 /* Convert parameter to an expression */
788 if ((gen_expr = param_to_expr(param)) == NULL) {
789 free_tree_expr(tree_expr);
793 //if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
795 /* Parse the rest of the line */
796 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
799 /* CASE 5: custom wave variable */
800 if (current_wave != NULL) {
801 if ((param = find_param_db(string, current_wave->param_tree, FALSE)) == NULL) {
802 if ((param = find_builtin_param(string)) == NULL)
803 if ((param = find_param_db(string, current_wave->param_tree, TRUE)) == NULL) {
804 free_tree_expr(tree_expr);
811 printf("parse_gen_expr: custom wave parameter (name = %s)... ", param->name);
815 /* Convert parameter to an expression */
816 if ((gen_expr = param_to_expr(param)) == NULL) {
817 free_tree_expr(tree_expr);
821 if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
823 /* Parse the rest of the line */
824 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
828 /* CASE 6: regular parameter. Will be created if necessary and the string has no invalid characters */
829 if ((param = find_param(string, preset, P_CREATE)) != NULL) {
832 printf("parse_gen_expr: parameter (name = %s)... ", param->name);
836 /* Convert parameter to an expression */
837 if ((gen_expr = param_to_expr(param)) == NULL) {
838 free_tree_expr(tree_expr);
842 if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
844 /* Parse the rest of the line */
845 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
849 /* CASE 7: Bad string, give up */
850 if (PARSE_DEBUG) printf("parse_gen_expr: syntax error [string = \"%s\"] (LINE %d)\n", string, line_count);
851 free_tree_expr(tree_expr);
858 /* Inserts expressions into tree according to operator precedence.
859 If root is null, a new tree is created, with gen_expr as only element */
861 tree_expr_t * insert_infix_op(infix_op_t * infix_op, tree_expr_t **root) {
863 tree_expr_t * new_root;
866 if (infix_op == NULL)
869 /* The root is null, so make this operator
873 new_root = new_tree_expr(infix_op, NULL, NULL, NULL);
878 /* The root node is not an infix function,
879 so we make this infix operator the new root */
881 if ((*root)->infix_op == NULL) {
882 new_root = new_tree_expr(infix_op, NULL, *root, NULL);
887 /* The root is an infix function. If the precedence
888 of the item to be inserted is greater than the root's
889 precedence, then make gen_expr the root */
891 if (infix_op->precedence > (*root)->infix_op->precedence) {
892 new_root = new_tree_expr(infix_op, NULL, *root, NULL);
897 /* If control flow reaches here, use a recursive helper
898 with the knowledge that the root is higher precedence
899 than the item to be inserted */
901 insert_infix_rec(infix_op, *root);
907 tree_expr_t * insert_gen_expr(gen_expr_t * gen_expr, tree_expr_t ** root) {
909 tree_expr_t * new_root;
911 /* If someone foolishly passes a null
912 pointer to insert, return the original tree */
914 if (gen_expr == NULL) {
918 /* If the root is null, generate a new expression tree,
919 using the passed expression as the root element */
922 new_root = new_tree_expr(NULL, gen_expr, NULL, NULL);
928 /* Otherwise. the new element definitely will not replace the current root.
929 Use a recursive helper function to do insertion */
931 insert_gen_rec(gen_expr, *root);
935 /* A recursive helper function to insert general expression elements into the operator tree */
936 int insert_gen_rec(gen_expr_t * gen_expr, tree_expr_t * root) {
938 /* Trivial Case: root is null */
941 ////if (PARSE_DEBUG) printf("insert_gen_rec: root is null, returning failure\n");
946 /* The current node's left pointer is null, and this
947 current node is an infix operator, so insert the
948 general expression at the left pointer */
950 if ((root->left == NULL) && (root->infix_op != NULL)) {
951 root->left = new_tree_expr(NULL, gen_expr, NULL, NULL);
955 /* The current node's right pointer is null, and this
956 current node is an infix operator, so insert the
957 general expression at the right pointer */
959 if ((root->right == NULL) && (root->infix_op != NULL)) {
960 root->right = new_tree_expr(NULL, gen_expr, NULL, NULL);
964 /* Otherwise recurse down to the left. If
965 this succeeds then return. If it fails, try
966 recursing down to the right */
968 if (insert_gen_rec(gen_expr, root->left) == FAILURE)
969 return insert_gen_rec(gen_expr, root->right);
971 /* Impossible for control flow to reach here, but in
972 the world of C programming, who knows... */
973 //if (PARSE_DEBUG) printf("insert_gen_rec: should never reach here!\n");
978 /* A recursive helper function to insert infix arguments by operator precedence */
979 int insert_infix_rec(infix_op_t * infix_op, tree_expr_t * root) {
981 /* Shouldn't happen, implies a parse error */
986 /* Also shouldn't happen, also implies a (different) parse error */
988 if (root->infix_op == NULL)
991 /* Left tree is empty, attach this operator to it.
992 I don't think this will ever happen */
993 if (root->left == NULL) {
994 root->left = new_tree_expr(infix_op, NULL, root->left, NULL);
998 /* Right tree is empty, attach this operator to it */
999 if (root->right == NULL) {
1000 root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
1004 /* The left element can now be ignored, since there is no way for this
1005 operator to use those expressions */
1007 /* If the right element is not an infix operator,
1008 then insert the expression here, attaching the old right branch
1009 to the left of the new expression */
1011 if (root->right->infix_op == NULL) {
1012 root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
1016 /* Traverse deeper if the inserting operator precedence is less than the
1017 the root's right operator precedence */
1018 if (infix_op->precedence < root->right->infix_op->precedence)
1019 return insert_infix_rec(infix_op, root->right);
1021 /* Otherwise, insert the operator here */
1023 root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
1028 /* Parses an infix operator */
1029 gen_expr_t * parse_infix_op(FILE * fs, token_t token, tree_expr_t * tree_expr, struct PRESET_T * preset) {
1031 gen_expr_t * gen_expr;
1034 /* All the infix operators */
1036 //if (PARSE_DEBUG) printf("parse_infix_op: found addition operator (LINE %d)\n", line_count);
1037 return parse_gen_expr(fs, insert_infix_op(infix_add, &tree_expr), preset);
1039 //if (PARSE_DEBUG) printf("parse_infix_op: found subtraction operator (LINE %d)\n", line_count);
1040 return parse_gen_expr(fs, insert_infix_op(infix_minus, &tree_expr), preset);
1042 //if (PARSE_DEBUG) printf("parse_infix_op: found multiplication operator (LINE %d)\n", line_count);
1043 return parse_gen_expr(fs, insert_infix_op(infix_mult, &tree_expr), preset);
1045 //if (PARSE_DEBUG) printf("parse_infix_op: found division operator (LINE %d)\n", line_count);
1046 return parse_gen_expr(fs, insert_infix_op(infix_div, &tree_expr), preset);
1048 //if (PARSE_DEBUG) printf("parse_infix_op: found modulo operator (LINE %d)\n", line_count);
1049 return parse_gen_expr(fs, insert_infix_op(infix_mod, &tree_expr), preset);
1051 //if (PARSE_DEBUG) printf("parse_infix_op: found bitwise or operator (LINE %d)\n", line_count);
1052 return parse_gen_expr(fs, insert_infix_op(infix_or, &tree_expr), preset);
1054 //if (PARSE_DEBUG) printf("parse_infix_op: found bitwise and operator (LINE %d)\n", line_count);
1055 return parse_gen_expr(fs, insert_infix_op(infix_and, &tree_expr), preset);
1057 //if (PARSE_DEBUG) printf("parse_infix_op: found positive operator (LINE %d)\n", line_count);
1058 return parse_gen_expr(fs, insert_infix_op(infix_positive, &tree_expr), preset);
1060 //if (PARSE_DEBUG) printf("parse_infix_op: found negative operator (LINE %d)\n", line_count);
1061 return parse_gen_expr(fs, insert_infix_op(infix_negative, &tree_expr), preset);
1068 //if (PARSE_DEBUG) printf("parse_infix_op: terminal found (LINE %d)\n", line_count);
1069 gen_expr = new_gen_expr(TREE_T, (void*)tree_expr);
1072 //if (PARSE_DEBUG) printf("parse_infix_op: operator or terminal expected, but not found (LINE %d)\n", line_count);
1073 free_tree_expr(tree_expr);
1077 /* Will never happen */
1082 /* Parses an integer, checks for +/- prefix */
1083 int parse_int(FILE * fs, int * int_ptr) {
1085 char string[MAX_TOKEN_SIZE];
1088 char * end_ptr = " ";
1090 token = parseToken(fs, string);
1096 token = parseToken(fs, string);
1100 token = parseToken(fs, string);
1111 /* Convert the string to an integer. *end_ptr
1112 should end up pointing to null terminator of 'string'
1113 if the conversion was successful. */
1114 // printf("STRING: \"%s\"\n", string);
1116 (*int_ptr) = sign*strtol(string, &end_ptr, 10);
1118 /* If end pointer is a return character or null terminator, all is well */
1119 if ((*end_ptr == '\r') || (*end_ptr == '\0'))
1125 /* Parses a floating point number */
1126 int string_to_float(char * string, double * float_ptr) {
1133 error_ptr = malloc(sizeof(char**));
1135 (*float_ptr) = strtod(string, error_ptr);
1137 /* These imply a succesful parse of the string */
1138 if ((**error_ptr == '\0') || (**error_ptr == '\r')) {
1148 /* Parses a floating point number */
1149 int parse_float(FILE * fs, double * float_ptr) {
1151 char string[MAX_TOKEN_SIZE];
1156 error_ptr = malloc(sizeof(char**));
1158 token = parseToken(fs, string);
1163 token = parseToken(fs, string);
1167 token = parseToken(fs, string);
1173 if (string[0] == 0) {
1178 (*float_ptr) = sign*strtod(string, error_ptr);
1180 /* No conversion was performed */
1181 if ((**error_ptr == '\0') || (**error_ptr == '\r')) {
1186 //if (PARSE_DEBUG) printf("parse_float: double conversion failed for string \"%s\"\n", string);
1196 /* Parses a per frame equation. That is, interprets a stream of data as a per frame equation */
1197 per_frame_eqn_t * parse_per_frame_eqn(FILE * fs, int index, struct PRESET_T * preset) {
1199 char string[MAX_TOKEN_SIZE];
1201 per_frame_eqn_t * per_frame_eqn;
1202 gen_expr_t * gen_expr;
1204 if (parseToken(fs, string) != tEq) {
1205 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
1209 /* Find the parameter associated with the string, create one if necessary */
1210 if ((param = find_param(string, preset, P_CREATE)) == NULL) {
1214 /* Make sure parameter is writable */
1215 if (param->flags & P_FLAG_READONLY) {
1216 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1220 /* Parse right side of equation as an expression */
1221 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1222 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: equation evaluated to null (LINE %d)\n", line_count);
1226 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: finished per frame equation evaluation (LINE %d)\n", line_count);
1228 /* Create a new per frame equation */
1229 if ((per_frame_eqn = new_per_frame_eqn(index, param, gen_expr)) == NULL) {
1230 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: failed to create a new per frame eqn, out of memory?\n");
1231 free_gen_expr(gen_expr);
1235 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: per_frame eqn parsed succesfully\n");
1237 return per_frame_eqn;
1240 /* Parses an 'implicit' per frame equation. That is, interprets a stream of data as a per frame equation without a prefix */
1241 per_frame_eqn_t * parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, struct PRESET_T * preset) {
1244 per_frame_eqn_t * per_frame_eqn;
1245 gen_expr_t * gen_expr;
1249 if (param_string == NULL)
1254 //rintf("param string: %s\n", param_string);
1255 /* Find the parameter associated with the string, create one if necessary */
1256 if ((param = find_param(param_string, preset, P_CREATE)) == NULL) {
1260 //printf("parse_implicit_per_frame_eqn: param is %s\n", param->name);
1262 /* Make sure parameter is writable */
1263 if (param->flags & P_FLAG_READONLY) {
1264 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1268 /* Parse right side of equation as an expression */
1269 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1270 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: equation evaluated to null (LINE %d)\n", line_count);
1274 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: finished per frame equation evaluation (LINE %d)\n", line_count);
1276 /* Create a new per frame equation */
1277 if ((per_frame_eqn = new_per_frame_eqn(index, param, gen_expr)) == NULL) {
1278 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: failed to create a new per frame eqn, out of memory?\n");
1279 free_gen_expr(gen_expr);
1283 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: per_frame eqn parsed succesfully\n");
1285 return per_frame_eqn;
1288 /* Parses an initial condition */
1289 init_cond_t * parse_init_cond(FILE * fs, char * name, struct PRESET_T * preset) {
1293 init_cond_t * init_cond;
1300 /* Search for the paramater in the database, creating it if necessary */
1301 if ((param = find_param(name, preset, P_CREATE)) == NULL) {
1305 //if (PARSE_DEBUG) printf("parse_init_cond: parameter = \"%s\" (LINE %d)\n", param->name, line_count);
1307 if (param->flags & P_FLAG_READONLY) {
1308 //if (PARSE_DEBUG) printf("parse_init_cond: builtin parameter \"%s\" marked as read only!\n", param->name);
1312 /* At this point, a parameter has been created or was found
1315 //if (PARSE_DEBUG) printf("parse_init_cond: parsing initial condition value... (LINE %d)\n", line_count);
1317 /* integer value (boolean is an integer in C) */
1318 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1319 if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {
1320 //if (PARSE_DEBUG) printf("parse_init_cond: error parsing integer!\n");
1326 else if (param->type == P_TYPE_DOUBLE) {
1327 if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
1328 //if (PARSE_DEBUG) printf("parse_init_cond: error parsing double!\n");
1335 //if (PARSE_DEBUG) printf("parse_init_cond: unknown parameter type!\n");
1339 /* Create new initial condition */
1340 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1341 //if (PARSE_DEBUG) printf("parse_init_cond: new_init_cond failed!\n");
1349 /* Parses a per frame init equation, not sure if this works right now */
1350 init_cond_t * parse_per_frame_init_eqn(FILE * fs, struct PRESET_T * preset, splaytree_t * database) {
1352 char name[MAX_TOKEN_SIZE];
1353 param_t * param = NULL;
1355 init_cond_t * init_cond;
1356 gen_expr_t * gen_expr;
1366 if ((token = parseToken(fs, name)) != tEq)
1370 /* If a database was specified,then use find_param_db instead */
1371 if ((database != NULL) && ((param = find_param_db(name, database, TRUE)) == NULL)) {
1375 /* Otherwise use the builtin parameter and user databases. This is confusing. Sorry. */
1376 if ((param == NULL) && ((param = find_param(name, preset, P_CREATE)) == NULL)) {
1380 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: parameter = \"%s\" (LINE %d)\n", param->name, line_count);
1382 if (param->flags & P_FLAG_READONLY) {
1383 //if (PARSE_DEBUG) printf("pars_per_frame_init_eqn: builtin parameter \"%s\" marked as read only!\n", param->name);
1387 /* At this point, a parameter has been created or was found
1390 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: parsing right hand side of per frame init equation.. (LINE %d)\n", line_count);
1392 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1393 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: failed to parse general expresion!\n");
1397 /* Compute initial condition value */
1398 val = eval_gen_expr(gen_expr);
1400 /* Free the general expression now that we are done with it */
1401 free_gen_expr(gen_expr);
1403 /* integer value (boolean is an integer in C) */
1404 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1405 init_val.int_val = (int)val;
1409 else if (param->type == P_TYPE_DOUBLE) {
1410 init_val.double_val = val;
1415 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: unknown parameter type!\n");
1420 /* Create new initial condition */
1421 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1422 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: new_init_cond failed!\n");
1431 int parse_wavecode(char * token, FILE * fs, preset_t * preset) {
1434 init_cond_t * init_cond;
1435 custom_wave_t * custom_wave;
1440 /* Null argument checks */
1448 /* token should be in the form wavecode_N_var, such as wavecode_1_samples */
1450 /* Get id and variable name from token string */
1451 if (parse_wavecode_prefix(token, &id, &var_string) < 0)
1454 //if (PARSE_DEBUG) printf("parse_wavecode: wavecode id = %d, parameter = \"%s\"\n", id, var_string);
1456 /* Retrieve custom wave information from preset. The 3rd argument
1457 if true creates a custom wave if one does not exist */
1458 if ((custom_wave = find_custom_wave(id, preset, TRUE)) == NULL) {
1459 //if (PARSE_DEBUG) printf("parse_wavecode: failed to load (or create) custom wave (id = %d)!\n", id);
1462 //if (PARSE_DEBUG) printf("parse_wavecode: custom wave found (id = %d)\n", custom_wave->id);
1464 /* Retrieve parameter from this custom waves parameter db */
1465 if ((param = find_param_db(var_string, custom_wave->param_tree, TRUE)) == NULL)
1468 //if (PARSE_DEBUG) printf("parse_wavecode: custom wave parameter found (name = %s)\n", param->name);
1470 /* integer value (boolean is an integer in C) */
1471 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1472 if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {
1473 //if (PARSE_DEBUG) printf("parse_wavecode: error parsing integer!\n");
1479 else if (param->type == P_TYPE_DOUBLE) {
1480 if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
1481 //if (PARSE_DEBUG) printf("parse_wavecode: error parsing double!\n");
1488 //if (PARSE_DEBUG) printf("parse_wavecode: unknown parameter type!\n");
1492 /* Create new initial condition */
1493 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1494 //if (PARSE_DEBUG) printf("parse_wavecode: new_init_cond failed!\n");
1498 if (splay_insert(init_cond, param->name, custom_wave->init_cond_tree) < 0) {
1499 free_init_cond(init_cond);
1503 //if (PARSE_DEBUG) printf("parse_wavecode: [success]\n");
1507 int parse_shapecode(char * token, FILE * fs, preset_t * preset) {
1510 init_cond_t * init_cond;
1511 custom_shape_t * custom_shape;
1516 /* Null argument checks */
1524 /* token should be in the form shapecode_N_var, such as shapecode_1_samples */
1526 /* Get id and variable name from token string */
1527 if (parse_shapecode_prefix(token, &id, &var_string) < 0)
1530 //if (PARSE_DEBUG) printf("parse_shapecode: shapecode id = %d, parameter = \"%s\"\n", id, var_string);
1532 /* Retrieve custom shape information from preset. The 3rd argument
1533 if true creates a custom shape if one does not exist */
1534 if ((custom_shape = find_custom_shape(id, preset, TRUE)) == NULL) {
1535 //if (PARSE_DEBUG) printf("parse_shapecode: failed to load (or create) custom shape (id = %d)!\n", id);
1538 //if (PARSE_DEBUG) printf("parse_shapecode: custom shape found (id = %d)\n", custom_shape->id);
1540 /* Retrieve parameter from this custom shapes parameter db */
1541 if ((param = find_param_db(var_string, custom_shape->param_tree, TRUE)) == NULL) {
1542 //if (PARSE_DEBUG) printf("parse_shapecode: failed to create parameter.\n");
1545 //if (PARSE_DEBUG) printf("parse_shapecode: custom shape parameter found (name = %s)\n", param->name);
1547 /* integer value (boolean is an integer in C) */
1548 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1549 if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {
1550 //if (PARSE_DEBUG) printf("parse_shapecode: error parsing integer!\n");
1556 else if (param->type == P_TYPE_DOUBLE) {
1557 if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
1558 //if (PARSE_DEBUG) printf("parse_shapecode: error parsing double!\n");
1565 //if (PARSE_DEBUG) printf("parse_shapecode: unknown parameter type!\n");
1569 /* Create new initial condition */
1570 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1571 //if (PARSE_DEBUG) printf("parse_shapecode: new_init_cond failed!\n");
1575 if (splay_insert(init_cond, param->name, custom_shape->init_cond_tree) < 0) {
1576 free_init_cond(init_cond);
1577 //if (PARSE_DEBUG) printf("parse_shapecode: initial condition already set, not reinserting it (param = \"%s\")\n", param->name);
1581 //if (PARSE_DEBUG) printf("parse_shapecode: [success]\n");
1586 int parse_wavecode_prefix(char * token, int * id, char ** var_string) {
1592 if (*var_string == NULL)
1597 len = strlen(token);
1599 /* Move pointer passed "wavecode_" prefix */
1600 if (len <= WAVECODE_STRING_LENGTH)
1602 i = WAVECODE_STRING_LENGTH;
1606 /* This loop grabs the integer id for this custom wave */
1607 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1608 if (j >= MAX_TOKEN_SIZE)
1611 (*id) = 10*(*id) + (token[i]-48);
1620 *var_string = token + i + 1;
1627 int parse_shapecode_prefix(char * token, int * id, char ** var_string) {
1633 if (*var_string == NULL)
1638 len = strlen(token);
1640 /* Move pointer passed "shapecode_" prefix */
1641 if (len <= SHAPECODE_STRING_LENGTH)
1643 i = SHAPECODE_STRING_LENGTH;
1647 /* This loop grabs the integer id for this custom shape */
1648 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1649 if (j >= MAX_TOKEN_SIZE)
1652 (*id) = 10*(*id) + (token[i]-48);
1661 *var_string = token + i + 1;
1667 int parse_wave_prefix(char * token, int * id, char ** eqn_string) {
1673 if (eqn_string == NULL)
1678 len = strlen(token);
1680 if (len <= WAVE_STRING_LENGTH)
1684 i = WAVE_STRING_LENGTH;
1688 /* This loop grabs the integer id for this custom wave */
1689 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1690 if (j >= MAX_TOKEN_SIZE)
1693 (*id) = 10*(*id) + (token[i]-48);
1701 *eqn_string = token + i + 1;
1707 int parse_shape_prefix(char * token, int * id, char ** eqn_string) {
1713 if (eqn_string == NULL)
1718 len = strlen(token);
1720 if (len <= SHAPE_STRING_LENGTH)
1724 i = SHAPE_STRING_LENGTH;
1728 /* This loop grabs the integer id for this custom wave */
1729 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1730 if (j >= MAX_TOKEN_SIZE)
1733 (*id) = 10*(*id) + (token[i]-48);
1741 *eqn_string = token + i + 1;
1747 /* Parses custom wave equations */
1748 int parse_wave(char * token, FILE * fs, preset_t * preset) {
1752 char string[MAX_TOKEN_SIZE];
1754 per_frame_eqn_t * per_frame_eqn;
1755 gen_expr_t * gen_expr;
1756 custom_wave_t * custom_wave;
1757 init_cond_t * init_cond;
1766 /* Grab custom wave id and equation type (per frame or per point) from string token */
1767 if (parse_wave_prefix(token, &id, &eqn_type) < 0) {
1768 //if (PARSE_DEBUG) printf("parse_wave: syntax error in custom wave prefix!\n");
1771 /* Retrieve custom wave associated with this id */
1772 if ((custom_wave = find_custom_wave(id, preset, TRUE)) == NULL)
1776 /* per frame init equation case */
1777 if (!strncmp(eqn_type, WAVE_INIT_STRING, WAVE_INIT_STRING_LENGTH)) {
1779 //if (PARSE_DEBUG) printf("parse_wave (per frame init): [begin] (LINE %d)\n", line_count);
1781 /* Parse the per frame equation */
1782 if ((init_cond = parse_per_frame_init_eqn(fs, preset, custom_wave->param_tree)) == NULL) {
1783 //if (PARSE_DEBUG) printf("parse_wave (per frame init): equation parsing failed (LINE %d)\n", line_count);
1787 /* Insert the equation in the per frame equation tree */
1788 if (splay_insert(init_cond, init_cond->param->name, custom_wave->per_frame_init_eqn_tree) < 0) {
1789 //if (PARSE_DEBUG) printf("parse_wave (per frame init): failed to add equation (ERROR)\n");
1790 free_init_cond(init_cond); /* will free the gen expr too */
1794 if (update_string_buffer(custom_wave->per_frame_init_eqn_string_buffer,
1795 &custom_wave->per_frame_init_eqn_string_index) < 0)
1802 /* per frame equation case */
1803 if (!strncmp(eqn_type, PER_FRAME_STRING_NO_UNDERSCORE, PER_FRAME_STRING_NO_UNDERSCORE_LENGTH)) {
1805 //if (PARSE_DEBUG) printf("parse_wave (per_frame): [start] (custom wave id = %d)\n", custom_wave->id);
1807 if (parseToken(fs, string) != tEq) {
1808 //if (PARSE_DEBUG) printf("parse_wave (per_frame): no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
1812 /* Find the parameter associated with the string in the custom wave database */
1813 if ((param = find_param_db(string, custom_wave->param_tree, TRUE)) == NULL) {
1814 //if (PARSE_DEBUG) printf("parse_wave (per_frame): parameter \"%s\" not found or cannot be malloc'ed!!\n", string);
1819 /* Make sure parameter is writable */
1820 if (param->flags & P_FLAG_READONLY) {
1821 //if (PARSE_DEBUG) printf("parse_wave (per_frame): parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1825 /* Parse right side of equation as an expression */
1827 current_wave = custom_wave;
1828 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1829 //if (PARSE_DEBUG) printf("parse_wave (per_frame): equation evaluated to null (LINE %d)\n", line_count);
1830 current_wave = NULL;
1834 current_wave = NULL;
1836 //if (PARSE_DEBUG) printf("parse_wave (per_frame): [finished parsing equation] (LINE %d)\n", line_count);
1838 /* Create a new per frame equation */
1839 if ((per_frame_eqn = new_per_frame_eqn(custom_wave->per_frame_count++, param, gen_expr)) == NULL) {
1840 //if (PARSE_DEBUG) printf("parse_wave (per_frame): failed to create a new per frame eqn, out of memory?\n");
1841 free_gen_expr(gen_expr);
1845 if (splay_insert(per_frame_eqn, &per_frame_eqn->index, custom_wave->per_frame_eqn_tree) < 0) {
1846 free_per_frame_eqn(per_frame_eqn);
1850 //if (PARSE_DEBUG) printf("parse_wave (per_frame): equation %d associated with custom wave %d [success]\n",
1851 // per_frame_eqn->index, custom_wave->id);
1854 /* Need to add stuff to string buffer so the editor can read the equations.
1855 Why not make a nice little helper function for this? - here it is: */
1858 if (update_string_buffer(custom_wave->per_frame_eqn_string_buffer, &custom_wave->per_frame_eqn_string_index) < 0)
1866 /* per point equation case */
1867 if (!strncmp(eqn_type, PER_POINT_STRING, PER_POINT_STRING_LENGTH)) {
1869 //if (PARSE_DEBUG) printf("parse_wave (per_point): per_pixel equation parsing start...(LINE %d)\n", line_count);
1871 if (parseToken(fs, string) != tEq) { /* parse per pixel operator name */
1872 //if (PARSE_DEBUG) printf("parse_wave (per_point): equal operator missing after per pixel operator! (LINE %d)\n", line_count);
1876 /* Parse right side of equation as an expression */
1877 current_wave = custom_wave;
1878 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1879 //if (PARSE_DEBUG) printf("parse_wave (per_point): equation evaluated to null? (LINE %d)\n", line_count);
1882 current_wave = NULL;
1884 /* Add the per point equation */
1885 if (add_per_point_eqn(string, gen_expr, custom_wave) < 0) {
1886 free_gen_expr(gen_expr);
1891 if (update_string_buffer(custom_wave->per_point_eqn_string_buffer, &custom_wave->per_point_eqn_string_index) < 0)
1894 //if (PARSE_DEBUG) printf("parse_wave (per_point): [finished] (custom wave id = %d)\n", custom_wave->id);
1899 /* Syntax error, return parse error */
1905 /* Parses custom shape equations */
1906 int parse_shape(char * token, FILE * fs, preset_t * preset) {
1910 char string[MAX_TOKEN_SIZE];
1912 per_frame_eqn_t * per_frame_eqn;
1913 gen_expr_t * gen_expr;
1914 custom_shape_t * custom_shape;
1915 init_cond_t * init_cond;
1925 /* Grab custom shape id and equation type (per frame or per point) from string token */
1926 if (parse_shape_prefix(token, &id, &eqn_type) < 0) {
1927 //if (PARSE_DEBUG) printf("parse_shape: syntax error in custom shape prefix!\n");
1930 /* Retrieve custom shape associated with this id */
1931 if ((custom_shape = find_custom_shape(id, preset, TRUE)) == NULL)
1935 /* per frame init equation case */
1936 if (!strncmp(eqn_type, SHAPE_INIT_STRING, SHAPE_INIT_STRING_LENGTH)) {
1938 //if (PARSE_DEBUG) printf("parse_shape (per frame init): [begin] (LINE %d)\n", line_count);
1940 /* Parse the per frame equation */
1941 if ((init_cond = parse_per_frame_init_eqn(fs, preset, custom_shape->param_tree)) == NULL) {
1942 //if (PARSE_DEBUG) printf("parse_shape (per frame init): equation parsing failed (LINE %d)\n", line_count);
1946 /* Insert the equation in the per frame equation tree */
1947 if (splay_insert(init_cond, init_cond->param->name, custom_shape->per_frame_init_eqn_tree) < 0) {
1948 //if (PARSE_DEBUG) printf("parse_shape (per frame init): failed to add equation (ERROR)\n");
1949 free_init_cond(init_cond); /* will free the gen expr too */
1953 if (update_string_buffer(custom_shape->per_frame_init_eqn_string_buffer,
1954 &custom_shape->per_frame_init_eqn_string_index) < 0)
1961 /* per frame equation case */
1962 if (!strncmp(eqn_type, PER_FRAME_STRING_NO_UNDERSCORE, PER_FRAME_STRING_NO_UNDERSCORE_LENGTH)) {
1964 //if (PARSE_DEBUG) printf("parse_shape (per_frame): [start] (custom shape id = %d)\n", custom_shape->id);
1966 if (parseToken(fs, string) != tEq) {
1967 //if (PARSE_DEBUG) printf("parse_shape (per_frame): no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
1971 /* Find the parameter associated with the string in the custom shape database */
1972 if ((param = find_param_db(string, custom_shape->param_tree, TRUE)) == NULL) {
1973 //if (PARSE_DEBUG) printf("parse_shape (per_frame): parameter \"%s\" not found or cannot be malloc'ed!!\n", string);
1978 /* Make sure parameter is writable */
1979 if (param->flags & P_FLAG_READONLY) {
1980 //if (PARSE_DEBUG) printf("parse_shape (per_frame): parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1984 /* Parse right side of equation as an expression */
1986 current_shape = custom_shape;
1987 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1988 //if (PARSE_DEBUG) printf("parse_shape (per_frame): equation evaluated to null (LINE %d)\n", line_count);
1989 current_shape = NULL;
1993 current_shape = NULL;
1995 //if (PARSE_DEBUG) printf("parse_shape (per_frame): [finished parsing equation] (LINE %d)\n", line_count);
1997 /* Create a new per frame equation */
1998 if ((per_frame_eqn = new_per_frame_eqn(custom_shape->per_frame_count++, param, gen_expr)) == NULL) {
1999 //if (PARSE_DEBUG) printf("parse_shape (per_frame): failed to create a new per frame eqn, out of memory?\n");
2000 free_gen_expr(gen_expr);
2004 if (splay_insert(per_frame_eqn, &per_frame_eqn->index, custom_shape->per_frame_eqn_tree) < 0) {
2005 free_per_frame_eqn(per_frame_eqn);
2009 //if (PARSE_DEBUG) printf("parse_shape (per_frame): equation %d associated with custom shape %d [success]\n",
2010 // per_frame_eqn->index, custom_shape->id);
2013 /* Need to add stuff to string buffer so the editor can read the equations.
2014 Why not make a nice little helper function for this? - here it is: */
2016 if (update_string_buffer(custom_shape->per_frame_eqn_string_buffer, &custom_shape->per_frame_eqn_string_index) < 0)
2024 /* Syntax error, return parse error */
2028 /* Helper function to update the string buffers used by the editor */
2029 int update_string_buffer(char * buffer, int * index) {
2040 /* If the string line buffer used by the parser is already full then quit */
2041 if (string_line_buffer_index == (STRING_LINE_SIZE-1))
2044 if ((skip_size = get_string_prefix_len(string_line_buffer)) == FAILURE)
2047 string_line_buffer[string_line_buffer_index++] = '\n';
2049 // string_length = strlen(string_line_buffer + strlen(eqn_string)+1);
2050 if (skip_size >= STRING_LINE_SIZE)
2053 string_length = strlen(string_line_buffer + skip_size);
2055 if (skip_size > (STRING_LINE_SIZE-1))
2058 /* Add line to string buffer */
2059 strncpy(buffer + (*index),
2060 string_line_buffer + skip_size, string_length);
2062 /* Buffer full, quit */
2063 if ((*index) > (STRING_BUFFER_SIZE - 1)) {
2064 //if (PARSE_DEBUG) printf("update_string_buffer: string buffer full!\n");
2068 /* Otherwise, increment string index by the added string length */
2069 (*index)+=string_length;
2076 /* Helper function: returns the length of the prefix portion in the line
2077 buffer (the passed string here). In other words, given
2078 the string 'per_frame_1 = x = ....', return the length of 'per_frame_1 = '
2079 Returns -1 if syntax error
2082 int get_string_prefix_len(char * string) {
2086 /* Null argument check */
2091 /* First find the equal sign */
2092 while (string[i] != '=') {
2098 /* If the string already ends at the next char then give up */
2099 if (string[i+1] == 0)
2102 /* Move past the equal sign */
2105 /* Now found the start of the LHS variable, ie skip the spaces */
2106 while(string[i] == ' ') {
2110 /* If this is the end of the string then its a syntax error */
2114 /* Finished succesfully, return the length */