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 *****************************************************************************/
33 #include "splaytree_types.h"
34 #include "splaytree.h"
35 #include "tree_types.h"
37 #include "expr_types.h"
40 #include "param_types.h"
43 #include "func_types.h"
46 #include "preset_types.h"
47 #include "builtin_funcs.h"
49 #include "per_pixel_eqn_types.h"
50 #include "per_pixel_eqn.h"
52 #include "init_cond_types.h"
53 #include "init_cond.h"
55 #include "per_frame_eqn_types.h"
56 #include "per_frame_eqn.h"
59 #include "engine_vars.h"
61 #include "custom_wave_types.h"
62 #include "custom_wave.h"
64 #include "custom_shape_types.h"
65 #include "custom_shape.h"
67 /* Strings that prefix (and denote the type of) equations */
70 #define PER_FRAME_STRING "per_frame_"
71 #define PER_FRAME_STRING_LENGTH 10
73 #define PER_PIXEL_STRING "per_pixel_"
74 #define PER_PIXEL_STRING_LENGTH 10
76 #define PER_FRAME_INIT_STRING "per_frame_init_"
77 #define PER_FRAME_INIT_STRING_LENGTH 15
79 #define WAVECODE_STRING "wavecode_"
80 #define WAVECODE_STRING_LENGTH 9
82 #define WAVE_STRING "wave_"
83 #define WAVE_STRING_LENGTH 5
85 #define PER_POINT_STRING "per_point"
86 #define PER_POINT_STRING_LENGTH 9
88 #define PER_FRAME_STRING_NO_UNDERSCORE "per_frame"
89 #define PER_FRAME_STRING_NO_UNDERSCORE_LENGTH 9
91 #define SHAPECODE_STRING "shapecode_"
92 #define SHAPECODE_STRING_LENGTH 10
94 #define SHAPE_STRING "shape_"
95 #define SHAPE_STRING_LENGTH 6
97 #define SHAPE_INIT_STRING "init"
98 #define SHAPE_INIT_STRING_LENGTH 4
100 #define WAVE_INIT_STRING "init"
101 #define WAVE_INIT_STRING_LENGTH 4
103 /* Stores a line of a file as its being parsed */
104 char string_line_buffer[STRING_LINE_SIZE];
106 /* The current position of the string line buffer (see above) */
107 int string_line_buffer_index = 0;
109 /* All infix operators (except '=') are prototyped here */
110 extern infix_op_t * infix_add, * infix_minus, * infix_div, * infix_mult,
111 * infix_or, * infix_and, * infix_mod, * infix_positive, * infix_negative;
113 /* If the parser reads a line with a custom wave, this pointer is set to
114 the custom wave of concern */
115 custom_wave_t * current_wave = NULL;
116 custom_shape_t * current_shape = NULL;
117 /* Counts the number of lines parsed */
118 unsigned int line_count = 1;
119 int per_frame_eqn_count = 0;
120 int per_frame_init_eqn_count = 0;
127 CUSTOM_WAVE_PER_POINT_LINE_MODE,
128 CUSTOM_WAVE_PER_FRAME_LINE_MODE,
129 CUSTOM_WAVE_WAVECODE_LINE_MODE,
130 CUSTOM_SHAPE_SHAPECODE_LINE_MODE,
133 line_mode_t line_mode = NORMAL_LINE_MODE;
135 /* Token enumeration type */
138 tEOL, /* end of a line, usually a '/n' or '/r' */
139 tEOF, /* end of file */
153 tPositive, /* + as a prefix operator */
154 tNegative, /* - as a prefix operator */
156 tStringTooLong, /* special token to indicate an invalid string length */
157 tStringBufferFilled /* the string buffer for this line is maxed out */
161 int get_string_prefix_len(char * string);
162 tree_expr_t * insert_gen_expr(gen_expr_t * gen_expr, tree_expr_t ** root);
163 tree_expr_t * insert_infix_op(infix_op_t * infix_op, tree_expr_t ** root);
164 token_t parseToken(FILE * fs, char * string);
165 gen_expr_t ** parse_prefix_args(FILE * fs, int num_args, struct PRESET_T * preset);
166 gen_expr_t * parse_infix_op(FILE * fs, token_t token, tree_expr_t * tree_expr, struct PRESET_T * preset);
167 gen_expr_t * parse_sign_arg(FILE * fs);
168 int parse_float(FILE * fs, double * float_ptr);
169 int parse_int(FILE * fs, int * int_ptr);
170 int insert_gen_rec(gen_expr_t * gen_expr, tree_expr_t * root);
171 int insert_infix_rec(infix_op_t * infix_op, tree_expr_t * root);
172 gen_expr_t * parse_gen_expr(FILE * fs, tree_expr_t * tree_expr, struct PRESET_T * preset);
173 per_frame_eqn_t * parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, struct PRESET_T * preset);
174 init_cond_t * parse_per_frame_init_eqn(FILE * fs, struct PRESET_T * preset, splaytree_t * database);
175 int parse_wavecode_prefix(char * token, int * id, char ** var_string);
176 int parse_wavecode(char * token, FILE * fs, preset_t * preset);
177 int parse_wave_prefix(char * token, int * id, char ** eqn_string);
179 int parse_shapecode(char * eqn_string, FILE * fs, preset_t * preset);
180 int parse_shapecode_prefix(char * token, int * id, char ** var_string);
182 int parse_wave(char * eqn_string, FILE * fs, preset_t * preset);
183 int parse_shape(char * eqn_string, FILE * fs, preset_t * preset);
184 int parse_shape_prefix(char * token, int * id, char ** eqn_string);
186 int update_string_buffer(char * buffer, int * index);
187 int string_to_float(char * string, double * float_ptr);
189 /* Grabs the next token from the file. The second argument points
192 token_t parseToken(FILE * fs, char * string) {
198 memset(string, 0, MAX_TOKEN_SIZE);
200 /* Loop until a delimiter is found, or the maximum string size is found */
201 for (i = 0; i < MAX_TOKEN_SIZE;i++) {
204 /* If the string line buffer is full, quit */
205 if (string_line_buffer_index == (STRING_LINE_SIZE - 1))
206 return tStringBufferFilled;
208 /* Otherwise add this character to the string line buffer */
209 string_line_buffer[string_line_buffer_index++] = c;
210 /* Now interpret the character */
221 /* check for line comment here */
222 if ((c = fgetc(fs)) == '/') {
226 line_mode = NORMAL_LINE_MODE;
230 line_mode = NORMAL_LINE_MODE;
237 /* Otherwise, just a regular division operator */
261 line_mode = NORMAL_LINE_MODE;
267 case ' ': /* space, skip the character */
272 line_mode = NORMAL_LINE_MODE;
282 /* String reached maximum length, return special token error */
283 return tStringTooLong;
287 /* Parse input in the form of "exp, exp, exp, ...)"
288 Returns a general expression list */
290 gen_expr_t ** parse_prefix_args(FILE * fs, int num_args, struct PRESET_T * preset) {
293 gen_expr_t ** expr_list; /* List of arguments to function */
294 gen_expr_t * gen_expr;
296 /* Malloc the expression list */
297 expr_list = (gen_expr_t**)malloc(sizeof(gen_expr_t*)*num_args);
300 if (expr_list == NULL)
306 while (i < num_args) {
307 //if (PARSE_DEBUG) printf("parse_prefix_args: parsing argument %d...\n", i+1);
308 /* Parse the ith expression in the list */
309 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
310 //if (PARSE_DEBUG) printf("parse_prefix_args: failed to get parameter # %d for function (LINE %d)\n", i+1, line_count);
311 for (j = 0; j < i; j++)
312 free_gen_expr(expr_list[j]);
316 /* Assign entry in expression list */
317 expr_list[i++] = gen_expr;
320 //if (PARSE_DEBUG) printf("parse_prefix_args: finished parsing %d arguments (LINE %d)\n", num_args, line_count);
321 /* Finally, return the resulting expression list */
326 /* Parses a comment at the top of the file. Stops when left bracket is found */
327 int parse_top_comment(FILE * fs) {
329 char string[MAX_TOKEN_SIZE];
332 /* Process tokens until left bracket is found */
333 while ((token = parseToken(fs, string)) != tLBr) {
338 /* Done, return success */
342 /* Right Bracket is parsed by this function.
343 puts a new string into name */
344 int parse_preset_name(FILE * fs, char * name) {
351 if ((token = parseToken(fs, name)) != tRBr)
354 //if (PARSE_DEBUG) printf("parse_preset_name: parsed preset (name = \"%s\")\n", name);
360 /* Parses per pixel equations */
361 int parse_per_pixel_eqn(FILE * fs, preset_t * preset) {
364 char string[MAX_TOKEN_SIZE];
365 gen_expr_t * gen_expr;
367 if (PARSE_DEBUG) printf("parse_per_pixel: per_pixel equation parsing start...(LINE %d)\n", line_count);
369 if (parseToken(fs, string) != tEq) { /* parse per pixel operator name */
370 if (PARSE_DEBUG) printf("parse_per_pixel: equal operator expected after per pixel operator \"%s\", but not found (LINE %d)\n",
375 /* Parse right side of equation as an expression */
376 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
377 if (PARSE_DEBUG) printf("parse_per_pixel: equation evaluated to null? (LINE %d)\n", line_count);
381 /* Add the per pixel equation */
382 if (add_per_pixel_eqn(string, gen_expr, preset) < 0) {
383 free_gen_expr(gen_expr);
390 /* Parses an equation line, this function is way too big, should add some helper functions */
391 int parse_line(FILE * fs, struct PRESET_T * preset) {
393 char eqn_string[MAX_TOKEN_SIZE];
395 init_cond_t * init_cond;
396 per_frame_eqn_t * per_frame_eqn;
398 /* Clear the string line buffer */
399 memset(string_line_buffer, 0, STRING_LINE_SIZE);
400 string_line_buffer_index = 0;
403 switch (token = parseToken(fs, eqn_string)) {
419 // if (PARSE_DEBUG) printf("parse_line: invalid token found at start of line (LINE %d)\n", line_count);
420 /* Invalid token found, return a parse error */
424 case tEOL: /* Empty line */
425 line_mode = NORMAL_LINE_MODE;
428 case tEOF: /* End of File */
429 line_mode = NORMAL_LINE_MODE;
433 case tSemiColon: /* Indicates end of expression */
436 /* Valid Case, either an initial condition or equation should follow */
439 /* CASE: PER FRAME INIT EQUATION */
440 if (!strncmp(eqn_string, PER_FRAME_INIT_STRING, PER_FRAME_INIT_STRING_LENGTH)) {
442 //if (PARSE_DEBUG) printf("parse_line: per frame init equation found...(LINE %d)\n", line_count);
444 /* Set the line mode to normal */
445 line_mode = NORMAL_LINE_MODE;
447 /* Parse the per frame equation */
448 if ((init_cond = parse_per_frame_init_eqn(fs, preset, NULL)) == NULL) {
449 //if (PARSE_DEBUG) printf("parse_line: per frame init equation parsing failed (LINE %d)\n", line_count);
453 /* Insert the equation in the per frame equation tree */
454 if (splay_insert(init_cond, init_cond->param->name, preset->per_frame_init_eqn_tree) < 0) {
455 //if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
456 free_init_cond(init_cond); /* will free the gen expr too */
461 if (update_string_buffer(preset->per_frame_init_eqn_string_buffer,
462 &preset->per_frame_init_eqn_string_index) < 0)
469 /* Per frame equation case */
470 if (!strncmp(eqn_string, PER_FRAME_STRING, PER_FRAME_STRING_LENGTH)) {
472 /* Sometimes per frame equations are implicitly defined without the
473 per_frame_ prefix. This informs the parser that one could follow */
474 line_mode = PER_FRAME_LINE_MODE;
476 //if (PARSE_DEBUG) printf("parse_line: per frame equation found...(LINE %d)\n", line_count);
478 /* Parse the per frame equation */
479 if ((per_frame_eqn = parse_per_frame_eqn(fs, ++per_frame_eqn_count, preset)) == NULL) {
480 if (PARSE_DEBUG) printf("parse_line: per frame equation parsing failed (LINE %d)\n", line_count);
484 /* Insert the equation in the per frame equation tree */
485 if (splay_insert(per_frame_eqn, &per_frame_eqn_count, preset->per_frame_eqn_tree) < 0) {
486 if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
487 free_per_frame_eqn(per_frame_eqn); /* will free the gen expr too */
491 if (update_string_buffer(preset->per_frame_eqn_string_buffer,
492 &preset->per_frame_eqn_string_index) < 0)
501 /* Wavecode initial condition case */
502 if (!strncmp(eqn_string, WAVECODE_STRING, WAVECODE_STRING_LENGTH)) {
504 line_mode = CUSTOM_WAVE_WAVECODE_LINE_MODE;
507 // printf("parse_line: wavecode prefix found: \"%s\"\n", eqn_string);
509 // printf("string:%d\n", 5);
511 //SUPER MYSTERIO-BUG - Don't Remove
514 return parse_wavecode(eqn_string, fs, preset);
517 /* Custom Wave Prefix */
518 if ((!strncmp(eqn_string, WAVE_STRING, WAVE_STRING_LENGTH)) &&
519 ((eqn_string[5] >= 48) && (eqn_string[5] <= 57))) {
521 // if (PARSE_DEBUG) printf("parse_line wave prefix found: \"%s\"\n", eqn_string);
523 return parse_wave(eqn_string, fs, preset);
528 /* Shapecode initial condition case */
529 if (!strncmp(eqn_string, SHAPECODE_STRING, SHAPECODE_STRING_LENGTH)) {
531 line_mode = CUSTOM_SHAPE_SHAPECODE_LINE_MODE;
533 if (PARSE_DEBUG) printf("parse_line: shapecode prefix found: \"%s\"\n", eqn_string);
535 return parse_shapecode(eqn_string, fs, preset);
538 /* Custom Shape Prefix */
539 if ((!strncmp(eqn_string, SHAPE_STRING, SHAPE_STRING_LENGTH)) &&
540 ((eqn_string[6] >= 48) && (eqn_string[6] <= 57))) {
542 if (PARSE_DEBUG) printf("parse_line shape prefix found: \"%s\"\n", eqn_string);
543 return parse_shape(eqn_string, fs, preset);
547 /* Per pixel equation case */
548 if (!strncmp(eqn_string, PER_PIXEL_STRING, PER_PIXEL_STRING_LENGTH)) {
549 line_mode = PER_PIXEL_LINE_MODE;
551 if (parse_per_pixel_eqn(fs, preset) < 0)
555 if (update_string_buffer(preset->per_pixel_eqn_string_buffer,
556 &preset->per_pixel_eqn_string_index) < 0)
559 if (PARSE_DEBUG) printf("parse_line: finished parsing per pixel equation (LINE %d)\n", line_count);
563 /* Sometimes equations are written implicitly in milkdrop files, in the form
565 per_frame_1 = p1 = eqn1; p2 = eqn2; p3 = eqn3;..;
567 which is analagous to:
569 per_frame_1 = p1 = eqn1; per_frame_2 = p2 = eqn2; per_frame_3 = p3 = eqn3; ...;
571 The following line mode hack allows such implicit declaration of the
572 prefix that specifies the equation type. An alternative method
573 may be to associate each equation line as list of equations separated
574 by semicolons (and a new line ends the list). Instead, however, a global
575 variable called "line_mode" specifies the last type of equation found,
576 and bases any implicitly typed input on this fact
578 Note added by Carmelo Piccione (cep@andrew.cmu.edu) 10/19/03
581 /* Per frame line mode previously, try to parse the equation implicitly */
582 if (line_mode == PER_FRAME_LINE_MODE) {
583 if ((per_frame_eqn = parse_implicit_per_frame_eqn(fs, eqn_string, ++per_frame_eqn_count, preset)) == NULL)
586 /* Insert the equation in the per frame equation tree */
587 if (splay_insert(per_frame_eqn, &per_frame_eqn_count, preset->per_frame_eqn_tree) < 0) {
588 if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
589 free_per_frame_eqn(per_frame_eqn); /* will free the gen expr too */
594 if (update_string_buffer(preset->per_frame_eqn_string_buffer,
595 &preset->per_frame_eqn_string_index) < 0)
603 //if (PARSE_DEBUG) printf("parse_line: found initial condition: name = \"%s\" (LINE %d)\n", eqn_string, line_count);
605 /* Evaluate the initial condition */
606 if ((init_cond = parse_init_cond(fs, eqn_string, preset)) == NULL) {
607 if (PARSE_DEBUG) printf("parse_line: failed to parse initial condition (LINE %d)\n", line_count);
611 /* Add equation to initial condition tree */
612 if (splay_insert(init_cond, init_cond->param->name, preset->init_cond_tree) < 0) {
613 if (PARSE_DEBUG) printf("parse_line: failed to add initial condition \"%s\" to equation tree (LINE %d)\n",
614 init_cond->param->name, line_count);
615 free_init_cond(init_cond);
619 /* Finished with initial condition line */
620 // if (PARSE_DEBUG) printf("parse_line: initial condition parsed successfully\n");
624 /* END INITIAL CONDITIONING PARSING */
627 default: /* an uncaught type or an error has occurred */
628 if (PARSE_DEBUG) printf("parse_line: uncaught case, token val = %d\n", token);
632 /* Because of the default in the case statement,
633 control flow should never actually reach here */
639 /* Parses a general expression, this function is the meat of the parser */
640 gen_expr_t * parse_gen_expr (FILE * fs, tree_expr_t * tree_expr, struct PRESET_T * preset) {
643 char string[MAX_TOKEN_SIZE];
645 gen_expr_t * gen_expr;
647 param_t * param = NULL;
649 gen_expr_t ** expr_list;
651 switch (token = parseToken(fs,string)) {
652 /* Left Parentice Case */
655 /* CASE 1 (Left Parentice): See if the previous string before this parentice is a function name */
656 if ((func = find_func(string)) != NULL) {
657 if (PARSE_DEBUG) printf("parse_gen_expr: found prefix function (name = %s) (LINE %d)\n", func->name, line_count);
659 /* Parse the functions arguments */
660 if ((expr_list = parse_prefix_args(fs, func->num_args, preset)) == NULL) {
661 if (PARSE_DEBUG) printf("parse_prefix_args: failed to generate an expresion list! (LINE %d) \n", line_count);
662 free_tree_expr(tree_expr);
666 /* Convert function to expression */
667 if ((gen_expr = prefun_to_expr((void*)func->func_ptr, expr_list, func->num_args)) == NULL) {
668 if (PARSE_DEBUG) printf("parse_prefix_args: failed to convert prefix function to general expression (LINE %d) \n",
670 free_tree_expr(tree_expr);
671 for (i = 0; i < func->num_args;i++)
672 free_gen_expr(expr_list[i]);
679 token = parseToken(fs, string);
682 if (PARSE_DEBUG) printf("parse_prefix_args: empty string expected, but not found...(LINE %d)\n", line_count);
683 /* continue anyway for now, could be implicit multiplication */
686 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
690 /* Case 2: (Left Parentice), a string coupled with a left parentice. Either an error or implicit
691 multiplication operator. For now treat it as an error */
693 if (PARSE_DEBUG) printf("parse_gen_expr: implicit multiplication case unimplemented!\n");
694 free_tree_expr(tree_expr);
698 /* CASE 3 (Left Parentice): the following is enclosed parentices to change order
699 of operations. So we create a new expression tree */
701 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
702 //if (PARSE_DEBUG) printf("parse_gen_expr: found left parentice, but failed to create new expression tree \n");
703 free_tree_expr(tree_expr);
707 if (PARSE_DEBUG) printf("parse_gen_expr: finished enclosed expression tree...\n");
708 token = parseToken(fs, string);
709 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
711 /* Plus is a prefix operator check */
715 //if (PARSE_DEBUG) printf("parse_gen_expr: plus used as prefix (LINE %d)\n", line_count);
717 /* Treat prefix plus as implict 0 preceding operator */
718 gen_expr = const_to_expr(0);
720 return parse_infix_op(fs, tPositive, insert_gen_expr(gen_expr, &tree_expr), preset);
723 /* Minus is a prefix operator check */
727 /* Use the negative infix operator, but first add an implicit zero to the operator tree */
728 gen_expr = const_to_expr(0);
729 //return parse_gen_expr(fs, insert_gen_expr(gen_expr, &tree_expr), preset);
730 return parse_infix_op(fs, tNegative, insert_gen_expr(gen_expr, &tree_expr), preset);
733 /* All the following cases are strings followed by an infix operator or terminal */
740 /* CASE 1 (terminal): string is empty, but not null. Not sure if this will actually happen
743 //if (PARSE_DEBUG) printf("parse_gen_expr: empty string coupled with terminal (LINE %d) \n", line_count);
744 return parse_infix_op(fs, token, tree_expr, preset);
750 /* CASE 0: Empty string, parse error */
752 if (PARSE_DEBUG) printf("parse_gen_expr: empty string coupled with infix op (ERROR!) (LINE %d) \n", line_count);
753 free_tree_expr(tree_expr);
757 /* CASE 1: Check if string is a just a floating point number */
758 if (string_to_float(string, &val) != PARSE_ERROR) {
759 if ((gen_expr = const_to_expr(val)) == NULL) {
760 free_tree_expr(tree_expr);
764 /* Parse the rest of the line */
765 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
770 /* CASE 4: custom shape variable */
771 if (current_shape != NULL) {
772 if ((param = find_param_db(string, current_shape->param_tree, FALSE)) == NULL) {
773 if ((param = find_builtin_param(string)) == NULL)
774 if ((param = find_param_db(string, current_shape->param_tree, TRUE)) == NULL) {
775 free_tree_expr(tree_expr);
781 printf("parse_gen_expr: custom shape parameter (name = %s)... ", param->name);
785 /* Convert parameter to an expression */
786 if ((gen_expr = param_to_expr(param)) == NULL) {
787 free_tree_expr(tree_expr);
791 //if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
793 /* Parse the rest of the line */
794 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
797 /* CASE 5: custom wave variable */
798 if (current_wave != NULL) {
799 if ((param = find_param_db(string, current_wave->param_tree, FALSE)) == NULL) {
800 if ((param = find_builtin_param(string)) == NULL)
801 if ((param = find_param_db(string, current_wave->param_tree, TRUE)) == NULL) {
802 free_tree_expr(tree_expr);
809 printf("parse_gen_expr: custom wave parameter (name = %s)... ", param->name);
813 /* Convert parameter to an expression */
814 if ((gen_expr = param_to_expr(param)) == NULL) {
815 free_tree_expr(tree_expr);
819 if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
821 /* Parse the rest of the line */
822 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
826 /* CASE 6: regular parameter. Will be created if necessary and the string has no invalid characters */
827 if ((param = find_param(string, preset, P_CREATE)) != NULL) {
830 printf("parse_gen_expr: parameter (name = %s)... ", param->name);
834 /* Convert parameter to an expression */
835 if ((gen_expr = param_to_expr(param)) == NULL) {
836 free_tree_expr(tree_expr);
840 if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
842 /* Parse the rest of the line */
843 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
847 /* CASE 7: Bad string, give up */
848 if (PARSE_DEBUG) printf("parse_gen_expr: syntax error [string = \"%s\"] (LINE %d)\n", string, line_count);
849 free_tree_expr(tree_expr);
856 /* Inserts expressions into tree according to operator precedence.
857 If root is null, a new tree is created, with gen_expr as only element */
859 tree_expr_t * insert_infix_op(infix_op_t * infix_op, tree_expr_t **root) {
861 tree_expr_t * new_root;
864 if (infix_op == NULL)
867 /* The root is null, so make this operator
871 new_root = new_tree_expr(infix_op, NULL, NULL, NULL);
876 /* The root node is not an infix function,
877 so we make this infix operator the new root */
879 if ((*root)->infix_op == NULL) {
880 new_root = new_tree_expr(infix_op, NULL, *root, NULL);
885 /* The root is an infix function. If the precedence
886 of the item to be inserted is greater than the root's
887 precedence, then make gen_expr the root */
889 if (infix_op->precedence > (*root)->infix_op->precedence) {
890 new_root = new_tree_expr(infix_op, NULL, *root, NULL);
895 /* If control flow reaches here, use a recursive helper
896 with the knowledge that the root is higher precedence
897 than the item to be inserted */
899 insert_infix_rec(infix_op, *root);
905 tree_expr_t * insert_gen_expr(gen_expr_t * gen_expr, tree_expr_t ** root) {
907 tree_expr_t * new_root;
909 /* If someone foolishly passes a null
910 pointer to insert, return the original tree */
912 if (gen_expr == NULL) {
916 /* If the root is null, generate a new expression tree,
917 using the passed expression as the root element */
920 new_root = new_tree_expr(NULL, gen_expr, NULL, NULL);
926 /* Otherwise. the new element definitely will not replace the current root.
927 Use a recursive helper function to do insertion */
929 insert_gen_rec(gen_expr, *root);
933 /* A recursive helper function to insert general expression elements into the operator tree */
934 int insert_gen_rec(gen_expr_t * gen_expr, tree_expr_t * root) {
936 /* Trivial Case: root is null */
939 ////if (PARSE_DEBUG) printf("insert_gen_rec: root is null, returning failure\n");
944 /* The current node's left pointer is null, and this
945 current node is an infix operator, so insert the
946 general expression at the left pointer */
948 if ((root->left == NULL) && (root->infix_op != NULL)) {
949 root->left = new_tree_expr(NULL, gen_expr, NULL, NULL);
953 /* The current node's right pointer is null, and this
954 current node is an infix operator, so insert the
955 general expression at the right pointer */
957 if ((root->right == NULL) && (root->infix_op != NULL)) {
958 root->right = new_tree_expr(NULL, gen_expr, NULL, NULL);
962 /* Otherwise recurse down to the left. If
963 this succeeds then return. If it fails, try
964 recursing down to the right */
966 if (insert_gen_rec(gen_expr, root->left) == FAILURE)
967 return insert_gen_rec(gen_expr, root->right);
969 /* Impossible for control flow to reach here, but in
970 the world of C programming, who knows... */
971 //if (PARSE_DEBUG) printf("insert_gen_rec: should never reach here!\n");
976 /* A recursive helper function to insert infix arguments by operator precedence */
977 int insert_infix_rec(infix_op_t * infix_op, tree_expr_t * root) {
979 /* Shouldn't happen, implies a parse error */
984 /* Also shouldn't happen, also implies a (different) parse error */
986 if (root->infix_op == NULL)
989 /* Left tree is empty, attach this operator to it.
990 I don't think this will ever happen */
991 if (root->left == NULL) {
992 root->left = new_tree_expr(infix_op, NULL, root->left, NULL);
996 /* Right tree is empty, attach this operator to it */
997 if (root->right == NULL) {
998 root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
1002 /* The left element can now be ignored, since there is no way for this
1003 operator to use those expressions */
1005 /* If the right element is not an infix operator,
1006 then insert the expression here, attaching the old right branch
1007 to the left of the new expression */
1009 if (root->right->infix_op == NULL) {
1010 root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
1014 /* Traverse deeper if the inserting operator precedence is less than the
1015 the root's right operator precedence */
1016 if (infix_op->precedence < root->right->infix_op->precedence)
1017 return insert_infix_rec(infix_op, root->right);
1019 /* Otherwise, insert the operator here */
1021 root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
1026 /* Parses an infix operator */
1027 gen_expr_t * parse_infix_op(FILE * fs, token_t token, tree_expr_t * tree_expr, struct PRESET_T * preset) {
1029 gen_expr_t * gen_expr;
1032 /* All the infix operators */
1034 //if (PARSE_DEBUG) printf("parse_infix_op: found addition operator (LINE %d)\n", line_count);
1035 return parse_gen_expr(fs, insert_infix_op(infix_add, &tree_expr), preset);
1037 //if (PARSE_DEBUG) printf("parse_infix_op: found subtraction operator (LINE %d)\n", line_count);
1038 return parse_gen_expr(fs, insert_infix_op(infix_minus, &tree_expr), preset);
1040 //if (PARSE_DEBUG) printf("parse_infix_op: found multiplication operator (LINE %d)\n", line_count);
1041 return parse_gen_expr(fs, insert_infix_op(infix_mult, &tree_expr), preset);
1043 //if (PARSE_DEBUG) printf("parse_infix_op: found division operator (LINE %d)\n", line_count);
1044 return parse_gen_expr(fs, insert_infix_op(infix_div, &tree_expr), preset);
1046 //if (PARSE_DEBUG) printf("parse_infix_op: found modulo operator (LINE %d)\n", line_count);
1047 return parse_gen_expr(fs, insert_infix_op(infix_mod, &tree_expr), preset);
1049 //if (PARSE_DEBUG) printf("parse_infix_op: found bitwise or operator (LINE %d)\n", line_count);
1050 return parse_gen_expr(fs, insert_infix_op(infix_or, &tree_expr), preset);
1052 //if (PARSE_DEBUG) printf("parse_infix_op: found bitwise and operator (LINE %d)\n", line_count);
1053 return parse_gen_expr(fs, insert_infix_op(infix_and, &tree_expr), preset);
1055 //if (PARSE_DEBUG) printf("parse_infix_op: found positive operator (LINE %d)\n", line_count);
1056 return parse_gen_expr(fs, insert_infix_op(infix_positive, &tree_expr), preset);
1058 //if (PARSE_DEBUG) printf("parse_infix_op: found negative operator (LINE %d)\n", line_count);
1059 return parse_gen_expr(fs, insert_infix_op(infix_negative, &tree_expr), preset);
1066 //if (PARSE_DEBUG) printf("parse_infix_op: terminal found (LINE %d)\n", line_count);
1067 gen_expr = new_gen_expr(TREE_T, (void*)tree_expr);
1070 //if (PARSE_DEBUG) printf("parse_infix_op: operator or terminal expected, but not found (LINE %d)\n", line_count);
1071 free_tree_expr(tree_expr);
1075 /* Will never happen */
1080 /* Parses an integer, checks for +/- prefix */
1081 int parse_int(FILE * fs, int * int_ptr) {
1083 char string[MAX_TOKEN_SIZE];
1086 char * end_ptr = " ";
1088 token = parseToken(fs, string);
1094 token = parseToken(fs, string);
1098 token = parseToken(fs, string);
1109 /* Convert the string to an integer. *end_ptr
1110 should end up pointing to null terminator of 'string'
1111 if the conversion was successful. */
1112 // printf("STRING: \"%s\"\n", string);
1114 (*int_ptr) = sign*strtol(string, &end_ptr, 10);
1116 /* If end pointer is a return character or null terminator, all is well */
1117 if ((*end_ptr == '\r') || (*end_ptr == '\0'))
1123 /* Parses a floating point number */
1124 int string_to_float(char * string, double * float_ptr) {
1131 error_ptr = malloc(sizeof(char**));
1133 (*float_ptr) = strtod(string, error_ptr);
1135 /* These imply a succesful parse of the string */
1136 if ((**error_ptr == '\0') || (**error_ptr == '\r')) {
1146 /* Parses a floating point number */
1147 int parse_float(FILE * fs, double * float_ptr) {
1149 char string[MAX_TOKEN_SIZE];
1154 error_ptr = malloc(sizeof(char**));
1156 token = parseToken(fs, string);
1161 token = parseToken(fs, string);
1165 token = parseToken(fs, string);
1171 if (string[0] == 0) {
1176 (*float_ptr) = sign*strtod(string, error_ptr);
1178 /* No conversion was performed */
1179 if ((**error_ptr == '\0') || (**error_ptr == '\r')) {
1184 //if (PARSE_DEBUG) printf("parse_float: double conversion failed for string \"%s\"\n", string);
1194 /* Parses a per frame equation. That is, interprets a stream of data as a per frame equation */
1195 per_frame_eqn_t * parse_per_frame_eqn(FILE * fs, int index, struct PRESET_T * preset) {
1197 char string[MAX_TOKEN_SIZE];
1199 per_frame_eqn_t * per_frame_eqn;
1200 gen_expr_t * gen_expr;
1202 if (parseToken(fs, string) != tEq) {
1203 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
1207 /* Find the parameter associated with the string, create one if necessary */
1208 if ((param = find_param(string, preset, P_CREATE)) == NULL) {
1212 /* Make sure parameter is writable */
1213 if (param->flags & P_FLAG_READONLY) {
1214 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1218 /* Parse right side of equation as an expression */
1219 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1220 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: equation evaluated to null (LINE %d)\n", line_count);
1224 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: finished per frame equation evaluation (LINE %d)\n", line_count);
1226 /* Create a new per frame equation */
1227 if ((per_frame_eqn = new_per_frame_eqn(index, param, gen_expr)) == NULL) {
1228 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: failed to create a new per frame eqn, out of memory?\n");
1229 free_gen_expr(gen_expr);
1233 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: per_frame eqn parsed succesfully\n");
1235 return per_frame_eqn;
1238 /* Parses an 'implicit' per frame equation. That is, interprets a stream of data as a per frame equation without a prefix */
1239 per_frame_eqn_t * parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, struct PRESET_T * preset) {
1242 per_frame_eqn_t * per_frame_eqn;
1243 gen_expr_t * gen_expr;
1247 if (param_string == NULL)
1252 //rintf("param string: %s\n", param_string);
1253 /* Find the parameter associated with the string, create one if necessary */
1254 if ((param = find_param(param_string, preset, P_CREATE)) == NULL) {
1258 //printf("parse_implicit_per_frame_eqn: param is %s\n", param->name);
1260 /* Make sure parameter is writable */
1261 if (param->flags & P_FLAG_READONLY) {
1262 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1266 /* Parse right side of equation as an expression */
1267 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1268 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: equation evaluated to null (LINE %d)\n", line_count);
1272 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: finished per frame equation evaluation (LINE %d)\n", line_count);
1274 /* Create a new per frame equation */
1275 if ((per_frame_eqn = new_per_frame_eqn(index, param, gen_expr)) == NULL) {
1276 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: failed to create a new per frame eqn, out of memory?\n");
1277 free_gen_expr(gen_expr);
1281 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: per_frame eqn parsed succesfully\n");
1283 return per_frame_eqn;
1286 /* Parses an initial condition */
1287 init_cond_t * parse_init_cond(FILE * fs, char * name, struct PRESET_T * preset) {
1291 init_cond_t * init_cond;
1298 /* Search for the paramater in the database, creating it if necessary */
1299 if ((param = find_param(name, preset, P_CREATE)) == NULL) {
1303 //if (PARSE_DEBUG) printf("parse_init_cond: parameter = \"%s\" (LINE %d)\n", param->name, line_count);
1305 if (param->flags & P_FLAG_READONLY) {
1306 //if (PARSE_DEBUG) printf("parse_init_cond: builtin parameter \"%s\" marked as read only!\n", param->name);
1310 /* At this point, a parameter has been created or was found
1313 //if (PARSE_DEBUG) printf("parse_init_cond: parsing initial condition value... (LINE %d)\n", line_count);
1315 /* integer value (boolean is an integer in C) */
1316 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1317 if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {
1318 //if (PARSE_DEBUG) printf("parse_init_cond: error parsing integer!\n");
1324 else if (param->type == P_TYPE_DOUBLE) {
1325 if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
1326 //if (PARSE_DEBUG) printf("parse_init_cond: error parsing double!\n");
1333 //if (PARSE_DEBUG) printf("parse_init_cond: unknown parameter type!\n");
1337 /* Create new initial condition */
1338 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1339 //if (PARSE_DEBUG) printf("parse_init_cond: new_init_cond failed!\n");
1347 /* Parses a per frame init equation, not sure if this works right now */
1348 init_cond_t * parse_per_frame_init_eqn(FILE * fs, struct PRESET_T * preset, splaytree_t * database) {
1350 char name[MAX_TOKEN_SIZE];
1351 param_t * param = NULL;
1353 init_cond_t * init_cond;
1354 gen_expr_t * gen_expr;
1364 if ((token = parseToken(fs, name)) != tEq)
1368 /* If a database was specified,then use find_param_db instead */
1369 if ((database != NULL) && ((param = find_param_db(name, database, TRUE)) == NULL)) {
1373 /* Otherwise use the builtin parameter and user databases. This is confusing. Sorry. */
1374 if ((param == NULL) && ((param = find_param(name, preset, P_CREATE)) == NULL)) {
1378 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: parameter = \"%s\" (LINE %d)\n", param->name, line_count);
1380 if (param->flags & P_FLAG_READONLY) {
1381 //if (PARSE_DEBUG) printf("pars_per_frame_init_eqn: builtin parameter \"%s\" marked as read only!\n", param->name);
1385 /* At this point, a parameter has been created or was found
1388 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: parsing right hand side of per frame init equation.. (LINE %d)\n", line_count);
1390 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1391 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: failed to parse general expresion!\n");
1395 /* Compute initial condition value */
1396 val = eval_gen_expr(gen_expr);
1398 /* Free the general expression now that we are done with it */
1399 free_gen_expr(gen_expr);
1401 /* integer value (boolean is an integer in C) */
1402 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1403 init_val.int_val = (int)val;
1407 else if (param->type == P_TYPE_DOUBLE) {
1408 init_val.double_val = val;
1413 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: unknown parameter type!\n");
1418 /* Create new initial condition */
1419 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1420 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: new_init_cond failed!\n");
1429 int parse_wavecode(char * token, FILE * fs, preset_t * preset) {
1432 init_cond_t * init_cond;
1433 custom_wave_t * custom_wave;
1438 /* Null argument checks */
1446 /* token should be in the form wavecode_N_var, such as wavecode_1_samples */
1448 /* Get id and variable name from token string */
1449 if (parse_wavecode_prefix(token, &id, &var_string) < 0)
1452 //if (PARSE_DEBUG) printf("parse_wavecode: wavecode id = %d, parameter = \"%s\"\n", id, var_string);
1454 /* Retrieve custom wave information from preset. The 3rd argument
1455 if true creates a custom wave if one does not exist */
1456 if ((custom_wave = find_custom_wave(id, preset, TRUE)) == NULL) {
1457 //if (PARSE_DEBUG) printf("parse_wavecode: failed to load (or create) custom wave (id = %d)!\n", id);
1460 //if (PARSE_DEBUG) printf("parse_wavecode: custom wave found (id = %d)\n", custom_wave->id);
1462 /* Retrieve parameter from this custom waves parameter db */
1463 if ((param = find_param_db(var_string, custom_wave->param_tree, TRUE)) == NULL)
1466 //if (PARSE_DEBUG) printf("parse_wavecode: custom wave parameter found (name = %s)\n", param->name);
1468 /* integer value (boolean is an integer in C) */
1469 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1470 if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {
1471 //if (PARSE_DEBUG) printf("parse_wavecode: error parsing integer!\n");
1477 else if (param->type == P_TYPE_DOUBLE) {
1478 if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
1479 //if (PARSE_DEBUG) printf("parse_wavecode: error parsing double!\n");
1486 //if (PARSE_DEBUG) printf("parse_wavecode: unknown parameter type!\n");
1490 /* Create new initial condition */
1491 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1492 //if (PARSE_DEBUG) printf("parse_wavecode: new_init_cond failed!\n");
1496 if (splay_insert(init_cond, param->name, custom_wave->init_cond_tree) < 0) {
1497 free_init_cond(init_cond);
1501 //if (PARSE_DEBUG) printf("parse_wavecode: [success]\n");
1505 int parse_shapecode(char * token, FILE * fs, preset_t * preset) {
1508 init_cond_t * init_cond;
1509 custom_shape_t * custom_shape;
1514 /* Null argument checks */
1522 /* token should be in the form shapecode_N_var, such as shapecode_1_samples */
1524 /* Get id and variable name from token string */
1525 if (parse_shapecode_prefix(token, &id, &var_string) < 0)
1528 //if (PARSE_DEBUG) printf("parse_shapecode: shapecode id = %d, parameter = \"%s\"\n", id, var_string);
1530 /* Retrieve custom shape information from preset. The 3rd argument
1531 if true creates a custom shape if one does not exist */
1532 if ((custom_shape = find_custom_shape(id, preset, TRUE)) == NULL) {
1533 //if (PARSE_DEBUG) printf("parse_shapecode: failed to load (or create) custom shape (id = %d)!\n", id);
1536 //if (PARSE_DEBUG) printf("parse_shapecode: custom shape found (id = %d)\n", custom_shape->id);
1538 /* Retrieve parameter from this custom shapes parameter db */
1539 if ((param = find_param_db(var_string, custom_shape->param_tree, TRUE)) == NULL) {
1540 //if (PARSE_DEBUG) printf("parse_shapecode: failed to create parameter.\n");
1543 //if (PARSE_DEBUG) printf("parse_shapecode: custom shape parameter found (name = %s)\n", param->name);
1545 /* integer value (boolean is an integer in C) */
1546 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1547 if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {
1548 //if (PARSE_DEBUG) printf("parse_shapecode: error parsing integer!\n");
1554 else if (param->type == P_TYPE_DOUBLE) {
1555 if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
1556 //if (PARSE_DEBUG) printf("parse_shapecode: error parsing double!\n");
1563 //if (PARSE_DEBUG) printf("parse_shapecode: unknown parameter type!\n");
1567 /* Create new initial condition */
1568 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1569 //if (PARSE_DEBUG) printf("parse_shapecode: new_init_cond failed!\n");
1573 if (splay_insert(init_cond, param->name, custom_shape->init_cond_tree) < 0) {
1574 free_init_cond(init_cond);
1575 //if (PARSE_DEBUG) printf("parse_shapecode: initial condition already set, not reinserting it (param = \"%s\")\n", param->name);
1579 //if (PARSE_DEBUG) printf("parse_shapecode: [success]\n");
1584 int parse_wavecode_prefix(char * token, int * id, char ** var_string) {
1590 if (*var_string == NULL)
1595 len = strlen(token);
1597 /* Move pointer passed "wavecode_" prefix */
1598 if (len <= WAVECODE_STRING_LENGTH)
1600 i = WAVECODE_STRING_LENGTH;
1604 /* This loop grabs the integer id for this custom wave */
1605 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1606 if (j >= MAX_TOKEN_SIZE)
1609 (*id) = 10*(*id) + (token[i]-48);
1618 *var_string = token + i + 1;
1625 int parse_shapecode_prefix(char * token, int * id, char ** var_string) {
1631 if (*var_string == NULL)
1636 len = strlen(token);
1638 /* Move pointer passed "shapecode_" prefix */
1639 if (len <= SHAPECODE_STRING_LENGTH)
1641 i = SHAPECODE_STRING_LENGTH;
1645 /* This loop grabs the integer id for this custom shape */
1646 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1647 if (j >= MAX_TOKEN_SIZE)
1650 (*id) = 10*(*id) + (token[i]-48);
1659 *var_string = token + i + 1;
1665 int parse_wave_prefix(char * token, int * id, char ** eqn_string) {
1671 if (eqn_string == NULL)
1676 len = strlen(token);
1678 if (len <= WAVE_STRING_LENGTH)
1682 i = WAVE_STRING_LENGTH;
1686 /* This loop grabs the integer id for this custom wave */
1687 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1688 if (j >= MAX_TOKEN_SIZE)
1691 (*id) = 10*(*id) + (token[i]-48);
1699 *eqn_string = token + i + 1;
1705 int parse_shape_prefix(char * token, int * id, char ** eqn_string) {
1711 if (eqn_string == NULL)
1716 len = strlen(token);
1718 if (len <= SHAPE_STRING_LENGTH)
1722 i = SHAPE_STRING_LENGTH;
1726 /* This loop grabs the integer id for this custom wave */
1727 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1728 if (j >= MAX_TOKEN_SIZE)
1731 (*id) = 10*(*id) + (token[i]-48);
1739 *eqn_string = token + i + 1;
1745 /* Parses custom wave equations */
1746 int parse_wave(char * token, FILE * fs, preset_t * preset) {
1750 char string[MAX_TOKEN_SIZE];
1752 per_frame_eqn_t * per_frame_eqn;
1753 gen_expr_t * gen_expr;
1754 custom_wave_t * custom_wave;
1755 init_cond_t * init_cond;
1764 /* Grab custom wave id and equation type (per frame or per point) from string token */
1765 if (parse_wave_prefix(token, &id, &eqn_type) < 0) {
1766 //if (PARSE_DEBUG) printf("parse_wave: syntax error in custom wave prefix!\n");
1769 /* Retrieve custom wave associated with this id */
1770 if ((custom_wave = find_custom_wave(id, preset, TRUE)) == NULL)
1774 /* per frame init equation case */
1775 if (!strncmp(eqn_type, WAVE_INIT_STRING, WAVE_INIT_STRING_LENGTH)) {
1777 //if (PARSE_DEBUG) printf("parse_wave (per frame init): [begin] (LINE %d)\n", line_count);
1779 /* Parse the per frame equation */
1780 if ((init_cond = parse_per_frame_init_eqn(fs, preset, custom_wave->param_tree)) == NULL) {
1781 //if (PARSE_DEBUG) printf("parse_wave (per frame init): equation parsing failed (LINE %d)\n", line_count);
1785 /* Insert the equation in the per frame equation tree */
1786 if (splay_insert(init_cond, init_cond->param->name, custom_wave->per_frame_init_eqn_tree) < 0) {
1787 //if (PARSE_DEBUG) printf("parse_wave (per frame init): failed to add equation (ERROR)\n");
1788 free_init_cond(init_cond); /* will free the gen expr too */
1792 if (update_string_buffer(custom_wave->per_frame_init_eqn_string_buffer,
1793 &custom_wave->per_frame_init_eqn_string_index) < 0)
1800 /* per frame equation case */
1801 if (!strncmp(eqn_type, PER_FRAME_STRING_NO_UNDERSCORE, PER_FRAME_STRING_NO_UNDERSCORE_LENGTH)) {
1803 //if (PARSE_DEBUG) printf("parse_wave (per_frame): [start] (custom wave id = %d)\n", custom_wave->id);
1805 if (parseToken(fs, string) != tEq) {
1806 //if (PARSE_DEBUG) printf("parse_wave (per_frame): no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
1810 /* Find the parameter associated with the string in the custom wave database */
1811 if ((param = find_param_db(string, custom_wave->param_tree, TRUE)) == NULL) {
1812 //if (PARSE_DEBUG) printf("parse_wave (per_frame): parameter \"%s\" not found or cannot be malloc'ed!!\n", string);
1817 /* Make sure parameter is writable */
1818 if (param->flags & P_FLAG_READONLY) {
1819 //if (PARSE_DEBUG) printf("parse_wave (per_frame): parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1823 /* Parse right side of equation as an expression */
1825 current_wave = custom_wave;
1826 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1827 //if (PARSE_DEBUG) printf("parse_wave (per_frame): equation evaluated to null (LINE %d)\n", line_count);
1828 current_wave = NULL;
1832 current_wave = NULL;
1834 //if (PARSE_DEBUG) printf("parse_wave (per_frame): [finished parsing equation] (LINE %d)\n", line_count);
1836 /* Create a new per frame equation */
1837 if ((per_frame_eqn = new_per_frame_eqn(custom_wave->per_frame_count++, param, gen_expr)) == NULL) {
1838 //if (PARSE_DEBUG) printf("parse_wave (per_frame): failed to create a new per frame eqn, out of memory?\n");
1839 free_gen_expr(gen_expr);
1843 if (splay_insert(per_frame_eqn, &per_frame_eqn->index, custom_wave->per_frame_eqn_tree) < 0) {
1844 free_per_frame_eqn(per_frame_eqn);
1848 //if (PARSE_DEBUG) printf("parse_wave (per_frame): equation %d associated with custom wave %d [success]\n",
1849 // per_frame_eqn->index, custom_wave->id);
1852 /* Need to add stuff to string buffer so the editor can read the equations.
1853 Why not make a nice little helper function for this? - here it is: */
1856 if (update_string_buffer(custom_wave->per_frame_eqn_string_buffer, &custom_wave->per_frame_eqn_string_index) < 0)
1864 /* per point equation case */
1865 if (!strncmp(eqn_type, PER_POINT_STRING, PER_POINT_STRING_LENGTH)) {
1867 //if (PARSE_DEBUG) printf("parse_wave (per_point): per_pixel equation parsing start...(LINE %d)\n", line_count);
1869 if (parseToken(fs, string) != tEq) { /* parse per pixel operator name */
1870 //if (PARSE_DEBUG) printf("parse_wave (per_point): equal operator missing after per pixel operator! (LINE %d)\n", line_count);
1874 /* Parse right side of equation as an expression */
1875 current_wave = custom_wave;
1876 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1877 //if (PARSE_DEBUG) printf("parse_wave (per_point): equation evaluated to null? (LINE %d)\n", line_count);
1880 current_wave = NULL;
1882 /* Add the per point equation */
1883 if (add_per_point_eqn(string, gen_expr, custom_wave) < 0) {
1884 free_gen_expr(gen_expr);
1889 if (update_string_buffer(custom_wave->per_point_eqn_string_buffer, &custom_wave->per_point_eqn_string_index) < 0)
1892 //if (PARSE_DEBUG) printf("parse_wave (per_point): [finished] (custom wave id = %d)\n", custom_wave->id);
1897 /* Syntax error, return parse error */
1903 /* Parses custom shape equations */
1904 int parse_shape(char * token, FILE * fs, preset_t * preset) {
1908 char string[MAX_TOKEN_SIZE];
1910 per_frame_eqn_t * per_frame_eqn;
1911 gen_expr_t * gen_expr;
1912 custom_shape_t * custom_shape;
1913 init_cond_t * init_cond;
1923 /* Grab custom shape id and equation type (per frame or per point) from string token */
1924 if (parse_shape_prefix(token, &id, &eqn_type) < 0) {
1925 //if (PARSE_DEBUG) printf("parse_shape: syntax error in custom shape prefix!\n");
1928 /* Retrieve custom shape associated with this id */
1929 if ((custom_shape = find_custom_shape(id, preset, TRUE)) == NULL)
1933 /* per frame init equation case */
1934 if (!strncmp(eqn_type, SHAPE_INIT_STRING, SHAPE_INIT_STRING_LENGTH)) {
1936 //if (PARSE_DEBUG) printf("parse_shape (per frame init): [begin] (LINE %d)\n", line_count);
1938 /* Parse the per frame equation */
1939 if ((init_cond = parse_per_frame_init_eqn(fs, preset, custom_shape->param_tree)) == NULL) {
1940 //if (PARSE_DEBUG) printf("parse_shape (per frame init): equation parsing failed (LINE %d)\n", line_count);
1944 /* Insert the equation in the per frame equation tree */
1945 if (splay_insert(init_cond, init_cond->param->name, custom_shape->per_frame_init_eqn_tree) < 0) {
1946 //if (PARSE_DEBUG) printf("parse_shape (per frame init): failed to add equation (ERROR)\n");
1947 free_init_cond(init_cond); /* will free the gen expr too */
1951 if (update_string_buffer(custom_shape->per_frame_init_eqn_string_buffer,
1952 &custom_shape->per_frame_init_eqn_string_index) < 0)
1959 /* per frame equation case */
1960 if (!strncmp(eqn_type, PER_FRAME_STRING_NO_UNDERSCORE, PER_FRAME_STRING_NO_UNDERSCORE_LENGTH)) {
1962 //if (PARSE_DEBUG) printf("parse_shape (per_frame): [start] (custom shape id = %d)\n", custom_shape->id);
1964 if (parseToken(fs, string) != tEq) {
1965 //if (PARSE_DEBUG) printf("parse_shape (per_frame): no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
1969 /* Find the parameter associated with the string in the custom shape database */
1970 if ((param = find_param_db(string, custom_shape->param_tree, TRUE)) == NULL) {
1971 //if (PARSE_DEBUG) printf("parse_shape (per_frame): parameter \"%s\" not found or cannot be malloc'ed!!\n", string);
1976 /* Make sure parameter is writable */
1977 if (param->flags & P_FLAG_READONLY) {
1978 //if (PARSE_DEBUG) printf("parse_shape (per_frame): parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1982 /* Parse right side of equation as an expression */
1984 current_shape = custom_shape;
1985 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1986 //if (PARSE_DEBUG) printf("parse_shape (per_frame): equation evaluated to null (LINE %d)\n", line_count);
1987 current_shape = NULL;
1991 current_shape = NULL;
1993 //if (PARSE_DEBUG) printf("parse_shape (per_frame): [finished parsing equation] (LINE %d)\n", line_count);
1995 /* Create a new per frame equation */
1996 if ((per_frame_eqn = new_per_frame_eqn(custom_shape->per_frame_count++, param, gen_expr)) == NULL) {
1997 //if (PARSE_DEBUG) printf("parse_shape (per_frame): failed to create a new per frame eqn, out of memory?\n");
1998 free_gen_expr(gen_expr);
2002 if (splay_insert(per_frame_eqn, &per_frame_eqn->index, custom_shape->per_frame_eqn_tree) < 0) {
2003 free_per_frame_eqn(per_frame_eqn);
2007 //if (PARSE_DEBUG) printf("parse_shape (per_frame): equation %d associated with custom shape %d [success]\n",
2008 // per_frame_eqn->index, custom_shape->id);
2011 /* Need to add stuff to string buffer so the editor can read the equations.
2012 Why not make a nice little helper function for this? - here it is: */
2014 if (update_string_buffer(custom_shape->per_frame_eqn_string_buffer, &custom_shape->per_frame_eqn_string_index) < 0)
2022 /* Syntax error, return parse error */
2026 /* Helper function to update the string buffers used by the editor */
2027 int update_string_buffer(char * buffer, int * index) {
2038 /* If the string line buffer used by the parser is already full then quit */
2039 if (string_line_buffer_index == (STRING_LINE_SIZE-1))
2042 if ((skip_size = get_string_prefix_len(string_line_buffer)) == FAILURE)
2045 string_line_buffer[string_line_buffer_index++] = '\n';
2047 // string_length = strlen(string_line_buffer + strlen(eqn_string)+1);
2048 if (skip_size >= STRING_LINE_SIZE)
2051 string_length = strlen(string_line_buffer + skip_size);
2053 if (skip_size > (STRING_LINE_SIZE-1))
2056 /* Add line to string buffer */
2057 strncpy(buffer + (*index),
2058 string_line_buffer + skip_size, string_length);
2060 /* Buffer full, quit */
2061 if ((*index) > (STRING_BUFFER_SIZE - 1)) {
2062 //if (PARSE_DEBUG) printf("update_string_buffer: string buffer full!\n");
2066 /* Otherwise, increment string index by the added string length */
2067 (*index)+=string_length;
2074 /* Helper function: returns the length of the prefix portion in the line
2075 buffer (the passed string here). In other words, given
2076 the string 'per_frame_1 = x = ....', return the length of 'per_frame_1 = '
2077 Returns -1 if syntax error
2080 int get_string_prefix_len(char * string) {
2084 /* Null argument check */
2089 /* First find the equal sign */
2090 while (string[i] != '=') {
2096 /* If the string already ends at the next char then give up */
2097 if (string[i+1] == 0)
2100 /* Move past the equal sign */
2103 /* Now found the start of the LHS variable, ie skip the spaces */
2104 while(string[i] == ' ') {
2108 /* If this is the end of the string then its a syntax error */
2112 /* Finished succesfully, return the length */