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 *****************************************************************************/
34 #include "splaytree_types.h"
35 #include "splaytree.h"
36 #include "tree_types.h"
38 #include "expr_types.h"
41 #include "param_types.h"
44 #include "func_types.h"
47 #include "preset_types.h"
48 #include "builtin_funcs.h"
50 #include "per_pixel_eqn_types.h"
51 #include "per_pixel_eqn.h"
53 #include "init_cond_types.h"
54 #include "init_cond.h"
56 #include "per_frame_eqn_types.h"
57 #include "per_frame_eqn.h"
60 #include "engine_vars.h"
62 #include "custom_wave_types.h"
63 #include "custom_wave.h"
65 #include "custom_shape_types.h"
66 #include "custom_shape.h"
68 /* Strings that prefix (and denote the type of) equations */
71 #define PER_FRAME_STRING "per_frame_"
72 #define PER_FRAME_STRING_LENGTH 10
74 #define PER_PIXEL_STRING "per_pixel_"
75 #define PER_PIXEL_STRING_LENGTH 10
77 #define PER_FRAME_INIT_STRING "per_frame_init_"
78 #define PER_FRAME_INIT_STRING_LENGTH 15
80 #define WAVECODE_STRING "wavecode_"
81 #define WAVECODE_STRING_LENGTH 9
83 #define WAVE_STRING "wave_"
84 #define WAVE_STRING_LENGTH 5
86 #define PER_POINT_STRING "per_point"
87 #define PER_POINT_STRING_LENGTH 9
89 #define PER_FRAME_STRING_NO_UNDERSCORE "per_frame"
90 #define PER_FRAME_STRING_NO_UNDERSCORE_LENGTH 9
92 #define SHAPECODE_STRING "shapecode_"
93 #define SHAPECODE_STRING_LENGTH 10
95 #define SHAPE_STRING "shape_"
96 #define SHAPE_STRING_LENGTH 6
98 #define SHAPE_INIT_STRING "init"
99 #define SHAPE_INIT_STRING_LENGTH 4
101 #define WAVE_INIT_STRING "init"
102 #define WAVE_INIT_STRING_LENGTH 4
104 /* Stores a line of a file as its being parsed */
105 char string_line_buffer[STRING_LINE_SIZE];
107 /* The current position of the string line buffer (see above) */
108 int string_line_buffer_index = 0;
110 /* All infix operators (except '=') are prototyped here */
111 extern infix_op_t * infix_add, * infix_minus, * infix_div, * infix_mult,
112 * infix_or, * infix_and, * infix_mod, * infix_positive, * infix_negative;
114 /* If the parser reads a line with a custom wave, this pointer is set to
115 the custom wave of concern */
116 custom_wave_t * current_wave = NULL;
117 custom_shape_t * current_shape = NULL;
118 /* Counts the number of lines parsed */
119 unsigned int line_count = 1;
120 int per_frame_eqn_count = 0;
121 int per_frame_init_eqn_count = 0;
128 CUSTOM_WAVE_PER_POINT_LINE_MODE,
129 CUSTOM_WAVE_PER_FRAME_LINE_MODE,
130 CUSTOM_WAVE_WAVECODE_LINE_MODE,
131 CUSTOM_SHAPE_SHAPECODE_LINE_MODE,
134 line_mode_t line_mode = NORMAL_LINE_MODE;
136 /* Token enumeration type */
139 tEOL, /* end of a line, usually a '/n' or '/r' */
140 tEOF, /* end of file */
154 tPositive, /* + as a prefix operator */
155 tNegative, /* - as a prefix operator */
157 tStringTooLong, /* special token to indicate an invalid string length */
158 tStringBufferFilled /* the string buffer for this line is maxed out */
162 int get_string_prefix_len(char * string);
163 tree_expr_t * insert_gen_expr(gen_expr_t * gen_expr, tree_expr_t ** root);
164 tree_expr_t * insert_infix_op(infix_op_t * infix_op, tree_expr_t ** root);
165 token_t parseToken(FILE * fs, char * string);
166 gen_expr_t ** parse_prefix_args(FILE * fs, int num_args, struct PRESET_T * preset);
167 gen_expr_t * parse_infix_op(FILE * fs, token_t token, tree_expr_t * tree_expr, struct PRESET_T * preset);
168 gen_expr_t * parse_sign_arg(FILE * fs);
169 int parse_float(FILE * fs, double * float_ptr);
170 int parse_int(FILE * fs, int * int_ptr);
171 int insert_gen_rec(gen_expr_t * gen_expr, tree_expr_t * root);
172 int insert_infix_rec(infix_op_t * infix_op, tree_expr_t * root);
173 gen_expr_t * parse_gen_expr(FILE * fs, tree_expr_t * tree_expr, struct PRESET_T * preset);
174 per_frame_eqn_t * parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, struct PRESET_T * preset);
175 init_cond_t * parse_per_frame_init_eqn(FILE * fs, struct PRESET_T * preset, splaytree_t * database);
176 int parse_wavecode_prefix(char * token, int * id, char ** var_string);
177 int parse_wavecode(char * token, FILE * fs, preset_t * preset);
178 int parse_wave_prefix(char * token, int * id, char ** eqn_string);
180 int parse_shapecode(char * eqn_string, FILE * fs, preset_t * preset);
181 int parse_shapecode_prefix(char * token, int * id, char ** var_string);
183 int parse_wave(char * eqn_string, FILE * fs, preset_t * preset);
184 int parse_shape(char * eqn_string, FILE * fs, preset_t * preset);
185 int parse_shape_prefix(char * token, int * id, char ** eqn_string);
187 int update_string_buffer(char * buffer, int * index);
188 int string_to_float(char * string, double * float_ptr);
190 /* Grabs the next token from the file. The second argument points
193 token_t parseToken(FILE * fs, char * string) {
199 memset(string, 0, MAX_TOKEN_SIZE);
201 /* Loop until a delimiter is found, or the maximum string size is found */
202 for (i = 0; i < MAX_TOKEN_SIZE;i++) {
205 /* If the string line buffer is full, quit */
206 if (string_line_buffer_index == (STRING_LINE_SIZE - 1))
207 return tStringBufferFilled;
209 /* Otherwise add this character to the string line buffer */
210 string_line_buffer[string_line_buffer_index++] = c;
211 /* Now interpret the character */
222 /* check for line comment here */
223 if ((c = fgetc(fs)) == '/') {
227 line_mode = NORMAL_LINE_MODE;
231 line_mode = NORMAL_LINE_MODE;
238 /* Otherwise, just a regular division operator */
262 line_mode = NORMAL_LINE_MODE;
268 case ' ': /* space, skip the character */
273 line_mode = NORMAL_LINE_MODE;
283 /* String reached maximum length, return special token error */
284 return tStringTooLong;
288 /* Parse input in the form of "exp, exp, exp, ...)"
289 Returns a general expression list */
291 gen_expr_t ** parse_prefix_args(FILE * fs, int num_args, struct PRESET_T * preset) {
294 gen_expr_t ** expr_list; /* List of arguments to function */
295 gen_expr_t * gen_expr;
297 /* Malloc the expression list */
298 expr_list = (gen_expr_t**)malloc(sizeof(gen_expr_t*)*num_args);
301 if (expr_list == NULL)
307 while (i < num_args) {
308 //if (PARSE_DEBUG) printf("parse_prefix_args: parsing argument %d...\n", i+1);
309 /* Parse the ith expression in the list */
310 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
311 //if (PARSE_DEBUG) printf("parse_prefix_args: failed to get parameter # %d for function (LINE %d)\n", i+1, line_count);
312 for (j = 0; j < i; j++)
313 free_gen_expr(expr_list[j]);
317 /* Assign entry in expression list */
318 expr_list[i++] = gen_expr;
321 //if (PARSE_DEBUG) printf("parse_prefix_args: finished parsing %d arguments (LINE %d)\n", num_args, line_count);
322 /* Finally, return the resulting expression list */
327 /* Parses a comment at the top of the file. Stops when left bracket is found */
328 int parse_top_comment(FILE * fs) {
330 char string[MAX_TOKEN_SIZE];
333 /* Process tokens until left bracket is found */
334 while ((token = parseToken(fs, string)) != tLBr) {
339 /* Done, return success */
343 /* Right Bracket is parsed by this function.
344 puts a new string into name */
345 int parse_preset_name(FILE * fs, char * name) {
352 if ((token = parseToken(fs, name)) != tRBr)
355 //if (PARSE_DEBUG) printf("parse_preset_name: parsed preset (name = \"%s\")\n", name);
361 /* Parses per pixel equations */
362 int parse_per_pixel_eqn(FILE * fs, preset_t * preset) {
365 char string[MAX_TOKEN_SIZE];
366 gen_expr_t * gen_expr;
368 if (PARSE_DEBUG) printf("parse_per_pixel: per_pixel equation parsing start...(LINE %d)\n", line_count);
370 if (parseToken(fs, string) != tEq) { /* parse per pixel operator name */
371 if (PARSE_DEBUG) printf("parse_per_pixel: equal operator expected after per pixel operator \"%s\", but not found (LINE %d)\n",
376 /* Parse right side of equation as an expression */
377 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
378 if (PARSE_DEBUG) printf("parse_per_pixel: equation evaluated to null? (LINE %d)\n", line_count);
382 /* Add the per pixel equation */
383 if (add_per_pixel_eqn(string, gen_expr, preset) < 0) {
384 free_gen_expr(gen_expr);
391 /* Parses an equation line, this function is way too big, should add some helper functions */
392 int parse_line(FILE * fs, struct PRESET_T * preset) {
394 char eqn_string[MAX_TOKEN_SIZE];
396 init_cond_t * init_cond;
397 per_frame_eqn_t * per_frame_eqn;
399 /* Clear the string line buffer */
400 memset(string_line_buffer, 0, STRING_LINE_SIZE);
401 string_line_buffer_index = 0;
404 switch (token = parseToken(fs, eqn_string)) {
420 // if (PARSE_DEBUG) printf("parse_line: invalid token found at start of line (LINE %d)\n", line_count);
421 /* Invalid token found, return a parse error */
425 case tEOL: /* Empty line */
426 line_mode = NORMAL_LINE_MODE;
429 case tEOF: /* End of File */
430 line_mode = NORMAL_LINE_MODE;
434 case tSemiColon: /* Indicates end of expression */
437 /* Valid Case, either an initial condition or equation should follow */
440 /* CASE: PER FRAME INIT EQUATION */
441 if (!strncmp(eqn_string, PER_FRAME_INIT_STRING, PER_FRAME_INIT_STRING_LENGTH)) {
443 //if (PARSE_DEBUG) printf("parse_line: per frame init equation found...(LINE %d)\n", line_count);
445 /* Set the line mode to normal */
446 line_mode = NORMAL_LINE_MODE;
448 /* Parse the per frame equation */
449 if ((init_cond = parse_per_frame_init_eqn(fs, preset, NULL)) == NULL) {
450 //if (PARSE_DEBUG) printf("parse_line: per frame init equation parsing failed (LINE %d)\n", line_count);
454 /* Insert the equation in the per frame equation tree */
455 if (splay_insert(init_cond, init_cond->param->name, preset->per_frame_init_eqn_tree) < 0) {
456 //if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
457 free_init_cond(init_cond); /* will free the gen expr too */
462 if (update_string_buffer(preset->per_frame_init_eqn_string_buffer,
463 &preset->per_frame_init_eqn_string_index) < 0)
470 /* Per frame equation case */
471 if (!strncmp(eqn_string, PER_FRAME_STRING, PER_FRAME_STRING_LENGTH)) {
473 /* Sometimes per frame equations are implicitly defined without the
474 per_frame_ prefix. This informs the parser that one could follow */
475 line_mode = PER_FRAME_LINE_MODE;
477 //if (PARSE_DEBUG) printf("parse_line: per frame equation found...(LINE %d)\n", line_count);
479 /* Parse the per frame equation */
480 if ((per_frame_eqn = parse_per_frame_eqn(fs, ++per_frame_eqn_count, preset)) == NULL) {
481 if (PARSE_DEBUG) printf("parse_line: per frame equation parsing failed (LINE %d)\n", line_count);
485 /* Insert the equation in the per frame equation tree */
486 if (splay_insert(per_frame_eqn, &per_frame_eqn_count, preset->per_frame_eqn_tree) < 0) {
487 if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
488 free_per_frame_eqn(per_frame_eqn); /* will free the gen expr too */
492 if (update_string_buffer(preset->per_frame_eqn_string_buffer,
493 &preset->per_frame_eqn_string_index) < 0)
502 /* Wavecode initial condition case */
503 if (!strncmp(eqn_string, WAVECODE_STRING, WAVECODE_STRING_LENGTH)) {
505 line_mode = CUSTOM_WAVE_WAVECODE_LINE_MODE;
508 // printf("parse_line: wavecode prefix found: \"%s\"\n", eqn_string);
510 // printf("string:%d\n", 5);
512 //SUPER MYSTERIO-BUG - Don't Remove
515 return parse_wavecode(eqn_string, fs, preset);
518 /* Custom Wave Prefix */
519 if ((!strncmp(eqn_string, WAVE_STRING, WAVE_STRING_LENGTH)) &&
520 ((eqn_string[5] >= 48) && (eqn_string[5] <= 57))) {
522 // if (PARSE_DEBUG) printf("parse_line wave prefix found: \"%s\"\n", eqn_string);
524 return parse_wave(eqn_string, fs, preset);
529 /* Shapecode initial condition case */
530 if (!strncmp(eqn_string, SHAPECODE_STRING, SHAPECODE_STRING_LENGTH)) {
532 line_mode = CUSTOM_SHAPE_SHAPECODE_LINE_MODE;
534 if (PARSE_DEBUG) printf("parse_line: shapecode prefix found: \"%s\"\n", eqn_string);
536 return parse_shapecode(eqn_string, fs, preset);
539 /* Custom Shape Prefix */
540 if ((!strncmp(eqn_string, SHAPE_STRING, SHAPE_STRING_LENGTH)) &&
541 ((eqn_string[6] >= 48) && (eqn_string[6] <= 57))) {
543 if (PARSE_DEBUG) printf("parse_line shape prefix found: \"%s\"\n", eqn_string);
544 return parse_shape(eqn_string, fs, preset);
548 /* Per pixel equation case */
549 if (!strncmp(eqn_string, PER_PIXEL_STRING, PER_PIXEL_STRING_LENGTH)) {
550 line_mode = PER_PIXEL_LINE_MODE;
552 if (parse_per_pixel_eqn(fs, preset) < 0)
556 if (update_string_buffer(preset->per_pixel_eqn_string_buffer,
557 &preset->per_pixel_eqn_string_index) < 0)
560 if (PARSE_DEBUG) printf("parse_line: finished parsing per pixel equation (LINE %d)\n", line_count);
564 /* Sometimes equations are written implicitly in milkdrop files, in the form
566 per_frame_1 = p1 = eqn1; p2 = eqn2; p3 = eqn3;..;
568 which is analagous to:
570 per_frame_1 = p1 = eqn1; per_frame_2 = p2 = eqn2; per_frame_3 = p3 = eqn3; ...;
572 The following line mode hack allows such implicit declaration of the
573 prefix that specifies the equation type. An alternative method
574 may be to associate each equation line as list of equations separated
575 by semicolons (and a new line ends the list). Instead, however, a global
576 variable called "line_mode" specifies the last type of equation found,
577 and bases any implicitly typed input on this fact
579 Note added by Carmelo Piccione (cep@andrew.cmu.edu) 10/19/03
582 /* Per frame line mode previously, try to parse the equation implicitly */
583 if (line_mode == PER_FRAME_LINE_MODE) {
584 if ((per_frame_eqn = parse_implicit_per_frame_eqn(fs, eqn_string, ++per_frame_eqn_count, preset)) == NULL)
587 /* Insert the equation in the per frame equation tree */
588 if (splay_insert(per_frame_eqn, &per_frame_eqn_count, preset->per_frame_eqn_tree) < 0) {
589 if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
590 free_per_frame_eqn(per_frame_eqn); /* will free the gen expr too */
595 if (update_string_buffer(preset->per_frame_eqn_string_buffer,
596 &preset->per_frame_eqn_string_index) < 0)
604 //if (PARSE_DEBUG) printf("parse_line: found initial condition: name = \"%s\" (LINE %d)\n", eqn_string, line_count);
606 /* Evaluate the initial condition */
607 if ((init_cond = parse_init_cond(fs, eqn_string, preset)) == NULL) {
608 if (PARSE_DEBUG) printf("parse_line: failed to parse initial condition (LINE %d)\n", line_count);
612 /* Add equation to initial condition tree */
613 if (splay_insert(init_cond, init_cond->param->name, preset->init_cond_tree) < 0) {
614 if (PARSE_DEBUG) printf("parse_line: failed to add initial condition \"%s\" to equation tree (LINE %d)\n",
615 init_cond->param->name, line_count);
616 free_init_cond(init_cond);
620 /* Finished with initial condition line */
621 // if (PARSE_DEBUG) printf("parse_line: initial condition parsed successfully\n");
625 /* END INITIAL CONDITIONING PARSING */
628 default: /* an uncaught type or an error has occurred */
629 if (PARSE_DEBUG) printf("parse_line: uncaught case, token val = %d\n", token);
633 /* Because of the default in the case statement,
634 control flow should never actually reach here */
640 /* Parses a general expression, this function is the meat of the parser */
641 gen_expr_t * parse_gen_expr (FILE * fs, tree_expr_t * tree_expr, struct PRESET_T * preset) {
644 char string[MAX_TOKEN_SIZE];
646 gen_expr_t * gen_expr;
648 param_t * param = NULL;
650 gen_expr_t ** expr_list;
652 switch (token = parseToken(fs,string)) {
653 /* Left Parentice Case */
656 /* CASE 1 (Left Parentice): See if the previous string before this parentice is a function name */
657 if ((func = find_func(string)) != NULL) {
658 if (PARSE_DEBUG) printf("parse_gen_expr: found prefix function (name = %s) (LINE %d)\n", func->name, line_count);
660 /* Parse the functions arguments */
661 if ((expr_list = parse_prefix_args(fs, func->num_args, preset)) == NULL) {
662 if (PARSE_DEBUG) printf("parse_prefix_args: failed to generate an expresion list! (LINE %d) \n", line_count);
663 free_tree_expr(tree_expr);
667 /* Convert function to expression */
668 if ((gen_expr = prefun_to_expr((void*)func->func_ptr, expr_list, func->num_args)) == NULL) {
669 if (PARSE_DEBUG) printf("parse_prefix_args: failed to convert prefix function to general expression (LINE %d) \n",
671 free_tree_expr(tree_expr);
672 for (i = 0; i < func->num_args;i++)
673 free_gen_expr(expr_list[i]);
680 token = parseToken(fs, string);
683 if (PARSE_DEBUG) printf("parse_prefix_args: empty string expected, but not found...(LINE %d)\n", line_count);
684 /* continue anyway for now, could be implicit multiplication */
687 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
691 /* Case 2: (Left Parentice), a string coupled with a left parentice. Either an error or implicit
692 multiplication operator. For now treat it as an error */
694 if (PARSE_DEBUG) printf("parse_gen_expr: implicit multiplication case unimplemented!\n");
695 free_tree_expr(tree_expr);
699 /* CASE 3 (Left Parentice): the following is enclosed parentices to change order
700 of operations. So we create a new expression tree */
702 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
703 //if (PARSE_DEBUG) printf("parse_gen_expr: found left parentice, but failed to create new expression tree \n");
704 free_tree_expr(tree_expr);
708 if (PARSE_DEBUG) printf("parse_gen_expr: finished enclosed expression tree...\n");
709 token = parseToken(fs, string);
710 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
712 /* Plus is a prefix operator check */
716 //if (PARSE_DEBUG) printf("parse_gen_expr: plus used as prefix (LINE %d)\n", line_count);
718 /* Treat prefix plus as implict 0 preceding operator */
719 gen_expr = const_to_expr(0);
721 return parse_infix_op(fs, tPositive, insert_gen_expr(gen_expr, &tree_expr), preset);
724 /* Minus is a prefix operator check */
728 /* Use the negative infix operator, but first add an implicit zero to the operator tree */
729 gen_expr = const_to_expr(0);
730 //return parse_gen_expr(fs, insert_gen_expr(gen_expr, &tree_expr), preset);
731 return parse_infix_op(fs, tNegative, insert_gen_expr(gen_expr, &tree_expr), preset);
734 /* All the following cases are strings followed by an infix operator or terminal */
741 /* CASE 1 (terminal): string is empty, but not null. Not sure if this will actually happen
744 //if (PARSE_DEBUG) printf("parse_gen_expr: empty string coupled with terminal (LINE %d) \n", line_count);
745 return parse_infix_op(fs, token, tree_expr, preset);
751 /* CASE 0: Empty string, parse error */
753 if (PARSE_DEBUG) printf("parse_gen_expr: empty string coupled with infix op (ERROR!) (LINE %d) \n", line_count);
754 free_tree_expr(tree_expr);
758 /* CASE 1: Check if string is a just a floating point number */
759 if (string_to_float(string, &val) != PARSE_ERROR) {
760 if ((gen_expr = const_to_expr(val)) == NULL) {
761 free_tree_expr(tree_expr);
765 /* Parse the rest of the line */
766 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
771 /* CASE 4: custom shape variable */
772 if (current_shape != NULL) {
773 if ((param = find_param_db(string, current_shape->param_tree, FALSE)) == NULL) {
774 if ((param = find_builtin_param(string)) == NULL)
775 if ((param = find_param_db(string, current_shape->param_tree, TRUE)) == NULL) {
776 free_tree_expr(tree_expr);
782 printf("parse_gen_expr: custom shape parameter (name = %s)... ", param->name);
786 /* Convert parameter to an expression */
787 if ((gen_expr = param_to_expr(param)) == NULL) {
788 free_tree_expr(tree_expr);
792 //if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
794 /* Parse the rest of the line */
795 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
798 /* CASE 5: custom wave variable */
799 if (current_wave != NULL) {
800 if ((param = find_param_db(string, current_wave->param_tree, FALSE)) == NULL) {
801 if ((param = find_builtin_param(string)) == NULL)
802 if ((param = find_param_db(string, current_wave->param_tree, TRUE)) == NULL) {
803 free_tree_expr(tree_expr);
810 printf("parse_gen_expr: custom wave parameter (name = %s)... ", param->name);
814 /* Convert parameter to an expression */
815 if ((gen_expr = param_to_expr(param)) == NULL) {
816 free_tree_expr(tree_expr);
820 if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
822 /* Parse the rest of the line */
823 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
827 /* CASE 6: regular parameter. Will be created if necessary and the string has no invalid characters */
828 if ((param = find_param(string, preset, P_CREATE)) != NULL) {
831 printf("parse_gen_expr: parameter (name = %s)... ", param->name);
835 /* Convert parameter to an expression */
836 if ((gen_expr = param_to_expr(param)) == NULL) {
837 free_tree_expr(tree_expr);
841 if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
843 /* Parse the rest of the line */
844 return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
848 /* CASE 7: Bad string, give up */
849 if (PARSE_DEBUG) printf("parse_gen_expr: syntax error [string = \"%s\"] (LINE %d)\n", string, line_count);
850 free_tree_expr(tree_expr);
857 /* Inserts expressions into tree according to operator precedence.
858 If root is null, a new tree is created, with gen_expr as only element */
860 tree_expr_t * insert_infix_op(infix_op_t * infix_op, tree_expr_t **root) {
862 tree_expr_t * new_root;
865 if (infix_op == NULL)
868 /* The root is null, so make this operator
872 new_root = new_tree_expr(infix_op, NULL, NULL, NULL);
877 /* The root node is not an infix function,
878 so we make this infix operator the new root */
880 if ((*root)->infix_op == NULL) {
881 new_root = new_tree_expr(infix_op, NULL, *root, NULL);
886 /* The root is an infix function. If the precedence
887 of the item to be inserted is greater than the root's
888 precedence, then make gen_expr the root */
890 if (infix_op->precedence > (*root)->infix_op->precedence) {
891 new_root = new_tree_expr(infix_op, NULL, *root, NULL);
896 /* If control flow reaches here, use a recursive helper
897 with the knowledge that the root is higher precedence
898 than the item to be inserted */
900 insert_infix_rec(infix_op, *root);
906 tree_expr_t * insert_gen_expr(gen_expr_t * gen_expr, tree_expr_t ** root) {
908 tree_expr_t * new_root;
910 /* If someone foolishly passes a null
911 pointer to insert, return the original tree */
913 if (gen_expr == NULL) {
917 /* If the root is null, generate a new expression tree,
918 using the passed expression as the root element */
921 new_root = new_tree_expr(NULL, gen_expr, NULL, NULL);
927 /* Otherwise. the new element definitely will not replace the current root.
928 Use a recursive helper function to do insertion */
930 insert_gen_rec(gen_expr, *root);
934 /* A recursive helper function to insert general expression elements into the operator tree */
935 int insert_gen_rec(gen_expr_t * gen_expr, tree_expr_t * root) {
937 /* Trivial Case: root is null */
940 ////if (PARSE_DEBUG) printf("insert_gen_rec: root is null, returning failure\n");
945 /* The current node's left pointer is null, and this
946 current node is an infix operator, so insert the
947 general expression at the left pointer */
949 if ((root->left == NULL) && (root->infix_op != NULL)) {
950 root->left = new_tree_expr(NULL, gen_expr, NULL, NULL);
954 /* The current node's right pointer is null, and this
955 current node is an infix operator, so insert the
956 general expression at the right pointer */
958 if ((root->right == NULL) && (root->infix_op != NULL)) {
959 root->right = new_tree_expr(NULL, gen_expr, NULL, NULL);
963 /* Otherwise recurse down to the left. If
964 this succeeds then return. If it fails, try
965 recursing down to the right */
967 if (insert_gen_rec(gen_expr, root->left) == FAILURE)
968 return insert_gen_rec(gen_expr, root->right);
970 /* Impossible for control flow to reach here, but in
971 the world of C programming, who knows... */
972 //if (PARSE_DEBUG) printf("insert_gen_rec: should never reach here!\n");
977 /* A recursive helper function to insert infix arguments by operator precedence */
978 int insert_infix_rec(infix_op_t * infix_op, tree_expr_t * root) {
980 /* Shouldn't happen, implies a parse error */
985 /* Also shouldn't happen, also implies a (different) parse error */
987 if (root->infix_op == NULL)
990 /* Left tree is empty, attach this operator to it.
991 I don't think this will ever happen */
992 if (root->left == NULL) {
993 root->left = new_tree_expr(infix_op, NULL, root->left, NULL);
997 /* Right tree is empty, attach this operator to it */
998 if (root->right == NULL) {
999 root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
1003 /* The left element can now be ignored, since there is no way for this
1004 operator to use those expressions */
1006 /* If the right element is not an infix operator,
1007 then insert the expression here, attaching the old right branch
1008 to the left of the new expression */
1010 if (root->right->infix_op == NULL) {
1011 root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
1015 /* Traverse deeper if the inserting operator precedence is less than the
1016 the root's right operator precedence */
1017 if (infix_op->precedence < root->right->infix_op->precedence)
1018 return insert_infix_rec(infix_op, root->right);
1020 /* Otherwise, insert the operator here */
1022 root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
1027 /* Parses an infix operator */
1028 gen_expr_t * parse_infix_op(FILE * fs, token_t token, tree_expr_t * tree_expr, struct PRESET_T * preset) {
1030 gen_expr_t * gen_expr;
1033 /* All the infix operators */
1035 //if (PARSE_DEBUG) printf("parse_infix_op: found addition operator (LINE %d)\n", line_count);
1036 return parse_gen_expr(fs, insert_infix_op(infix_add, &tree_expr), preset);
1038 //if (PARSE_DEBUG) printf("parse_infix_op: found subtraction operator (LINE %d)\n", line_count);
1039 return parse_gen_expr(fs, insert_infix_op(infix_minus, &tree_expr), preset);
1041 //if (PARSE_DEBUG) printf("parse_infix_op: found multiplication operator (LINE %d)\n", line_count);
1042 return parse_gen_expr(fs, insert_infix_op(infix_mult, &tree_expr), preset);
1044 //if (PARSE_DEBUG) printf("parse_infix_op: found division operator (LINE %d)\n", line_count);
1045 return parse_gen_expr(fs, insert_infix_op(infix_div, &tree_expr), preset);
1047 //if (PARSE_DEBUG) printf("parse_infix_op: found modulo operator (LINE %d)\n", line_count);
1048 return parse_gen_expr(fs, insert_infix_op(infix_mod, &tree_expr), preset);
1050 //if (PARSE_DEBUG) printf("parse_infix_op: found bitwise or operator (LINE %d)\n", line_count);
1051 return parse_gen_expr(fs, insert_infix_op(infix_or, &tree_expr), preset);
1053 //if (PARSE_DEBUG) printf("parse_infix_op: found bitwise and operator (LINE %d)\n", line_count);
1054 return parse_gen_expr(fs, insert_infix_op(infix_and, &tree_expr), preset);
1056 //if (PARSE_DEBUG) printf("parse_infix_op: found positive operator (LINE %d)\n", line_count);
1057 return parse_gen_expr(fs, insert_infix_op(infix_positive, &tree_expr), preset);
1059 //if (PARSE_DEBUG) printf("parse_infix_op: found negative operator (LINE %d)\n", line_count);
1060 return parse_gen_expr(fs, insert_infix_op(infix_negative, &tree_expr), preset);
1067 //if (PARSE_DEBUG) printf("parse_infix_op: terminal found (LINE %d)\n", line_count);
1068 gen_expr = new_gen_expr(TREE_T, (void*)tree_expr);
1071 //if (PARSE_DEBUG) printf("parse_infix_op: operator or terminal expected, but not found (LINE %d)\n", line_count);
1072 free_tree_expr(tree_expr);
1076 /* Will never happen */
1081 /* Parses an integer, checks for +/- prefix */
1082 int parse_int(FILE * fs, int * int_ptr) {
1084 char string[MAX_TOKEN_SIZE];
1087 char * end_ptr = " ";
1089 token = parseToken(fs, string);
1095 token = parseToken(fs, string);
1099 token = parseToken(fs, string);
1110 /* Convert the string to an integer. *end_ptr
1111 should end up pointing to null terminator of 'string'
1112 if the conversion was successful. */
1113 // printf("STRING: \"%s\"\n", string);
1115 (*int_ptr) = sign*strtol(string, &end_ptr, 10);
1117 /* If end pointer is a return character or null terminator, all is well */
1118 if ((*end_ptr == '\r') || (*end_ptr == '\0'))
1124 /* Parses a floating point number */
1125 int string_to_float(char * string, double * float_ptr) {
1132 error_ptr = malloc(sizeof(char**));
1134 (*float_ptr) = strtod(string, error_ptr);
1136 /* These imply a succesful parse of the string */
1137 if ((**error_ptr == '\0') || (**error_ptr == '\r')) {
1147 /* Parses a floating point number */
1148 int parse_float(FILE * fs, double * float_ptr) {
1150 char string[MAX_TOKEN_SIZE];
1155 error_ptr = malloc(sizeof(char**));
1157 token = parseToken(fs, string);
1162 token = parseToken(fs, string);
1166 token = parseToken(fs, string);
1172 if (string[0] == 0) {
1177 (*float_ptr) = sign*strtod(string, error_ptr);
1179 /* No conversion was performed */
1180 if ((**error_ptr == '\0') || (**error_ptr == '\r')) {
1185 //if (PARSE_DEBUG) printf("parse_float: double conversion failed for string \"%s\"\n", string);
1195 /* Parses a per frame equation. That is, interprets a stream of data as a per frame equation */
1196 per_frame_eqn_t * parse_per_frame_eqn(FILE * fs, int index, struct PRESET_T * preset) {
1198 char string[MAX_TOKEN_SIZE];
1200 per_frame_eqn_t * per_frame_eqn;
1201 gen_expr_t * gen_expr;
1203 if (parseToken(fs, string) != tEq) {
1204 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
1208 /* Find the parameter associated with the string, create one if necessary */
1209 if ((param = find_param(string, preset, P_CREATE)) == NULL) {
1213 /* Make sure parameter is writable */
1214 if (param->flags & P_FLAG_READONLY) {
1215 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1219 /* Parse right side of equation as an expression */
1220 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1221 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: equation evaluated to null (LINE %d)\n", line_count);
1225 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: finished per frame equation evaluation (LINE %d)\n", line_count);
1227 /* Create a new per frame equation */
1228 if ((per_frame_eqn = new_per_frame_eqn(index, param, gen_expr)) == NULL) {
1229 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: failed to create a new per frame eqn, out of memory?\n");
1230 free_gen_expr(gen_expr);
1234 //if (PARSE_DEBUG) printf("parse_per_frame_eqn: per_frame eqn parsed succesfully\n");
1236 return per_frame_eqn;
1239 /* Parses an 'implicit' per frame equation. That is, interprets a stream of data as a per frame equation without a prefix */
1240 per_frame_eqn_t * parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, struct PRESET_T * preset) {
1243 per_frame_eqn_t * per_frame_eqn;
1244 gen_expr_t * gen_expr;
1248 if (param_string == NULL)
1253 //rintf("param string: %s\n", param_string);
1254 /* Find the parameter associated with the string, create one if necessary */
1255 if ((param = find_param(param_string, preset, P_CREATE)) == NULL) {
1259 //printf("parse_implicit_per_frame_eqn: param is %s\n", param->name);
1261 /* Make sure parameter is writable */
1262 if (param->flags & P_FLAG_READONLY) {
1263 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1267 /* Parse right side of equation as an expression */
1268 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1269 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: equation evaluated to null (LINE %d)\n", line_count);
1273 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: finished per frame equation evaluation (LINE %d)\n", line_count);
1275 /* Create a new per frame equation */
1276 if ((per_frame_eqn = new_per_frame_eqn(index, param, gen_expr)) == NULL) {
1277 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: failed to create a new per frame eqn, out of memory?\n");
1278 free_gen_expr(gen_expr);
1282 //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: per_frame eqn parsed succesfully\n");
1284 return per_frame_eqn;
1287 /* Parses an initial condition */
1288 init_cond_t * parse_init_cond(FILE * fs, char * name, struct PRESET_T * preset) {
1292 init_cond_t * init_cond;
1299 /* Search for the paramater in the database, creating it if necessary */
1300 if ((param = find_param(name, preset, P_CREATE)) == NULL) {
1304 //if (PARSE_DEBUG) printf("parse_init_cond: parameter = \"%s\" (LINE %d)\n", param->name, line_count);
1306 if (param->flags & P_FLAG_READONLY) {
1307 //if (PARSE_DEBUG) printf("parse_init_cond: builtin parameter \"%s\" marked as read only!\n", param->name);
1311 /* At this point, a parameter has been created or was found
1314 //if (PARSE_DEBUG) printf("parse_init_cond: parsing initial condition value... (LINE %d)\n", line_count);
1316 /* integer value (boolean is an integer in C) */
1317 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1318 if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {
1319 //if (PARSE_DEBUG) printf("parse_init_cond: error parsing integer!\n");
1325 else if (param->type == P_TYPE_DOUBLE) {
1326 if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
1327 //if (PARSE_DEBUG) printf("parse_init_cond: error parsing double!\n");
1334 //if (PARSE_DEBUG) printf("parse_init_cond: unknown parameter type!\n");
1338 /* Create new initial condition */
1339 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1340 //if (PARSE_DEBUG) printf("parse_init_cond: new_init_cond failed!\n");
1348 /* Parses a per frame init equation, not sure if this works right now */
1349 init_cond_t * parse_per_frame_init_eqn(FILE * fs, struct PRESET_T * preset, splaytree_t * database) {
1351 char name[MAX_TOKEN_SIZE];
1352 param_t * param = NULL;
1354 init_cond_t * init_cond;
1355 gen_expr_t * gen_expr;
1365 if ((token = parseToken(fs, name)) != tEq)
1369 /* If a database was specified,then use find_param_db instead */
1370 if ((database != NULL) && ((param = find_param_db(name, database, TRUE)) == NULL)) {
1374 /* Otherwise use the builtin parameter and user databases. This is confusing. Sorry. */
1375 if ((param == NULL) && ((param = find_param(name, preset, P_CREATE)) == NULL)) {
1379 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: parameter = \"%s\" (LINE %d)\n", param->name, line_count);
1381 if (param->flags & P_FLAG_READONLY) {
1382 //if (PARSE_DEBUG) printf("pars_per_frame_init_eqn: builtin parameter \"%s\" marked as read only!\n", param->name);
1386 /* At this point, a parameter has been created or was found
1389 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: parsing right hand side of per frame init equation.. (LINE %d)\n", line_count);
1391 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1392 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: failed to parse general expresion!\n");
1396 /* Compute initial condition value */
1397 val = eval_gen_expr(gen_expr);
1399 /* Free the general expression now that we are done with it */
1400 free_gen_expr(gen_expr);
1402 /* integer value (boolean is an integer in C) */
1403 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1404 init_val.int_val = (int)val;
1408 else if (param->type == P_TYPE_DOUBLE) {
1409 init_val.double_val = val;
1414 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: unknown parameter type!\n");
1419 /* Create new initial condition */
1420 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1421 //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: new_init_cond failed!\n");
1430 int parse_wavecode(char * token, FILE * fs, preset_t * preset) {
1433 init_cond_t * init_cond;
1434 custom_wave_t * custom_wave;
1439 /* Null argument checks */
1447 /* token should be in the form wavecode_N_var, such as wavecode_1_samples */
1449 /* Get id and variable name from token string */
1450 if (parse_wavecode_prefix(token, &id, &var_string) < 0)
1453 //if (PARSE_DEBUG) printf("parse_wavecode: wavecode id = %d, parameter = \"%s\"\n", id, var_string);
1455 /* Retrieve custom wave information from preset. The 3rd argument
1456 if true creates a custom wave if one does not exist */
1457 if ((custom_wave = find_custom_wave(id, preset, TRUE)) == NULL) {
1458 //if (PARSE_DEBUG) printf("parse_wavecode: failed to load (or create) custom wave (id = %d)!\n", id);
1461 //if (PARSE_DEBUG) printf("parse_wavecode: custom wave found (id = %d)\n", custom_wave->id);
1463 /* Retrieve parameter from this custom waves parameter db */
1464 if ((param = find_param_db(var_string, custom_wave->param_tree, TRUE)) == NULL)
1467 //if (PARSE_DEBUG) printf("parse_wavecode: custom wave parameter found (name = %s)\n", param->name);
1469 /* integer value (boolean is an integer in C) */
1470 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1471 if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {
1472 //if (PARSE_DEBUG) printf("parse_wavecode: error parsing integer!\n");
1478 else if (param->type == P_TYPE_DOUBLE) {
1479 if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
1480 //if (PARSE_DEBUG) printf("parse_wavecode: error parsing double!\n");
1487 //if (PARSE_DEBUG) printf("parse_wavecode: unknown parameter type!\n");
1491 /* Create new initial condition */
1492 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1493 //if (PARSE_DEBUG) printf("parse_wavecode: new_init_cond failed!\n");
1497 if (splay_insert(init_cond, param->name, custom_wave->init_cond_tree) < 0) {
1498 free_init_cond(init_cond);
1502 //if (PARSE_DEBUG) printf("parse_wavecode: [success]\n");
1506 int parse_shapecode(char * token, FILE * fs, preset_t * preset) {
1509 init_cond_t * init_cond;
1510 custom_shape_t * custom_shape;
1515 /* Null argument checks */
1523 /* token should be in the form shapecode_N_var, such as shapecode_1_samples */
1525 /* Get id and variable name from token string */
1526 if (parse_shapecode_prefix(token, &id, &var_string) < 0)
1529 //if (PARSE_DEBUG) printf("parse_shapecode: shapecode id = %d, parameter = \"%s\"\n", id, var_string);
1531 /* Retrieve custom shape information from preset. The 3rd argument
1532 if true creates a custom shape if one does not exist */
1533 if ((custom_shape = find_custom_shape(id, preset, TRUE)) == NULL) {
1534 //if (PARSE_DEBUG) printf("parse_shapecode: failed to load (or create) custom shape (id = %d)!\n", id);
1537 //if (PARSE_DEBUG) printf("parse_shapecode: custom shape found (id = %d)\n", custom_shape->id);
1539 /* Retrieve parameter from this custom shapes parameter db */
1540 if ((param = find_param_db(var_string, custom_shape->param_tree, TRUE)) == NULL) {
1541 //if (PARSE_DEBUG) printf("parse_shapecode: failed to create parameter.\n");
1544 //if (PARSE_DEBUG) printf("parse_shapecode: custom shape parameter found (name = %s)\n", param->name);
1546 /* integer value (boolean is an integer in C) */
1547 if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
1548 if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {
1549 //if (PARSE_DEBUG) printf("parse_shapecode: error parsing integer!\n");
1555 else if (param->type == P_TYPE_DOUBLE) {
1556 if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
1557 //if (PARSE_DEBUG) printf("parse_shapecode: error parsing double!\n");
1564 //if (PARSE_DEBUG) printf("parse_shapecode: unknown parameter type!\n");
1568 /* Create new initial condition */
1569 if ((init_cond = new_init_cond(param, init_val)) == NULL) {
1570 //if (PARSE_DEBUG) printf("parse_shapecode: new_init_cond failed!\n");
1574 if (splay_insert(init_cond, param->name, custom_shape->init_cond_tree) < 0) {
1575 free_init_cond(init_cond);
1576 //if (PARSE_DEBUG) printf("parse_shapecode: initial condition already set, not reinserting it (param = \"%s\")\n", param->name);
1580 //if (PARSE_DEBUG) printf("parse_shapecode: [success]\n");
1585 int parse_wavecode_prefix(char * token, int * id, char ** var_string) {
1591 if (*var_string == NULL)
1596 len = strlen(token);
1598 /* Move pointer passed "wavecode_" prefix */
1599 if (len <= WAVECODE_STRING_LENGTH)
1601 i = WAVECODE_STRING_LENGTH;
1605 /* This loop grabs the integer id for this custom wave */
1606 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1607 if (j >= MAX_TOKEN_SIZE)
1610 (*id) = 10*(*id) + (token[i]-48);
1619 *var_string = token + i + 1;
1626 int parse_shapecode_prefix(char * token, int * id, char ** var_string) {
1632 if (*var_string == NULL)
1637 len = strlen(token);
1639 /* Move pointer passed "shapecode_" prefix */
1640 if (len <= SHAPECODE_STRING_LENGTH)
1642 i = SHAPECODE_STRING_LENGTH;
1646 /* This loop grabs the integer id for this custom shape */
1647 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1648 if (j >= MAX_TOKEN_SIZE)
1651 (*id) = 10*(*id) + (token[i]-48);
1660 *var_string = token + i + 1;
1666 int parse_wave_prefix(char * token, int * id, char ** eqn_string) {
1672 if (eqn_string == NULL)
1677 len = strlen(token);
1679 if (len <= WAVE_STRING_LENGTH)
1683 i = WAVE_STRING_LENGTH;
1687 /* This loop grabs the integer id for this custom wave */
1688 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1689 if (j >= MAX_TOKEN_SIZE)
1692 (*id) = 10*(*id) + (token[i]-48);
1700 *eqn_string = token + i + 1;
1706 int parse_shape_prefix(char * token, int * id, char ** eqn_string) {
1712 if (eqn_string == NULL)
1717 len = strlen(token);
1719 if (len <= SHAPE_STRING_LENGTH)
1723 i = SHAPE_STRING_LENGTH;
1727 /* This loop grabs the integer id for this custom wave */
1728 while ((i < len) && (token[i] >= 48) && (token[i] <= 57)) {
1729 if (j >= MAX_TOKEN_SIZE)
1732 (*id) = 10*(*id) + (token[i]-48);
1740 *eqn_string = token + i + 1;
1746 /* Parses custom wave equations */
1747 int parse_wave(char * token, FILE * fs, preset_t * preset) {
1751 char string[MAX_TOKEN_SIZE];
1753 per_frame_eqn_t * per_frame_eqn;
1754 gen_expr_t * gen_expr;
1755 custom_wave_t * custom_wave;
1756 init_cond_t * init_cond;
1765 /* Grab custom wave id and equation type (per frame or per point) from string token */
1766 if (parse_wave_prefix(token, &id, &eqn_type) < 0) {
1767 //if (PARSE_DEBUG) printf("parse_wave: syntax error in custom wave prefix!\n");
1770 /* Retrieve custom wave associated with this id */
1771 if ((custom_wave = find_custom_wave(id, preset, TRUE)) == NULL)
1775 /* per frame init equation case */
1776 if (!strncmp(eqn_type, WAVE_INIT_STRING, WAVE_INIT_STRING_LENGTH)) {
1778 //if (PARSE_DEBUG) printf("parse_wave (per frame init): [begin] (LINE %d)\n", line_count);
1780 /* Parse the per frame equation */
1781 if ((init_cond = parse_per_frame_init_eqn(fs, preset, custom_wave->param_tree)) == NULL) {
1782 //if (PARSE_DEBUG) printf("parse_wave (per frame init): equation parsing failed (LINE %d)\n", line_count);
1786 /* Insert the equation in the per frame equation tree */
1787 if (splay_insert(init_cond, init_cond->param->name, custom_wave->per_frame_init_eqn_tree) < 0) {
1788 //if (PARSE_DEBUG) printf("parse_wave (per frame init): failed to add equation (ERROR)\n");
1789 free_init_cond(init_cond); /* will free the gen expr too */
1793 if (update_string_buffer(custom_wave->per_frame_init_eqn_string_buffer,
1794 &custom_wave->per_frame_init_eqn_string_index) < 0)
1801 /* per frame equation case */
1802 if (!strncmp(eqn_type, PER_FRAME_STRING_NO_UNDERSCORE, PER_FRAME_STRING_NO_UNDERSCORE_LENGTH)) {
1804 //if (PARSE_DEBUG) printf("parse_wave (per_frame): [start] (custom wave id = %d)\n", custom_wave->id);
1806 if (parseToken(fs, string) != tEq) {
1807 //if (PARSE_DEBUG) printf("parse_wave (per_frame): no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
1811 /* Find the parameter associated with the string in the custom wave database */
1812 if ((param = find_param_db(string, custom_wave->param_tree, TRUE)) == NULL) {
1813 //if (PARSE_DEBUG) printf("parse_wave (per_frame): parameter \"%s\" not found or cannot be malloc'ed!!\n", string);
1818 /* Make sure parameter is writable */
1819 if (param->flags & P_FLAG_READONLY) {
1820 //if (PARSE_DEBUG) printf("parse_wave (per_frame): parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1824 /* Parse right side of equation as an expression */
1826 current_wave = custom_wave;
1827 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1828 //if (PARSE_DEBUG) printf("parse_wave (per_frame): equation evaluated to null (LINE %d)\n", line_count);
1829 current_wave = NULL;
1833 current_wave = NULL;
1835 //if (PARSE_DEBUG) printf("parse_wave (per_frame): [finished parsing equation] (LINE %d)\n", line_count);
1837 /* Create a new per frame equation */
1838 if ((per_frame_eqn = new_per_frame_eqn(custom_wave->per_frame_count++, param, gen_expr)) == NULL) {
1839 //if (PARSE_DEBUG) printf("parse_wave (per_frame): failed to create a new per frame eqn, out of memory?\n");
1840 free_gen_expr(gen_expr);
1844 if (splay_insert(per_frame_eqn, &per_frame_eqn->index, custom_wave->per_frame_eqn_tree) < 0) {
1845 free_per_frame_eqn(per_frame_eqn);
1849 //if (PARSE_DEBUG) printf("parse_wave (per_frame): equation %d associated with custom wave %d [success]\n",
1850 // per_frame_eqn->index, custom_wave->id);
1853 /* Need to add stuff to string buffer so the editor can read the equations.
1854 Why not make a nice little helper function for this? - here it is: */
1857 if (update_string_buffer(custom_wave->per_frame_eqn_string_buffer, &custom_wave->per_frame_eqn_string_index) < 0)
1865 /* per point equation case */
1866 if (!strncmp(eqn_type, PER_POINT_STRING, PER_POINT_STRING_LENGTH)) {
1868 //if (PARSE_DEBUG) printf("parse_wave (per_point): per_pixel equation parsing start...(LINE %d)\n", line_count);
1870 if (parseToken(fs, string) != tEq) { /* parse per pixel operator name */
1871 //if (PARSE_DEBUG) printf("parse_wave (per_point): equal operator missing after per pixel operator! (LINE %d)\n", line_count);
1875 /* Parse right side of equation as an expression */
1876 current_wave = custom_wave;
1877 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1878 //if (PARSE_DEBUG) printf("parse_wave (per_point): equation evaluated to null? (LINE %d)\n", line_count);
1881 current_wave = NULL;
1883 /* Add the per point equation */
1884 if (add_per_point_eqn(string, gen_expr, custom_wave) < 0) {
1885 free_gen_expr(gen_expr);
1890 if (update_string_buffer(custom_wave->per_point_eqn_string_buffer, &custom_wave->per_point_eqn_string_index) < 0)
1893 //if (PARSE_DEBUG) printf("parse_wave (per_point): [finished] (custom wave id = %d)\n", custom_wave->id);
1898 /* Syntax error, return parse error */
1904 /* Parses custom shape equations */
1905 int parse_shape(char * token, FILE * fs, preset_t * preset) {
1909 char string[MAX_TOKEN_SIZE];
1911 per_frame_eqn_t * per_frame_eqn;
1912 gen_expr_t * gen_expr;
1913 custom_shape_t * custom_shape;
1914 init_cond_t * init_cond;
1924 /* Grab custom shape id and equation type (per frame or per point) from string token */
1925 if (parse_shape_prefix(token, &id, &eqn_type) < 0) {
1926 //if (PARSE_DEBUG) printf("parse_shape: syntax error in custom shape prefix!\n");
1929 /* Retrieve custom shape associated with this id */
1930 if ((custom_shape = find_custom_shape(id, preset, TRUE)) == NULL)
1934 /* per frame init equation case */
1935 if (!strncmp(eqn_type, SHAPE_INIT_STRING, SHAPE_INIT_STRING_LENGTH)) {
1937 //if (PARSE_DEBUG) printf("parse_shape (per frame init): [begin] (LINE %d)\n", line_count);
1939 /* Parse the per frame equation */
1940 if ((init_cond = parse_per_frame_init_eqn(fs, preset, custom_shape->param_tree)) == NULL) {
1941 //if (PARSE_DEBUG) printf("parse_shape (per frame init): equation parsing failed (LINE %d)\n", line_count);
1945 /* Insert the equation in the per frame equation tree */
1946 if (splay_insert(init_cond, init_cond->param->name, custom_shape->per_frame_init_eqn_tree) < 0) {
1947 //if (PARSE_DEBUG) printf("parse_shape (per frame init): failed to add equation (ERROR)\n");
1948 free_init_cond(init_cond); /* will free the gen expr too */
1952 if (update_string_buffer(custom_shape->per_frame_init_eqn_string_buffer,
1953 &custom_shape->per_frame_init_eqn_string_index) < 0)
1960 /* per frame equation case */
1961 if (!strncmp(eqn_type, PER_FRAME_STRING_NO_UNDERSCORE, PER_FRAME_STRING_NO_UNDERSCORE_LENGTH)) {
1963 //if (PARSE_DEBUG) printf("parse_shape (per_frame): [start] (custom shape id = %d)\n", custom_shape->id);
1965 if (parseToken(fs, string) != tEq) {
1966 //if (PARSE_DEBUG) printf("parse_shape (per_frame): no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
1970 /* Find the parameter associated with the string in the custom shape database */
1971 if ((param = find_param_db(string, custom_shape->param_tree, TRUE)) == NULL) {
1972 //if (PARSE_DEBUG) printf("parse_shape (per_frame): parameter \"%s\" not found or cannot be malloc'ed!!\n", string);
1977 /* Make sure parameter is writable */
1978 if (param->flags & P_FLAG_READONLY) {
1979 //if (PARSE_DEBUG) printf("parse_shape (per_frame): parameter %s is marked as read only (LINE %d)\n", param->name, line_count);
1983 /* Parse right side of equation as an expression */
1985 current_shape = custom_shape;
1986 if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
1987 //if (PARSE_DEBUG) printf("parse_shape (per_frame): equation evaluated to null (LINE %d)\n", line_count);
1988 current_shape = NULL;
1992 current_shape = NULL;
1994 //if (PARSE_DEBUG) printf("parse_shape (per_frame): [finished parsing equation] (LINE %d)\n", line_count);
1996 /* Create a new per frame equation */
1997 if ((per_frame_eqn = new_per_frame_eqn(custom_shape->per_frame_count++, param, gen_expr)) == NULL) {
1998 //if (PARSE_DEBUG) printf("parse_shape (per_frame): failed to create a new per frame eqn, out of memory?\n");
1999 free_gen_expr(gen_expr);
2003 if (splay_insert(per_frame_eqn, &per_frame_eqn->index, custom_shape->per_frame_eqn_tree) < 0) {
2004 free_per_frame_eqn(per_frame_eqn);
2008 //if (PARSE_DEBUG) printf("parse_shape (per_frame): equation %d associated with custom shape %d [success]\n",
2009 // per_frame_eqn->index, custom_shape->id);
2012 /* Need to add stuff to string buffer so the editor can read the equations.
2013 Why not make a nice little helper function for this? - here it is: */
2015 if (update_string_buffer(custom_shape->per_frame_eqn_string_buffer, &custom_shape->per_frame_eqn_string_index) < 0)
2023 /* Syntax error, return parse error */
2027 /* Helper function to update the string buffers used by the editor */
2028 int update_string_buffer(char * buffer, int * index) {
2039 /* If the string line buffer used by the parser is already full then quit */
2040 if (string_line_buffer_index == (STRING_LINE_SIZE-1))
2043 if ((skip_size = get_string_prefix_len(string_line_buffer)) == FAILURE)
2046 string_line_buffer[string_line_buffer_index++] = '\n';
2048 // string_length = strlen(string_line_buffer + strlen(eqn_string)+1);
2049 if (skip_size >= STRING_LINE_SIZE)
2052 string_length = strlen(string_line_buffer + skip_size);
2054 if (skip_size > (STRING_LINE_SIZE-1))
2057 /* Add line to string buffer */
2058 strncpy(buffer + (*index),
2059 string_line_buffer + skip_size, string_length);
2061 /* Buffer full, quit */
2062 if ((*index) > (STRING_BUFFER_SIZE - 1)) {
2063 //if (PARSE_DEBUG) printf("update_string_buffer: string buffer full!\n");
2067 /* Otherwise, increment string index by the added string length */
2068 (*index)+=string_length;
2075 /* Helper function: returns the length of the prefix portion in the line
2076 buffer (the passed string here). In other words, given
2077 the string 'per_frame_1 = x = ....', return the length of 'per_frame_1 = '
2078 Returns -1 if syntax error
2081 int get_string_prefix_len(char * string) {
2085 /* Null argument check */
2090 /* First find the equal sign */
2091 while (string[i] != '=') {
2097 /* If the string already ends at the next char then give up */
2098 if (string[i+1] == 0)
2101 /* Move past the equal sign */
2104 /* Now found the start of the LHS variable, ie skip the spaces */
2105 while(string[i] == ' ') {
2109 /* If this is the end of the string then its a syntax error */
2113 /* Finished succesfully, return the length */