]> git.sesse.net Git - vlc/blob - modules/visualization/galaktos/parser.c
Removes trailing spaces. Removes tabs.
[vlc] / modules / visualization / galaktos / parser.c
1 /*****************************************************************************
2  * parser.c:
3  *****************************************************************************
4  * Copyright (C) 2004 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Cyril Deguet <asmax@videolan.org>
8  *          code from projectM http://xmms-projectm.sourceforge.net
9  *
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.
14  *
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.
19  *
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  *****************************************************************************/
24
25
26
27 /* parser.c */
28
29 #include <stdlib.h>
30
31 #include "common.h"
32 #include "fatal.h"
33
34 #include "splaytree_types.h"
35 #include "splaytree.h"
36 #include "tree_types.h"
37
38 #include "expr_types.h"
39 #include "eval.h"
40
41 #include "param_types.h"
42 #include "param.h"
43
44 #include "func_types.h"
45 #include "func.h"
46
47 #include "preset_types.h"
48 #include "builtin_funcs.h"
49
50 #include "per_pixel_eqn_types.h"
51 #include "per_pixel_eqn.h"
52
53 #include "init_cond_types.h"
54 #include "init_cond.h"
55
56 #include "per_frame_eqn_types.h"
57 #include "per_frame_eqn.h"
58
59 #include "parser.h"
60 #include "engine_vars.h"
61
62 #include "custom_wave_types.h"
63 #include "custom_wave.h"
64
65 #include "custom_shape_types.h"
66 #include "custom_shape.h"
67
68 /* Strings that prefix (and denote the type of) equations */
69
70
71 #define PER_FRAME_STRING "per_frame_"
72 #define PER_FRAME_STRING_LENGTH 10
73
74 #define PER_PIXEL_STRING "per_pixel_"
75 #define PER_PIXEL_STRING_LENGTH 10
76
77 #define PER_FRAME_INIT_STRING "per_frame_init_"
78 #define PER_FRAME_INIT_STRING_LENGTH 15
79
80 #define WAVECODE_STRING "wavecode_"
81 #define WAVECODE_STRING_LENGTH 9
82
83 #define WAVE_STRING "wave_"
84 #define WAVE_STRING_LENGTH 5
85
86 #define PER_POINT_STRING "per_point"
87 #define PER_POINT_STRING_LENGTH 9
88
89 #define PER_FRAME_STRING_NO_UNDERSCORE "per_frame"
90 #define PER_FRAME_STRING_NO_UNDERSCORE_LENGTH 9
91
92 #define SHAPECODE_STRING "shapecode_"
93 #define SHAPECODE_STRING_LENGTH 10
94
95 #define SHAPE_STRING "shape_"
96 #define SHAPE_STRING_LENGTH 6
97
98 #define SHAPE_INIT_STRING "init"
99 #define SHAPE_INIT_STRING_LENGTH 4
100
101 #define WAVE_INIT_STRING "init"
102 #define WAVE_INIT_STRING_LENGTH 4
103
104 /* Stores a line of a file as its being parsed */
105 char string_line_buffer[STRING_LINE_SIZE];
106
107 /* The current position of the string line buffer (see above) */
108 int string_line_buffer_index = 0;
109
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;
113
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;
122
123 typedef enum {
124   NORMAL_LINE_MODE,
125   PER_FRAME_LINE_MODE,
126   PER_PIXEL_LINE_MODE,
127   INIT_COND_LINE_MODE,
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,
132 } line_mode_t;
133
134 line_mode_t line_mode = NORMAL_LINE_MODE;
135
136 /* Token enumeration type */
137 typedef enum {
138
139   tEOL,   /* end of a line, usually a '/n' or '/r' */
140   tEOF,   /* end of file */
141   tLPr,   /* ( */
142   tRPr,   /* ) */
143   tLBr,   /* [ */
144   tRBr,   /* ] */
145   tEq,    /* = */
146   tPlus,  /* + */
147   tMinus, /* - */
148   tMult,  /* * */
149   tMod,   /* % */
150   tDiv,   /* / */
151   tOr,    /* | */
152   tAnd,   /* & */
153   tComma, /* , */
154   tPositive, /* + as a prefix operator */
155   tNegative, /* - as a prefix operator */
156   tSemiColon, /* ; */
157   tStringTooLong, /* special token to indicate an invalid string length */
158   tStringBufferFilled /* the string buffer for this line is maxed out */
159 } token_t;
160
161
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);
179
180 int parse_shapecode(char * eqn_string, FILE * fs, preset_t * preset);
181 int parse_shapecode_prefix(char * token, int * id, char ** var_string);
182
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);
186
187 int update_string_buffer(char * buffer, int * index);
188 int string_to_float(char * string, double * float_ptr);
189
190 /* Grabs the next token from the file. The second argument points
191    to the raw string */
192
193 token_t parseToken(FILE * fs, char * string) {
194  
195   char c;
196   int i;
197  
198   if (string != NULL)
199     memset(string, 0, MAX_TOKEN_SIZE);
200  
201   /* Loop until a delimiter is found, or the maximum string size is found */
202   for (i = 0; i < MAX_TOKEN_SIZE;i++) {
203     c = fgetc(fs);
204  
205     /* If the string line buffer is full, quit */
206     if (string_line_buffer_index == (STRING_LINE_SIZE - 1))
207       return tStringBufferFilled;
208  
209     /* Otherwise add this character to the string line buffer */
210     string_line_buffer[string_line_buffer_index++] = c;
211     /* Now interpret the character */
212     switch (c) {
213  
214     case '+':
215       return tPlus;
216     case '-':
217       return tMinus;
218     case '%':
219       return tMod;
220     case '/':
221  
222       /* check for line comment here */
223       if ((c = fgetc(fs)) == '/') {
224     while(1) {
225       c = fgetc(fs);
226       if (c == EOF) {
227         line_mode = NORMAL_LINE_MODE;
228         return tEOF;                
229       }
230       if (c == '\n') {
231         line_mode = NORMAL_LINE_MODE;
232         return tEOL;
233       }
234     }
235     
236       }
237  
238       /* Otherwise, just a regular division operator */
239       ungetc(c, fs);
240       return tDiv;
241  
242     case '*':
243       return tMult;
244     case '|':
245       return tOr;
246     case '&':
247       return tAnd;
248     case '(':
249       return tLPr;
250     case ')':
251       return tRPr;
252     case '[':
253       return tLBr;
254     case ']':
255       return tRBr;
256     case '=':
257       return tEq;
258       //    case '\r':
259       //break;
260     case '\n':
261       line_count++;
262       line_mode = NORMAL_LINE_MODE;
263       return tEOL;
264     case ',':
265       return tComma;
266     case ';':
267       return tSemiColon;
268     case ' ': /* space, skip the character */
269       i--;
270       break;
271     case EOF:
272       line_count = 1;
273       line_mode = NORMAL_LINE_MODE;
274       return tEOF;
275  
276     default:
277       if (string != NULL)
278     string[i] = c;
279     }
280  
281   }
282  
283  /* String reached maximum length, return special token error */
284   return tStringTooLong;
285  
286 }
287
288 /* Parse input in the form of "exp, exp, exp, ...)"
289    Returns a general expression list */
290
291 gen_expr_t ** parse_prefix_args(FILE * fs, int num_args, struct PRESET_T * preset) {
292
293   int i, j;
294   gen_expr_t ** expr_list; /* List of arguments to function */
295   gen_expr_t * gen_expr;
296  
297   /* Malloc the expression list */
298   expr_list =  (gen_expr_t**)malloc(sizeof(gen_expr_t*)*num_args);
299  
300   /* Malloc failed */
301   if (expr_list == NULL)
302     return NULL;
303  
304  
305   i = 0;
306
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]);
314       free(expr_list);
315       return NULL;
316     }
317     /* Assign entry in expression list */
318     expr_list[i++] = gen_expr;
319   }
320  
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 */
323   return expr_list;
324  
325 }
326
327 /* Parses a comment at the top of the file. Stops when left bracket is found */
328 int parse_top_comment(FILE * fs) {
329
330   char string[MAX_TOKEN_SIZE];
331   token_t token;
332     
333   /* Process tokens until left bracket is found */
334   while ((token = parseToken(fs, string)) != tLBr) {
335     if (token == tEOF)
336       return PARSE_ERROR;
337   }
338
339  /* Done, return success */
340  return SUCCESS;
341 }    
342
343 /* Right Bracket is parsed by this function.
344    puts a new string into name */
345 int parse_preset_name(FILE * fs, char * name) {
346
347   token_t token;
348
349   if (name == NULL)
350     return FAILURE;
351
352   if ((token = parseToken(fs, name)) != tRBr)
353     return PARSE_ERROR;
354      
355   //if (PARSE_DEBUG) printf("parse_preset_name: parsed preset (name = \"%s\")\n", name);
356  
357   return SUCCESS;
358 }
359
360
361 /* Parses per pixel equations */
362 int parse_per_pixel_eqn(FILE * fs, preset_t * preset) {
363
364
365   char string[MAX_TOKEN_SIZE];
366   gen_expr_t * gen_expr;
367
368   if (PARSE_DEBUG) printf("parse_per_pixel: per_pixel equation parsing start...(LINE %d)\n", line_count);
369
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",
372                     string, line_count);
373     return PARSE_ERROR;
374   }
375  
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);
379     return PARSE_ERROR;
380   }
381  
382   /* Add the per pixel equation */
383   if (add_per_pixel_eqn(string, gen_expr, preset) < 0) {
384     free_gen_expr(gen_expr);
385     return PARSE_ERROR;
386   }
387
388   return SUCCESS;
389 }
390
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) {
393
394   char eqn_string[MAX_TOKEN_SIZE];
395   token_t token;
396   init_cond_t * init_cond;
397   per_frame_eqn_t * per_frame_eqn;
398  
399   /* Clear the string line buffer */
400   memset(string_line_buffer, 0, STRING_LINE_SIZE);
401   string_line_buffer_index = 0;
402  
403  
404   switch (token = parseToken(fs, eqn_string)) {
405  
406     /* Invalid Cases */
407   case tRBr:
408   case tLPr:
409   case tRPr:
410   case tComma:
411   case tLBr:
412   case tPlus:
413   case tMinus:
414   case tMod:
415   case tMult:
416   case tOr:
417   case tAnd:
418   case tDiv:
419  
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 */
422     return PARSE_ERROR;
423  
424  
425   case tEOL:  /* Empty line */
426     line_mode = NORMAL_LINE_MODE;
427     return SUCCESS;
428  
429   case tEOF: /* End of File */
430     line_mode = NORMAL_LINE_MODE;
431     line_count = 1;
432     return EOF;
433  
434   case tSemiColon: /* Indicates end of expression */
435     return SUCCESS;
436  
437     /* Valid Case, either an initial condition or equation should follow */
438   case tEq:
439  
440     /* CASE: PER FRAME INIT EQUATION */    
441     if (!strncmp(eqn_string, PER_FRAME_INIT_STRING, PER_FRAME_INIT_STRING_LENGTH)) {
442  
443       //if (PARSE_DEBUG) printf("parse_line: per frame init equation found...(LINE %d)\n", line_count);
444  
445       /* Set the line mode to normal */
446       line_mode = NORMAL_LINE_MODE;
447  
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);
451     return PARSE_ERROR;
452       }    
453  
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 */        
458     return ERROR;
459       }
460  
461  
462       if (update_string_buffer(preset->per_frame_init_eqn_string_buffer,
463                    &preset->per_frame_init_eqn_string_index) < 0)
464     {    return FAILURE;}
465  
466       return SUCCESS;
467  
468     }
469
470     /* Per frame equation case */    
471     if (!strncmp(eqn_string, PER_FRAME_STRING, PER_FRAME_STRING_LENGTH)) {
472  
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;
476  
477       //if (PARSE_DEBUG) printf("parse_line: per frame equation found...(LINE %d)\n", line_count);
478  
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);
482     return PARSE_ERROR;
483       }    
484  
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 */        
489     return ERROR;
490       }
491  
492       if (update_string_buffer(preset->per_frame_eqn_string_buffer,
493                    &preset->per_frame_eqn_string_index) < 0)
494     return FAILURE;
495  
496  
497  
498       return SUCCESS;
499  
500     }
501  
502     /* Wavecode initial condition case */
503     if (!strncmp(eqn_string, WAVECODE_STRING, WAVECODE_STRING_LENGTH)) {
504  
505           line_mode = CUSTOM_WAVE_WAVECODE_LINE_MODE;
506
507       //if (PARSE_DEBUG)
508       //      printf("parse_line: wavecode prefix found: \"%s\"\n", eqn_string);
509
510       //      printf("string:%d\n", 5);
511
512       //SUPER MYSTERIO-BUG - Don't Remove
513       printf("");
514     
515       return parse_wavecode(eqn_string, fs, preset);
516     }
517  
518     /* Custom Wave Prefix */
519     if ((!strncmp(eqn_string, WAVE_STRING, WAVE_STRING_LENGTH)) &&
520     ((eqn_string[5] >= 48) && (eqn_string[5] <= 57))) {
521  
522       //    if (PARSE_DEBUG) printf("parse_line wave prefix found: \"%s\"\n", eqn_string);
523  
524       return parse_wave(eqn_string, fs, preset);
525  
526     }
527  
528  
529     /* Shapecode initial condition case */
530     if (!strncmp(eqn_string, SHAPECODE_STRING, SHAPECODE_STRING_LENGTH)) {
531  
532       line_mode = CUSTOM_SHAPE_SHAPECODE_LINE_MODE;
533  
534       if (PARSE_DEBUG) printf("parse_line: shapecode prefix found: \"%s\"\n", eqn_string);
535  
536       return parse_shapecode(eqn_string, fs, preset);
537     }
538  
539     /* Custom Shape Prefix */
540     if ((!strncmp(eqn_string, SHAPE_STRING, SHAPE_STRING_LENGTH)) &&
541     ((eqn_string[6] >= 48) && (eqn_string[6] <= 57))) {
542  
543       if (PARSE_DEBUG) printf("parse_line shape prefix found: \"%s\"\n", eqn_string);
544       return parse_shape(eqn_string, fs, preset);
545  
546     }
547  
548     /* Per pixel equation case */
549     if (!strncmp(eqn_string, PER_PIXEL_STRING, PER_PIXEL_STRING_LENGTH)) {
550       line_mode = PER_PIXEL_LINE_MODE;
551  
552       if (parse_per_pixel_eqn(fs, preset) < 0)
553     return PARSE_ERROR;
554  
555  
556       if (update_string_buffer(preset->per_pixel_eqn_string_buffer,
557                    &preset->per_pixel_eqn_string_index) < 0)
558     return FAILURE;
559  
560       if (PARSE_DEBUG) printf("parse_line: finished parsing per pixel equation (LINE %d)\n", line_count);
561       return SUCCESS;
562     }
563  
564     /* Sometimes equations are written implicitly in milkdrop files, in the form
565  
566     per_frame_1 = p1 = eqn1; p2 = eqn2; p3 = eqn3;..;
567  
568     which is analagous to:
569  
570     per_frame_1 = p1 = eqn1; per_frame_2 = p2 = eqn2; per_frame_3 = p3 = eqn3; ...;
571  
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
578  
579     Note added by Carmelo Piccione (cep@andrew.cmu.edu) 10/19/03
580     */
581  
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)
585     return PARSE_ERROR;
586  
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 */        
591     return ERROR;
592       }
593  
594  
595       if (update_string_buffer(preset->per_frame_eqn_string_buffer,
596                    &preset->per_frame_eqn_string_index) < 0)
597     return FAILURE;
598  
599  
600  
601       return SUCCESS;
602     }
603  
604     //if (PARSE_DEBUG) printf("parse_line: found initial condition: name = \"%s\" (LINE %d)\n", eqn_string, line_count);
605  
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);
609       return PARSE_ERROR;
610     }    
611  
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);
617       return FAILURE;
618     }
619  
620     /* Finished with initial condition line */
621     //    if (PARSE_DEBUG) printf("parse_line: initial condition parsed successfully\n");
622  
623     return SUCCESS;
624  
625     /* END INITIAL CONDITIONING PARSING */
626  
627  
628   default: /* an uncaught type or an error has occurred */
629     if (PARSE_DEBUG) printf("parse_line: uncaught case, token val = %d\n", token);
630     return PARSE_ERROR;
631   }
632  
633   /* Because of the default in the case statement,
634      control flow should never actually reach here */
635   return PARSE_ERROR;
636 }
637
638
639
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) {
642  
643   int i;
644   char string[MAX_TOKEN_SIZE];
645   token_t token;
646   gen_expr_t * gen_expr;
647   double val;
648   param_t * param = NULL;
649   func_t * func;
650   gen_expr_t ** expr_list;
651
652   switch (token = parseToken(fs,string)) {
653   /* Left Parentice Case */
654   case tLPr:
655  
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);
659  
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);
664     return NULL;
665       }
666  
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",
670                       line_count);
671     free_tree_expr(tree_expr);
672     for (i = 0; i < func->num_args;i++)
673       free_gen_expr(expr_list[i]);
674     free(expr_list);
675     return NULL;
676       }
677  
678  
679  
680       token = parseToken(fs, string);
681
682       if (*string != 0) {
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 */                
685       }        
686  
687       return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
688     }
689  
690  
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 */
693     if (*string != 0) {
694       if (PARSE_DEBUG) printf("parse_gen_expr: implicit multiplication case unimplemented!\n");
695       free_tree_expr(tree_expr);
696       return NULL;
697     }
698  
699     /* CASE 3 (Left Parentice): the following is enclosed parentices to change order
700        of operations. So we create a new expression tree */
701  
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);
705       return NULL;
706     }
707  
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);
711
712     /* Plus is a prefix operator check */
713   case tPlus:
714     if (*string == 0) {
715  
716       //if (PARSE_DEBUG) printf("parse_gen_expr: plus used as prefix (LINE %d)\n", line_count);
717
718       /* Treat prefix plus as implict 0 preceding operator */
719       gen_expr = const_to_expr(0);
720
721       return parse_infix_op(fs, tPositive, insert_gen_expr(gen_expr, &tree_expr), preset);    
722     }
723  
724     /* Minus is a prefix operator check */
725   case tMinus:
726     if (*string == 0) {
727  
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);
732     }
733  
734     /* All the following cases are strings followed by an infix operator or terminal */
735   case tRPr:
736   case tEOL:
737   case tEOF:
738   case tSemiColon:
739   case tComma:
740  
741     /* CASE 1 (terminal): string is empty, but not null. Not sure if this will actually happen
742        any more. */
743     if (*string == 0) {
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);
746  
747     }
748  
749   default:
750
751     /* CASE 0: Empty string, parse error */
752     if (*string == 0) {
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);
755       return NULL;
756     }
757
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);
762     return NULL;
763       }
764  
765       /* Parse the rest of the line */
766       return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
767  
768     }
769
770  
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);
777         return NULL;
778       }
779       }
780  
781       if (PARSE_DEBUG) {
782     printf("parse_gen_expr: custom shape parameter (name = %s)... ", param->name);
783     fflush(stdout);
784       }
785  
786       /* Convert parameter to an expression */
787       if ((gen_expr = param_to_expr(param)) == NULL) {
788     free_tree_expr(tree_expr);
789     return NULL;
790       }
791  
792       //if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
793  
794       /* Parse the rest of the line */
795       return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
796     }
797  
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);
804         return NULL;
805       }
806  
807       }
808
809       if (PARSE_DEBUG) {
810     printf("parse_gen_expr: custom wave parameter (name = %s)... ", param->name);
811     fflush(stdout);
812       }
813     
814     /* Convert parameter to an expression */
815     if ((gen_expr = param_to_expr(param)) == NULL) {
816       free_tree_expr(tree_expr);
817       return NULL;
818     }
819     
820     if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
821     
822     /* Parse the rest of the line */
823     return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
824  
825     }
826
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) {
829  
830       if (PARSE_DEBUG) {
831     printf("parse_gen_expr: parameter (name = %s)... ", param->name);
832     fflush(stdout);
833       }
834  
835         /* Convert parameter to an expression */
836       if ((gen_expr = param_to_expr(param)) == NULL) {
837     free_tree_expr(tree_expr);
838     return NULL;
839       }
840  
841       if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
842  
843       /* Parse the rest of the line */
844       return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
845  
846     }
847  
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);
851     return NULL;
852   }
853 }
854  
855
856
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 */
859
860 tree_expr_t * insert_infix_op(infix_op_t * infix_op, tree_expr_t **root) {
861
862   tree_expr_t * new_root;
863  
864   /* Sanity check */
865   if (infix_op == NULL)
866     return NULL;
867  
868   /* The root is null, so make this operator
869      the new root */
870  
871   if (*root == NULL) {
872     new_root = new_tree_expr(infix_op, NULL, NULL, NULL);
873     *root = new_root;
874     return new_root;        
875   }
876  
877   /* The root node is not an infix function,
878      so we make this infix operator the new root  */
879  
880   if ((*root)->infix_op == NULL) {
881     new_root = new_tree_expr(infix_op, NULL, *root, NULL);
882     (*root) = new_root;
883     return new_root;
884   }
885  
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 */
889  
890   if (infix_op->precedence > (*root)->infix_op->precedence) {
891     new_root = new_tree_expr(infix_op, NULL, *root, NULL);
892     (*root) = new_root;
893       return new_root;
894   }
895  
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 */
899  
900   insert_infix_rec(infix_op, *root);
901   return *root;
902  
903 }
904
905
906 tree_expr_t * insert_gen_expr(gen_expr_t * gen_expr, tree_expr_t ** root) {
907
908   tree_expr_t * new_root;
909  
910   /* If someone foolishly passes a null
911      pointer to insert, return the original tree */
912  
913   if (gen_expr == NULL) {
914     return *root;
915   }
916
917   /* If the root is null, generate a new expression tree,
918      using the passed expression as the root element */
919  
920   if (*root == NULL) {
921     new_root = new_tree_expr(NULL, gen_expr, NULL, NULL);
922     *root = new_root;
923     return new_root;
924   }
925  
926  
927   /* Otherwise. the new element definitely will not replace the current root.
928      Use a recursive helper function to do insertion */
929
930   insert_gen_rec(gen_expr, *root);
931   return *root;
932 }
933
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) {
936  
937   /* Trivial Case: root is null */
938  
939   if (root == NULL) {
940     ////if (PARSE_DEBUG) printf("insert_gen_rec: root is null, returning failure\n");
941     return FAILURE;
942   }
943  
944  
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 */
948  
949   if ((root->left == NULL) && (root->infix_op != NULL)) {
950     root->left = new_tree_expr(NULL, gen_expr, NULL, NULL);
951     return SUCCESS;
952   }
953  
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 */
957  
958   if ((root->right == NULL) && (root->infix_op != NULL)) {
959     root->right = new_tree_expr(NULL, gen_expr, NULL, NULL);
960     return SUCCESS;
961   }
962  
963   /* Otherwise recurse down to the left. If
964      this succeeds then return. If it fails, try
965      recursing down to the right */
966  
967   if (insert_gen_rec(gen_expr, root->left) == FAILURE)
968     return insert_gen_rec(gen_expr, root->right);
969
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");
973   return FAILURE;    
974 }    
975
976
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) {
979
980   /* Shouldn't happen, implies a parse error */
981
982   if (root == NULL)
983     return FAILURE;
984  
985   /* Also shouldn't happen, also implies a (different) parse error */
986
987   if (root->infix_op == NULL)
988     return FAILURE;
989
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);
994     return SUCCESS;
995   }
996  
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);
1000     return SUCCESS;
1001   }
1002
1003   /* The left element can now be ignored, since there is no way for this
1004      operator to use those expressions */
1005
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 */
1009
1010   if (root->right->infix_op == NULL) {
1011     root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
1012     return SUCCESS;
1013   }
1014  
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);
1019
1020   /* Otherwise, insert the operator here */
1021  
1022   root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
1023   return SUCCESS;
1024
1025 }
1026
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) {
1029     
1030   gen_expr_t * gen_expr;
1031
1032   switch (token) {
1033      /* All the infix operators */
1034   case tPlus:
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);
1037   case tMinus:
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);
1040   case tMult:
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);
1043   case tDiv:
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);
1046   case tMod:
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);
1049   case tOr:
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);
1052   case tAnd:     
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);
1055   case tPositive:
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);
1058   case tNegative:
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);
1061
1062   case tEOL:
1063   case tEOF:
1064   case tSemiColon:
1065   case tRPr:
1066   case tComma:    
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);
1069       return gen_expr;
1070   default:
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);
1073     return NULL;
1074   }
1075
1076   /* Will never happen */
1077   return NULL;
1078  
1079 }
1080
1081 /* Parses an integer, checks for +/- prefix */
1082 int parse_int(FILE * fs, int * int_ptr) {
1083
1084 char string[MAX_TOKEN_SIZE];
1085   token_t token;
1086   int sign;
1087   char * end_ptr = " ";
1088     
1089   token = parseToken(fs, string);
1090
1091  
1092   switch (token) {
1093   case tMinus:
1094     sign = -1;
1095     token = parseToken(fs, string);
1096     break;
1097   case tPlus:
1098     sign = 1;
1099     token = parseToken(fs, string);
1100     break;
1101   default:
1102     sign = 1;
1103     break;
1104   }
1105
1106  
1107   if (string[0] == 0)
1108     return PARSE_ERROR;
1109  
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);
1114
1115   (*int_ptr) = sign*strtol(string, &end_ptr, 10);
1116
1117   /* If end pointer is a return character or null terminator, all is well */
1118   if ((*end_ptr == '\r') || (*end_ptr == '\0'))
1119     return SUCCESS;
1120
1121     return PARSE_ERROR;
1122  
1123 }
1124 /* Parses a floating point number */
1125 int string_to_float(char * string, double * float_ptr) {
1126
1127   char ** error_ptr;
1128
1129   if (*string == 0)
1130     return PARSE_ERROR;
1131
1132   error_ptr = malloc(sizeof(char**));
1133  
1134   (*float_ptr) = strtod(string, error_ptr);
1135  
1136   /* These imply a succesful parse of the string */
1137   if ((**error_ptr == '\0') || (**error_ptr == '\r')) {
1138     free(error_ptr);
1139     return SUCCESS;
1140   }
1141  
1142   (*float_ptr) = 0;
1143   free(error_ptr);
1144   return PARSE_ERROR;
1145 }
1146
1147 /* Parses a floating point number */
1148 int parse_float(FILE * fs, double * float_ptr) {
1149
1150   char string[MAX_TOKEN_SIZE];
1151   char ** error_ptr;
1152   token_t token;
1153   int sign;
1154  
1155   error_ptr = malloc(sizeof(char**));
1156
1157   token = parseToken(fs, string);
1158
1159   switch (token) {
1160   case tMinus:
1161   sign = -1;
1162   token = parseToken(fs, string);
1163   break;
1164   case tPlus:
1165   sign = 1;
1166   token = parseToken(fs, string);
1167   break;
1168   default:
1169     sign = 1;
1170   }
1171  
1172   if (string[0] == 0) {
1173     free(error_ptr);
1174     return PARSE_ERROR;
1175   }
1176
1177   (*float_ptr) = sign*strtod(string, error_ptr);
1178  
1179   /* No conversion was performed */
1180   if ((**error_ptr == '\0') || (**error_ptr == '\r')) {
1181     free(error_ptr);
1182     return SUCCESS;
1183   }
1184  
1185   //if (PARSE_DEBUG) printf("parse_float: double conversion failed for string \"%s\"\n", string);
1186
1187   (*float_ptr) = 0;
1188   free(error_ptr);
1189   return PARSE_ERROR;
1190  
1191
1192  
1193 }
1194
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) {
1197  
1198   char string[MAX_TOKEN_SIZE];
1199   param_t * param;
1200   per_frame_eqn_t * per_frame_eqn;
1201   gen_expr_t * gen_expr;
1202  
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);
1205     return NULL;            
1206   }
1207  
1208   /* Find the parameter associated with the string, create one if necessary */
1209   if ((param = find_param(string, preset, P_CREATE)) == NULL) {
1210     return NULL;    
1211   }
1212  
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);
1216       return NULL;
1217   }
1218  
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);
1222     return NULL;
1223   }
1224  
1225   //if (PARSE_DEBUG) printf("parse_per_frame_eqn: finished per frame equation evaluation (LINE %d)\n", line_count);
1226  
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);
1231     return NULL;
1232   }
1233  
1234   //if (PARSE_DEBUG) printf("parse_per_frame_eqn: per_frame eqn parsed succesfully\n");
1235  
1236   return per_frame_eqn;
1237 }
1238
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) {
1241  
1242   param_t * param;
1243   per_frame_eqn_t * per_frame_eqn;
1244   gen_expr_t * gen_expr;
1245  
1246   if (fs == NULL)
1247     return NULL;
1248   if (param_string == NULL)
1249     return NULL;
1250   if (preset == NULL)
1251     return NULL;
1252
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) {
1256     return NULL;    
1257   }
1258  
1259   //printf("parse_implicit_per_frame_eqn: param is %s\n", param->name);
1260
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);
1264     return NULL;
1265   }
1266  
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);
1270     return NULL;
1271   }
1272  
1273   //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: finished per frame equation evaluation (LINE %d)\n", line_count);
1274  
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);
1279     return NULL;
1280   }
1281  
1282   //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: per_frame eqn parsed succesfully\n");
1283  
1284   return per_frame_eqn;
1285 }
1286
1287 /* Parses an initial condition */
1288 init_cond_t * parse_init_cond(FILE * fs, char * name, struct PRESET_T * preset) {
1289
1290   param_t * param;
1291   value_t init_val;
1292   init_cond_t * init_cond;
1293     
1294   if (name == NULL)
1295     return NULL;
1296   if (preset == NULL)
1297     return NULL;
1298  
1299   /* Search for the paramater in the database, creating it if necessary */
1300   if ((param = find_param(name, preset, P_CREATE)) == NULL) {
1301     return NULL;
1302   }
1303  
1304   //if (PARSE_DEBUG) printf("parse_init_cond: parameter = \"%s\" (LINE %d)\n", param->name, line_count);
1305  
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);
1308     return NULL;
1309   }        
1310  
1311   /* At this point, a parameter has been created or was found
1312      in the database. */
1313  
1314   //if (PARSE_DEBUG) printf("parse_init_cond: parsing initial condition value... (LINE %d)\n", line_count);
1315  
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");
1320       return NULL;
1321     }
1322   }
1323  
1324   /* double value */
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");
1328       return NULL;
1329     }
1330   }
1331  
1332   /* Unknown value */
1333   else {
1334     //if (PARSE_DEBUG) printf("parse_init_cond: unknown parameter type!\n");
1335     return NULL;
1336   }
1337  
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");
1341       return NULL;
1342   }
1343  
1344   /* Finished */
1345   return init_cond;
1346 }
1347
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) {
1350  
1351   char name[MAX_TOKEN_SIZE];
1352   param_t * param = NULL;
1353   value_t init_val;
1354   init_cond_t * init_cond;
1355   gen_expr_t * gen_expr;
1356   double val;
1357   token_t token;
1358
1359
1360   if (preset == NULL)
1361     return NULL;
1362   if (fs == NULL)
1363     return NULL;
1364
1365   if ((token = parseToken(fs, name)) != tEq)
1366     return NULL;
1367  
1368
1369   /* If a database was specified,then use find_param_db instead */
1370   if ((database != NULL) && ((param = find_param_db(name, database, TRUE)) == NULL)) {
1371     return NULL;
1372   }
1373
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)) {
1376     return NULL;
1377   }
1378  
1379   //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: parameter = \"%s\" (LINE %d)\n", param->name, line_count);
1380  
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);
1383     return NULL;
1384   }        
1385  
1386   /* At this point, a parameter has been created or was found
1387      in the database. */
1388  
1389   //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: parsing right hand side of per frame init equation.. (LINE %d)\n", line_count);
1390  
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");
1393     return NULL;
1394   }
1395  
1396   /* Compute initial condition value */
1397   val = eval_gen_expr(gen_expr);
1398  
1399   /* Free the general expression now that we are done with it */
1400   free_gen_expr(gen_expr);
1401
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;
1405   }
1406  
1407   /* double value */
1408   else if (param->type == P_TYPE_DOUBLE) {
1409     init_val.double_val = val;
1410   }
1411  
1412   /* Unknown value */
1413   else {
1414     //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: unknown parameter type!\n");
1415     return NULL;
1416   }
1417  
1418
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");
1422       return NULL;
1423   }
1424
1425
1426   /* Finished */
1427   return init_cond;
1428 }
1429
1430 int parse_wavecode(char * token, FILE * fs, preset_t * preset) {
1431
1432   char * var_string;
1433   init_cond_t * init_cond;
1434   custom_wave_t * custom_wave;
1435   int id;
1436   value_t init_val;
1437   param_t * param;
1438
1439   /* Null argument checks */
1440   if (preset == NULL)
1441     return FAILURE;
1442   if (fs == NULL)
1443     return FAILURE;
1444   if (token == NULL)
1445     return FAILURE;
1446
1447   /* token should be in the form wavecode_N_var, such as wavecode_1_samples */
1448  
1449   /* Get id and variable name from token string */
1450   if (parse_wavecode_prefix(token, &id, &var_string) < 0)
1451     return PARSE_ERROR;
1452  
1453   //if (PARSE_DEBUG) printf("parse_wavecode: wavecode id = %d, parameter = \"%s\"\n", id, var_string);
1454
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);
1459     return FAILURE;
1460   }
1461   //if (PARSE_DEBUG) printf("parse_wavecode: custom wave found (id = %d)\n", custom_wave->id);
1462
1463   /* Retrieve parameter from this custom waves parameter db */
1464   if ((param = find_param_db(var_string, custom_wave->param_tree, TRUE)) == NULL)
1465     return FAILURE;
1466
1467   //if (PARSE_DEBUG) printf("parse_wavecode: custom wave parameter found (name = %s)\n", param->name);
1468
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");
1473       return PARSE_ERROR;
1474     }
1475   }
1476  
1477   /* double value */
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");
1481       return PARSE_ERROR;
1482     }
1483   }
1484  
1485   /* Unknown value */
1486   else {
1487     //if (PARSE_DEBUG) printf("parse_wavecode: unknown parameter type!\n");
1488     return PARSE_ERROR;
1489   }
1490  
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");
1494       return FAILURE;
1495   }
1496  
1497   if (splay_insert(init_cond, param->name, custom_wave->init_cond_tree) < 0) {
1498     free_init_cond(init_cond);
1499     return PARSE_ERROR;
1500   }
1501
1502   //if (PARSE_DEBUG) printf("parse_wavecode: [success]\n");
1503   return SUCCESS;
1504 }
1505
1506 int parse_shapecode(char * token, FILE * fs, preset_t * preset) {
1507
1508   char * var_string;
1509   init_cond_t * init_cond;
1510   custom_shape_t * custom_shape;
1511   int id;
1512   value_t init_val;
1513   param_t * param;
1514
1515   /* Null argument checks */
1516   if (preset == NULL)
1517     return FAILURE;
1518   if (fs == NULL)
1519     return FAILURE;
1520   if (token == NULL)
1521     return FAILURE;
1522
1523   /* token should be in the form shapecode_N_var, such as shapecode_1_samples */
1524  
1525   /* Get id and variable name from token string */
1526   if (parse_shapecode_prefix(token, &id, &var_string) < 0)
1527     return PARSE_ERROR;
1528  
1529   //if (PARSE_DEBUG) printf("parse_shapecode: shapecode id = %d, parameter = \"%s\"\n", id, var_string);
1530
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);
1535     return FAILURE;
1536   }
1537   //if (PARSE_DEBUG) printf("parse_shapecode: custom shape found (id = %d)\n", custom_shape->id);
1538
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");
1542     return FAILURE;
1543   }
1544   //if (PARSE_DEBUG) printf("parse_shapecode: custom shape parameter found (name = %s)\n", param->name);
1545
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");
1550       return PARSE_ERROR;
1551     }
1552   }
1553  
1554   /* double value */
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");
1558       return PARSE_ERROR;
1559     }
1560   }
1561  
1562   /* Unknown value */
1563   else {
1564     //if (PARSE_DEBUG) printf("parse_shapecode: unknown parameter type!\n");
1565     return PARSE_ERROR;
1566   }
1567  
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");
1571       return FAILURE;
1572   }
1573  
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);
1577     return PARSE_ERROR;
1578   }
1579
1580   //if (PARSE_DEBUG) printf("parse_shapecode: [success]\n");
1581   return SUCCESS;
1582 }
1583
1584
1585 int parse_wavecode_prefix(char * token, int * id, char ** var_string) {
1586
1587   int len, i, j;
1588  
1589   if (token == NULL)
1590     return FAILURE;
1591   if (*var_string == NULL)
1592     return FAILURE;
1593   if (id == NULL)
1594     return FAILURE;
1595  
1596   len = strlen(token);
1597
1598   /* Move pointer passed "wavecode_" prefix */
1599   if (len <= WAVECODE_STRING_LENGTH)
1600     return FAILURE;
1601   i = WAVECODE_STRING_LENGTH;
1602   j = 0;
1603   (*id) = 0;
1604  
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)
1608       return FAILURE;
1609  
1610     (*id) = 10*(*id) + (token[i]-48);
1611     j++;
1612     i++;
1613   }
1614
1615  
1616   if (i > (len - 2))
1617     return FAILURE;
1618  
1619   *var_string = token + i + 1;
1620  
1621   return SUCCESS;
1622
1623 }
1624
1625
1626 int parse_shapecode_prefix(char * token, int * id, char ** var_string) {
1627
1628   int len, i, j;
1629  
1630   if (token == NULL)
1631     return FAILURE;
1632   if (*var_string == NULL)
1633     return FAILURE;
1634   if (id == NULL)
1635     return FAILURE;
1636  
1637   len = strlen(token);
1638
1639   /* Move pointer passed "shapecode_" prefix */
1640   if (len <= SHAPECODE_STRING_LENGTH)
1641     return FAILURE;
1642   i = SHAPECODE_STRING_LENGTH;
1643   j = 0;
1644   (*id) = 0;
1645  
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)
1649       return FAILURE;
1650  
1651     (*id) = 10*(*id) + (token[i]-48);
1652     j++;
1653     i++;
1654   }
1655
1656  
1657   if (i > (len - 2))
1658     return FAILURE;
1659  
1660   *var_string = token + i + 1;
1661  
1662   return SUCCESS;
1663
1664 }
1665
1666 int parse_wave_prefix(char * token, int * id, char ** eqn_string) {
1667
1668   int len, i, j;
1669  
1670   if (token == NULL)
1671     return FAILURE;
1672   if (eqn_string == NULL)
1673     return FAILURE;
1674   if (id == NULL)
1675     return FAILURE;
1676  
1677   len = strlen(token);
1678  
1679   if (len <= WAVE_STRING_LENGTH)
1680     return FAILURE;
1681
1682
1683   i = WAVE_STRING_LENGTH;
1684   j = 0;
1685   (*id) = 0;
1686  
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)
1690       return FAILURE;
1691  
1692     (*id) = 10*(*id) + (token[i]-48);
1693     j++;
1694     i++;
1695   }
1696
1697   if (i > (len - 2))
1698     return FAILURE;
1699  
1700   *eqn_string = token + i + 1;
1701  
1702   return SUCCESS;
1703
1704 }
1705
1706 int parse_shape_prefix(char * token, int * id, char ** eqn_string) {
1707
1708   int len, i, j;
1709  
1710   if (token == NULL)
1711     return FAILURE;
1712   if (eqn_string == NULL)
1713     return FAILURE;
1714   if (id == NULL)
1715     return FAILURE;
1716  
1717   len = strlen(token);
1718  
1719   if (len <= SHAPE_STRING_LENGTH)
1720     return FAILURE;
1721
1722
1723   i = SHAPE_STRING_LENGTH;
1724   j = 0;
1725   (*id) = 0;
1726  
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)
1730       return FAILURE;
1731  
1732     (*id) = 10*(*id) + (token[i]-48);
1733     j++;
1734     i++;
1735   }
1736
1737   if (i > (len - 2))
1738     return FAILURE;
1739  
1740   *eqn_string = token + i + 1;
1741  
1742   return SUCCESS;
1743
1744 }
1745
1746 /* Parses custom wave equations */
1747 int parse_wave(char * token, FILE * fs, preset_t * preset) {
1748  
1749   int id;
1750   char * eqn_type;
1751   char string[MAX_TOKEN_SIZE];
1752   param_t * param;
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;
1757
1758   if (token == NULL)
1759     return FAILURE;
1760   if (fs == NULL)
1761     return FAILURE;
1762   if (preset == NULL)
1763     return FAILURE;
1764  
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");
1768     return FAILURE;
1769   }
1770   /* Retrieve custom wave associated with this id */
1771   if ((custom_wave = find_custom_wave(id, preset, TRUE)) == NULL)
1772     return FAILURE;
1773
1774
1775   /* per frame init equation case */    
1776   if (!strncmp(eqn_type, WAVE_INIT_STRING, WAVE_INIT_STRING_LENGTH)) {
1777
1778     //if (PARSE_DEBUG) printf("parse_wave (per frame init): [begin] (LINE %d)\n", line_count);
1779
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);
1783       return PARSE_ERROR;
1784     }    
1785
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 */        
1790       return FAILURE;
1791     }
1792  
1793     if (update_string_buffer(custom_wave->per_frame_init_eqn_string_buffer,
1794                  &custom_wave->per_frame_init_eqn_string_index) < 0)
1795       return FAILURE;
1796     
1797     return SUCCESS;
1798  
1799   }
1800
1801   /* per frame equation case */
1802   if (!strncmp(eqn_type, PER_FRAME_STRING_NO_UNDERSCORE, PER_FRAME_STRING_NO_UNDERSCORE_LENGTH)) {
1803
1804     //if (PARSE_DEBUG) printf("parse_wave (per_frame): [start] (custom wave id = %d)\n", custom_wave->id);
1805  
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);
1808       return PARSE_ERROR;            
1809     }
1810  
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);
1814       return FAILURE;    
1815     }
1816  
1817  
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);
1821       return FAILURE;
1822     }
1823  
1824     /* Parse right side of equation as an expression */
1825
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;
1830       return PARSE_ERROR;
1831
1832     }
1833     current_wave = NULL;
1834
1835     //if (PARSE_DEBUG) printf("parse_wave (per_frame): [finished parsing equation] (LINE %d)\n", line_count);
1836  
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);
1841       return FAILURE;
1842     }
1843  
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);
1846       return FAILURE;
1847     }
1848  
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);
1851
1852  
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: */
1855
1856  
1857     if (update_string_buffer(custom_wave->per_frame_eqn_string_buffer, &custom_wave->per_frame_eqn_string_index) < 0)
1858       return FAILURE;
1859
1860  
1861     return SUCCESS;
1862   }
1863
1864
1865   /* per point equation case */
1866   if (!strncmp(eqn_type, PER_POINT_STRING, PER_POINT_STRING_LENGTH)) {
1867
1868     //if (PARSE_DEBUG) printf("parse_wave (per_point): per_pixel equation parsing start...(LINE %d)\n", line_count);
1869
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);
1872       return PARSE_ERROR;
1873     }
1874  
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);
1879       return PARSE_ERROR;
1880     }
1881     current_wave = NULL;
1882
1883     /* Add the per point equation */
1884     if (add_per_point_eqn(string, gen_expr, custom_wave) < 0) {
1885       free_gen_expr(gen_expr);
1886       return PARSE_ERROR;
1887     }
1888
1889  
1890     if (update_string_buffer(custom_wave->per_point_eqn_string_buffer, &custom_wave->per_point_eqn_string_index) < 0)
1891       return FAILURE;
1892
1893     //if (PARSE_DEBUG) printf("parse_wave (per_point): [finished] (custom wave id = %d)\n", custom_wave->id);
1894     return SUCCESS;
1895   }
1896
1897
1898   /* Syntax error, return parse error */
1899   return PARSE_ERROR;
1900 }
1901
1902
1903
1904 /* Parses custom shape equations */
1905 int parse_shape(char * token, FILE * fs, preset_t * preset) {
1906  
1907   int id;
1908   char * eqn_type;
1909   char string[MAX_TOKEN_SIZE];
1910   param_t * param;
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;
1915
1916   if (token == NULL)
1917
1918     return FAILURE;
1919   if (fs == NULL)
1920     return FAILURE;
1921   if (preset == NULL)
1922     return FAILURE;
1923  
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");
1927     return PARSE_ERROR;
1928   }
1929   /* Retrieve custom shape associated with this id */
1930   if ((custom_shape = find_custom_shape(id, preset, TRUE)) == NULL)
1931     return FAILURE;
1932
1933
1934   /* per frame init equation case */    
1935   if (!strncmp(eqn_type, SHAPE_INIT_STRING, SHAPE_INIT_STRING_LENGTH)) {
1936
1937     //if (PARSE_DEBUG) printf("parse_shape (per frame init): [begin] (LINE %d)\n", line_count);
1938
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);
1942       return PARSE_ERROR;
1943     }    
1944  
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 */        
1949       return ERROR;
1950     }
1951
1952     if (update_string_buffer(custom_shape->per_frame_init_eqn_string_buffer,
1953                  &custom_shape->per_frame_init_eqn_string_index) < 0)
1954       return FAILURE;
1955     
1956     return SUCCESS;
1957  
1958   }
1959
1960   /* per frame equation case */
1961   if (!strncmp(eqn_type, PER_FRAME_STRING_NO_UNDERSCORE, PER_FRAME_STRING_NO_UNDERSCORE_LENGTH)) {
1962
1963     //if (PARSE_DEBUG) printf("parse_shape (per_frame): [start] (custom shape id = %d)\n", custom_shape->id);
1964  
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);
1967       return PARSE_ERROR;            
1968     }
1969  
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);
1973       return FAILURE;    
1974     }
1975  
1976  
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);
1980       return FAILURE;
1981     }
1982  
1983     /* Parse right side of equation as an expression */
1984
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;
1989       return PARSE_ERROR;
1990     }
1991
1992     current_shape = NULL;
1993
1994     //if (PARSE_DEBUG) printf("parse_shape (per_frame): [finished parsing equation] (LINE %d)\n", line_count);
1995  
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);
2000       return FAILURE;
2001     }
2002  
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);
2005       return FAILURE;
2006     }
2007  
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);
2010
2011  
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: */
2014  
2015     if (update_string_buffer(custom_shape->per_frame_eqn_string_buffer, &custom_shape->per_frame_eqn_string_index) < 0)
2016       return FAILURE;
2017
2018  
2019     return SUCCESS;
2020   }
2021
2022
2023   /* Syntax error, return parse error */
2024   return PARSE_ERROR;
2025 }
2026
2027 /* Helper function to update the string buffers used by the editor */
2028 int update_string_buffer(char * buffer, int * index) {
2029
2030   int string_length;
2031   int skip_size;
2032
2033   if (!buffer)
2034     return FAILURE;
2035   if (!index)
2036     return FAILURE;
2037
2038  
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))
2041     return FAILURE;
2042
2043   if ((skip_size = get_string_prefix_len(string_line_buffer)) == FAILURE)
2044     return FAILURE;
2045
2046   string_line_buffer[string_line_buffer_index++] = '\n';
2047
2048   //  string_length = strlen(string_line_buffer + strlen(eqn_string)+1);
2049   if (skip_size >= STRING_LINE_SIZE)
2050     return FAILURE;
2051
2052   string_length = strlen(string_line_buffer + skip_size);
2053
2054   if (skip_size > (STRING_LINE_SIZE-1))
2055     return FAILURE;
2056
2057   /* Add line to string buffer */
2058   strncpy(buffer + (*index),
2059       string_line_buffer + skip_size, string_length);
2060  
2061   /* Buffer full, quit */
2062   if ((*index) > (STRING_BUFFER_SIZE - 1)) {
2063     //if (PARSE_DEBUG) printf("update_string_buffer: string buffer full!\n");
2064     return FAILURE;
2065   }    
2066  
2067   /* Otherwise, increment string index by the added string length */
2068   (*index)+=string_length;
2069  
2070   return SUCCESS;
2071  
2072 }
2073
2074
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
2079 */
2080
2081 int get_string_prefix_len(char * string) {
2082  
2083   int i = 0;
2084
2085   /* Null argument check */
2086   if (string == NULL)
2087     return FAILURE;
2088
2089  
2090   /* First find the equal sign */
2091   while (string[i] != '=') {
2092     if (string[i] == 0)
2093       return FAILURE;
2094     i++;
2095   }
2096
2097   /* If the string already ends at the next char then give up */
2098   if (string[i+1] == 0)
2099     return FAILURE;
2100
2101   /* Move past the equal sign */
2102   i++;
2103
2104   /* Now found the start of the LHS variable, ie skip the spaces */
2105   while(string[i] == ' ') {
2106     i++;
2107   }
2108
2109   /* If this is the end of the string then its a syntax error */
2110   if (string[i] == 0)
2111     return FAILURE;
2112
2113   /* Finished succesfully, return the length */
2114   return i;
2115 }