Main Page | Modules | Class Hierarchy | Class List | Directories | File List | Class Members | File Members | Related Pages

parser.c

00001 /*****************************************************************************
00002  * parser.c:
00003  *****************************************************************************
00004  * Copyright (C) 2004 the VideoLAN team
00005  * $Id: parser.c 11664 2005-07-09 06:17:09Z courmisch $
00006  *
00007  * Authors: Cyril Deguet <[email protected]>
00008  *          code from projectM http://xmms-projectm.sourceforge.net
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2 of the License, or
00013  * (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software
00022  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
00023  *****************************************************************************/
00024 
00025 
00026 
00027 /* parser.c */
00028 
00029 #include <stdio.h>
00030 #include <string.h>
00031 #include <stdlib.h>
00032 
00033 #include "common.h"
00034 #include "fatal.h"
00035 
00036 #include "splaytree_types.h"
00037 #include "splaytree.h"
00038 #include "tree_types.h"
00039 
00040 #include "expr_types.h"
00041 #include "eval.h"
00042 
00043 #include "param_types.h"
00044 #include "param.h"
00045 
00046 #include "func_types.h"
00047 #include "func.h"
00048 
00049 #include "preset_types.h"
00050 #include "builtin_funcs.h"
00051 
00052 #include "per_pixel_eqn_types.h"
00053 #include "per_pixel_eqn.h"
00054 
00055 #include "init_cond_types.h"
00056 #include "init_cond.h"
00057 
00058 #include "per_frame_eqn_types.h"
00059 #include "per_frame_eqn.h"
00060 
00061 #include "parser.h"
00062 #include "engine_vars.h"
00063 
00064 #include "custom_wave_types.h"
00065 #include "custom_wave.h"
00066 
00067 #include "custom_shape_types.h"
00068 #include "custom_shape.h"
00069 
00070 /* Strings that prefix (and denote the type of) equations */
00071 
00072 
00073 #define PER_FRAME_STRING "per_frame_"
00074 #define PER_FRAME_STRING_LENGTH 10
00075 
00076 #define PER_PIXEL_STRING "per_pixel_"
00077 #define PER_PIXEL_STRING_LENGTH 10
00078 
00079 #define PER_FRAME_INIT_STRING "per_frame_init_"
00080 #define PER_FRAME_INIT_STRING_LENGTH 15
00081 
00082 #define WAVECODE_STRING "wavecode_"
00083 #define WAVECODE_STRING_LENGTH 9
00084 
00085 #define WAVE_STRING "wave_"
00086 #define WAVE_STRING_LENGTH 5
00087 
00088 #define PER_POINT_STRING "per_point"
00089 #define PER_POINT_STRING_LENGTH 9
00090 
00091 #define PER_FRAME_STRING_NO_UNDERSCORE "per_frame"
00092 #define PER_FRAME_STRING_NO_UNDERSCORE_LENGTH 9
00093 
00094 #define SHAPECODE_STRING "shapecode_"
00095 #define SHAPECODE_STRING_LENGTH 10
00096 
00097 #define SHAPE_STRING "shape_"
00098 #define SHAPE_STRING_LENGTH 6
00099 
00100 #define SHAPE_INIT_STRING "init"
00101 #define SHAPE_INIT_STRING_LENGTH 4
00102 
00103 #define WAVE_INIT_STRING "init"
00104 #define WAVE_INIT_STRING_LENGTH 4
00105 
00106 /* Stores a line of a file as its being parsed */
00107 char string_line_buffer[STRING_LINE_SIZE]; 
00108 
00109 /* The current position of the string line buffer (see above) */
00110 int string_line_buffer_index = 0;
00111 
00112 /* All infix operators (except '=') are prototyped here */
00113 extern infix_op_t * infix_add, * infix_minus, * infix_div, * infix_mult,
00114   * infix_or, * infix_and, * infix_mod, * infix_positive, * infix_negative;
00115 
00116 /* If the parser reads a line with a custom wave, this pointer is set to
00117    the custom wave of concern */
00118 custom_wave_t * current_wave = NULL;
00119 custom_shape_t * current_shape = NULL;
00120 /* Counts the number of lines parsed */
00121 unsigned int line_count = 1;
00122 int per_frame_eqn_count  = 0;
00123 int per_frame_init_eqn_count = 0;
00124 
00125 typedef enum {
00126   NORMAL_LINE_MODE,
00127   PER_FRAME_LINE_MODE,
00128   PER_PIXEL_LINE_MODE,
00129   INIT_COND_LINE_MODE,
00130   CUSTOM_WAVE_PER_POINT_LINE_MODE,
00131   CUSTOM_WAVE_PER_FRAME_LINE_MODE,
00132   CUSTOM_WAVE_WAVECODE_LINE_MODE,
00133   CUSTOM_SHAPE_SHAPECODE_LINE_MODE,
00134 } line_mode_t;
00135 
00136 line_mode_t line_mode = NORMAL_LINE_MODE;
00137 
00138 /* Token enumeration type */
00139 typedef enum {
00140 
00141   tEOL,   /* end of a line, usually a '/n' or '/r' */
00142   tEOF,   /* end of file */
00143   tLPr,   /* ( */
00144   tRPr,   /* ) */
00145   tLBr,   /* [ */
00146   tRBr,   /* ] */
00147   tEq,    /* = */
00148   tPlus,  /* + */
00149   tMinus, /* - */
00150   tMult,  /* * */
00151   tMod,   /* % */
00152   tDiv,   /* / */
00153   tOr,    /* | */
00154   tAnd,   /* & */
00155   tComma, /* , */
00156   tPositive, /* + as a prefix operator */
00157   tNegative, /* - as a prefix operator */
00158   tSemiColon, /* ; */
00159   tStringTooLong, /* special token to indicate an invalid string length */
00160   tStringBufferFilled /* the string buffer for this line is maxed out */
00161 } token_t;
00162 
00163 
00164 int get_string_prefix_len(char * string);
00165 tree_expr_t * insert_gen_expr(gen_expr_t * gen_expr, tree_expr_t ** root);
00166 tree_expr_t * insert_infix_op(infix_op_t * infix_op, tree_expr_t ** root);
00167 token_t parseToken(FILE * fs, char * string);
00168 gen_expr_t ** parse_prefix_args(FILE * fs, int num_args, struct PRESET_T * preset);
00169 gen_expr_t * parse_infix_op(FILE * fs, token_t token, tree_expr_t * tree_expr, struct PRESET_T * preset);
00170 gen_expr_t * parse_sign_arg(FILE * fs);
00171 int parse_float(FILE * fs, double * float_ptr);
00172 int parse_int(FILE * fs, int * int_ptr);
00173 int insert_gen_rec(gen_expr_t * gen_expr, tree_expr_t * root);
00174 int insert_infix_rec(infix_op_t * infix_op, tree_expr_t * root);
00175 gen_expr_t * parse_gen_expr(FILE * fs, tree_expr_t * tree_expr, struct PRESET_T * preset);
00176 per_frame_eqn_t * parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, struct PRESET_T * preset);
00177 init_cond_t * parse_per_frame_init_eqn(FILE * fs, struct PRESET_T * preset, splaytree_t * database);
00178 int parse_wavecode_prefix(char * token, int * id, char ** var_string);
00179 int parse_wavecode(char * token, FILE * fs, preset_t * preset);
00180 int parse_wave_prefix(char * token, int * id, char ** eqn_string);
00181 
00182 int parse_shapecode(char * eqn_string, FILE * fs, preset_t * preset);
00183 int parse_shapecode_prefix(char * token, int * id, char ** var_string);
00184 
00185 int parse_wave(char * eqn_string, FILE * fs, preset_t * preset);
00186 int parse_shape(char * eqn_string, FILE * fs, preset_t * preset);
00187 int parse_shape_prefix(char * token, int * id, char ** eqn_string);
00188 
00189 int update_string_buffer(char * buffer, int * index);
00190 int string_to_float(char * string, double * float_ptr);
00191 
00192 /* Grabs the next token from the file. The second argument points
00193    to the raw string */
00194 
00195 token_t parseToken(FILE * fs, char * string) {
00196   
00197   char c;
00198   int i;
00199   
00200   if (string != NULL)
00201     memset(string, 0, MAX_TOKEN_SIZE);
00202   
00203   /* Loop until a delimiter is found, or the maximum string size is found */
00204   for (i = 0; i < MAX_TOKEN_SIZE;i++) {
00205     c = fgetc(fs);
00206     
00207     /* If the string line buffer is full, quit */
00208     if (string_line_buffer_index == (STRING_LINE_SIZE - 1))
00209       return tStringBufferFilled;
00210     
00211     /* Otherwise add this character to the string line buffer */
00212     string_line_buffer[string_line_buffer_index++] = c;
00213     /* Now interpret the character */
00214     switch (c) {
00215       
00216     case '+':
00217       return tPlus; 
00218     case '-':
00219       return tMinus;
00220     case '%':
00221       return tMod;
00222     case '/':
00223       
00224       /* check for line comment here */
00225       if ((c = fgetc(fs)) == '/') {
00226         while(1) {
00227           c = fgetc(fs);
00228           if (c == EOF) {
00229             line_mode = NORMAL_LINE_MODE;
00230             return tEOF;                                
00231           }
00232           if (c == '\n') {
00233             line_mode = NORMAL_LINE_MODE;
00234             return tEOL;
00235           }
00236         }
00237         
00238       }
00239       
00240       /* Otherwise, just a regular division operator */
00241       ungetc(c, fs);
00242       return tDiv;
00243       
00244     case '*':
00245       return tMult;
00246     case '|':
00247       return tOr;
00248     case '&':
00249       return tAnd;
00250     case '(': 
00251       return tLPr;
00252     case ')':
00253       return tRPr;
00254     case '[': 
00255       return tLBr;
00256     case ']':
00257       return tRBr;
00258     case '=': 
00259       return tEq;
00260       //    case '\r':
00261       //break;
00262     case '\n':
00263       line_count++;
00264       line_mode = NORMAL_LINE_MODE;
00265       return tEOL;
00266     case ',':
00267       return tComma;
00268     case ';':
00269       return tSemiColon;
00270     case ' ': /* space, skip the character */
00271       i--;
00272       break;
00273     case EOF:
00274       line_count = 1;
00275       line_mode = NORMAL_LINE_MODE;
00276       return tEOF;
00277       
00278     default: 
00279       if (string != NULL)
00280         string[i] = c;
00281     } 
00282     
00283   }
00284   
00285  /* String reached maximum length, return special token error */ 
00286   return tStringTooLong;
00287   
00288 }
00289 
00290 /* Parse input in the form of "exp, exp, exp, ...)" 
00291    Returns a general expression list */
00292 
00293 gen_expr_t ** parse_prefix_args(FILE * fs, int num_args, struct PRESET_T * preset) {
00294 
00295   int i, j;
00296   gen_expr_t ** expr_list; /* List of arguments to function */
00297   gen_expr_t * gen_expr;
00298   
00299   /* Malloc the expression list */
00300   expr_list =  (gen_expr_t**)malloc(sizeof(gen_expr_t*)*num_args);
00301   
00302   /* Malloc failed */
00303   if (expr_list == NULL)
00304     return NULL;
00305   
00306   
00307   i = 0;
00308 
00309   while (i < num_args) {
00310     //if (PARSE_DEBUG) printf("parse_prefix_args: parsing argument %d...\n", i+1);
00311     /* Parse the ith expression in the list */
00312     if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
00313       //if (PARSE_DEBUG) printf("parse_prefix_args: failed to get parameter # %d for function (LINE %d)\n", i+1, line_count);
00314       for (j = 0; j < i; j++) 
00315         free_gen_expr(expr_list[j]);
00316       free(expr_list);
00317       return NULL;
00318     }
00319     /* Assign entry in expression list */
00320     expr_list[i++] = gen_expr;
00321   }
00322   
00323   //if (PARSE_DEBUG) printf("parse_prefix_args: finished parsing %d arguments (LINE %d)\n", num_args, line_count);      
00324   /* Finally, return the resulting expression list */
00325   return expr_list;
00326   
00327 }
00328 
00329 /* Parses a comment at the top of the file. Stops when left bracket is found */
00330 int parse_top_comment(FILE * fs) {
00331 
00332   char string[MAX_TOKEN_SIZE];
00333   token_t token;
00334           
00335   /* Process tokens until left bracket is found */
00336   while ((token = parseToken(fs, string)) != tLBr) {
00337     if (token == tEOF) 
00338       return PARSE_ERROR;
00339   }
00340 
00341  /* Done, return success */
00342  return SUCCESS; 
00343 }       
00344 
00345 /* Right Bracket is parsed by this function.
00346    puts a new string into name */
00347 int parse_preset_name(FILE * fs, char * name) {
00348 
00349   token_t token;
00350 
00351   if (name == NULL)
00352         return FAILURE;
00353 
00354   if ((token = parseToken(fs, name)) != tRBr)
00355     return PARSE_ERROR;
00356         
00357   //if (PARSE_DEBUG) printf("parse_preset_name: parsed preset (name = \"%s\")\n", name);
00358   
00359   return SUCCESS;
00360 }
00361 
00362 
00363 /* Parses per pixel equations */
00364 int parse_per_pixel_eqn(FILE * fs, preset_t * preset) {
00365 
00366 
00367   char string[MAX_TOKEN_SIZE];
00368   gen_expr_t * gen_expr;
00369 
00370   if (PARSE_DEBUG) printf("parse_per_pixel: per_pixel equation parsing start...(LINE %d)\n", line_count);
00371 
00372   if (parseToken(fs, string) != tEq) { /* parse per pixel operator  name */
00373     if (PARSE_DEBUG) printf("parse_per_pixel: equal operator expected after per pixel operator \"%s\", but not found (LINE %d)\n", 
00374                             string, line_count);
00375     return PARSE_ERROR;
00376   }
00377   
00378   /* Parse right side of equation as an expression */
00379   if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
00380     if (PARSE_DEBUG) printf("parse_per_pixel: equation evaluated to null? (LINE %d)\n", line_count);
00381     return PARSE_ERROR;
00382   }
00383   
00384   /* Add the per pixel equation */
00385   if (add_per_pixel_eqn(string, gen_expr, preset) < 0) {
00386     free_gen_expr(gen_expr);
00387     return PARSE_ERROR;
00388   }
00389 
00390   return SUCCESS;
00391 }
00392 
00393 /* Parses an equation line, this function is way too big, should add some helper functions */
00394 int parse_line(FILE * fs, struct PRESET_T * preset) {
00395 
00396   char eqn_string[MAX_TOKEN_SIZE];
00397   token_t token;
00398   init_cond_t * init_cond;
00399   per_frame_eqn_t * per_frame_eqn;
00400   
00401   /* Clear the string line buffer */
00402   memset(string_line_buffer, 0, STRING_LINE_SIZE);
00403   string_line_buffer_index = 0;
00404   
00405   
00406   switch (token = parseToken(fs, eqn_string)) {
00407     
00408     /* Invalid Cases */
00409   case tRBr:
00410   case tLPr:
00411   case tRPr:
00412   case tComma:
00413   case tLBr:
00414   case tPlus:
00415   case tMinus:
00416   case tMod:
00417   case tMult:
00418   case tOr:
00419   case tAnd:
00420   case tDiv:
00421     
00422     //    if (PARSE_DEBUG) printf("parse_line: invalid token found at start of line (LINE %d)\n", line_count);
00423     /* Invalid token found, return a parse error */
00424     return PARSE_ERROR;
00425     
00426     
00427   case tEOL:  /* Empty line */
00428     line_mode = NORMAL_LINE_MODE;
00429     return SUCCESS;
00430     
00431   case tEOF: /* End of File */
00432     line_mode = NORMAL_LINE_MODE;
00433     line_count = 1;
00434     return EOF;
00435     
00436   case tSemiColon: /* Indicates end of expression */
00437     return SUCCESS;
00438     
00439     /* Valid Case, either an initial condition or equation should follow */
00440   case tEq:
00441     
00442     /* CASE: PER FRAME INIT EQUATION */     
00443     if (!strncmp(eqn_string, PER_FRAME_INIT_STRING, PER_FRAME_INIT_STRING_LENGTH)) {
00444       
00445       //if (PARSE_DEBUG) printf("parse_line: per frame init equation found...(LINE %d)\n", line_count);
00446       
00447       /* Set the line mode to normal */
00448       line_mode = NORMAL_LINE_MODE;
00449       
00450       /* Parse the per frame equation */
00451       if ((init_cond = parse_per_frame_init_eqn(fs, preset, NULL)) == NULL) {
00452         //if (PARSE_DEBUG) printf("parse_line: per frame init equation parsing failed (LINE %d)\n", line_count);
00453         return PARSE_ERROR;
00454       } 
00455       
00456       /* Insert the equation in the per frame equation tree */
00457       if (splay_insert(init_cond, init_cond->param->name, preset->per_frame_init_eqn_tree) < 0) {
00458         //if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
00459         free_init_cond(init_cond); /* will free the gen expr too */             
00460         return ERROR;
00461       }
00462       
00463      
00464       if (update_string_buffer(preset->per_frame_init_eqn_string_buffer, 
00465                                &preset->per_frame_init_eqn_string_index) < 0)
00466         {       return FAILURE;}
00467       
00468       return SUCCESS;
00469       
00470     }
00471 
00472     /* Per frame equation case */           
00473     if (!strncmp(eqn_string, PER_FRAME_STRING, PER_FRAME_STRING_LENGTH)) {
00474       
00475       /* Sometimes per frame equations are implicitly defined without the
00476          per_frame_ prefix. This informs the parser that one could follow */
00477       line_mode = PER_FRAME_LINE_MODE;
00478       
00479       //if (PARSE_DEBUG) printf("parse_line: per frame equation found...(LINE %d)\n", line_count);
00480       
00481       /* Parse the per frame equation */
00482       if ((per_frame_eqn = parse_per_frame_eqn(fs, ++per_frame_eqn_count, preset)) == NULL) {
00483         if (PARSE_DEBUG) printf("parse_line: per frame equation parsing failed (LINE %d)\n", line_count);
00484         return PARSE_ERROR;
00485       } 
00486       
00487       /* Insert the equation in the per frame equation tree */
00488       if (splay_insert(per_frame_eqn, &per_frame_eqn_count, preset->per_frame_eqn_tree) < 0) {
00489         if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
00490         free_per_frame_eqn(per_frame_eqn); /* will free the gen expr too */             
00491         return ERROR;
00492       }
00493     
00494       if (update_string_buffer(preset->per_frame_eqn_string_buffer, 
00495                                &preset->per_frame_eqn_string_index) < 0)
00496         return FAILURE;
00497       
00498       
00499       
00500       return SUCCESS;
00501       
00502     }
00503     
00504     /* Wavecode initial condition case */
00505     if (!strncmp(eqn_string, WAVECODE_STRING, WAVECODE_STRING_LENGTH)) {
00506       
00507           line_mode = CUSTOM_WAVE_WAVECODE_LINE_MODE;
00508 
00509       //if (PARSE_DEBUG) 
00510       //      printf("parse_line: wavecode prefix found: \"%s\"\n", eqn_string);
00511 
00512           //      printf("string:%d\n", 5);
00513 
00514           //SUPER MYSTERIO-BUG - Don't Remove
00515           printf("");
00516           
00517       return parse_wavecode(eqn_string, fs, preset);
00518     }
00519     
00520     /* Custom Wave Prefix */
00521     if ((!strncmp(eqn_string, WAVE_STRING, WAVE_STRING_LENGTH)) && 
00522         ((eqn_string[5] >= 48) && (eqn_string[5] <= 57))) {
00523       
00524       //    if (PARSE_DEBUG) printf("parse_line wave prefix found: \"%s\"\n", eqn_string);
00525       
00526       return parse_wave(eqn_string, fs, preset);
00527       
00528     }
00529     
00530     
00531     /* Shapecode initial condition case */
00532     if (!strncmp(eqn_string, SHAPECODE_STRING, SHAPECODE_STRING_LENGTH)) {
00533       
00534       line_mode = CUSTOM_SHAPE_SHAPECODE_LINE_MODE;
00535       
00536       if (PARSE_DEBUG) printf("parse_line: shapecode prefix found: \"%s\"\n", eqn_string);
00537       
00538       return parse_shapecode(eqn_string, fs, preset);
00539     }
00540     
00541     /* Custom Shape Prefix */
00542     if ((!strncmp(eqn_string, SHAPE_STRING, SHAPE_STRING_LENGTH)) && 
00543         ((eqn_string[6] >= 48) && (eqn_string[6] <= 57))) {
00544       
00545       if (PARSE_DEBUG) printf("parse_line shape prefix found: \"%s\"\n", eqn_string);
00546       return parse_shape(eqn_string, fs, preset);
00547       
00548     }
00549     
00550     /* Per pixel equation case */
00551     if (!strncmp(eqn_string, PER_PIXEL_STRING, PER_PIXEL_STRING_LENGTH)) {
00552       line_mode = PER_PIXEL_LINE_MODE;
00553       
00554       if (parse_per_pixel_eqn(fs, preset) < 0)
00555         return PARSE_ERROR;
00556       
00557       
00558       if (update_string_buffer(preset->per_pixel_eqn_string_buffer, 
00559                                &preset->per_pixel_eqn_string_index) < 0)
00560         return FAILURE;
00561       
00562       if (PARSE_DEBUG) printf("parse_line: finished parsing per pixel equation (LINE %d)\n", line_count);
00563       return SUCCESS;
00564     } 
00565     
00566     /* Sometimes equations are written implicitly in milkdrop files, in the form
00567        
00568     per_frame_1 = p1 = eqn1; p2 = eqn2; p3 = eqn3;..; 
00569     
00570     which is analagous to:
00571     
00572     per_frame_1 = p1 = eqn1; per_frame_2 = p2 = eqn2; per_frame_3 = p3 = eqn3; ...;
00573     
00574     The following line mode hack allows such implicit declaration of the 
00575     prefix that specifies the equation type. An alternative method
00576     may be to associate each equation line as list of equations separated
00577     by semicolons (and a new line ends the list). Instead, however, a global
00578     variable called "line_mode" specifies the last type of equation found,
00579     and bases any implicitly typed input on this fact
00580     
00581     Note added by Carmelo Piccione ([email protected]) 10/19/03
00582     */
00583     
00584     /* Per frame line mode previously, try to parse the equation implicitly */
00585     if (line_mode == PER_FRAME_LINE_MODE) {
00586       if ((per_frame_eqn = parse_implicit_per_frame_eqn(fs, eqn_string, ++per_frame_eqn_count, preset)) == NULL)
00587         return PARSE_ERROR;
00588       
00589       /* Insert the equation in the per frame equation tree */
00590       if (splay_insert(per_frame_eqn, &per_frame_eqn_count, preset->per_frame_eqn_tree) < 0) {
00591         if (PARSE_DEBUG) printf("parse_line: failed to add a perframe equation (ERROR)\n");
00592         free_per_frame_eqn(per_frame_eqn); /* will free the gen expr too */             
00593         return ERROR;
00594       }
00595       
00596       
00597       if (update_string_buffer(preset->per_frame_eqn_string_buffer, 
00598                                &preset->per_frame_eqn_string_index) < 0)
00599         return FAILURE;
00600       
00601       
00602       
00603       return SUCCESS;
00604     }
00605     
00606     //if (PARSE_DEBUG) printf("parse_line: found initial condition: name = \"%s\" (LINE %d)\n", eqn_string, line_count);
00607     
00608     /* Evaluate the initial condition */
00609     if ((init_cond = parse_init_cond(fs, eqn_string, preset)) == NULL) {
00610        if (PARSE_DEBUG) printf("parse_line: failed to parse initial condition (LINE %d)\n", line_count);
00611       return PARSE_ERROR; 
00612     }   
00613     
00614     /* Add equation to initial condition tree */
00615     if (splay_insert(init_cond, init_cond->param->name, preset->init_cond_tree) < 0) {
00616       if (PARSE_DEBUG) printf("parse_line: failed to add initial condition \"%s\" to equation tree (LINE %d)\n", 
00617                       init_cond->param->name, line_count);
00618       free_init_cond(init_cond);
00619       return FAILURE;
00620     }
00621     
00622     /* Finished with initial condition line */
00623     //    if (PARSE_DEBUG) printf("parse_line: initial condition parsed successfully\n");
00624     
00625     return SUCCESS;
00626     
00627     /* END INITIAL CONDITIONING PARSING */
00628     
00629     
00630   default: /* an uncaught type or an error has occurred */
00631     if (PARSE_DEBUG) printf("parse_line: uncaught case, token val = %d\n", token); 
00632     return PARSE_ERROR;
00633   }
00634   
00635   /* Because of the default in the case statement, 
00636      control flow should never actually reach here */ 
00637   return PARSE_ERROR;
00638 }
00639 
00640 
00641 
00642 /* Parses a general expression, this function is the meat of the parser */
00643 gen_expr_t * parse_gen_expr (FILE * fs, tree_expr_t * tree_expr, struct PRESET_T * preset) {
00644   
00645   int i;
00646   char string[MAX_TOKEN_SIZE];
00647   token_t token;
00648   gen_expr_t * gen_expr;
00649   double val;
00650   param_t * param = NULL;
00651   func_t * func;
00652   gen_expr_t ** expr_list;
00653 
00654   switch (token = parseToken(fs,string)) {
00655   /* Left Parentice Case */
00656   case tLPr:
00657     
00658     /* CASE 1 (Left Parentice): See if the previous string before this parentice is a function name */
00659     if ((func = find_func(string)) != NULL) {
00660         if (PARSE_DEBUG) printf("parse_gen_expr: found prefix function (name = %s) (LINE %d)\n", func->name, line_count);
00661       
00662       /* Parse the functions arguments */
00663       if ((expr_list = parse_prefix_args(fs, func->num_args, preset)) == NULL) {
00664         if (PARSE_DEBUG) printf("parse_prefix_args: failed to generate an expresion list! (LINE %d) \n", line_count);
00665         free_tree_expr(tree_expr);
00666         return NULL;
00667       }
00668       
00669       /* Convert function to expression */
00670       if ((gen_expr = prefun_to_expr((void*)func->func_ptr, expr_list, func->num_args)) == NULL)  {     
00671           if (PARSE_DEBUG) printf("parse_prefix_args: failed to convert prefix function to general expression (LINE %d) \n", 
00672                                         line_count);
00673         free_tree_expr(tree_expr);
00674         for (i = 0; i < func->num_args;i++)
00675           free_gen_expr(expr_list[i]);
00676         free(expr_list);
00677         return NULL;
00678       }
00679     
00680       
00681       
00682       token = parseToken(fs, string);
00683 
00684       if (*string != 0) {
00685         if (PARSE_DEBUG) printf("parse_prefix_args: empty string expected, but not found...(LINE %d)\n", line_count);
00686         /* continue anyway for now, could be implicit multiplication */                         
00687       }         
00688       
00689       return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
00690     }
00691      
00692     
00693     /* Case 2: (Left Parentice), a string coupled with a left parentice. Either an error or implicit 
00694        multiplication operator. For now treat it as an error */
00695     if (*string != 0) {
00696       if (PARSE_DEBUG) printf("parse_gen_expr: implicit multiplication case unimplemented!\n");
00697       free_tree_expr(tree_expr);
00698       return NULL;
00699     }
00700     
00701     /* CASE 3 (Left Parentice): the following is enclosed parentices to change order
00702        of operations. So we create a new expression tree */
00703     
00704     if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
00705       //if (PARSE_DEBUG) printf("parse_gen_expr:  found left parentice, but failed to create new expression tree \n");
00706       free_tree_expr(tree_expr);
00707       return NULL;
00708     }
00709     
00710     if (PARSE_DEBUG) printf("parse_gen_expr: finished enclosed expression tree...\n");  
00711     token = parseToken(fs, string);
00712     return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
00713 
00714     /* Plus is a prefix operator check */
00715   case tPlus:
00716     if (*string == 0) {
00717       
00718       //if (PARSE_DEBUG) printf("parse_gen_expr: plus used as prefix (LINE %d)\n", line_count);
00719 
00720           /* Treat prefix plus as implict 0 preceding operator */
00721       gen_expr = const_to_expr(0);
00722 
00723       return parse_infix_op(fs, tPositive, insert_gen_expr(gen_expr, &tree_expr), preset);      
00724     }
00725     
00726     /* Minus is a prefix operator check */
00727   case tMinus:
00728     if (*string == 0) {
00729      
00730       /* Use the negative infix operator, but first add an implicit zero to the operator tree */
00731       gen_expr = const_to_expr(0);
00732       //return parse_gen_expr(fs, insert_gen_expr(gen_expr, &tree_expr), preset);
00733                 return parse_infix_op(fs, tNegative, insert_gen_expr(gen_expr, &tree_expr), preset);
00734     }
00735     
00736     /* All the following cases are strings followed by an infix operator or terminal */
00737   case tRPr:
00738   case tEOL: 
00739   case tEOF:
00740   case tSemiColon:
00741   case tComma:
00742     
00743     /* CASE 1 (terminal): string is empty, but not null. Not sure if this will actually happen
00744        any more. */
00745     if (*string == 0) {
00746       //if (PARSE_DEBUG) printf("parse_gen_expr: empty string coupled with terminal (LINE %d) \n", line_count);
00747       return parse_infix_op(fs, token, tree_expr, preset);
00748       
00749     }
00750     
00751   default:  
00752 
00753     /* CASE 0: Empty string, parse error */
00754     if (*string == 0) {
00755       if (PARSE_DEBUG) printf("parse_gen_expr: empty string coupled with infix op (ERROR!) (LINE %d) \n", line_count);
00756       free_tree_expr(tree_expr);
00757       return NULL;
00758     }
00759 
00760     /* CASE 1: Check if string is a just a floating point number */
00761     if (string_to_float(string, &val) != PARSE_ERROR) {
00762       if ((gen_expr = const_to_expr(val)) == NULL) {
00763         free_tree_expr(tree_expr);
00764         return NULL;
00765       }
00766       
00767       /* Parse the rest of the line */
00768       return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);          
00769     
00770     }
00771 
00772       
00773     /* CASE 4: custom shape variable */
00774     if (current_shape != NULL) {
00775       if ((param = find_param_db(string, current_shape->param_tree, FALSE)) == NULL) {
00776         if ((param = find_builtin_param(string)) == NULL)
00777           if ((param = find_param_db(string, current_shape->param_tree, TRUE)) == NULL) {
00778             free_tree_expr(tree_expr);
00779             return NULL;
00780           }
00781       }
00782       
00783       if (PARSE_DEBUG) {
00784         printf("parse_gen_expr: custom shape parameter (name = %s)... ", param->name);
00785         fflush(stdout);
00786       }  
00787       
00788       /* Convert parameter to an expression */
00789       if ((gen_expr = param_to_expr(param)) == NULL) {
00790         free_tree_expr(tree_expr);
00791         return NULL;
00792       }
00793       
00794       //if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
00795       
00796       /* Parse the rest of the line */
00797       return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
00798     }
00799     
00800     /* CASE 5: custom wave variable */
00801     if (current_wave != NULL) {
00802       if ((param = find_param_db(string, current_wave->param_tree, FALSE)) == NULL) {
00803         if ((param = find_builtin_param(string)) == NULL) 
00804           if ((param = find_param_db(string, current_wave->param_tree, TRUE)) == NULL) {
00805             free_tree_expr(tree_expr);
00806             return NULL;
00807           }
00808         
00809       }
00810 
00811       if (PARSE_DEBUG) {
00812         printf("parse_gen_expr: custom wave parameter (name = %s)... ", param->name);
00813         fflush(stdout);
00814       }
00815         
00816         /* Convert parameter to an expression */
00817         if ((gen_expr = param_to_expr(param)) == NULL) {
00818           free_tree_expr(tree_expr);
00819           return NULL;
00820         }
00821         
00822         if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
00823         
00824         /* Parse the rest of the line */
00825         return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
00826       
00827     }
00828 
00829     /* CASE 6: regular parameter. Will be created if necessary and the string has no invalid characters */
00830     if ((param = find_param(string, preset, P_CREATE)) != NULL) {
00831       
00832       if (PARSE_DEBUG) {
00833         printf("parse_gen_expr: parameter (name = %s)... ", param->name);
00834         fflush(stdout);
00835       }  
00836     
00837                 /* Convert parameter to an expression */
00838       if ((gen_expr = param_to_expr(param)) == NULL) {
00839         free_tree_expr(tree_expr);
00840         return NULL;
00841       }
00842       
00843       if (PARSE_DEBUG) printf("converted to expression (LINE %d)\n", line_count);
00844       
00845       /* Parse the rest of the line */
00846       return parse_infix_op(fs, token, insert_gen_expr(gen_expr, &tree_expr), preset);
00847           
00848     }
00849    
00850     /* CASE 7: Bad string, give up */
00851     if (PARSE_DEBUG) printf("parse_gen_expr: syntax error [string = \"%s\"] (LINE %d)\n", string, line_count);
00852     free_tree_expr(tree_expr);
00853     return NULL;
00854   }
00855 }
00856   
00857 
00858 
00859 /* Inserts expressions into tree according to operator precedence.
00860    If root is null, a new tree is created, with gen_expr as only element */
00861 
00862 tree_expr_t * insert_infix_op(infix_op_t * infix_op, tree_expr_t **root) {
00863 
00864   tree_expr_t * new_root;
00865   
00866   /* Sanity check */
00867   if (infix_op == NULL)
00868     return NULL;
00869   
00870   /* The root is null, so make this operator
00871      the new root */
00872   
00873   if (*root == NULL) {
00874     new_root = new_tree_expr(infix_op, NULL, NULL, NULL);
00875     *root = new_root;
00876     return new_root;            
00877   }
00878   
00879   /* The root node is not an infix function,
00880      so we make this infix operator the new root  */ 
00881   
00882   if ((*root)->infix_op == NULL) {
00883     new_root = new_tree_expr(infix_op, NULL, *root, NULL);
00884     (*root) = new_root;
00885     return new_root;
00886   }
00887   
00888   /* The root is an infix function. If the precedence
00889      of the item to be inserted is greater than the root's
00890      precedence, then make gen_expr the root */
00891   
00892   if (infix_op->precedence > (*root)->infix_op->precedence) {
00893     new_root = new_tree_expr(infix_op, NULL, *root, NULL);
00894     (*root) = new_root;
00895       return new_root;
00896   }
00897   
00898   /* If control flow reaches here, use a recursive helper
00899      with the knowledge that the root is higher precedence
00900      than the item to be inserted */
00901   
00902   insert_infix_rec(infix_op, *root);
00903   return *root;
00904   
00905 }
00906 
00907 
00908 tree_expr_t * insert_gen_expr(gen_expr_t * gen_expr, tree_expr_t ** root) {
00909 
00910   tree_expr_t * new_root;
00911   
00912   /* If someone foolishly passes a null
00913      pointer to insert, return the original tree */
00914   
00915   if (gen_expr == NULL) {
00916     return *root;
00917   }
00918 
00919   /* If the root is null, generate a new expression tree,
00920      using the passed expression as the root element */
00921   
00922   if (*root == NULL) {
00923     new_root = new_tree_expr(NULL, gen_expr, NULL, NULL);
00924     *root = new_root;
00925     return new_root;
00926   }
00927   
00928   
00929   /* Otherwise. the new element definitely will not replace the current root.
00930      Use a recursive helper function to do insertion */
00931 
00932   insert_gen_rec(gen_expr, *root);
00933   return *root;
00934 }
00935 
00936 /* A recursive helper function to insert general expression elements into the operator tree */
00937 int insert_gen_rec(gen_expr_t * gen_expr, tree_expr_t * root) {
00938   
00939   /* Trivial Case: root is null */
00940   
00941   if (root == NULL) {
00943     return FAILURE;
00944   }
00945   
00946   
00947   /* The current node's left pointer is null, and this
00948      current node is an infix operator, so insert the
00949      general expression at the left pointer */
00950   
00951   if ((root->left == NULL) && (root->infix_op != NULL)) {
00952     root->left = new_tree_expr(NULL, gen_expr, NULL, NULL);
00953     return SUCCESS;
00954   }
00955   
00956   /* The current node's right pointer is null, and this
00957      current node is an infix operator, so insert the
00958      general expression at the right pointer */
00959   
00960   if ((root->right == NULL) && (root->infix_op != NULL)) {
00961     root->right = new_tree_expr(NULL, gen_expr, NULL, NULL);
00962     return SUCCESS;
00963   }
00964   
00965   /* Otherwise recurse down to the left. If
00966      this succeeds then return. If it fails, try
00967      recursing down to the right */
00968   
00969   if (insert_gen_rec(gen_expr, root->left) == FAILURE) 
00970     return insert_gen_rec(gen_expr, root->right);
00971 
00972   /* Impossible for control flow to reach here, but in
00973      the world of C programming, who knows... */
00974   //if (PARSE_DEBUG) printf("insert_gen_rec: should never reach here!\n");  
00975   return FAILURE;       
00976 }       
00977 
00978 
00979 /* A recursive helper function to insert infix arguments by operator precedence */
00980 int insert_infix_rec(infix_op_t * infix_op, tree_expr_t * root) {
00981 
00982   /* Shouldn't happen, implies a parse error */
00983 
00984   if (root == NULL)
00985     return FAILURE;
00986   
00987   /* Also shouldn't happen, also implies a (different) parse error */
00988 
00989   if (root->infix_op == NULL)
00990     return FAILURE;
00991 
00992   /* Left tree is empty, attach this operator to it. 
00993      I don't think this will ever happen */
00994   if (root->left == NULL) {
00995     root->left = new_tree_expr(infix_op, NULL, root->left, NULL);
00996     return SUCCESS;
00997   }
00998  
00999   /* Right tree is empty, attach this operator to it */
01000   if (root->right == NULL) {
01001     root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
01002     return SUCCESS;
01003   }
01004 
01005   /* The left element can now be ignored, since there is no way for this
01006      operator to use those expressions */
01007 
01008   /* If the right element is not an infix operator,
01009      then insert the expression here, attaching the old right branch
01010      to the left of the new expression */
01011 
01012   if (root->right->infix_op == NULL) {
01013     root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
01014     return SUCCESS;
01015   }
01016   
01017   /* Traverse deeper if the inserting operator precedence is less than the
01018      the root's right operator precedence */
01019   if (infix_op->precedence < root->right->infix_op->precedence) 
01020     return insert_infix_rec(infix_op, root->right);
01021 
01022   /* Otherwise, insert the operator here */
01023   
01024   root->right = new_tree_expr(infix_op, NULL, root->right, NULL);
01025   return SUCCESS;
01026 
01027 }
01028 
01029 /* Parses an infix operator */
01030 gen_expr_t * parse_infix_op(FILE * fs, token_t token, tree_expr_t * tree_expr, struct PRESET_T * preset) {
01031         
01032   gen_expr_t * gen_expr;
01033 
01034   switch (token) {
01035         /* All the infix operators */
01036   case tPlus:
01037     //if (PARSE_DEBUG) printf("parse_infix_op: found addition operator (LINE %d)\n", line_count);
01038     return parse_gen_expr(fs, insert_infix_op(infix_add, &tree_expr), preset);
01039   case tMinus:
01040     //if (PARSE_DEBUG) printf("parse_infix_op: found subtraction operator (LINE %d)\n", line_count);
01041     return parse_gen_expr(fs, insert_infix_op(infix_minus, &tree_expr), preset);
01042   case tMult:
01043     //if (PARSE_DEBUG) printf("parse_infix_op: found multiplication operator (LINE %d)\n", line_count);
01044     return parse_gen_expr(fs, insert_infix_op(infix_mult, &tree_expr), preset);
01045   case tDiv:
01046     //if (PARSE_DEBUG) printf("parse_infix_op: found division operator (LINE %d)\n", line_count);  
01047     return parse_gen_expr(fs, insert_infix_op(infix_div, &tree_expr), preset);
01048   case tMod:
01049     //if (PARSE_DEBUG) printf("parse_infix_op: found modulo operator (LINE %d)\n", line_count);  
01050     return parse_gen_expr(fs, insert_infix_op(infix_mod, &tree_expr), preset);
01051   case tOr:  
01052     //if (PARSE_DEBUG) printf("parse_infix_op: found bitwise or operator (LINE %d)\n", line_count);       
01053     return parse_gen_expr(fs, insert_infix_op(infix_or, &tree_expr), preset);
01054   case tAnd:      
01055     //if (PARSE_DEBUG) printf("parse_infix_op: found bitwise and operator (LINE %d)\n", line_count);      
01056     return parse_gen_expr(fs, insert_infix_op(infix_and, &tree_expr), preset);
01057   case tPositive:
01058     //if (PARSE_DEBUG) printf("parse_infix_op: found positive operator (LINE %d)\n", line_count);         
01059     return parse_gen_expr(fs, insert_infix_op(infix_positive, &tree_expr), preset);
01060   case tNegative:
01061     //if (PARSE_DEBUG) printf("parse_infix_op: found negative operator (LINE %d)\n", line_count);         
01062     return parse_gen_expr(fs, insert_infix_op(infix_negative, &tree_expr), preset);
01063 
01064   case tEOL:
01065   case tEOF:
01066   case tSemiColon:
01067   case tRPr:
01068   case tComma:    
01069         //if (PARSE_DEBUG) printf("parse_infix_op: terminal found (LINE %d)\n", line_count);
01070         gen_expr = new_gen_expr(TREE_T, (void*)tree_expr);
01071         return gen_expr;
01072   default:
01073     //if (PARSE_DEBUG) printf("parse_infix_op: operator or terminal expected, but not found (LINE %d)\n", line_count);
01074     free_tree_expr(tree_expr);
01075     return NULL;
01076   }  
01077 
01078   /* Will never happen */
01079   return NULL;
01080   
01081 }
01082 
01083 /* Parses an integer, checks for +/- prefix */
01084 int parse_int(FILE * fs, int * int_ptr) {
01085 
01086 char string[MAX_TOKEN_SIZE];
01087   token_t token;
01088   int sign;
01089   char * end_ptr = " ";
01090         
01091   token = parseToken(fs, string);
01092 
01093  
01094   switch (token) {
01095   case tMinus:
01096     sign = -1;
01097     token = parseToken(fs, string); 
01098     break;
01099   case tPlus:
01100     sign = 1;
01101     token = parseToken(fs, string);
01102     break;
01103   default: 
01104     sign = 1;
01105     break;
01106   }
01107 
01108  
01109   if (string[0] == 0) 
01110     return PARSE_ERROR;
01111   
01112   /* Convert the string to an integer. *end_ptr
01113      should end up pointing to null terminator of 'string' 
01114      if the conversion was successful. */
01115   //  printf("STRING: \"%s\"\n", string);
01116 
01117   (*int_ptr) = sign*strtol(string, &end_ptr, 10);
01118 
01119   /* If end pointer is a return character or null terminator, all is well */
01120   if ((*end_ptr == '\r') || (*end_ptr == '\0')) 
01121     return SUCCESS;
01122 
01123     return PARSE_ERROR;
01124   
01125 }
01126 /* Parses a floating point number */
01127 int string_to_float(char * string, double * float_ptr) {
01128 
01129   char ** error_ptr;
01130 
01131   if (*string == 0)
01132     return PARSE_ERROR;
01133 
01134   error_ptr = malloc(sizeof(char**));
01135   
01136   (*float_ptr) = strtod(string, error_ptr);
01137  
01138   /* These imply a succesful parse of the string */
01139   if ((**error_ptr == '\0') || (**error_ptr == '\r')) {
01140     free(error_ptr);
01141     return SUCCESS;
01142   }
01143     
01144   (*float_ptr) = 0;
01145   free(error_ptr);
01146   return PARSE_ERROR;  
01147 }
01148 
01149 /* Parses a floating point number */
01150 int parse_float(FILE * fs, double * float_ptr) {
01151 
01152   char string[MAX_TOKEN_SIZE];
01153   char ** error_ptr;
01154   token_t token;
01155   int sign;
01156   
01157   error_ptr = malloc(sizeof(char**));
01158 
01159   token = parseToken(fs, string);
01160 
01161   switch (token) {
01162   case tMinus:
01163   sign = -1;
01164   token = parseToken(fs, string); 
01165   break;
01166   case tPlus:
01167   sign = 1;
01168   token = parseToken(fs, string);
01169   break;
01170   default: 
01171     sign = 1;  
01172   }
01173  
01174   if (string[0] == 0) {
01175     free(error_ptr);
01176     return PARSE_ERROR;
01177   }
01178 
01179   (*float_ptr) = sign*strtod(string, error_ptr);
01180  
01181   /* No conversion was performed */
01182   if ((**error_ptr == '\0') || (**error_ptr == '\r')) {
01183     free(error_ptr);
01184     return SUCCESS;
01185   }
01186     
01187   //if (PARSE_DEBUG) printf("parse_float: double conversion failed for string \"%s\"\n", string);
01188 
01189   (*float_ptr) = 0;
01190   free(error_ptr);
01191   return PARSE_ERROR;
01192   
01193 
01194   
01195 }
01196 
01197 /* Parses a per frame equation. That is, interprets a stream of data as a per frame equation */
01198 per_frame_eqn_t * parse_per_frame_eqn(FILE * fs, int index, struct PRESET_T * preset) {
01199   
01200   char string[MAX_TOKEN_SIZE];
01201   param_t * param;
01202   per_frame_eqn_t * per_frame_eqn;
01203   gen_expr_t * gen_expr;
01204   
01205   if (parseToken(fs, string) != tEq) {
01206     //if (PARSE_DEBUG) printf("parse_per_frame_eqn: no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
01207     return NULL;                        
01208   }
01209   
01210   /* Find the parameter associated with the string, create one if necessary */
01211   if ((param = find_param(string, preset, P_CREATE)) == NULL) { 
01212     return NULL;        
01213   }
01214   
01215   /* Make sure parameter is writable */
01216   if (param->flags & P_FLAG_READONLY) {
01217       //if (PARSE_DEBUG) printf("parse_per_frame_eqn: parameter %s is marked as read only (LINE %d)\n", param->name, line_count);  
01218       return NULL;
01219   }
01220   
01221   /* Parse right side of equation as an expression */
01222   if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
01223     //if (PARSE_DEBUG) printf("parse_per_frame_eqn: equation evaluated to null (LINE %d)\n", line_count);
01224     return NULL;
01225   }
01226   
01227   //if (PARSE_DEBUG) printf("parse_per_frame_eqn: finished per frame equation evaluation (LINE %d)\n", line_count);
01228   
01229   /* Create a new per frame equation */
01230   if ((per_frame_eqn = new_per_frame_eqn(index, param, gen_expr)) == NULL) {
01231     //if (PARSE_DEBUG) printf("parse_per_frame_eqn: failed to create a new per frame eqn, out of memory?\n");
01232     free_gen_expr(gen_expr);
01233     return NULL;
01234   }
01235   
01236   //if (PARSE_DEBUG) printf("parse_per_frame_eqn: per_frame eqn parsed succesfully\n");
01237   
01238   return per_frame_eqn;
01239 }
01240 
01241 /* Parses an 'implicit' per frame equation. That is, interprets a stream of data as a per frame equation without a prefix */
01242 per_frame_eqn_t * parse_implicit_per_frame_eqn(FILE * fs, char * param_string, int index, struct PRESET_T * preset) {
01243   
01244   param_t * param;
01245   per_frame_eqn_t * per_frame_eqn;
01246   gen_expr_t * gen_expr;
01247   
01248   if (fs == NULL)
01249     return NULL;
01250   if (param_string == NULL)
01251     return NULL;
01252   if (preset == NULL)
01253     return NULL;
01254 
01255   //rintf("param string: %s\n", param_string);
01256   /* Find the parameter associated with the string, create one if necessary */
01257   if ((param = find_param(param_string, preset, P_CREATE)) == NULL) { 
01258     return NULL;        
01259   }
01260   
01261   //printf("parse_implicit_per_frame_eqn: param is %s\n", param->name);
01262 
01263   /* Make sure parameter is writable */
01264   if (param->flags & P_FLAG_READONLY) {
01265     //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: parameter %s is marked as read only (LINE %d)\n", param->name, line_count);  
01266     return NULL;
01267   }
01268   
01269   /* Parse right side of equation as an expression */
01270   if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
01271     //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: equation evaluated to null (LINE %d)\n", line_count);
01272     return NULL;
01273   }
01274   
01275   //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: finished per frame equation evaluation (LINE %d)\n", line_count);
01276   
01277   /* Create a new per frame equation */
01278   if ((per_frame_eqn = new_per_frame_eqn(index, param, gen_expr)) == NULL) {
01279     //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: failed to create a new per frame eqn, out of memory?\n");
01280     free_gen_expr(gen_expr);
01281     return NULL;
01282   }
01283   
01284   //if (PARSE_DEBUG) printf("parse_implicit_per_frame_eqn: per_frame eqn parsed succesfully\n");
01285   
01286   return per_frame_eqn;
01287 }
01288 
01289 /* Parses an initial condition */
01290 init_cond_t * parse_init_cond(FILE * fs, char * name, struct PRESET_T * preset) {
01291 
01292   param_t * param;
01293   value_t init_val;
01294   init_cond_t * init_cond;
01295         
01296   if (name == NULL)
01297     return NULL;
01298   if (preset == NULL)
01299     return NULL;
01300   
01301   /* Search for the paramater in the database, creating it if necessary */
01302   if ((param = find_param(name, preset, P_CREATE)) == NULL) {
01303     return NULL;
01304   }
01305   
01306   //if (PARSE_DEBUG) printf("parse_init_cond: parameter = \"%s\" (LINE %d)\n", param->name, line_count);
01307   
01308   if (param->flags & P_FLAG_READONLY) {
01309     //if (PARSE_DEBUG) printf("parse_init_cond: builtin parameter \"%s\" marked as read only!\n", param->name);
01310     return NULL;
01311   }             
01312   
01313   /* At this point, a parameter has been created or was found
01314      in the database. */
01315   
01316   //if (PARSE_DEBUG) printf("parse_init_cond: parsing initial condition value... (LINE %d)\n", line_count);
01317   
01318   /* integer value (boolean is an integer in C) */
01319   if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
01320     if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {      
01321       //if (PARSE_DEBUG) printf("parse_init_cond: error parsing integer!\n");
01322       return NULL;
01323     }
01324   }
01325   
01326   /* double value */
01327   else if (param->type == P_TYPE_DOUBLE) {
01328     if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
01329       //if (PARSE_DEBUG) printf("parse_init_cond: error parsing double!\n");
01330       return NULL;
01331     }
01332   }
01333   
01334   /* Unknown value */
01335   else {
01336     //if (PARSE_DEBUG) printf("parse_init_cond: unknown parameter type!\n");
01337     return NULL;
01338   }
01339   
01340   /* Create new initial condition */
01341   if ((init_cond = new_init_cond(param, init_val)) == NULL) {
01342       //if (PARSE_DEBUG) printf("parse_init_cond: new_init_cond failed!\n");
01343       return NULL;
01344   }
01345   
01346   /* Finished */
01347   return init_cond;
01348 }
01349 
01350 /* Parses a per frame init equation, not sure if this works right now */
01351 init_cond_t * parse_per_frame_init_eqn(FILE * fs, struct PRESET_T * preset, splaytree_t * database) {
01352   
01353   char name[MAX_TOKEN_SIZE];
01354   param_t * param = NULL;
01355   value_t init_val;
01356   init_cond_t * init_cond;
01357   gen_expr_t * gen_expr;
01358   double val;
01359   token_t token;
01360 
01361 
01362   if (preset == NULL)
01363     return NULL;
01364   if (fs == NULL)
01365     return NULL;
01366 
01367   if ((token = parseToken(fs, name)) != tEq)
01368     return NULL;
01369   
01370 
01371   /* If a database was specified,then use find_param_db instead */
01372   if ((database != NULL) && ((param = find_param_db(name, database, TRUE)) == NULL)) {
01373     return NULL;
01374   }
01375 
01376   /* Otherwise use the builtin parameter and user databases. This is confusing. Sorry. */
01377   if ((param == NULL) && ((param = find_param(name, preset, P_CREATE)) == NULL)) {
01378     return NULL;
01379   }
01380   
01381   //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: parameter = \"%s\" (LINE %d)\n", param->name, line_count);
01382   
01383   if (param->flags & P_FLAG_READONLY) {
01384     //if (PARSE_DEBUG) printf("pars_per_frame_init_eqn: builtin parameter \"%s\" marked as read only!\n", param->name);
01385     return NULL;
01386   }             
01387   
01388   /* At this point, a parameter has been created or was found
01389      in the database. */
01390   
01391   //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: parsing right hand side of per frame init equation.. (LINE %d)\n", line_count);
01392   
01393   if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
01394     //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: failed to parse general expresion!\n");
01395     return NULL;
01396   }
01397  
01398   /* Compute initial condition value */
01399   val = eval_gen_expr(gen_expr);
01400   
01401   /* Free the general expression now that we are done with it */
01402   free_gen_expr(gen_expr);
01403 
01404   /* integer value (boolean is an integer in C) */
01405   if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
01406     init_val.int_val = (int)val;
01407   }
01408   
01409   /* double value */
01410   else if (param->type == P_TYPE_DOUBLE) {
01411     init_val.double_val = val;
01412   }
01413   
01414   /* Unknown value */
01415   else {
01416     //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: unknown parameter type!\n");
01417     return NULL;
01418   }
01419   
01420 
01421   /* Create new initial condition */
01422   if ((init_cond = new_init_cond(param, init_val)) == NULL) {
01423       //if (PARSE_DEBUG) printf("parse_per_frame_init_eqn: new_init_cond failed!\n");
01424       return NULL;
01425   }
01426 
01427 
01428   /* Finished */
01429   return init_cond;
01430 }
01431 
01432 int parse_wavecode(char * token, FILE * fs, preset_t * preset) {
01433 
01434   char * var_string;
01435   init_cond_t * init_cond;
01436   custom_wave_t * custom_wave;
01437   int id;
01438   value_t init_val;
01439   param_t * param;
01440 
01441   /* Null argument checks */
01442   if (preset == NULL)
01443     return FAILURE;
01444   if (fs == NULL)
01445     return FAILURE;
01446   if (token == NULL)
01447     return FAILURE;
01448 
01449   /* token should be in the form wavecode_N_var, such as wavecode_1_samples */
01450   
01451   /* Get id and variable name from token string */
01452   if (parse_wavecode_prefix(token, &id, &var_string) < 0)   
01453     return PARSE_ERROR;
01454   
01455   //if (PARSE_DEBUG) printf("parse_wavecode: wavecode id = %d, parameter = \"%s\"\n", id, var_string);
01456 
01457   /* Retrieve custom wave information from preset. The 3rd argument
01458      if true creates a custom wave if one does not exist */
01459   if ((custom_wave = find_custom_wave(id, preset, TRUE)) == NULL) {
01460     //if (PARSE_DEBUG) printf("parse_wavecode: failed to load (or create) custom wave (id = %d)!\n", id);
01461     return FAILURE;
01462   }
01463   //if (PARSE_DEBUG) printf("parse_wavecode: custom wave found (id = %d)\n", custom_wave->id);
01464 
01465   /* Retrieve parameter from this custom waves parameter db */
01466   if ((param = find_param_db(var_string, custom_wave->param_tree, TRUE)) == NULL)
01467     return FAILURE;
01468 
01469   //if (PARSE_DEBUG) printf("parse_wavecode: custom wave parameter found (name = %s)\n", param->name);
01470 
01471   /* integer value (boolean is an integer in C) */
01472   if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
01473     if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {      
01474       //if (PARSE_DEBUG) printf("parse_wavecode: error parsing integer!\n");
01475       return PARSE_ERROR;
01476     }
01477   }
01478   
01479   /* double value */
01480   else if (param->type == P_TYPE_DOUBLE) {
01481     if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
01482       //if (PARSE_DEBUG) printf("parse_wavecode: error parsing double!\n");
01483       return PARSE_ERROR;
01484     }
01485   }
01486   
01487   /* Unknown value */
01488   else {
01489     //if (PARSE_DEBUG) printf("parse_wavecode: unknown parameter type!\n");
01490     return PARSE_ERROR;
01491   }
01492   
01493   /* Create new initial condition */
01494   if ((init_cond = new_init_cond(param, init_val)) == NULL) {
01495       //if (PARSE_DEBUG) printf("parse_wavecode: new_init_cond failed!\n");
01496       return FAILURE;
01497   }
01498   
01499   if (splay_insert(init_cond, param->name, custom_wave->init_cond_tree) < 0) {
01500     free_init_cond(init_cond);
01501     return PARSE_ERROR;
01502   }
01503 
01504   //if (PARSE_DEBUG) printf("parse_wavecode: [success]\n");
01505   return SUCCESS;
01506 }
01507 
01508 int parse_shapecode(char * token, FILE * fs, preset_t * preset) {
01509 
01510   char * var_string;
01511   init_cond_t * init_cond;
01512   custom_shape_t * custom_shape;
01513   int id;
01514   value_t init_val;
01515   param_t * param;
01516 
01517   /* Null argument checks */
01518   if (preset == NULL)
01519     return FAILURE;
01520   if (fs == NULL)
01521     return FAILURE;
01522   if (token == NULL)
01523     return FAILURE;
01524 
01525   /* token should be in the form shapecode_N_var, such as shapecode_1_samples */
01526   
01527   /* Get id and variable name from token string */
01528   if (parse_shapecode_prefix(token, &id, &var_string) < 0)   
01529     return PARSE_ERROR;
01530   
01531   //if (PARSE_DEBUG) printf("parse_shapecode: shapecode id = %d, parameter = \"%s\"\n", id, var_string);
01532 
01533   /* Retrieve custom shape information from preset. The 3rd argument
01534      if true creates a custom shape if one does not exist */
01535   if ((custom_shape = find_custom_shape(id, preset, TRUE)) == NULL) {
01536     //if (PARSE_DEBUG) printf("parse_shapecode: failed to load (or create) custom shape (id = %d)!\n", id);
01537     return FAILURE;
01538   }
01539   //if (PARSE_DEBUG) printf("parse_shapecode: custom shape found (id = %d)\n", custom_shape->id);
01540 
01541   /* Retrieve parameter from this custom shapes parameter db */
01542   if ((param = find_param_db(var_string, custom_shape->param_tree, TRUE)) == NULL) {
01543     //if (PARSE_DEBUG) printf("parse_shapecode: failed to create parameter.\n");
01544     return FAILURE;
01545   }
01546   //if (PARSE_DEBUG) printf("parse_shapecode: custom shape parameter found (name = %s)\n", param->name);
01547 
01548   /* integer value (boolean is an integer in C) */
01549   if ((param->type == P_TYPE_INT) || (param->type == P_TYPE_BOOL)) {
01550     if ((parse_int(fs, (int*)&init_val.int_val)) == PARSE_ERROR) {      
01551       //if (PARSE_DEBUG) printf("parse_shapecode: error parsing integer!\n");
01552       return PARSE_ERROR;
01553     }
01554   }
01555   
01556   /* double value */
01557   else if (param->type == P_TYPE_DOUBLE) {
01558     if ((parse_float(fs, (double*)&init_val.double_val)) == PARSE_ERROR) {
01559       //if (PARSE_DEBUG) printf("parse_shapecode: error parsing double!\n");
01560       return PARSE_ERROR;
01561     }
01562   }
01563   
01564   /* Unknown value */
01565   else {
01566     //if (PARSE_DEBUG) printf("parse_shapecode: unknown parameter type!\n");
01567     return PARSE_ERROR;
01568   }
01569   
01570   /* Create new initial condition */
01571   if ((init_cond = new_init_cond(param, init_val)) == NULL) {
01572       //if (PARSE_DEBUG) printf("parse_shapecode: new_init_cond failed!\n");
01573       return FAILURE;
01574   }
01575  
01576   if (splay_insert(init_cond, param->name, custom_shape->init_cond_tree) < 0) {
01577     free_init_cond(init_cond);
01578     //if (PARSE_DEBUG) printf("parse_shapecode: initial condition already set, not reinserting it (param = \"%s\")\n", param->name);
01579     return PARSE_ERROR;
01580   }
01581 
01582   //if (PARSE_DEBUG) printf("parse_shapecode: [success]\n");
01583   return SUCCESS;
01584 }
01585 
01586 
01587 int parse_wavecode_prefix(char * token, int * id, char ** var_string) {
01588 
01589   int len, i, j;
01590   
01591   if (token == NULL)
01592     return FAILURE;
01593   if (*var_string == NULL)
01594     return FAILURE;
01595   if (id == NULL)
01596     return FAILURE;
01597   
01598   len = strlen(token);
01599 
01600   /* Move pointer passed "wavecode_" prefix */
01601   if (len <= WAVECODE_STRING_LENGTH)
01602     return FAILURE;
01603   i = WAVECODE_STRING_LENGTH;
01604   j = 0;
01605   (*id) = 0;
01606   
01607   /* This loop grabs the integer id for this custom wave */
01608   while ((i < len) && (token[i] >=  48) && (token[i] <= 57)) {
01609     if (j >= MAX_TOKEN_SIZE)
01610       return FAILURE;
01611     
01612     (*id) = 10*(*id) + (token[i]-48);
01613     j++;
01614     i++;
01615   }
01616 
01617  
01618   if (i > (len - 2))
01619     return FAILURE;
01620   
01621   *var_string = token + i + 1;
01622  
01623   return SUCCESS;
01624 
01625 }
01626 
01627 
01628 int parse_shapecode_prefix(char * token, int * id, char ** var_string) {
01629 
01630   int len, i, j;
01631   
01632   if (token == NULL)
01633     return FAILURE;
01634   if (*var_string == NULL)
01635     return FAILURE;
01636   if (id == NULL)
01637     return FAILURE;
01638   
01639   len = strlen(token);
01640 
01641   /* Move pointer passed "shapecode_" prefix */
01642   if (len <= SHAPECODE_STRING_LENGTH)
01643     return FAILURE;
01644   i = SHAPECODE_STRING_LENGTH;
01645   j = 0;
01646   (*id) = 0;
01647   
01648   /* This loop grabs the integer id for this custom shape */
01649   while ((i < len) && (token[i] >=  48) && (token[i] <= 57)) {
01650     if (j >= MAX_TOKEN_SIZE)
01651       return FAILURE;
01652     
01653     (*id) = 10*(*id) + (token[i]-48);
01654     j++;
01655     i++;
01656   }
01657 
01658  
01659   if (i > (len - 2))
01660     return FAILURE;
01661   
01662   *var_string = token + i + 1;
01663  
01664   return SUCCESS;
01665 
01666 }
01667 
01668 int parse_wave_prefix(char * token, int * id, char ** eqn_string) {
01669 
01670   int len, i, j;
01671   
01672   if (token == NULL)
01673     return FAILURE;
01674   if (eqn_string == NULL)
01675     return FAILURE;
01676   if (id == NULL)
01677     return FAILURE;
01678   
01679   len = strlen(token);
01680  
01681   if (len <= WAVE_STRING_LENGTH)
01682     return FAILURE;
01683 
01684 
01685   i = WAVE_STRING_LENGTH;
01686   j = 0;
01687   (*id) = 0;
01688   
01689   /* This loop grabs the integer id for this custom wave */
01690   while ((i < len) && (token[i] >=  48) && (token[i] <= 57)) {
01691     if (j >= MAX_TOKEN_SIZE)
01692       return FAILURE;
01693     
01694     (*id) = 10*(*id) + (token[i]-48);
01695     j++;
01696     i++;
01697   }
01698 
01699   if (i > (len - 2))
01700     return FAILURE;
01701  
01702   *eqn_string = token + i + 1;
01703  
01704   return SUCCESS;
01705 
01706 }
01707 
01708 int parse_shape_prefix(char * token, int * id, char ** eqn_string) {
01709 
01710   int len, i, j;
01711   
01712   if (token == NULL)
01713     return FAILURE;
01714   if (eqn_string == NULL)
01715     return FAILURE;
01716   if (id == NULL)
01717     return FAILURE;
01718   
01719   len = strlen(token);
01720  
01721   if (len <= SHAPE_STRING_LENGTH)
01722     return FAILURE;
01723 
01724 
01725   i = SHAPE_STRING_LENGTH;
01726   j = 0;
01727   (*id) = 0;
01728   
01729   /* This loop grabs the integer id for this custom wave */
01730   while ((i < len) && (token[i] >=  48) && (token[i] <= 57)) {
01731     if (j >= MAX_TOKEN_SIZE)
01732       return FAILURE;
01733     
01734     (*id) = 10*(*id) + (token[i]-48);
01735     j++;
01736     i++;
01737   }
01738 
01739   if (i > (len - 2))
01740     return FAILURE;
01741  
01742   *eqn_string = token + i + 1;
01743  
01744   return SUCCESS;
01745 
01746 }
01747 
01748 /* Parses custom wave equations */
01749 int parse_wave(char * token, FILE * fs, preset_t * preset) {
01750   
01751   int id;
01752   char * eqn_type;
01753   char string[MAX_TOKEN_SIZE];
01754   param_t * param;
01755   per_frame_eqn_t * per_frame_eqn;
01756   gen_expr_t * gen_expr;
01757   custom_wave_t * custom_wave;
01758   init_cond_t * init_cond;
01759 
01760   if (token == NULL)
01761     return FAILURE;
01762   if (fs == NULL)
01763     return FAILURE;
01764   if (preset == NULL)
01765     return FAILURE;
01766   
01767   /* Grab custom wave id and equation type (per frame or per point) from string token */
01768   if (parse_wave_prefix(token, &id, &eqn_type) < 0) {
01769     //if (PARSE_DEBUG) printf("parse_wave: syntax error in custom wave prefix!\n");
01770     return FAILURE;
01771   }
01772   /* Retrieve custom wave associated with this id */
01773   if ((custom_wave = find_custom_wave(id, preset, TRUE)) == NULL)
01774     return FAILURE;
01775 
01776 
01777   /* per frame init equation case */        
01778   if (!strncmp(eqn_type, WAVE_INIT_STRING, WAVE_INIT_STRING_LENGTH)) {
01779 
01780     //if (PARSE_DEBUG) printf("parse_wave (per frame init): [begin] (LINE %d)\n", line_count);
01781 
01782     /* Parse the per frame equation */
01783     if ((init_cond = parse_per_frame_init_eqn(fs, preset, custom_wave->param_tree)) == NULL) {
01784       //if (PARSE_DEBUG) printf("parse_wave (per frame init): equation parsing failed (LINE %d)\n", line_count);
01785       return PARSE_ERROR;
01786     }   
01787 
01788     /* Insert the equation in the per frame equation tree */
01789     if (splay_insert(init_cond, init_cond->param->name, custom_wave->per_frame_init_eqn_tree) < 0) {
01790       //if (PARSE_DEBUG) printf("parse_wave (per frame init): failed to add equation (ERROR)\n");
01791        free_init_cond(init_cond); /* will free the gen expr too */              
01792       return FAILURE;
01793     }
01794    
01795     if (update_string_buffer(custom_wave->per_frame_init_eqn_string_buffer, 
01796                              &custom_wave->per_frame_init_eqn_string_index) < 0)
01797       return FAILURE;
01798         
01799     return SUCCESS;
01800   
01801   }
01802 
01803   /* per frame equation case */
01804   if (!strncmp(eqn_type, PER_FRAME_STRING_NO_UNDERSCORE, PER_FRAME_STRING_NO_UNDERSCORE_LENGTH)) {
01805 
01806     //if (PARSE_DEBUG) printf("parse_wave (per_frame): [start] (custom wave id = %d)\n", custom_wave->id);
01807     
01808     if (parseToken(fs, string) != tEq) {
01809       //if (PARSE_DEBUG) printf("parse_wave (per_frame): no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
01810       return PARSE_ERROR;                       
01811     }
01812   
01813     /* Find the parameter associated with the string in the custom wave database */
01814     if ((param = find_param_db(string, custom_wave->param_tree, TRUE)) == NULL) { 
01815       //if (PARSE_DEBUG) printf("parse_wave (per_frame): parameter \"%s\" not found or cannot be malloc'ed!!\n", string);
01816       return FAILURE;   
01817     }
01818   
01819     
01820     /* Make sure parameter is writable */
01821     if (param->flags & P_FLAG_READONLY) {
01822       //if (PARSE_DEBUG) printf("parse_wave (per_frame): parameter %s is marked as read only (LINE %d)\n", param->name, line_count);  
01823       return FAILURE;
01824     }
01825   
01826     /* Parse right side of equation as an expression */
01827 
01828     current_wave = custom_wave;
01829     if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
01830       //if (PARSE_DEBUG) printf("parse_wave (per_frame): equation evaluated to null (LINE %d)\n", line_count);
01831       current_wave = NULL;
01832       return PARSE_ERROR;
01833 
01834     }
01835     current_wave = NULL;
01836 
01837     //if (PARSE_DEBUG) printf("parse_wave (per_frame): [finished parsing equation] (LINE %d)\n", line_count);
01838   
01839     /* Create a new per frame equation */
01840     if ((per_frame_eqn = new_per_frame_eqn(custom_wave->per_frame_count++, param, gen_expr)) == NULL) {
01841       //if (PARSE_DEBUG) printf("parse_wave (per_frame): failed to create a new per frame eqn, out of memory?\n");
01842       free_gen_expr(gen_expr);
01843       return FAILURE;
01844     }
01845  
01846     if (splay_insert(per_frame_eqn, &per_frame_eqn->index, custom_wave->per_frame_eqn_tree) < 0) {
01847       free_per_frame_eqn(per_frame_eqn);
01848       return FAILURE;
01849     }
01850        
01851     //if (PARSE_DEBUG) printf("parse_wave (per_frame): equation %d associated with custom wave %d [success]\n", 
01852     //                      per_frame_eqn->index, custom_wave->id);
01853 
01854     
01855     /* Need to add stuff to string buffer so the editor can read the equations. 
01856        Why not make a nice little helper function for this? - here it is: */
01857 
01858    
01859     if (update_string_buffer(custom_wave->per_frame_eqn_string_buffer, &custom_wave->per_frame_eqn_string_index) < 0)
01860       return FAILURE;
01861 
01862  
01863     return SUCCESS;
01864   }
01865 
01866 
01867   /* per point equation case */
01868   if (!strncmp(eqn_type, PER_POINT_STRING, PER_POINT_STRING_LENGTH)) {
01869 
01870     //if (PARSE_DEBUG) printf("parse_wave (per_point): per_pixel equation parsing start...(LINE %d)\n", line_count);
01871 
01872     if (parseToken(fs, string) != tEq) { /* parse per pixel operator  name */
01873       //if (PARSE_DEBUG) printf("parse_wave (per_point): equal operator missing after per pixel operator! (LINE %d)\n", line_count);
01874       return PARSE_ERROR;
01875     }
01876     
01877     /* Parse right side of equation as an expression */
01878     current_wave = custom_wave;
01879     if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
01880       //if (PARSE_DEBUG) printf("parse_wave (per_point): equation evaluated to null? (LINE %d)\n", line_count);
01881       return PARSE_ERROR;
01882     }
01883     current_wave = NULL;
01884 
01885     /* Add the per point equation */
01886     if (add_per_point_eqn(string, gen_expr, custom_wave) < 0) {
01887       free_gen_expr(gen_expr);
01888       return PARSE_ERROR;
01889     }
01890 
01891    
01892     if (update_string_buffer(custom_wave->per_point_eqn_string_buffer, &custom_wave->per_point_eqn_string_index) < 0)
01893       return FAILURE;
01894 
01895     //if (PARSE_DEBUG) printf("parse_wave (per_point): [finished] (custom wave id = %d)\n", custom_wave->id);
01896     return SUCCESS;
01897   }
01898 
01899 
01900   /* Syntax error, return parse error */
01901   return PARSE_ERROR;
01902 }
01903 
01904 
01905 
01906 /* Parses custom shape equations */
01907 int parse_shape(char * token, FILE * fs, preset_t * preset) {
01908   
01909   int id;
01910   char * eqn_type;
01911   char string[MAX_TOKEN_SIZE];
01912   param_t * param;
01913   per_frame_eqn_t * per_frame_eqn;
01914   gen_expr_t * gen_expr;
01915   custom_shape_t * custom_shape;
01916   init_cond_t * init_cond;
01917 
01918   if (token == NULL)
01919 
01920     return FAILURE;
01921   if (fs == NULL)
01922     return FAILURE;
01923   if (preset == NULL)
01924     return FAILURE;
01925   
01926   /* Grab custom shape id and equation type (per frame or per point) from string token */
01927   if (parse_shape_prefix(token, &id, &eqn_type) < 0) {
01928     //if (PARSE_DEBUG) printf("parse_shape: syntax error in custom shape prefix!\n");
01929     return PARSE_ERROR;
01930   }
01931   /* Retrieve custom shape associated with this id */
01932   if ((custom_shape = find_custom_shape(id, preset, TRUE)) == NULL)
01933     return FAILURE;
01934 
01935 
01936   /* per frame init equation case */        
01937   if (!strncmp(eqn_type, SHAPE_INIT_STRING, SHAPE_INIT_STRING_LENGTH)) {
01938 
01939     //if (PARSE_DEBUG) printf("parse_shape (per frame init): [begin] (LINE %d)\n", line_count);
01940 
01941     /* Parse the per frame equation */
01942     if ((init_cond = parse_per_frame_init_eqn(fs, preset, custom_shape->param_tree)) == NULL) {
01943       //if (PARSE_DEBUG) printf("parse_shape (per frame init): equation parsing failed (LINE %d)\n", line_count);
01944       return PARSE_ERROR;
01945     }   
01946     
01947     /* Insert the equation in the per frame equation tree */
01948     if (splay_insert(init_cond, init_cond->param->name, custom_shape->per_frame_init_eqn_tree) < 0) {
01949       //if (PARSE_DEBUG) printf("parse_shape (per frame init): failed to add equation (ERROR)\n");
01950       free_init_cond(init_cond); /* will free the gen expr too */               
01951       return ERROR;
01952     }
01953 
01954     if (update_string_buffer(custom_shape->per_frame_init_eqn_string_buffer, 
01955                              &custom_shape->per_frame_init_eqn_string_index) < 0)
01956       return FAILURE;
01957         
01958     return SUCCESS;
01959   
01960   }
01961 
01962   /* per frame equation case */
01963   if (!strncmp(eqn_type, PER_FRAME_STRING_NO_UNDERSCORE, PER_FRAME_STRING_NO_UNDERSCORE_LENGTH)) {
01964 
01965     //if (PARSE_DEBUG) printf("parse_shape (per_frame): [start] (custom shape id = %d)\n", custom_shape->id);
01966     
01967     if (parseToken(fs, string) != tEq) {
01968       //if (PARSE_DEBUG) printf("parse_shape (per_frame): no equal sign after string \"%s\" (LINE %d)\n", string, line_count);
01969       return PARSE_ERROR;                       
01970     }
01971   
01972     /* Find the parameter associated with the string in the custom shape database */
01973     if ((param = find_param_db(string, custom_shape->param_tree, TRUE)) == NULL) { 
01974       //if (PARSE_DEBUG) printf("parse_shape (per_frame): parameter \"%s\" not found or cannot be malloc'ed!!\n", string);
01975       return FAILURE;   
01976     }
01977   
01978     
01979     /* Make sure parameter is writable */
01980     if (param->flags & P_FLAG_READONLY) {
01981       //if (PARSE_DEBUG) printf("parse_shape (per_frame): parameter %s is marked as read only (LINE %d)\n", param->name, line_count);  
01982       return FAILURE;
01983     }
01984   
01985     /* Parse right side of equation as an expression */
01986 
01987     current_shape = custom_shape;
01988     if ((gen_expr = parse_gen_expr(fs, NULL, preset)) == NULL) {
01989       //if (PARSE_DEBUG) printf("parse_shape (per_frame): equation evaluated to null (LINE %d)\n", line_count);
01990       current_shape = NULL;
01991       return PARSE_ERROR;
01992     }
01993 
01994     current_shape = NULL;
01995 
01996     //if (PARSE_DEBUG) printf("parse_shape (per_frame): [finished parsing equation] (LINE %d)\n", line_count);
01997   
01998     /* Create a new per frame equation */
01999     if ((per_frame_eqn = new_per_frame_eqn(custom_shape->per_frame_count++, param, gen_expr)) == NULL) {
02000       //if (PARSE_DEBUG) printf("parse_shape (per_frame): failed to create a new per frame eqn, out of memory?\n");
02001       free_gen_expr(gen_expr);
02002       return FAILURE;
02003     }
02004  
02005     if (splay_insert(per_frame_eqn, &per_frame_eqn->index, custom_shape->per_frame_eqn_tree) < 0) {
02006       free_per_frame_eqn(per_frame_eqn);
02007       return FAILURE;
02008     }
02009        
02010     //if (PARSE_DEBUG) printf("parse_shape (per_frame): equation %d associated with custom shape %d [success]\n", 
02011     //                      per_frame_eqn->index, custom_shape->id);
02012 
02013     
02014     /* Need to add stuff to string buffer so the editor can read the equations.
02015        Why not make a nice little helper function for this? - here it is: */
02016     
02017     if (update_string_buffer(custom_shape->per_frame_eqn_string_buffer, &custom_shape->per_frame_eqn_string_index) < 0)
02018       return FAILURE;
02019 
02020  
02021     return SUCCESS;
02022   }
02023 
02024 
02025   /* Syntax error, return parse error */
02026   return PARSE_ERROR;
02027 }
02028 
02029 /* Helper function to update the string buffers used by the editor */
02030 int update_string_buffer(char * buffer, int * index) {
02031 
02032   int string_length;
02033   int skip_size;
02034 
02035   if (!buffer)
02036     return FAILURE;
02037   if (!index)
02038     return FAILURE;
02039 
02040   
02041   /* If the string line buffer used by the parser is already full then quit */
02042   if (string_line_buffer_index == (STRING_LINE_SIZE-1))
02043     return FAILURE;
02044 
02045   if ((skip_size = get_string_prefix_len(string_line_buffer)) == FAILURE)
02046     return FAILURE;
02047 
02048   string_line_buffer[string_line_buffer_index++] = '\n';
02049 
02050   //  string_length = strlen(string_line_buffer + strlen(eqn_string)+1);
02051   if (skip_size >= STRING_LINE_SIZE)
02052     return FAILURE;
02053 
02054   string_length = strlen(string_line_buffer + skip_size);
02055 
02056   if (skip_size > (STRING_LINE_SIZE-1))
02057     return FAILURE;
02058 
02059   /* Add line to string buffer */
02060   strncpy(buffer + (*index), 
02061           string_line_buffer + skip_size, string_length);
02062   
02063   /* Buffer full, quit */
02064   if ((*index) > (STRING_BUFFER_SIZE - 1)) {
02065     //if (PARSE_DEBUG) printf("update_string_buffer: string buffer full!\n");
02066     return FAILURE;
02067   }     
02068   
02069   /* Otherwise, increment string index by the added string length */
02070   (*index)+=string_length;
02071     
02072   return SUCCESS;
02073   
02074 }
02075 
02076 
02077 /* Helper function: returns the length of the prefix portion in the line
02078    buffer (the passed string here). In other words, given
02079    the string 'per_frame_1 = x = ....', return the length of 'per_frame_1 = '
02080    Returns -1 if syntax error
02081 */
02082 
02083 int get_string_prefix_len(char * string) {
02084   
02085   int i = 0;
02086 
02087   /* Null argument check */
02088   if (string == NULL)
02089     return FAILURE;
02090 
02091   
02092   /* First find the equal sign */
02093   while (string[i] != '=') {
02094     if (string[i] == 0)
02095       return FAILURE;
02096     i++;
02097   }
02098 
02099   /* If the string already ends at the next char then give up */
02100   if (string[i+1] == 0)
02101     return FAILURE;
02102 
02103   /* Move past the equal sign */
02104   i++;
02105 
02106   /* Now found the start of the LHS variable, ie skip the spaces */
02107   while(string[i] == ' ') {
02108     i++;
02109   }
02110 
02111   /* If this is the end of the string then its a syntax error */
02112   if (string[i] == 0)
02113     return FAILURE;
02114 
02115   /* Finished succesfully, return the length */
02116   return i;
02117 }

Generated on Tue Dec 20 10:14:58 2005 for vlc-0.8.4a by  doxygen 1.4.2