home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Graphics / Graphics.zip / povsrc31.zip / Express.c < prev    next >
C/C++ Source or Header  |  2001-01-31  |  89KB  |  3,712 lines

  1. /****************************************************************************
  2. *                express.c
  3. *
  4. *  This module implements an expression parser for the floats, vectors and
  5. *  colours in scene description files.
  6. *
  7. *  from Persistence of Vision(tm) Ray Tracer
  8. *  Copyright 1996,1999 Persistence of Vision Team
  9. *---------------------------------------------------------------------------
  10. *  NOTICE: This source code file is provided so that users may experiment
  11. *  with enhancements to POV-Ray and to port the software to platforms other
  12. *  than those supported by the POV-Ray Team.  There are strict rules under
  13. *  which you are permitted to use this file.  The rules are in the file
  14. *  named POVLEGAL.DOC which should be distributed with this file.
  15. *  If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  16. *  Team Coordinator by email to team-coord@povray.org or visit us on the web at
  17. *  http://www.povray.org. The latest version of POV-Ray may be found at this site.
  18. *
  19. * This program is based on the popular DKB raytracer version 2.12.
  20. * DKBTrace was originally written by David K. Buck.
  21. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  22. *
  23. * Modifications by Thomas Willhalm, March 1999, used with permission
  24. *
  25. *****************************************************************************
  26. *
  27. * This source file has been modified by Ronald L. Parker (parkerr@mail.fwi.com)
  28. * to add the keywords min_extent and max_extent, used to determine the bounds of
  29. * objects
  30. *
  31. *
  32. *****************************************************************************/
  33.  
  34. #include <ctype.h>
  35. #include "frame.h"
  36. #include "vector.h"
  37. #include "povproto.h"
  38. #include "parse.h"
  39. #include "parstxtr.h"
  40. #include "colour.h"
  41. #ifdef SplinePatch
  42. #include "splines.h"
  43. #endif
  44. #include "express.h"
  45. #include "matrices.h"
  46. #include "povray.h"
  47. #include "tokenize.h"
  48. #include "pattern.h"
  49. #include "pigment.h"
  50. #include "normal.h"
  51. #include "texture.h"
  52.  
  53. #include "hfield.h"
  54. #include "render.h"
  55. #include "ray.h"
  56. #include "objects.h"
  57.  #ifdef TimeDatePatch
  58. #include <time.h>
  59. #endif
  60. #ifdef ComplexFunctionsPatch
  61. /*dfs -- complex functions*/
  62. #include "fractal.h"
  63. #include "hcmplx.h"
  64. /*--dfs*/
  65. #endif
  66. /*****************************************************************************
  67. * Local preprocessor defines
  68. ******************************************************************************/
  69. #ifdef VtransformPatch
  70. #define IsInverse 1 
  71. #define IsNotInverse 0
  72. static void Parse_VTransform(VECTOR result, unsigned char inverse );
  73. #endif
  74.  
  75. #define ftrue(f) ((int)(fabs(f)>EPSILON))
  76. #ifndef FIX_WATCOM_BUG
  77. #define FIX_WATCOM_BUG
  78. #endif
  79.  
  80. #ifdef GetTicksPatch
  81. /*YS enabling time mesurement */
  82. DBL ChronoStart;
  83. DBL ChronoEnd;
  84. #endif
  85.  
  86. /*****************************************************************************
  87. * Local typedefs
  88. ******************************************************************************/
  89.  
  90.  
  91.  
  92. /*****************************************************************************
  93. * Local variables
  94. ******************************************************************************/
  95.  
  96. static unsigned int Number_Of_Random_Generators;
  97. static unsigned long *next_rand;
  98.  
  99.  
  100. /*****************************************************************************
  101. * Static functions
  102. ******************************************************************************/
  103.  
  104. static void Parse_Vector_Param (VECTOR Vector);
  105. static void Parse_Vector_Param2 (VECTOR Vect1, VECTOR Vect2);
  106. static void Parse_Num_Factor (EXPRESS Express, int *Terms);
  107. static void Parse_Num_Term (EXPRESS Express, int *Terms);
  108. static void Parse_Rel_Factor (EXPRESS Express, int *Terms);
  109. static void Parse_Rel_Term (EXPRESS Express, int *Terms);
  110. static void Parse_Logical (EXPRESS Express, int *Terms);
  111. static void Parse_Express (EXPRESS Express, int *Terms);
  112. static void Promote_Express (EXPRESS Express,int *Old_Terms,int New_Terms);
  113. static void POV_strupr (char *s);
  114. static void POV_strlwr (char *s);
  115.  
  116. static DBL stream_rand (int stream);
  117. static int stream_seed (int seed);
  118.  
  119.  
  120.  
  121. /*****************************************************************************
  122. *
  123. * FUNCTION
  124. *
  125. * INPUT
  126. *
  127. * OUTPUT
  128. *
  129. * RETURNS
  130. *
  131. * AUTHOR
  132. *
  133. * DESCRIPTION
  134. *
  135. * CHANGES
  136. *
  137. ******************************************************************************/
  138.  
  139. DBL Parse_Float_Param()
  140. {
  141.   DBL Local;
  142.   EXPRESS Express;
  143.   int Terms = 1;
  144.  
  145.   GET(LEFT_PAREN_TOKEN);
  146.   Parse_Express(Express,&Terms);
  147.  
  148.   if (Terms>1)
  149.   {
  150.     Error ("Float expected but vector or color expression found.");
  151.   }
  152.  
  153.   Local = Express[0];
  154.  
  155.   GET(RIGHT_PAREN_TOKEN);
  156.  
  157.   return (Local);
  158. }
  159.  
  160.  
  161.  
  162. /*****************************************************************************
  163. *
  164. * FUNCTION
  165. *
  166. * INPUT
  167. *
  168. * OUTPUT
  169. *
  170. * RETURNS
  171. *
  172. * AUTHOR
  173. *
  174. * DESCRIPTION
  175. *
  176. * CHANGES
  177. *
  178. ******************************************************************************/
  179.  
  180. void Parse_Float_Param2(DBL *Val1,DBL *Val2)
  181. {
  182.    GET (LEFT_PAREN_TOKEN);
  183.    *Val1 = Parse_Float();
  184.    Parse_Comma();
  185.    *Val2 = Parse_Float();
  186.    GET (RIGHT_PAREN_TOKEN);
  187.   }
  188.  
  189.  
  190.  
  191. /*****************************************************************************
  192. *
  193. * FUNCTION
  194. *
  195. * INPUT
  196. *
  197. * OUTPUT
  198. *
  199. * RETURNS
  200. *
  201. * AUTHOR
  202. *
  203. * DESCRIPTION
  204. *
  205. * CHANGES
  206. *
  207. ******************************************************************************/
  208.  
  209. static void Parse_Vector_Param(VECTOR Vector)
  210. {
  211.   GET(LEFT_PAREN_TOKEN);
  212.   Parse_Vector(Vector);
  213.   GET(RIGHT_PAREN_TOKEN);
  214.   }
  215.  
  216.  
  217.  
  218. /*****************************************************************************
  219. *
  220. * FUNCTION
  221. *
  222. * INPUT
  223. *
  224. * OUTPUT
  225. *
  226. * RETURNS
  227. *
  228. * AUTHOR
  229. *
  230. * DESCRIPTION
  231. *
  232. * CHANGES
  233. *
  234. ******************************************************************************/
  235.  
  236. static void Parse_Vector_Param2(VECTOR Val1,VECTOR Val2)
  237. {
  238.    GET (LEFT_PAREN_TOKEN);
  239.    Parse_Vector(Val1);
  240.    Parse_Comma();
  241.    Parse_Vector(Val2);
  242.    GET (RIGHT_PAREN_TOKEN);
  243.   }
  244.  
  245. #ifdef TracePatch
  246. /*****************************************************************************
  247. *
  248. * FUNCTION
  249. *
  250. * INPUT
  251. *
  252. * OUTPUT
  253. *
  254. * RETURNS
  255. *
  256. * AUTHOR
  257. *
  258. * DESCRIPTION
  259. *
  260. * CHANGES
  261. *
  262. ******************************************************************************/
  263.  
  264. static void Parse_Trace(VECTOR Res)
  265.   {
  266.    OBJECT *Object;  
  267.    INTERSECTION Intersect;
  268.    RAY    Ray;
  269.    VECTOR Local_Normal;
  270.  
  271.    GET (LEFT_PAREN_TOKEN);
  272.    
  273.    EXPECT
  274.      CASE (OBJECT_ID_TOKEN)
  275.        Object =(OBJECT*) Token.Data;
  276.        EXIT
  277.      END_CASE
  278.  
  279.      OTHERWISE
  280.        Object = NULL;
  281.        UNGET
  282.        EXIT
  283.      END_CASE
  284.    END_EXPECT
  285.  
  286.    if ( !Object ) {
  287.      Error ("Object Identifier Expected.");
  288.    }
  289.  
  290.    Parse_Comma();
  291.   
  292.    Initialize_Ray_Containers( &Ray );
  293.    Parse_Vector(Ray.Initial);
  294.    Parse_Comma();
  295.    Parse_Vector(Ray.Direction);
  296.    VNormalizeEq(Ray.Direction);
  297.  
  298.    Parse_Comma();
  299.  
  300.    if ( Intersection( &Intersect, Object, &Ray ) ) {
  301.      Assign_Vector( Res, Intersect.IPoint );
  302.      Normal( Local_Normal, Intersect.Object, &Intersect );
  303.    }
  304.    else {
  305.      Res[X]=Res[Y]=Res[Z]=0;
  306.      Local_Normal[X] = Local_Normal[Y] = Local_Normal[Z] = 0;
  307.    }
  308.  
  309.    EXPECT
  310.      CASE (VECTOR_FUNCT_TOKEN)
  311.        /* All of these functions return a VECTOR result */
  312.        if(Token.Function_Id == VECTOR_ID_TOKEN) {
  313.          Assign_Vector(Token.Data, Local_Normal);
  314.        }
  315.        else {
  316.          UNGET
  317.        }
  318.        EXIT
  319.      END_CASE
  320.  
  321.      OTHERWISE
  322.        UNGET
  323.        EXIT
  324.      END_CASE
  325.    END_EXPECT
  326.  
  327.    GET (RIGHT_PAREN_TOKEN);
  328.  
  329.   }
  330. #endif
  331.  
  332. /*****************************************************************************
  333. *
  334. * FUNCTION
  335. *
  336. * INPUT
  337. *
  338. * OUTPUT
  339. *
  340. * RETURNS
  341. *
  342. * AUTHOR
  343. *
  344. * DESCRIPTION
  345. *
  346. * CHANGES
  347. *
  348. ******************************************************************************/
  349.  
  350. static void Parse_Num_Factor (EXPRESS Express,int *Terms)
  351. {
  352.   int i = 0;
  353.   DBL Val,Val2;
  354.   VECTOR Vect,Vect2,Vect3;
  355. #ifdef SplinePatch
  356.   SPLINE2 *spline;
  357.   OBJECT *Object;  
  358. #endif
  359.   TRANSFORM Trans;
  360. #ifdef VturbulencePatch
  361.   TURB Turb;                           /* Added by bajcik */
  362. #endif
  363. #ifdef ComplexFunctionsPatch
  364. /*dfs -- complex functions*/
  365.   CMPLX cmplx1,cmplx2,cmplx3;
  366. /*--dfs*/
  367. #endif
  368. #ifdef HfHeightAtPatch
  369.   HFIELD *hfield;
  370. #endif  
  371.   char *Local_String, *Local_String2;
  372.   FILE *f;
  373.   POV_ARRAY *a;
  374.   int Old_Ok=Ok_To_Declare;
  375. #ifdef BoundPatch
  376. #ifndef SplinePatch
  377.   OBJECT *Object;
  378. #endif
  379. #endif
  380. #ifdef BsplinePatch
  381.   SPLINE *help;
  382.   SPLINE_3D *help_3d;
  383.   int  done=FALSE,t;
  384. #endif
  385.  
  386.  Ok_To_Declare=TRUE;
  387.  
  388.   EXPECT
  389.     CASE (FLOAT_FUNCT_TOKEN)
  390.        /* All of these functions return a DBL result */
  391.        switch(Token.Function_Id)
  392.          {
  393.           case ABS_TOKEN:
  394.             Val = Parse_Float_Param();
  395.             Val = fabs(Val);
  396.             break;
  397.  
  398.           case ACOS_TOKEN:
  399.             Val = acos(Parse_Float_Param());
  400.             break;
  401.  
  402.           case VAL_TOKEN:
  403.             GET (LEFT_PAREN_TOKEN);
  404.             Local_String=Parse_String();
  405.             Val = atof(Local_String);
  406.             POV_FREE(Local_String);
  407.             GET (RIGHT_PAREN_TOKEN);
  408.             break;
  409.  
  410.           case ASC_TOKEN:
  411.             GET (LEFT_PAREN_TOKEN);
  412.             Local_String=Parse_String();
  413.             Val = (DBL)Local_String[0];
  414.             POV_FREE(Local_String);
  415.             GET (RIGHT_PAREN_TOKEN);
  416.             break;
  417.  
  418.           case ASIN_TOKEN:
  419.             Val = asin(Parse_Float_Param());
  420.             break;
  421.  
  422.           case ATAN2_TOKEN:
  423.             Parse_Float_Param2(&Val,&Val2);
  424.             if (ftrue(Val) || ftrue(Val2))
  425.             {
  426.                Val=atan2(Val,Val2);
  427.             }
  428.             else
  429.             {
  430.                Error("Domain error in atan2\n");
  431.             }
  432.             break;
  433.           /*dfs-- added cosh, sinh, tanh, acosh, asinh, atanh */
  434.           case COSH_TOKEN:
  435.             #ifdef UnofficialBlocking
  436.               parseUnofficialFeature(40);
  437.             #endif
  438.                Val = COSH(Parse_Float_Param());
  439.                break;
  440.           case SINH_TOKEN:
  441.             #ifdef UnofficialBlocking
  442.               parseUnofficialFeature(40);
  443.             #endif
  444.                Val = SINH(Parse_Float_Param());
  445.                break;
  446.           case TANH_TOKEN:
  447.             #ifdef UnofficialBlocking
  448.               parseUnofficialFeature(40);
  449.             #endif
  450.                Val = TANH(Parse_Float_Param());
  451.                break;
  452. #ifndef _WIN32
  453.           case ACOSH_TOKEN:
  454.             #ifdef UnofficialBlocking
  455.               parseUnofficialFeature(40);
  456.             #endif
  457.                Val = ACOSH(Parse_Float_Param());
  458.                break;
  459.           case ASINH_TOKEN:
  460.             #ifdef UnofficialBlocking
  461.               parseUnofficialFeature(40);
  462.             #endif
  463.                Val = ASINH(Parse_Float_Param());
  464.                break;
  465.           case ATANH_TOKEN:
  466.             #ifdef UnofficialBlocking
  467.               parseUnofficialFeature(40);
  468.             #endif
  469.                Val = ATANH(Parse_Float_Param());
  470.                break;
  471. #endif
  472.           /*--dfs*/
  473.  
  474.           case CEIL_TOKEN:
  475.             Val = ceil(Parse_Float_Param());
  476.             break;
  477.  
  478.           case CLOCK_TOKEN:
  479.             Val = opts.FrameSeq.Clock_Value;
  480.             break;
  481. #ifdef GetImageSizePatch
  482.           case IMAGE_WIDTH_TOKEN:
  483.             Val = Frame.Screen_Width;
  484.             break;
  485.  
  486.           case IMAGE_HEIGHT_TOKEN:
  487.             Val = Frame.Screen_Height;
  488.             break;
  489. #endif
  490. #ifdef HfHeightAtPatch
  491.           /* added JB 2/18/98 */
  492.           case HF_HEIGHT_AT_TOKEN:
  493.             /* hf_height_at( x, z, hfield ) */
  494.             GET( LEFT_PAREN_TOKEN );
  495.             Val = Parse_Float(); /* 0 - 1 */
  496.             GET( COMMA_TOKEN );
  497.             Val2 = Parse_Float(); /* 0 - 1 */
  498.             GET( COMMA_TOKEN );
  499.             GET( OBJECT_ID_TOKEN );
  500.             hfield = (HFIELD*)Token.Data;
  501.             GET( RIGHT_PAREN_TOKEN );
  502.             if( hfield->Type & HFIELD_OBJECT != HFIELD_OBJECT )
  503.               Error( "Cannot find height of non-height-field.\n" );
  504.             if( ( Val < 0 ) || ( Val2 < 0 ) ||
  505.                 ( Val > 1 ) || ( Val2 > 1 ) )
  506.               Error( "Height-field index out of bounds [0 1].\n" );
  507.             Val *= (hfield->Data->max_x-1);
  508.             Val2 *= (hfield->Data->max_z-1);
  509.             /* get the height, normalized to [0 1] */
  510.             Val = hfield->Data->Map[ (int)Val2 ][ (int)Val ] / 65536.0;
  511.             break;
  512.           /* --- */
  513. #endif
  514. #ifdef GetTicksPatch
  515. /*YS enabeling time mesurement */
  516.           case START_CHRONO_TOKEN:
  517.             ChronoStart=GET_TICKS;
  518.             Val = 0.0;
  519.             break;
  520.  
  521.           case CURRENT_CHRONO_TOKEN:
  522.             ChronoEnd=GET_TICKS;
  523.             Val = ((DBL)ChronoEnd-(DBL)ChronoStart)/CLOCKDIVIDER;
  524.             break;
  525.           case GET_CLK_TCK_TOKEN:
  526.             Val =GET_TICKS;
  527.             break;
  528. #endif
  529. #ifdef GetClockValuesPatch
  530.           case CLOCK_ON_TOKEN:
  531.             #ifdef UnofficialBlocking
  532.               parseUnofficialFeature(60);
  533.             #endif
  534.                 if ( opts.FrameSeq.FrameType == FT_MULTIPLE_FRAME )
  535.                     Val=1.0;
  536.                 else 
  537.                      Val = 0.0;
  538.             break;
  539.  
  540.           case FRAMENUMBER_TOKEN:
  541.             Val = opts.FrameSeq.FrameNumber;
  542.             break;
  543.  
  544.           case INITIALFRAME_TOKEN:
  545.             Val = opts.FrameSeq.InitialFrame;
  546.             break;
  547.           case FINALFRAME_TOKEN:
  548.             Val = opts.FrameSeq.FinalFrame;
  549.             break;
  550.           case INITIALCLOCK_TOKEN:
  551.             Val = opts.FrameSeq.InitialClock;
  552.             break;
  553.           case FINALCLOCK_TOKEN:
  554.             Val = opts.FrameSeq.FinalClock;
  555.             break;
  556. #endif
  557.           case COS_TOKEN:
  558.             Val = cos(Parse_Float_Param());
  559.             break;
  560.  
  561.           case DEFINED_TOKEN:
  562.             Val = Parse_Ifdef_Param();
  563.             break;
  564.  
  565.           case DEGREES_TOKEN:
  566.             Val = Parse_Float_Param()/M_PI_180;
  567.             break;
  568.  
  569.           case DIV_TOKEN:
  570.             Parse_Float_Param2(&Val,&Val2);
  571.             Val=(DBL) ( (int)(Val/Val2) );
  572.             break;
  573. #ifdef BsplinePatch
  574.  
  575.             
  576.           case EVAL_SPLINE_TOKEN:
  577.             GET (LEFT_PAREN_TOKEN);
  578.             Local_String=Parse_String();
  579.             Parse_Comma();
  580.             Val2 = Parse_Float();
  581.             GET (RIGHT_PAREN_TOKEN);
  582.  
  583.             help=The_Splines;
  584.             while (help!=NULL)
  585.             {
  586.                 if (strcmp(Local_String,help->name)==0) break;
  587.                 help=(SPLINE*)help->next;
  588.             }
  589.             if (help==NULL) Error("Spline named %s does no exist.",Local_String);
  590.  
  591.             if ((help->type==NATURAL_SPLINE)&&(Val2<help->Knots[0].t))
  592.             {
  593.                 Val=help->Knots[0].y-(3*help->Coeffs[0].c[3]*help->Knots[0].t*help->Knots[0].t+
  594.                 2*help->Coeffs[0].c[2]*help->Knots[0].t+help->Coeffs[0].c[1])*(help->Knots[0].t-Val2);
  595.                 done=TRUE;
  596.             }
  597.             if ((help->type==NATURAL_SPLINE)&&(Val2>help->Knots[help->res].t))
  598.             {
  599.                 Val=help->Knots[help->res].y+(3*help->Coeffs[help->res-1].c[3]*help->Knots[help->res].t*help->Knots[help->res].t+
  600.                 2*help->Coeffs[help->res-1].c[2]*help->Knots[help->res].t+help->Coeffs[help->res-1].c[1])
  601.                 *(Val2-help->Knots[help->res].t);
  602.                 done=TRUE;
  603.             }
  604.  
  605.                
  606.             if (help->type==CLOSED_SPLINE)
  607.             {
  608.                 while(Val2<help->Knots[0].t) Val2 = Val2+(help->Knots[help->res].t-help->Knots[0].t);
  609.                 while(Val2>help->Knots[help->res].t) Val2 = Val2-(help->Knots[help->res].t-help->Knots[0].t);
  610.             }
  611.            
  612.             if (!done)
  613.             {
  614.                 t=1;
  615.                 while (Val2 > help->Knots[t].t) t++;
  616.                 t--;
  617.                 Val=help->Coeffs[t].c[3]*Val2*Val2*Val2+help->Coeffs[t].c[2]*Val2*Val2+help->Coeffs[t].c[1]*Val2+help->Coeffs[t].c[0];
  618.             }
  619.             /*YS sept 17 2000 Memory Leak */
  620.             POV_FREE(Local_String);
  621.             break;
  622. #endif
  623.  
  624.           case EXP_TOKEN:
  625.             Val = exp(Parse_Float_Param());
  626.             break;
  627.  
  628.           case FILE_EXISTS_TOKEN:
  629.             GET (LEFT_PAREN_TOKEN);
  630.             Local_String=Parse_String();
  631.             Val = ((f=Locate_File(Local_String,READ_BINFILE_STRING,"","",NULL,FALSE))==NULL) ? 0.0 : 1.0;
  632.             if (f != NULL)
  633.             {
  634.                fclose(f);
  635.             }
  636.             POV_FREE(Local_String);
  637.             GET (RIGHT_PAREN_TOKEN);
  638.             break;
  639.  
  640.           case FLOAT_ID_TOKEN:
  641.             Val = *((DBL *) Token.Data);
  642.             break;
  643.  
  644.           case FLOAT_TOKEN:
  645.             Val = Token.Token_Float;
  646.             break;
  647.  
  648.           case FLOOR_TOKEN:
  649.             Val = floor(Parse_Float_Param());
  650.             break;
  651.  
  652.           case INT_TOKEN:
  653.             Val = (DBL) ((int) Parse_Float_Param());
  654.             break;
  655.  
  656.           case LOG_TOKEN:
  657.             Val = Parse_Float_Param();
  658.             if (Val<=0.0)
  659.             {
  660.               Error("Log of negative number %lf\n",Val);
  661.             }
  662.             else
  663.             {
  664.               Val = log(Val);
  665.             }
  666.             break;
  667. #ifdef ComplexFunctionsPatch
  668.          case CREAL_TOKEN:
  669.             #ifdef UnofficialBlocking
  670.               parseUnofficialFeature(40);
  671.             #endif
  672.             Parse_Vector_Param(Vect);
  673.             Val=Vect[0];
  674.             break;
  675.           case CIMAG_TOKEN:
  676.             #ifdef UnofficialBlocking
  677.               parseUnofficialFeature(40);
  678.             #endif
  679.             Parse_Vector_Param(Vect);
  680.             Val=Vect[1];
  681.             break;
  682.           case CABS2_TOKEN:
  683.             #ifdef UnofficialBlocking
  684.               parseUnofficialFeature(40);
  685.             #endif
  686.             Parse_Vector_Param(Vect);
  687.             Val=Vect[0]*Vect[0]+Vect[1]*Vect[1];
  688.             break;
  689. #endif
  690.           case MAX_TOKEN:
  691.             Parse_Float_Param2(&Val,&Val2);
  692.             Val = max(Val,Val2);
  693.             break;
  694.  
  695.           case MIN_TOKEN:
  696.             Parse_Float_Param2(&Val,&Val2);
  697.             Val = min(Val,Val2);
  698.             break;
  699.  
  700.           case MOD_TOKEN:
  701.             Parse_Float_Param2(&Val,&Val2);
  702.             Val = fmod(Val,Val2);
  703.             break;
  704.  
  705.           case PI_TOKEN:
  706.             Val = M_PI;
  707.             break;
  708.  
  709. #ifdef SignPatch
  710.           case SGN_TOKEN: /*Chris Huff "sign() function"*/
  711.             #ifdef UnofficialBlocking
  712.             parseUnofficialFeature(70);
  713.             #endif          
  714.             Val = Parse_Float_Param();
  715.             if(Val<0)
  716.               Val=-1;
  717.             else 
  718.               Val=1;
  719.           break;
  720. #endif
  721.  
  722. #ifdef EvalPatternPatch
  723.           case EVALPAT_TOKEN: /*Chris Huff "eval_pattern function"*/
  724.             Val = Parse_eval_pat();
  725.             break;
  726. #endif
  727.  
  728. #ifdef Noise3DPatch
  729.           case NOISE3D_TOKEN: /*Chris Huff "noise3d function"*/
  730.             Parse_Vector_Param(Vect);
  731.             Val = Noise(Vect);
  732.             break;
  733. #endif
  734.  
  735. #ifdef CubeSqrHatPatch
  736.           case SQR_TOKEN:/*Chris Huff "sqr function"*/
  737.             Val = Parse_Float_Param();
  738.             Val = (Val*Val);
  739.             break;
  740.  
  741.           case CUBE_TOKEN:/*Chris Huff "cube function"*/
  742.             Val = Parse_Float_Param();
  743.             Val = (Val*Val*Val);
  744.             break;
  745. #endif
  746.           case POW_TOKEN:
  747.             Parse_Float_Param2(&Val,&Val2);
  748.             {
  749.               DBL Temp = (DBL)((long)Val2);
  750.               if (fabs(Temp-Val2)>EPSILON && Val2<0)
  751.               {
  752.                 Error("You cannot use pow() with a negative fractional power.");
  753.               }
  754.             }
  755.             Val=pow(Val,Val2);
  756.             break;
  757.  
  758.           case RADIANS_TOKEN:
  759.             Val = Parse_Float_Param()*M_PI_180;
  760.             break;
  761.  
  762.           case SIN_TOKEN:
  763.             Val = sin(Parse_Float_Param());
  764.             break;
  765.  
  766.           case SQRT_TOKEN:
  767.             Val = Parse_Float_Param();
  768.             if (Val<0.0)
  769.             {
  770.               Error("sqrt of negative number %lf\n",Val);
  771.             }
  772.             else
  773.             {
  774.               Val = sqrt(Val);
  775.             }
  776.             break;
  777.  
  778.           case STRCMP_TOKEN:
  779.             GET (LEFT_PAREN_TOKEN);
  780.             Local_String=Parse_String();
  781.             Parse_Comma();
  782.             Local_String2=Parse_String();
  783.             Val = (DBL)strcmp(Local_String,Local_String2);
  784.             POV_FREE(Local_String);
  785.             POV_FREE(Local_String2);
  786.             GET (RIGHT_PAREN_TOKEN);
  787.             break;
  788.  
  789.           case STRLEN_TOKEN:
  790.             GET (LEFT_PAREN_TOKEN);
  791.             Local_String=Parse_String();
  792.             Val = (DBL)strlen(Local_String);
  793.             POV_FREE(Local_String);
  794.             GET (RIGHT_PAREN_TOKEN);
  795.             break;
  796.  
  797.           case TAN_TOKEN:
  798.             Val = tan(Parse_Float_Param());
  799.             break;
  800.  
  801.           case VDOT_TOKEN:
  802.             Parse_Vector_Param2(Vect,Vect2);
  803.             VDot(Val,Vect,Vect2);
  804.             break;
  805.  
  806.           case VLENGTH_TOKEN:
  807.             Parse_Vector_Param(Vect);
  808.             VLength(Val,Vect);
  809.             break;
  810.  
  811.           case VERSION_TOKEN:
  812.             /*Val = opts.Language_Version;*/
  813.             Val = (DBL)opts.Language_Version/100.0;
  814.             break;
  815.  
  816. #ifdef UnofficialBlocking
  817.           case UNOFFICIAL_VERSION_TOKEN:
  818.             Val = getUnofficialVersion()/100.0;
  819.             break;
  820. #endif
  821.  
  822.           case TRUE_TOKEN:
  823.           case YES_TOKEN:
  824.           case ON_TOKEN:
  825.             Val = 1.0;
  826.             break;
  827.  
  828.           case FALSE_TOKEN:
  829.           case NO_TOKEN:
  830.           case OFF_TOKEN:
  831.             Val = 0.0;
  832.             break;
  833.  
  834.           case SEED_TOKEN:
  835.             Val = stream_seed((int)Parse_Float_Param());
  836.             break;
  837.  
  838.           case RAND_TOKEN:
  839.             i = (int)Parse_Float_Param();
  840.             if ((i < 0) || (i >= Number_Of_Random_Generators))
  841.             {
  842.               Error("Illegal random number generator.");
  843.             }
  844.             Val = stream_rand(i);
  845.             break;
  846.  
  847.           case CLOCK_DELTA_TOKEN:
  848.             Val = Clock_Delta;
  849.             break;
  850.  
  851.           case DIMENSIONS_TOKEN:
  852.             GET(LEFT_PAREN_TOKEN)
  853.             GET(ARRAY_ID_TOKEN)
  854.             a = (POV_ARRAY *)(*(Token.DataPtr));
  855.             Val = a->Dims+1;
  856.             GET(RIGHT_PAREN_TOKEN)
  857.             break;
  858.  
  859.           case DIMENSION_SIZE_TOKEN:
  860.             GET(LEFT_PAREN_TOKEN)
  861.             GET(ARRAY_ID_TOKEN)
  862.             Parse_Comma();
  863.             a = (POV_ARRAY *)(*(Token.DataPtr));
  864.             i = (int)Parse_Float()-1;
  865.             if ((i < 0) || (i > a->Dims))
  866.             {
  867.               Val = 0.0;
  868.             }
  869.             else
  870.             {
  871.               Val = a->Sizes[i];
  872.             }
  873.             GET(RIGHT_PAREN_TOKEN)
  874.             break;
  875.          }
  876.        for (i=0; i < *Terms; i++)
  877.          Express[i]=Val;
  878.        EXIT
  879.      END_CASE
  880.  
  881.      CASE (VECTOR_FUNCT_TOKEN)
  882.        /* All of these functions return a VECTOR result */
  883.        switch(Token.Function_Id)
  884.          {
  885. #ifdef VturbulencePatch
  886.           case VTURBULENCE_TOKEN:          /* Added by bajcik */
  887.             GET (LEFT_PAREN_TOKEN);
  888.             Turb.Lambda = Parse_Float();
  889.             Parse_Comma();
  890.             Turb.Omega = Parse_Float();
  891.             Parse_Comma();
  892.             Turb.Octaves = (int)Parse_Float();
  893.             if(Turb.Octaves < 1)
  894.                Turb.Octaves = 1;
  895.             if(Turb.Octaves > 10)  /* Avoid DOMAIN errors */
  896.                Turb.Octaves = 10;
  897.             Parse_Comma();
  898.             Parse_Vector(Vect2);     /* Input Vector */
  899.             Parse_Comma();
  900.             GET (RIGHT_PAREN_TOKEN);
  901.             DTurbulence(Vect,Vect2,&Turb);
  902.             break;
  903. #endif 
  904.  
  905. #ifdef BsplinePatch
  906.  
  907.            case EVAL_3D_SPLINE_TOKEN:
  908.             GET (LEFT_PAREN_TOKEN);
  909.             Local_String=Parse_String();
  910.             Parse_Comma();
  911.             Val2 = Parse_Float();
  912.             GET (RIGHT_PAREN_TOKEN);
  913.  
  914.             help_3d=The_3D_Splines;
  915.             while (help_3d!=NULL)
  916.             {
  917.                 if (strcmp(Local_String,help_3d->name)==0) break;
  918.                 help_3d=(SPLINE_3D*)help_3d->next;
  919.             }
  920.             if (help_3d==NULL) Error("Spline named %s does no exist.",Local_String);
  921.  
  922.             if ((help_3d->type==NATURAL_SPLINE)&&(Val2<0))
  923.             {
  924.                 Vect[X]=help_3d->Knots[0].y[X]-(3*help_3d->Coeffs[0].c[X][3]*help_3d->Knots[0].t*help_3d->Knots[0].t+
  925.                 2*help_3d->Coeffs[0].c[X][2]*help_3d->Knots[0].t+help_3d->Coeffs[0].c[X][1])*(help_3d->Knots[0].t-Val2);
  926.                 Vect[Y]=help_3d->Knots[0].y[Y]-(3*help_3d->Coeffs[0].c[Y][3]*help_3d->Knots[0].t*help_3d->Knots[0].t+
  927.                 2*help_3d->Coeffs[0].c[Y][2]*help_3d->Knots[0].t+help_3d->Coeffs[0].c[Y][1])*(help_3d->Knots[0].t-Val2);
  928.                 Vect[Z]=help_3d->Knots[0].y[Z]-(3*help_3d->Coeffs[0].c[Z][3]*help_3d->Knots[0].t*help_3d->Knots[0].t+
  929.                 2*help_3d->Coeffs[0].c[Z][2]*help_3d->Knots[0].t+help_3d->Coeffs[0].c[Z][1])*(help_3d->Knots[0].t-Val2);
  930.                 done=TRUE;
  931.             }
  932.             if ((help_3d->type==NATURAL_SPLINE)&&(Val2>1))
  933.             {
  934.                 Vect[X]=help_3d->Knots[help_3d->res].y[X]+(3*help_3d->Coeffs[help_3d->res-1].c[X][3]*help_3d->Knots[help_3d->res].t*help_3d->Knots[help_3d->res].t+
  935.                 2*help_3d->Coeffs[help_3d->res-1].c[X][2]*help_3d->Knots[help_3d->res].t+help_3d->Coeffs[help_3d->res-1].c[X][1])
  936.                 *(Val2-help_3d->Knots[help_3d->res].t);
  937.  
  938.                 Vect[Y]=help_3d->Knots[help_3d->res].y[Y]+(3*help_3d->Coeffs[help_3d->res-1].c[Y][3]*help_3d->Knots[help_3d->res].t*help_3d->Knots[help_3d->res].t+
  939.                 2*help_3d->Coeffs[help_3d->res-1].c[Y][2]*help_3d->Knots[help_3d->res].t+help_3d->Coeffs[help_3d->res-1].c[Y][1])
  940.                 *(Val2-help_3d->Knots[help_3d->res].t);
  941.  
  942.                 Vect[Z]=help_3d->Knots[help_3d->res].y[Z]+(3*help_3d->Coeffs[help_3d->res-1].c[Z][3]*help_3d->Knots[help_3d->res].t*help_3d->Knots[help_3d->res].t+
  943.                 2*help_3d->Coeffs[help_3d->res-1].c[Z][2]*help_3d->Knots[help_3d->res].t+help_3d->Coeffs[help_3d->res-1].c[Z][1])
  944.                 *(Val2-help_3d->Knots[help_3d->res].t);
  945.                 
  946.                 done=TRUE;
  947.             }
  948.                
  949.             if (help_3d->type==CLOSED_SPLINE)
  950.             {
  951.                 while(Val2<0) Val2++;
  952.                 while(Val2>1) Val2--;
  953.             }
  954.            
  955.             if (!done)
  956.             {
  957.                 t=1;
  958.                 while (Val2 > help_3d->Knots[t].t) t++;
  959.                 t--;
  960.                 Vect[X]=help_3d->Coeffs[t].c[X][3]*Val2*Val2*Val2+help_3d->Coeffs[t].c[X][2]*Val2*Val2+help_3d->Coeffs[t].c[X][1]*Val2+help_3d->Coeffs[t].c[X][0];
  961.                 Vect[Y]=help_3d->Coeffs[t].c[Y][3]*Val2*Val2*Val2+help_3d->Coeffs[t].c[Y][2]*Val2*Val2+help_3d->Coeffs[t].c[Y][1]*Val2+help_3d->Coeffs[t].c[Y][0];
  962.                 Vect[Z]=help_3d->Coeffs[t].c[Z][3]*Val2*Val2*Val2+help_3d->Coeffs[t].c[Z][2]*Val2*Val2+help_3d->Coeffs[t].c[Z][1]*Val2+help_3d->Coeffs[t].c[Z][0];
  963.             }
  964.             
  965.             break;
  966. #endif
  967.  
  968. #ifdef VtransformPatch
  969.       case VTRANSFORM_TOKEN: /*Chris Huff "vtransform function"*/
  970.             #ifdef UnofficialBlocking
  971.               parseUnofficialFeature(40);
  972.             #endif
  973.             Parse_VTransform(Vect,IsNotInverse);
  974.       break;
  975.        case VINV_TRANSFORM_TOKEN:/*Chris Huff "vinv_transform function"*/
  976.             #ifdef UnofficialBlocking
  977.               parseUnofficialFeature(50);
  978.             #endif           
  979.             Parse_VTransform(Vect,IsInverse);
  980.          break;      
  981. #endif
  982. #ifdef VWarpPatch
  983.       case VWARP_TOKEN: /*Chris Huff "vtransform function"*/
  984.             #ifdef UnofficialBlocking
  985.               parseUnofficialFeature(60);
  986.             #endif
  987.             Parse_VWarp(Vect);
  988.       break;    
  989. #endif
  990.           case VAXIS_ROTATE_TOKEN:
  991.             GET (LEFT_PAREN_TOKEN);
  992.             Parse_Vector(Vect2);
  993.             Parse_Comma();
  994.             Parse_Vector(Vect3);
  995.             Parse_Comma();
  996.             Val=Parse_Float()*M_PI_180;
  997.             GET (RIGHT_PAREN_TOKEN);
  998.             Compute_Axis_Rotation_Transform(&Trans,Vect3,Val);
  999.             MTransPoint(Vect, Vect2, &Trans);
  1000.             break;
  1001.  
  1002.           case VCROSS_TOKEN:
  1003.             Parse_Vector_Param2(Vect2,Vect3);
  1004.             VCross(Vect,Vect2,Vect3);
  1005.             break;
  1006.  
  1007.           case VECTOR_ID_TOKEN:
  1008.             Assign_Vector(Vect,Token.Data);
  1009.             break;
  1010.  
  1011.           case VNORMALIZE_TOKEN:
  1012.             Parse_Vector_Param(Vect);
  1013.             VLength(Val,Vect);
  1014.             if (Val==0.0)
  1015.             {
  1016.               Make_Vector(Vect,0.0,0.0,0.0);
  1017.             }
  1018.             else
  1019.             {
  1020.               VInverseScaleEq(Vect,Val);
  1021.             }
  1022.             break;
  1023.  
  1024.           case VROTATE_TOKEN:
  1025.             Parse_Vector_Param2(Vect2,Vect3);
  1026.             Compute_Rotation_Transform (&Trans, Vect3);
  1027.             MTransPoint(Vect, Vect2, &Trans);
  1028.             break;
  1029.  
  1030.           case X_TOKEN:
  1031.             Make_Vector(Vect,1.0,0.0,0.0)
  1032.             break;
  1033.  
  1034.           case Y_TOKEN:
  1035.             Make_Vector(Vect,0.0,1.0,0.0)
  1036.             break;
  1037.  
  1038.           case Z_TOKEN:
  1039.             Make_Vector(Vect,0.0,0.0,1.0)
  1040.             break;
  1041. #ifdef ComplexFunctionsPatch
  1042.         /*dfs -- complex functions*/
  1043.           case CCONJ_TOKEN:
  1044.             #ifdef UnofficialBlocking
  1045.               parseUnofficialFeature(40);
  1046.             #endif
  1047.             Parse_Vector_Param(Vect);
  1048.             Make_Vector(Vect,Vect[0],-Vect[1],0.0);
  1049.             break;
  1050.          case CSQR_TOKEN:
  1051.             #ifdef UnofficialBlocking
  1052.               parseUnofficialFeature(40);
  1053.             #endif
  1054.             Parse_Vector_Param(Vect);
  1055.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1056.             Make_Vector(Vect,cmplx2.x*cmplx2.x-cmplx2.y*cmplx2.y,2*cmplx2.x*cmplx2.y,0.0);
  1057.             break;
  1058.          case CSQRT_TOKEN:
  1059.             #ifdef UnofficialBlocking
  1060.               parseUnofficialFeature(40);
  1061.             #endif
  1062.             Parse_Vector_Param(Vect);
  1063.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1064.             Complex_Sqrt(&cmplx1,&cmplx2);
  1065.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1066.             break;
  1067.          case CMULT_TOKEN:
  1068.             #ifdef UnofficialBlocking
  1069.               parseUnofficialFeature(40);
  1070.             #endif
  1071.             Parse_Vector_Param2(Vect2,Vect3);
  1072.             cmplx2.x=Vect2[0];cmplx2.y=Vect2[1];
  1073.             cmplx3.x=Vect3[0];cmplx3.y=Vect3[1];
  1074.             Complex_Mult(&cmplx1,&cmplx2,&cmplx3);
  1075.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1076.             break;
  1077.          case CDIV_TOKEN:
  1078.             #ifdef UnofficialBlocking
  1079.               parseUnofficialFeature(40);
  1080.             #endif
  1081.             Parse_Vector_Param2(Vect2,Vect3);
  1082.             cmplx2.x=Vect2[0];cmplx2.y=Vect2[1];
  1083.             cmplx3.x=Vect3[0];cmplx3.y=Vect3[1];
  1084.             Complex_Div(&cmplx1,&cmplx2,&cmplx3);
  1085.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1086.             break;
  1087.          case CEXP_TOKEN:
  1088.             #ifdef UnofficialBlocking
  1089.               parseUnofficialFeature(40);
  1090.             #endif
  1091.             Parse_Vector_Param(Vect);
  1092.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1093.             Complex_Exp(&cmplx1,&cmplx2);
  1094.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1095.             break;
  1096.          case CLOG_TOKEN:
  1097.             #ifdef UnofficialBlocking
  1098.               parseUnofficialFeature(40);
  1099.             #endif
  1100.             Parse_Vector_Param(Vect);
  1101.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1102.             Complex_Log(&cmplx1,&cmplx2);
  1103.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1104.             break;
  1105.          case CPOW_TOKEN:
  1106.             #ifdef UnofficialBlocking
  1107.               parseUnofficialFeature(40);
  1108.             #endif
  1109.             Parse_Vector_Param2(Vect2,Vect3);
  1110.             cmplx2.x=Vect2[0];cmplx2.y=Vect2[1];
  1111.             cmplx3.x=Vect3[0];cmplx3.y=Vect3[1];
  1112.             Complex_Power(&cmplx1,&cmplx2,&cmplx3);
  1113.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1114.             break;
  1115.          case CSIN_TOKEN:
  1116.             #ifdef UnofficialBlocking
  1117.               parseUnofficialFeature(40);
  1118.             #endif
  1119.             Parse_Vector_Param(Vect);
  1120.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1121.             Complex_Sin(&cmplx1,&cmplx2);
  1122.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1123.             break;
  1124.          case CCOS_TOKEN:
  1125.             #ifdef UnofficialBlocking
  1126.               parseUnofficialFeature(40);
  1127.             #endif
  1128.             Parse_Vector_Param(Vect);
  1129.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1130.             Complex_Cos(&cmplx1,&cmplx2);
  1131.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1132.             break;
  1133.          case CTAN_TOKEN:
  1134.             #ifdef UnofficialBlocking
  1135.               parseUnofficialFeature(40);
  1136.             #endif
  1137.             Parse_Vector_Param(Vect);
  1138.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1139.             Complex_Tan(&cmplx1,&cmplx2);
  1140.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1141.             break;
  1142.          case CSINH_TOKEN:
  1143.             #ifdef UnofficialBlocking
  1144.               parseUnofficialFeature(40);
  1145.             #endif
  1146.             Parse_Vector_Param(Vect);
  1147.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1148.             Complex_Sinh(&cmplx1,&cmplx2);
  1149.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1150.             break;
  1151.          case CCOSH_TOKEN:
  1152.             #ifdef UnofficialBlocking
  1153.               parseUnofficialFeature(40);
  1154.             #endif
  1155.             Parse_Vector_Param(Vect);
  1156.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1157.             Complex_Cosh(&cmplx1,&cmplx2);
  1158.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1159.             break;
  1160.          case CTANH_TOKEN:
  1161.             #ifdef UnofficialBlocking
  1162.               parseUnofficialFeature(40);
  1163.             #endif
  1164.             Parse_Vector_Param(Vect);
  1165.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1166.             Complex_Tanh(&cmplx1,&cmplx2);
  1167.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1168.             break;
  1169.          case CASIN_TOKEN:
  1170.             #ifdef UnofficialBlocking
  1171.               parseUnofficialFeature(40);
  1172.             #endif
  1173.             Parse_Vector_Param(Vect);
  1174.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1175.             Complex_ASin(&cmplx1,&cmplx2);
  1176.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1177.             break;
  1178.          case CACOS_TOKEN:
  1179.             #ifdef UnofficialBlocking
  1180.               parseUnofficialFeature(40);
  1181.             #endif
  1182.             Parse_Vector_Param(Vect);
  1183.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1184.             Complex_ACos(&cmplx1,&cmplx2);
  1185.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1186.             break;
  1187.          case CATAN_TOKEN:
  1188.             #ifdef UnofficialBlocking
  1189.               parseUnofficialFeature(40);
  1190.             #endif
  1191.             Parse_Vector_Param(Vect);
  1192.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1193.             Complex_ATan(&cmplx1,&cmplx2);
  1194.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1195.             break;
  1196.          case CASINH_TOKEN:
  1197.             #ifdef UnofficialBlocking
  1198.               parseUnofficialFeature(40);
  1199.             #endif
  1200.             Parse_Vector_Param(Vect);
  1201.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1202.             Complex_ASinh(&cmplx1,&cmplx2);
  1203.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1204.             break;
  1205.          case CACOSH_TOKEN:
  1206.             #ifdef UnofficialBlocking
  1207.               parseUnofficialFeature(40);
  1208.             #endif
  1209.             Parse_Vector_Param(Vect);
  1210.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1211.             Complex_ACosh(&cmplx1,&cmplx2);
  1212.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1213.             break;
  1214.          case CATANH_TOKEN:
  1215.             #ifdef UnofficialBlocking
  1216.               parseUnofficialFeature(40);
  1217.             #endif
  1218.             Parse_Vector_Param(Vect);
  1219.             cmplx2.x=Vect[0];cmplx2.y=Vect[1];
  1220.             Complex_ATanh(&cmplx1,&cmplx2);
  1221.             Make_Vector(Vect,cmplx1.x,cmplx1.y,0.0);
  1222.             break;
  1223. /* end of added complex functions*/
  1224. /*--dfs*/
  1225. #endif
  1226.  
  1227. #ifdef TracePatch
  1228.           case TRACE_TOKEN:
  1229.             Parse_Trace( Vect );
  1230.             break;
  1231. #endif   
  1232. #ifdef EvalPigmentPatch
  1233.           case EVALPIG_TOKEN: /*Chris Huff "eval_pigment function"*/
  1234.             Parse_eval_pig(Vect);
  1235.             break;
  1236. #endif     
  1237. #ifdef BoundPatch
  1238.           case MIN_EXTENT_TOKEN:
  1239.             GET (LEFT_PAREN_TOKEN);
  1240.  
  1241.             EXPECT
  1242.               CASE (OBJECT_ID_TOKEN)
  1243.                 Object =(OBJECT*) Token.Data;
  1244.                 if ( Object ) {
  1245.                   Vect[X]=Object->BBox.Lower_Left[X];
  1246.                   Vect[Y]=Object->BBox.Lower_Left[Y];
  1247.                   Vect[Z]=Object->BBox.Lower_Left[Z];
  1248.                 }
  1249.                 EXIT
  1250.               END_CASE
  1251.  
  1252.               OTHERWISE
  1253.                 Object = NULL;
  1254.                 UNGET
  1255.                 EXIT
  1256.               END_CASE
  1257.             END_EXPECT
  1258.  
  1259.             GET (RIGHT_PAREN_TOKEN);
  1260.             break;
  1261.  
  1262.           case MAX_EXTENT_TOKEN:
  1263.             GET (LEFT_PAREN_TOKEN);
  1264.  
  1265.             EXPECT
  1266.               CASE (OBJECT_ID_TOKEN)
  1267.                 Object = (OBJECT*)Token.Data;
  1268.                 if ( Object ) {
  1269.                 Vect[X]=Object->BBox.Lower_Left[X]+Object->BBox.Lengths[X];
  1270.                 Vect[Y]=Object->BBox.Lower_Left[Y]+Object->BBox.Lengths[Y];
  1271.                 Vect[Z]=Object->BBox.Lower_Left[Z]+Object->BBox.Lengths[Z];
  1272.                 }
  1273.                 EXIT
  1274.               END_CASE
  1275.  
  1276.               OTHERWISE
  1277.                 Object = NULL;
  1278.                 UNGET
  1279.                 EXIT
  1280.               END_CASE
  1281.             END_EXPECT
  1282.  
  1283.             GET (RIGHT_PAREN_TOKEN);
  1284.             break;
  1285. #endif
  1286.  
  1287.  
  1288.          }
  1289.  
  1290.        /* If it was expecting a DBL, promote it to a VECTOR.
  1291.           I haven't yet figured out what to do if it was expecting
  1292.           a COLOUR value with Terms>3
  1293.        */
  1294.        if (*Terms==1)
  1295.          *Terms=3;
  1296.  
  1297.        for (i=0; i < 3; i++)
  1298.          Express[i]=Vect[i];
  1299.        EXIT
  1300.      END_CASE
  1301.  
  1302.      CASE (COLOUR_ID_TOKEN)
  1303.        *Terms=5;
  1304.        for (i=0; i<5; i++)
  1305.          Express[i]=(DBL)(  ((COLC *)(Token.Data))[i]  );
  1306.        EXIT
  1307.      END_CASE
  1308.  
  1309. #ifdef SplinePatch
  1310.      CASE (SPLINE_ID_TOKEN)
  1311.         *Terms=3;
  1312.         spline=(SPLINE2*)(Token.Data);
  1313.         GET(LEFT_PAREN_TOKEN);
  1314.         Val=Parse_Float();
  1315.         Get_Token();
  1316.  
  1317.         if(Token.Token_Id == COMMA_TOKEN)
  1318.         {
  1319.           /*If there is a second parameter, make a copy of the spline
  1320.           with a new type and evaluate that.*/
  1321.           spline = Copy_Spline(spline);
  1322.           Get_Token();
  1323.           switch(Token.Token_Id)
  1324.           {
  1325.             case LINEAR_SPLINE_TOKEN:
  1326.             spline->Type = LINEAR_SPLINE;
  1327.             break;
  1328.  
  1329.             case QUADRATIC_SPLINE_TOKEN:
  1330.             spline->Type = QUADRATIC_SPLINE;
  1331.             break;
  1332.  
  1333.             case CUBIC_SPLINE_TOKEN:
  1334.             spline->Type = CUBIC_SPLINE;
  1335.             break;
  1336.  
  1337.             default:
  1338.             Error("linear_spline, quadratic_spline, or cubic_spline expected.");
  1339.             break;
  1340.           }
  1341.  
  1342.           GET(RIGHT_PAREN_TOKEN);
  1343.           Get_Spline_Val(spline,Val,Express);
  1344.           Destroy_Spline(spline);
  1345.           spline = NULL;
  1346.         }
  1347.         else
  1348.         {
  1349.           UNGET
  1350.           GET(RIGHT_PAREN_TOKEN);
  1351.           Get_Spline_Val(spline, Val, Express);
  1352.         }
  1353.  
  1354.        EXIT
  1355.      END_CASE
  1356. #endif
  1357.  
  1358.      CASE (UV_ID_TOKEN)
  1359.        *Terms=2;
  1360.        for (i=0; i<2; i++)
  1361.          Express[i]=(DBL)(  ((DBL *)(Token.Data))[i]  );
  1362.        EXIT
  1363.      END_CASE
  1364.  
  1365.      CASE (VECTOR_4D_ID_TOKEN)
  1366.        *Terms=4;
  1367.        for (i=0; i<4; i++)
  1368.          Express[i]=(DBL)(  ((DBL *)(Token.Data))[i]  );
  1369.        EXIT
  1370.      END_CASE
  1371.  
  1372.      CASE (T_TOKEN)
  1373.        *Terms=4;
  1374.        Express[0]=0.0;
  1375.        Express[1]=0.0;
  1376.        Express[2]=0.0;
  1377.        Express[3]=1.0;
  1378.        EXIT
  1379.      END_CASE
  1380.  
  1381.      CASE (U_TOKEN)
  1382.        *Terms=2;
  1383.        Express[0]=1.0;
  1384.        Express[1]=0.0;
  1385.        EXIT
  1386.      END_CASE
  1387.  
  1388.      CASE (V_TOKEN)
  1389.        *Terms=2;
  1390.        Express[0]=0.0;
  1391.        Express[1]=1.0;
  1392.        EXIT
  1393.      END_CASE
  1394.  
  1395.      CASE (PLUS_TOKEN)
  1396.      END_CASE
  1397.  
  1398.      CASE (DASH_TOKEN)
  1399.        Ok_To_Declare=Old_Ok;
  1400.        Parse_Num_Factor(Express,Terms);
  1401.        Old_Ok=Ok_To_Declare;
  1402.        Ok_To_Declare=TRUE;
  1403.        for (i=0; i<*Terms; i++)
  1404.          Express[i]=-Express[i];
  1405.        EXIT
  1406.      END_CASE
  1407.  
  1408.      CASE (EXCLAMATION_TOKEN)
  1409.        Ok_To_Declare=Old_Ok;
  1410.        Parse_Num_Factor(Express,Terms);
  1411.        Old_Ok=Ok_To_Declare;
  1412.        Ok_To_Declare=TRUE;
  1413.        for (i=0; i<*Terms; i++)
  1414.          Express[i] = ftrue(Express[i])?0.0:1.0;
  1415.        EXIT
  1416.      END_CASE
  1417.  
  1418.      CASE (LEFT_PAREN_TOKEN)
  1419.        Parse_Express(Express,Terms);
  1420.        GET(RIGHT_PAREN_TOKEN);
  1421.        EXIT
  1422.      END_CASE
  1423.  
  1424. /* This case parses a 2, 3, 4, or 5 term vector.  First parse 2 terms.
  1425.    Note Parse_Comma won't crash if it doesn't find one.
  1426.  */
  1427.  
  1428.      CASE (LEFT_ANGLE_TOKEN)
  1429.        Express[X] = Parse_Float();   Parse_Comma();
  1430.        Express[Y] = Parse_Float();   Parse_Comma();
  1431.        *Terms=2;
  1432.  
  1433.        EXPECT
  1434.          CASE_EXPRESS
  1435.            /* If a 3th float is found, parse it. */
  1436.            Express[2] = Parse_Float(); Parse_Comma();
  1437.            *Terms=3;
  1438.            EXPECT
  1439.              CASE_EXPRESS
  1440.                /* If a 4th float is found, parse it. */
  1441.                Express[3] = Parse_Float(); Parse_Comma();
  1442.                *Terms=4;
  1443.                EXPECT
  1444.                  CASE_EXPRESS
  1445.                    /* If a 5th float is found, parse it. */
  1446.                    Express[4] = Parse_Float();
  1447.                    *Terms=5;
  1448.                  END_CASE
  1449.  
  1450.                  OTHERWISE
  1451.                    /* Only 4 found. */
  1452.                    UNGET
  1453.                    GET (RIGHT_ANGLE_TOKEN)
  1454.                    EXIT
  1455.                  END_CASE
  1456.                END_EXPECT
  1457.                EXIT
  1458.              END_CASE
  1459.  
  1460.              OTHERWISE
  1461.                /* Only 3 found. */
  1462.                UNGET
  1463.                GET (RIGHT_ANGLE_TOKEN)
  1464.                EXIT
  1465.              END_CASE
  1466.            END_EXPECT
  1467.            EXIT
  1468.          END_CASE
  1469.  
  1470.          OTHERWISE
  1471.            /* Only 2 found. */
  1472.            UNGET
  1473.            GET (RIGHT_ANGLE_TOKEN)
  1474.            EXIT
  1475.          END_CASE
  1476.        END_EXPECT
  1477.        EXIT
  1478.      END_CASE
  1479.  
  1480.      OTHERWISE
  1481.        Parse_Error_Str ("numeric expression");
  1482.      END_CASE
  1483.    END_EXPECT
  1484.    
  1485.    Ok_To_Declare=Old_Ok;
  1486.  
  1487.    /* Parse VECTOR.x or COLOR.red type things */
  1488.    EXPECT
  1489.      CASE(PERIOD_TOKEN)
  1490.        EXPECT
  1491.          CASE (VECTOR_FUNCT_TOKEN)
  1492.            switch(Token.Function_Id)
  1493.            {
  1494.              case X_TOKEN:
  1495.                i=X;
  1496.                break;
  1497.  
  1498.              case Y_TOKEN:
  1499.                i=Y;
  1500.                break;
  1501.  
  1502.              case Z_TOKEN:
  1503.                i=Z;
  1504.                break;
  1505.                
  1506.              default:
  1507.                Parse_Error_Str ("x, y, or z");
  1508.            }
  1509.            EXIT
  1510.          END_CASE
  1511.  
  1512.          CASE (COLOUR_KEY_TOKEN)
  1513.            switch(Token.Function_Id)
  1514.            {
  1515.              case RED_TOKEN:
  1516.                i=RED;
  1517.                break;
  1518.                
  1519.              case GREEN_TOKEN:
  1520.                i=GREEN;
  1521.                break;
  1522.  
  1523.              case BLUE_TOKEN:
  1524.                i=BLUE;
  1525.                break;
  1526.  
  1527.              case FILTER_TOKEN:
  1528.                i=FILTER;
  1529.                break;
  1530.                
  1531.              case TRANSMIT_TOKEN:
  1532.                i=TRANSM;
  1533.                break;
  1534.                
  1535.              default:
  1536.                Parse_Error_Str ("red, green, blue, filter, or transmit");
  1537.            }
  1538.            EXIT
  1539.          END_CASE
  1540.  
  1541.          CASE(U_TOKEN)
  1542.            i=U;
  1543.            EXIT
  1544.          END_CASE
  1545.  
  1546.          CASE(V_TOKEN)
  1547.            i=V;
  1548.            EXIT
  1549.          END_CASE
  1550.  
  1551.          CASE(T_TOKEN)
  1552.            i=T;
  1553.            EXIT
  1554.          END_CASE
  1555.  
  1556.          OTHERWISE
  1557.            Parse_Error_Str ("x, y, z or color component");
  1558.          END_CASE
  1559.        END_EXPECT
  1560.  
  1561.        if (i>=*Terms)
  1562.        {
  1563.           Error("Bad operands for period operator.");
  1564.        }
  1565.        *Terms=1;
  1566.        Express[0]=Express[i];
  1567.        EXIT
  1568.      END_CASE
  1569.      
  1570.      OTHERWISE
  1571.        UNGET
  1572.        EXIT
  1573.      END_CASE
  1574.    END_EXPECT
  1575.   }
  1576.  
  1577.  
  1578.  
  1579. /*****************************************************************************
  1580. *
  1581. * FUNCTION
  1582. *
  1583. * INPUT
  1584. *
  1585. * OUTPUT
  1586. *
  1587. * RETURNS
  1588. *
  1589. * AUTHOR
  1590. *
  1591. * DESCRIPTION
  1592. *
  1593. * CHANGES
  1594. *
  1595. ******************************************************************************/
  1596.  
  1597. /* If first operand of a 2-operand function had more terms than the second,
  1598.    then the parsing of the 2nd operand would have automatically promoted it.
  1599.    But if 2nd operand has more terms then we must go back promote the 1st
  1600.    operand before combining them  Promote_Express does it.  If Old_Terms=1
  1601.    then set all terms to Express[0].  Otherwise pad extra terms with 0.0.
  1602. */
  1603.  
  1604. static void Promote_Express(EXPRESS Express,int *Old_Terms,int New_Terms)
  1605. {
  1606.    register int i;
  1607.  
  1608.    if (*Old_Terms >= New_Terms)
  1609.      return;
  1610.  
  1611.    if (*Old_Terms==1)
  1612.    {
  1613.      for(i=1;i<New_Terms;i++)
  1614.      {
  1615.         Express[i]=Express[0];
  1616.      }
  1617.    }
  1618.    else
  1619.    {
  1620.      for(i=(*Old_Terms);i<New_Terms;i++)
  1621.      {
  1622.         Express[i]=0.0;
  1623.      }
  1624.    }
  1625.  
  1626.    *Old_Terms=New_Terms;
  1627.   }
  1628.  
  1629.  
  1630.  
  1631.  
  1632. /*****************************************************************************
  1633. *
  1634. * FUNCTION
  1635. *
  1636. * INPUT
  1637. *
  1638. * OUTPUT
  1639. *
  1640. * RETURNS
  1641. *
  1642. * AUTHOR
  1643. *
  1644. * DESCRIPTION
  1645. *
  1646. * CHANGES
  1647. *
  1648. ******************************************************************************/
  1649.  
  1650. static void Parse_Num_Term (EXPRESS Express,int *Terms)
  1651. {
  1652.    register int i;
  1653.    EXPRESS Local_Express;
  1654.    int Local_Terms;
  1655.  
  1656.    Parse_Num_Factor(Express,Terms);
  1657.  
  1658.    Local_Terms=*Terms;
  1659.  
  1660.    EXPECT
  1661.      CASE (STAR_TOKEN)
  1662.        Parse_Num_Factor(Local_Express,&Local_Terms);
  1663.        /* NK promotion bugfix */
  1664.        if (Local_Terms>*Terms)
  1665.          Promote_Express(Express,Terms,Local_Terms);
  1666.        else
  1667.          Promote_Express(Local_Express,&Local_Terms,*Terms);
  1668.        /* NK ---- */
  1669.  
  1670.        for(i=0;i<*Terms;i++)
  1671.          Express[i] *= Local_Express[i];
  1672.      END_CASE
  1673. #ifdef CubeSqrHatPatch
  1674.      /*START Chris Huff (^ for pow())*/
  1675.      CASE (HAT_TOKEN)
  1676.        Parse_Num_Factor(Local_Express,&Local_Terms);
  1677.        /* NK promotion bugfix */
  1678.        if (Local_Terms>*Terms)
  1679.          Promote_Express(Express,Terms,Local_Terms);
  1680.        else
  1681.          Promote_Express(Local_Express,&Local_Terms,*Terms);
  1682.        /* NK ---- */    for(i=0;i<*Terms;i++)
  1683.        Express[i] = pow(Express[i], Local_Express[i]);
  1684.      END_CASE
  1685.      /*END Chris Huff (^ for pow())*/
  1686. #endif
  1687.      CASE (SLASH_TOKEN)
  1688.        Parse_Num_Factor(Local_Express,&Local_Terms);
  1689.        /* NK promotion bugfix */
  1690.        if (Local_Terms>*Terms)
  1691.          Promote_Express(Express,Terms,Local_Terms);
  1692.        else
  1693.          Promote_Express(Local_Express,&Local_Terms,*Terms);
  1694.        /* NK ---- */
  1695.  
  1696.        for(i=0;i<*Terms;i++)
  1697.        {
  1698.          if (Local_Express[i]==0.0) /* must be 0.0, not EPSILON */
  1699.          {
  1700.            Express[i]=HUGE_VAL;
  1701.            Warn(0,"Divide by zero.");
  1702.          }
  1703.          else
  1704.          {
  1705.            Express[i] /= Local_Express[i];
  1706.          }
  1707.        }
  1708.      END_CASE
  1709.  
  1710.      OTHERWISE
  1711.        UNGET
  1712.        EXIT
  1713.      END_CASE
  1714.    END_EXPECT
  1715.  
  1716.   }
  1717.  
  1718.  
  1719.  
  1720. /*****************************************************************************
  1721. *
  1722. * FUNCTION
  1723. *
  1724. * INPUT
  1725. *
  1726. * OUTPUT
  1727. *
  1728. * RETURNS
  1729. *
  1730. * AUTHOR
  1731. *
  1732. * DESCRIPTION
  1733. *
  1734. * CHANGES
  1735. *
  1736. ******************************************************************************/
  1737.  
  1738. static void Parse_Rel_Factor (EXPRESS Express,int *Terms)
  1739. {
  1740.    register int i;
  1741.    EXPRESS Local_Express;
  1742.    int Local_Terms;
  1743.  
  1744.    Parse_Num_Term(Express,Terms);
  1745.  
  1746.    Local_Terms=*Terms;
  1747.  
  1748.    EXPECT
  1749.      CASE (PLUS_TOKEN)
  1750.        Parse_Num_Term(Local_Express,&Local_Terms);
  1751.        /* NK promotion bugfix */
  1752.        if (Local_Terms>*Terms)
  1753.        {
  1754.          Promote_Express(Express,Terms,Local_Terms);
  1755.        }
  1756.        else
  1757.        {
  1758.          Promote_Express(Local_Express,&Local_Terms,*Terms);
  1759.        }
  1760.        /* NK ---- */
  1761.  
  1762.        for(i=0;i<*Terms;i++)
  1763.          Express[i] += Local_Express[i];
  1764.      END_CASE
  1765.  
  1766.      CASE (DASH_TOKEN)
  1767.        Parse_Num_Term(Local_Express,&Local_Terms);
  1768.        /* NK promotion bugfix */
  1769.        if (Local_Terms>*Terms)
  1770.        {
  1771.          Promote_Express(Express,Terms,Local_Terms);
  1772.        }
  1773.        else
  1774.        {
  1775.          Promote_Express(Local_Express,&Local_Terms,*Terms);
  1776.        }
  1777.        /* NK ---- */
  1778.  
  1779.        for(i=0;i<*Terms;i++)
  1780.          Express[i] -= Local_Express[i];
  1781.      END_CASE
  1782.  
  1783.      OTHERWISE
  1784.        UNGET
  1785.        EXIT
  1786.      END_CASE
  1787.    END_EXPECT
  1788.  
  1789.   }
  1790.  
  1791.  
  1792.  
  1793. /*****************************************************************************
  1794. *
  1795. * FUNCTION
  1796. *
  1797. * INPUT
  1798. *
  1799. * OUTPUT
  1800. *
  1801. * RETURNS
  1802. *
  1803. * AUTHOR
  1804. *
  1805. * DESCRIPTION
  1806. *
  1807. * CHANGES
  1808. *
  1809. ******************************************************************************/
  1810.  
  1811. static void Parse_Rel_Term (EXPRESS Express,int *Terms)
  1812. {
  1813.    register int i;
  1814.    EXPRESS Local_Express;
  1815.    int Local_Terms;
  1816.  
  1817.    Parse_Rel_Factor(Express,Terms);
  1818.  
  1819.    Local_Terms=*Terms;
  1820.  
  1821.    EXPECT
  1822.      CASE (LEFT_ANGLE_TOKEN)
  1823.        Parse_Rel_Factor(Local_Express,&Local_Terms);
  1824.        Promote_Express(Express,Terms,Local_Terms);
  1825.  
  1826.        for(i=0;i<*Terms;i++)
  1827.          Express[i] = (DBL)(Express[i] < Local_Express[i]);
  1828.      END_CASE
  1829.  
  1830.      CASE (REL_LE_TOKEN)
  1831.        Parse_Rel_Factor(Local_Express,&Local_Terms);
  1832.        Promote_Express(Express,Terms,Local_Terms);
  1833.  
  1834.        for(i=0;i<*Terms;i++)
  1835.          Express[i] = (DBL)(Express[i] <= Local_Express[i]);
  1836.      END_CASE
  1837.  
  1838.      CASE (EQUALS_TOKEN)
  1839.        Parse_Rel_Factor(Local_Express,&Local_Terms);
  1840.        Promote_Express(Express,Terms,Local_Terms);
  1841.  
  1842.        for(i=0;i<*Terms;i++)
  1843.          Express[i] = (DBL)(!ftrue(Express[i]-Local_Express[i]));
  1844.      END_CASE
  1845.  
  1846.      CASE (REL_NE_TOKEN)
  1847.        Parse_Rel_Factor(Local_Express,&Local_Terms);
  1848.        Promote_Express(Express,Terms,Local_Terms);
  1849.  
  1850.        for(i=0;i<*Terms;i++)
  1851.          Express[i] = (DBL)ftrue(Express[i]-Local_Express[i]);
  1852.      END_CASE
  1853.  
  1854.      CASE (REL_GE_TOKEN)
  1855.        Parse_Rel_Factor(Local_Express,&Local_Terms);
  1856.        Promote_Express(Express,Terms,Local_Terms);
  1857.  
  1858.        for(i=0;i<*Terms;i++)
  1859.          Express[i] = (DBL)(Express[i] >= Local_Express[i]);
  1860.      END_CASE
  1861.  
  1862.      CASE (RIGHT_ANGLE_TOKEN)
  1863.        Parse_Rel_Factor(Local_Express,&Local_Terms);
  1864.        Promote_Express(Express,Terms,Local_Terms);
  1865.  
  1866.        for(i=0;i<*Terms;i++)
  1867.          Express[i] = (DBL)(Express[i] > Local_Express[i]);
  1868.      END_CASE
  1869.  
  1870.      OTHERWISE
  1871.        UNGET
  1872.        EXIT
  1873.      END_CASE
  1874.    END_EXPECT
  1875.  
  1876.   }
  1877.  
  1878.  
  1879.  
  1880. /*****************************************************************************
  1881. *
  1882. * FUNCTION
  1883. *
  1884. * INPUT
  1885. *
  1886. * OUTPUT
  1887. *
  1888. * RETURNS
  1889. *
  1890. * AUTHOR
  1891. *
  1892. * DESCRIPTION
  1893. *
  1894. * CHANGES
  1895. *
  1896. ******************************************************************************/
  1897.  
  1898. static void Parse_Logical (EXPRESS Express,int *Terms)
  1899. {
  1900.    register int i;
  1901.    EXPRESS Local_Express;
  1902.    int Local_Terms;
  1903.  
  1904.    Parse_Rel_Term(Express,Terms);
  1905.  
  1906.    Local_Terms=*Terms;
  1907.  
  1908.    EXPECT
  1909.      CASE (AMPERSAND_TOKEN)
  1910.        Parse_Rel_Term(Local_Express,&Local_Terms);
  1911.        Promote_Express(Express,Terms,Local_Terms);
  1912.  
  1913.        for(i=0;i<*Terms;i++)
  1914.          Express[i] = (DBL)(ftrue(Express[i]) && ftrue(Local_Express[i]));
  1915.      END_CASE
  1916.  
  1917.      CASE (BAR_TOKEN)
  1918.        Parse_Rel_Term(Local_Express,&Local_Terms);
  1919.        Promote_Express(Express,Terms,Local_Terms);
  1920.  
  1921.        for(i=0;i<*Terms;i++)
  1922.          Express[i] = (DBL)(ftrue(Express[i]) || ftrue(Local_Express[i]));
  1923.      END_CASE
  1924.  
  1925.      OTHERWISE
  1926.        UNGET
  1927.        EXIT
  1928.      END_CASE
  1929.    END_EXPECT
  1930.  
  1931.   }
  1932.  
  1933.  
  1934.  
  1935. /*****************************************************************************
  1936. *
  1937. * FUNCTION
  1938. *
  1939. * INPUT
  1940. *
  1941. * OUTPUT
  1942. *
  1943. * RETURNS
  1944. *
  1945. * AUTHOR
  1946. *
  1947. * DESCRIPTION
  1948. *
  1949. * CHANGES
  1950. *
  1951. ******************************************************************************/
  1952.  
  1953. static void Parse_Express (EXPRESS Express,int *Terms)
  1954. {
  1955.    EXPRESS Local_Express1, Local_Express2;
  1956.    EXPRESS *Chosen;
  1957.    int Local_Terms1, Local_Terms2;
  1958.  
  1959.    Local_Terms1 = 1;
  1960.  
  1961.    Parse_Logical(Express,&Local_Terms1);
  1962.  
  1963.    EXPECT
  1964.      CASE (QUESTION_TOKEN)
  1965.        if (Local_Terms1 != 1)
  1966.          Error("Conditional must evaluate to a float.");
  1967.        Local_Terms1 = Local_Terms2 = *Terms;
  1968.        Parse_Express(Local_Express1,&Local_Terms1);
  1969.        GET(COLON_TOKEN);
  1970.        Parse_Express(Local_Express2,&Local_Terms2);
  1971.        if (ftrue(Express[0]))
  1972.          {
  1973.           Chosen = (EXPRESS *)&Local_Express1;
  1974.           *Terms = Local_Terms1;
  1975.          }
  1976.        else
  1977.          {
  1978.           Chosen = (EXPRESS *)&Local_Express2;
  1979.           *Terms = Local_Terms2;
  1980.          }
  1981.        memcpy(Express,Chosen,sizeof(EXPRESS));
  1982.        EXIT
  1983.      END_CASE
  1984.  
  1985.      OTHERWISE
  1986.        /* Not a (c)?a:b expression.  Since Express was parsed with
  1987.           Local_Terms1=1 then we may have to promote this.  Suppose
  1988.           Terms=3 but Local_Terms1=1.  If this had been a (c)?a:b
  1989.           then a float is ok but since it is not a condition then
  1990.           it must be promoted to Terms=3.  Note that the parameters
  1991.           below look wrong but they are not.
  1992.         */
  1993.        Promote_Express (Express,&Local_Terms1,*Terms);
  1994.        /* On the other hand, Local_Terms1 may be bigger than Terms.
  1995.           If so, Express already is promoted and Terms must reflect that.
  1996.         */
  1997.        *Terms=Local_Terms1;
  1998.        UNGET
  1999.        EXIT
  2000.      END_CASE
  2001.    END_EXPECT
  2002.  
  2003.   }
  2004.  
  2005.  
  2006.  
  2007. /*****************************************************************************
  2008. *
  2009. * FUNCTION
  2010. *
  2011. * INPUT
  2012. *
  2013. * OUTPUT
  2014. *
  2015. * RETURNS
  2016. *
  2017. * AUTHOR
  2018. *
  2019. * DESCRIPTION
  2020. *
  2021. * CHANGES
  2022. *
  2023. ******************************************************************************/
  2024.  
  2025. DBL Parse_Raw_Number()
  2026. {
  2027.   int Terms;
  2028.   DBL Val;
  2029.   EXPRESS Express;
  2030.  
  2031.   Terms = 1;
  2032.  
  2033.   Parse_Num_Factor(Express, &Terms);
  2034.  
  2035.   Val = Express[0];
  2036.  
  2037.   if (Terms != 1)
  2038.   {
  2039.     Error("Raw float expected but vector found instead.");
  2040.   }
  2041.  
  2042.   return (Val);
  2043. }
  2044.  
  2045.  
  2046.  
  2047. /*****************************************************************************
  2048. *
  2049. * FUNCTION
  2050. *
  2051. * INPUT
  2052. *
  2053. * OUTPUT
  2054. *
  2055. * RETURNS
  2056. *
  2057. * AUTHOR
  2058. *
  2059. * DESCRIPTION
  2060. *
  2061. * CHANGES
  2062. *
  2063. ******************************************************************************/
  2064.  
  2065. DBL Parse_Float ()
  2066. {
  2067.    EXPRESS Express;
  2068.    int Terms;
  2069.  
  2070.    Terms=1;
  2071.  
  2072.    if (opts.Language_Version < 150)
  2073.           Parse_Num_Factor(Express,&Terms);
  2074.    else
  2075.       Parse_Rel_Factor(Express,&Terms);
  2076.  
  2077.    if (Terms>1)
  2078.       Error ("Float expected but vector or color expression found.");
  2079.  
  2080.    return (Express[0]);
  2081.   }
  2082.  
  2083.  
  2084.  
  2085. /*****************************************************************************
  2086. *
  2087. * FUNCTION
  2088. *
  2089. * INPUT
  2090. *
  2091. * OUTPUT
  2092. *
  2093. * RETURNS
  2094. *
  2095. * AUTHOR
  2096. *
  2097. * DESCRIPTION
  2098. *
  2099. * CHANGES
  2100. *
  2101. ******************************************************************************/
  2102.  
  2103. DBL Allow_Float (DBL defval)
  2104. {
  2105.   DBL retval;
  2106.  
  2107.   EXPECT
  2108.     CASE_EXPRESS
  2109.       retval = Parse_Float();
  2110.       EXIT
  2111.     END_CASE
  2112.  
  2113.     OTHERWISE
  2114.       UNGET
  2115.       retval = defval;
  2116.       EXIT
  2117.     END_CASE
  2118.   END_EXPECT
  2119.  
  2120.   return (retval);
  2121. }
  2122. #ifdef PatternWarpPatch
  2123. /*****************************************************************************
  2124. *
  2125. * FUNCTION
  2126. *
  2127. * INPUT
  2128. *
  2129. * OUTPUT
  2130. *
  2131. * RETURNS
  2132. *
  2133. * AUTHOR
  2134. *
  2135. * DESCRIPTION
  2136. *
  2137. * CHANGES
  2138. *
  2139. ******************************************************************************/
  2140.  
  2141. int Allow_Vector (VECTOR Vect)
  2142. {
  2143.   int retval;
  2144.  
  2145.   EXPECT
  2146.     CASE_EXPRESS
  2147.       Parse_Vector(Vect);
  2148.       retval = TRUE;
  2149.       EXIT
  2150.     END_CASE
  2151.  
  2152.     OTHERWISE
  2153.       UNGET
  2154.       retval = FALSE;
  2155.       EXIT
  2156.     END_CASE
  2157.   END_EXPECT
  2158.  
  2159.   return (retval);
  2160. }
  2161. #endif
  2162.  
  2163.  
  2164. /*****************************************************************************
  2165. *
  2166. * FUNCTION
  2167. *
  2168. * INPUT
  2169. *
  2170. * OUTPUT
  2171. *
  2172. * RETURNS
  2173. *
  2174. * AUTHOR
  2175. *
  2176. * DESCRIPTION
  2177. *
  2178. * CHANGES
  2179. *
  2180. ******************************************************************************/
  2181.  
  2182. void Parse_Vector (VECTOR Vector)
  2183. {
  2184.    EXPRESS Express;
  2185.    int Terms;
  2186.  
  2187.    /* Initialize expression. [DB 12/94] */
  2188.  
  2189.    for (Terms = 0; Terms < 5; Terms++)
  2190.    {
  2191.      Express[Terms] = 0.0;
  2192.    }
  2193.  
  2194.    Terms=3;
  2195.  
  2196.    if (opts.Language_Version < 150)
  2197.           Parse_Num_Factor(Express,&Terms);
  2198.    else
  2199.       Parse_Rel_Factor(Express,&Terms);
  2200.  
  2201.    if (Terms>3)
  2202.       Error ("Vector expected but color expression found.");
  2203.  
  2204.    for(Terms=0;Terms<3;Terms++)
  2205.       Vector[Terms]=Express[Terms];
  2206.   }
  2207.  
  2208.  
  2209. /*****************************************************************************
  2210. *
  2211. * FUNCTION
  2212. *
  2213. * INPUT
  2214. *
  2215. * OUTPUT
  2216. *
  2217. * RETURNS
  2218. *
  2219. * AUTHOR
  2220. *
  2221. * DESCRIPTION
  2222. *
  2223. * CHANGES
  2224. *
  2225. ******************************************************************************/
  2226.  
  2227. void Parse_Vector4D (VECTOR Vector)
  2228. {
  2229.    EXPRESS Express;
  2230.    int Terms;
  2231.    int Dim = 4;
  2232.    /* Initialize expression. [DB 12/94] */
  2233.  
  2234.    for (Terms = 0; Terms < 5; Terms++)
  2235.    {
  2236.      Express[Terms] = 0.0;
  2237.    }
  2238.  
  2239.    Terms=Dim;
  2240.  
  2241.    if (opts.Language_Version < 150)
  2242.           Parse_Num_Factor(Express,&Terms);
  2243.    else
  2244.       Parse_Rel_Factor(Express,&Terms);
  2245.  
  2246.    if (Terms>Dim)
  2247.       Error ("Vector expected but color expression found.");
  2248.  
  2249.    for(Terms=0;Terms<Dim;Terms++)
  2250.       Vector[Terms]=Express[Terms];
  2251.   }
  2252. #ifdef RBezierPatch
  2253.  
  2254. void Parse_RBezierPatchVector4D (VECTOR Vector)
  2255. {
  2256.    EXPRESS Express;
  2257.    int Terms;
  2258.    int Dim = 4;
  2259.    /* Initialize expression. [DB 12/94] */
  2260.  
  2261.    for (Terms = 0; Terms < 5; Terms++)
  2262.    {
  2263.      Express[Terms] = 0.0;
  2264.    }
  2265.  
  2266.    Terms=Dim;
  2267.  
  2268.    if (opts.Language_Version < 150)
  2269.           Parse_Num_Factor(Express,&Terms);
  2270.    else
  2271.       Parse_Rel_Factor(Express,&Terms);
  2272.    if ( Terms != 4)
  2273.       Error("\nNeeds a 4D vector, %dD vector found instead\n",Terms);
  2274.    if (Terms>Dim)
  2275.       Error ("Vector expected but color expression found.");
  2276.  
  2277.    for(Terms=0;Terms<Dim;Terms++)
  2278.       Vector[Terms]=Express[Terms];
  2279.   }
  2280.  
  2281. #endif
  2282.   #ifdef BsplinePatch
  2283.  
  2284.  
  2285. /*****************************************************************************
  2286. *
  2287. * FUNCTION
  2288. *
  2289. * INPUT
  2290. *
  2291. * OUTPUT
  2292. *
  2293. * RETURNS
  2294. *
  2295. * AUTHOR
  2296. *
  2297. * DESCRIPTION
  2298. *
  2299. * CHANGES
  2300. *
  2301. ******************************************************************************/
  2302.  
  2303. void Parse_Vector2D ( VECTOR Vector)
  2304.  
  2305.   {
  2306.    EXPRESS Express;
  2307.    int Terms;
  2308.    int Dim = 2;
  2309.    /* Initialize expression. [DB 12/94] */
  2310.  
  2311.    for (Terms = 0; Terms < 5; Terms++)
  2312.    {
  2313.      Express[Terms] = 0.0;
  2314.    }
  2315.  
  2316.    Terms=Dim;
  2317.  
  2318.    if (opts.Language_Version < 150)
  2319.           Parse_Num_Factor(Express,&Terms);
  2320.    else
  2321.       Parse_Rel_Factor(Express,&Terms);
  2322.  
  2323.    if (Terms>Dim)
  2324.       Error ("2D-Vector expected but something bigger found.");
  2325.  
  2326.    for(Terms=0;Terms<Dim;Terms++)
  2327.       Vector[Terms]=Express[Terms];
  2328.   }
  2329. #endif
  2330.  
  2331. /*****************************************************************************
  2332. *
  2333. * FUNCTION
  2334. *
  2335. * INPUT
  2336. *
  2337. * OUTPUT
  2338. *
  2339. * RETURNS
  2340. *
  2341. * AUTHOR
  2342. *
  2343. * DESCRIPTION
  2344. *
  2345. * CHANGES
  2346. *
  2347. ******************************************************************************/
  2348.  
  2349. void Parse_UV_Vect (UV_VECT UV_Vect)
  2350. {
  2351.    EXPRESS Express;
  2352.    int Terms;
  2353.  
  2354.    /* Initialize expression. [DB 12/94] */
  2355.  
  2356.    for (Terms = 0; Terms < 5; Terms++)
  2357.    {
  2358.      Express[Terms] = 0.0;
  2359.    }
  2360.  
  2361.    Terms=2;
  2362.  
  2363.    if (opts.Language_Version < 150)
  2364.           Parse_Num_Factor(Express,&Terms);
  2365.    else
  2366.       Parse_Rel_Factor(Express,&Terms);
  2367.  
  2368.    if (Terms>2)
  2369.       Error ("UV_Vector expected but vector or color expression found.");
  2370.  
  2371.    for(Terms=0;Terms<2;Terms++)
  2372.       UV_Vect[Terms]=Express[Terms];
  2373.   }
  2374.  
  2375.  
  2376.  
  2377. /*****************************************************************************
  2378. *
  2379. * FUNCTION
  2380. *
  2381. * INPUT
  2382. *
  2383. * OUTPUT
  2384. *
  2385. * RETURNS
  2386. *
  2387. * AUTHOR
  2388. *
  2389. * DESCRIPTION
  2390. *
  2391. * CHANGES
  2392. *
  2393. ******************************************************************************/
  2394.  
  2395. int Parse_Unknown_Vector(EXPRESS Express)
  2396. {
  2397.    int Terms;
  2398.  
  2399.    /* Initialize expression. [DB 12/94] */
  2400.  
  2401.    for (Terms = 0; Terms < 5; Terms++)
  2402.    {
  2403.      Express[Terms] = 0.0;
  2404.    }
  2405.  
  2406.    Terms=1;
  2407.  
  2408.    if (opts.Language_Version < 150)
  2409.    {
  2410.      Parse_Num_Factor(Express,&Terms);
  2411.    }
  2412.    else
  2413.    {
  2414.      Parse_Rel_Factor(Express,&Terms);
  2415.    }
  2416.  
  2417.    return(Terms);
  2418. }
  2419.  
  2420. /*****************************************************************************
  2421. *
  2422. * FUNCTION
  2423. *
  2424. * INPUT
  2425. *
  2426. * OUTPUT
  2427. *
  2428. * RETURNS
  2429. *
  2430. * AUTHOR
  2431. *
  2432. * DESCRIPTION
  2433. *
  2434. * CHANGES
  2435. *
  2436. ******************************************************************************/
  2437.  
  2438. void Parse_Scale_Vector (VECTOR Vector)
  2439. {
  2440.    Parse_Vector(Vector);
  2441.  
  2442.    if (Vector[X] == 0.0)
  2443.     {
  2444.      Vector[X] = 1.0;
  2445.      Warn(0, "Illegal Value: Scale X by 0.0. Changed to 1.0.");
  2446.     }
  2447.    if (Vector[Y] == 0.0)
  2448.     {
  2449.      Vector[Y] = 1.0;
  2450.      Warn(0, "Illegal Value: Scale Y by 0.0. Changed to 1.0.");
  2451.     }
  2452.    if (Vector[Z] == 0.0)
  2453.     {
  2454.      Vector[Z] = 1.0;
  2455.      Warn(0, "Illegal Value: Scale Z by 0.0. Changed to 1.0.");
  2456.     }
  2457.   }
  2458.  
  2459.  
  2460.  
  2461. /*****************************************************************************
  2462. *
  2463. * FUNCTION
  2464. *
  2465. * INPUT
  2466. *
  2467. * OUTPUT
  2468. *
  2469. * RETURNS
  2470. *
  2471. * AUTHOR
  2472. *
  2473. * DESCRIPTION
  2474. *
  2475. * CHANGES
  2476. *
  2477. ******************************************************************************/
  2478.  
  2479. void Parse_Colour (COLOUR Colour)
  2480. {
  2481.   EXPRESS Express;
  2482.   int Terms;
  2483.   register int i;
  2484.  
  2485.   /* Initialize expression. [DB 12/94] */
  2486.  
  2487.   for (Terms = 0; Terms < 5; Terms++)
  2488.   {
  2489.     Express[Terms] = 0.0;
  2490.   }
  2491.  
  2492.   Make_ColourA (Colour, 0.0, 0.0, 0.0, 0.0, 0.0);
  2493.  
  2494.   ALLOW(COLOUR_TOKEN)
  2495.  
  2496.   EXPECT
  2497.     CASE (COLOUR_KEY_TOKEN)
  2498.       switch(Token.Function_Id)
  2499.         {
  2500.          case ALPHA_TOKEN:
  2501.            Warn(155, "Keyword ALPHA discontinued. Use FILTER instead.");
  2502.            /* missing break deliberate */
  2503.  
  2504.          case FILTER_TOKEN:
  2505.                    Colour[FILTER] = (COLC)Parse_Float();
  2506.                    break;
  2507.  
  2508.          case BLUE_TOKEN:
  2509.                    Colour[BLUE] = (COLC)Parse_Float();
  2510.                    break;
  2511.  
  2512.          case GREEN_TOKEN:
  2513.                    Colour[GREEN] = (COLC)Parse_Float();
  2514.                    break;
  2515.  
  2516.          case RED_TOKEN:
  2517.                    Colour[RED] = (COLC)Parse_Float();
  2518.                    break;
  2519.  
  2520.          case TRANSMIT_TOKEN:
  2521.                    Colour[TRANSM] = (COLC)Parse_Float();
  2522.                    break;
  2523.  
  2524.          case RGB_TOKEN:
  2525.            Terms=3;
  2526.            Parse_Express(Express,&Terms);
  2527.            if (Terms != 3)
  2528.              Warn(0, "Suspicious expression after rgb.");
  2529.            for (i=0;i<Terms;i++)
  2530.              Colour[i]=(COLC)Express[i];
  2531.            break;
  2532.  
  2533.          case RGBF_TOKEN:
  2534.            Terms=4;
  2535.            Parse_Express(Express,&Terms);
  2536.            if (Terms != 4)
  2537.              Warn(0, "Suspicious expression after rgbf.");
  2538.            for (i=0;i<Terms;i++)
  2539.              Colour[i]=(COLC)Express[i];
  2540.            break;
  2541.  
  2542.          case RGBT_TOKEN:
  2543.            Terms=4;
  2544.            Parse_Express(Express,&Terms);
  2545.            if (Terms != 4)
  2546.              Warn(0, "Suspicious expression after rgbt.");
  2547.            for (i=0;i<Terms;i++)
  2548.              Colour[i]=(COLC)Express[i];
  2549.            Colour[TRANSM]=Colour[FILTER];
  2550.            Colour[FILTER]=0.0;
  2551.            break;
  2552.  
  2553.          case RGBFT_TOKEN:
  2554.            Terms=5;
  2555.            Parse_Express(Express,&Terms);
  2556.            if (Terms != 5)
  2557.              Warn(0, "Suspicious expression after rgbft.");
  2558.            for (i=0;i<Terms;i++)
  2559.              Colour[i]=(COLC)Express[i];
  2560.            break;
  2561.         }
  2562.     END_CASE
  2563.  
  2564.     CASE (COLOUR_ID_TOKEN)
  2565.       UNGET
  2566.       Terms=5;
  2567.       Parse_Express(Express,&Terms);
  2568.       for (i=0;i<Terms;i++)
  2569.         Colour[i]=(COLC)Express[i];
  2570.     END_CASE
  2571.  
  2572.     CASE_EXPRESS
  2573.       UNGET
  2574.       Terms=5;
  2575.       Parse_Express(Express,&Terms);
  2576.       if (Terms != 5)
  2577.         Error("Color expression expected but float or vector expression found.");
  2578.       for (i=0;i<Terms;i++)
  2579.         Colour[i]=(COLC)Express[i];
  2580.     END_CASE
  2581.  
  2582.     OTHERWISE
  2583.       UNGET
  2584.       EXIT
  2585.     END_CASE
  2586.   END_EXPECT
  2587. }
  2588.  
  2589. /*****************************************************************************
  2590. *
  2591. * FUNCTION
  2592. *
  2593. *   Parse_Blend_Map
  2594. *
  2595. * INPUT
  2596. *
  2597. *   Type of map to parse: pigment_map, normal_map etc
  2598. *   
  2599. * OUTPUT
  2600. *   
  2601. * RETURNS
  2602. *
  2603. *   Pointer to created blend map
  2604. *   
  2605. * AUTHOR
  2606. *
  2607. *   Chris Young 11/94
  2608. *   
  2609. * DESCRIPTION   :
  2610. *
  2611. * CHANGES
  2612. *
  2613. ******************************************************************************/
  2614.  
  2615. BLEND_MAP *Parse_Blend_Map (int Blend_Type,int Pat_Type)
  2616. {
  2617.    BLEND_MAP *New = NULL;
  2618.    BLEND_MAP_ENTRY *Temp_Ent;
  2619.    int i;
  2620.  
  2621.    Parse_Begin ();
  2622.  
  2623.    EXPECT
  2624.      CASE2 (COLOUR_MAP_ID_TOKEN, PIGMENT_MAP_ID_TOKEN)
  2625.      CASE3 (NORMAL_MAP_ID_TOKEN, TEXTURE_MAP_ID_TOKEN, SLOPE_MAP_ID_TOKEN)
  2626.        New = Copy_Blend_Map ((BLEND_MAP *) Token.Data);
  2627.        if (Blend_Type != New->Type)
  2628.        {
  2629.           Error("Wrong identifier type\n");
  2630.        }
  2631.        EXIT
  2632.      END_CASE
  2633.  
  2634.      OTHERWISE
  2635.        UNGET
  2636.        Temp_Ent = Create_BMap_Entries(MAX_BLEND_MAP_ENTRIES);
  2637.        i = 0;
  2638.  
  2639.        EXPECT
  2640.          CASE (LEFT_SQUARE_TOKEN)
  2641.            switch (Pat_Type)
  2642.            {
  2643.               case AVERAGE_PATTERN:
  2644.                 Temp_Ent[i].value = Allow_Float(1.0);
  2645.                 Parse_Comma();
  2646.                 break;
  2647.               
  2648.               default:
  2649.                 Temp_Ent[i].value = Parse_Float();
  2650.                 Parse_Comma();
  2651.                 break;
  2652.            }
  2653.  
  2654.            switch (Blend_Type)
  2655.            {
  2656.             case PIGMENT_TYPE:
  2657.               Temp_Ent[i].Vals.Pigment=Copy_Pigment(Default_Texture->Pigment);
  2658.               Parse_Pigment(&(Temp_Ent[i].Vals.Pigment));
  2659.               break;
  2660.  
  2661.             case NORMAL_TYPE:
  2662.               Temp_Ent[i].Vals.Tnormal=Copy_Tnormal(Default_Texture->Tnormal);
  2663.               Parse_Tnormal(&(Temp_Ent[i].Vals.Tnormal));
  2664.               break;
  2665.  
  2666.             case SLOPE_TYPE:
  2667.               Parse_UV_Vect(Temp_Ent[i].Vals.Point_Slope);
  2668.               break;
  2669.  
  2670.             case TEXTURE_TYPE:
  2671.               Temp_Ent[i].Vals.Texture=Parse_Texture();
  2672.               break;
  2673.  
  2674.             case DENSITY_TYPE:
  2675.               Temp_Ent[i].Vals.Pigment=NULL;
  2676.               Parse_Media_Density_Pattern (&(Temp_Ent[i].Vals.Pigment));
  2677.               break;
  2678.  
  2679.             default:
  2680.               Error("Type not implemented yet.");
  2681.            }
  2682.            if (++i > MAX_BLEND_MAP_ENTRIES)
  2683.              Error ("Blend_Map too long");
  2684.  
  2685.            GET (RIGHT_SQUARE_TOKEN);
  2686.          END_CASE
  2687.  
  2688.          OTHERWISE
  2689.            UNGET
  2690.            if (i < 1)
  2691.              Error ("Must have at least one entry in map.");
  2692.            New = Create_Blend_Map ();
  2693.            New->Number_Of_Entries = i;
  2694.            New->Type=Blend_Type;
  2695.            New->Transparency_Flag=TRUE; /*Temp fix.  Really set in Post_???*/
  2696.            New->Blend_Map_Entries = (BLEND_MAP_ENTRY *)POV_REALLOC(Temp_Ent,sizeof(BLEND_MAP_ENTRY)*i,"blend map entries");
  2697.            EXIT
  2698.          END_CASE
  2699.        END_EXPECT
  2700.        EXIT
  2701.      END_CASE
  2702.    END_EXPECT
  2703.  
  2704.    Parse_End ();
  2705.  
  2706.    return (New);
  2707.   }
  2708.  
  2709.  
  2710.  
  2711. /*****************************************************************************
  2712. *
  2713. * FUNCTION
  2714. *
  2715. * INPUT
  2716. *
  2717. * OUTPUT
  2718. *
  2719. * RETURNS
  2720. *
  2721. * AUTHOR
  2722. *
  2723. * DESCRIPTION
  2724. *
  2725. * CHANGES
  2726. *
  2727. ******************************************************************************/
  2728.  
  2729. BLEND_MAP *Parse_Blend_List (int Count,BLEND_MAP *Def_Map,int Blend_Type)
  2730. {
  2731.    BLEND_MAP *New;
  2732.    BLEND_MAP_ENTRY *Temp_Ent;
  2733.    int Type, i;
  2734.  
  2735.    i = 0;
  2736.  
  2737.    if(Blend_Type == PIGMENT_TYPE)
  2738.    {
  2739.      EXPECT
  2740.        CASE(PIGMENT_TOKEN)
  2741.          UNGET
  2742.          Type=PIGMENT_TYPE;
  2743.          EXIT
  2744.        END_CASE
  2745.  
  2746.        OTHERWISE
  2747.          UNGET
  2748.          Type=COLOUR_TYPE;
  2749.          EXIT
  2750.        END_CASE
  2751.      END_EXPECT
  2752.    }
  2753.    else
  2754.    {
  2755.      Type=Blend_Type;
  2756.    }
  2757.  
  2758.    Temp_Ent = Create_BMap_Entries(Count);
  2759.  
  2760.    switch(Type)
  2761.    {
  2762.      case COLOUR_TYPE:
  2763.        EXPECT
  2764.          CASE_COLOUR
  2765.          CASE_EXPRESS
  2766.            Parse_Colour (Temp_Ent[i].Vals.Colour);
  2767.            Parse_Comma ();
  2768.            Temp_Ent[i].value = (SNGL)i;
  2769.            if (++i >= Count)
  2770.              EXIT
  2771.          END_CASE
  2772.  
  2773.          OTHERWISE
  2774.            UNGET
  2775.            EXIT
  2776.          END_CASE
  2777.        END_EXPECT
  2778.        break;
  2779.  
  2780.      case PIGMENT_TYPE:
  2781.        EXPECT
  2782.          CASE(PIGMENT_TOKEN)
  2783.            Parse_Begin ();
  2784.            Temp_Ent[i].Vals.Pigment=Copy_Pigment(Default_Texture->Pigment);
  2785.            Parse_Pigment(&(Temp_Ent[i].Vals.Pigment));
  2786.            Parse_End ();
  2787.            Parse_Comma ();
  2788.            Temp_Ent[i].value = (SNGL)i;
  2789.            if (++i >= Count)
  2790.              EXIT
  2791.          END_CASE
  2792.  
  2793.          OTHERWISE
  2794.            UNGET
  2795.            EXIT
  2796.          END_CASE
  2797.        END_EXPECT
  2798.        break;
  2799.  
  2800.      case NORMAL_TYPE:
  2801.        EXPECT
  2802.          CASE(TNORMAL_TOKEN)
  2803.            Parse_Begin ();
  2804.            Temp_Ent[i].Vals.Tnormal=Copy_Tnormal(Default_Texture->Tnormal);
  2805.            Parse_Tnormal(&(Temp_Ent[i].Vals.Tnormal));
  2806.            Parse_End ();
  2807.            Parse_Comma ();
  2808.            Temp_Ent[i].value = (SNGL)i;
  2809.            if (++i >= Count)
  2810.              EXIT
  2811.          END_CASE
  2812.  
  2813.          OTHERWISE
  2814.            UNGET
  2815.            EXIT
  2816.          END_CASE
  2817.        END_EXPECT
  2818.        break;
  2819.  
  2820.      case TEXTURE_TYPE:
  2821.        EXPECT
  2822.          CASE(TEXTURE_TOKEN)
  2823.            Parse_Begin ();
  2824.            Temp_Ent[i].Vals.Texture=Parse_Texture();
  2825.            Parse_End ();
  2826.            Parse_Comma ();
  2827.            Temp_Ent[i].value = (SNGL)i;
  2828.            if (++i >= Count)
  2829.              EXIT
  2830.          END_CASE
  2831.  
  2832.          OTHERWISE
  2833.            UNGET
  2834.            EXIT
  2835.          END_CASE
  2836.        END_EXPECT
  2837.        break;
  2838.  
  2839.      case DENSITY_TYPE:
  2840.        EXPECT
  2841.          CASE(DENSITY_TOKEN)
  2842.            Parse_Begin ();
  2843.            Temp_Ent[i].Vals.Pigment=NULL;
  2844.            Parse_Media_Density_Pattern (&(Temp_Ent[i].Vals.Pigment));
  2845.            Parse_End ();
  2846.            Parse_Comma ();
  2847.            Temp_Ent[i].value = (SNGL)i;
  2848.            if (++i >= Count)
  2849.              EXIT
  2850.          END_CASE
  2851.  
  2852.          OTHERWISE
  2853.            UNGET
  2854.            EXIT
  2855.          END_CASE
  2856.        END_EXPECT
  2857.        break;
  2858.  
  2859.    }
  2860.    
  2861.    if ((Type==NORMAL_TYPE) && (i==0))
  2862.    {
  2863.      POV_FREE(Temp_Ent);
  2864.      return (NULL);
  2865.    }
  2866.  
  2867.    while (i < Count)
  2868.    {
  2869.      switch (Type)
  2870.      {
  2871.         case COLOUR_TYPE:
  2872.           Assign_Colour(Temp_Ent[i].Vals.Colour,Def_Map->Blend_Map_Entries[i].Vals.Colour);
  2873.           break;
  2874.  
  2875.         case PIGMENT_TYPE:
  2876.           Temp_Ent[i].Vals.Pigment=Copy_Pigment(Default_Texture->Pigment);
  2877.           break;
  2878.  
  2879.         case NORMAL_TYPE:
  2880.           Temp_Ent[i].Vals.Tnormal=Copy_Tnormal(Default_Texture->Tnormal);
  2881.           break;
  2882.  
  2883.         case TEXTURE_TYPE:
  2884.           Temp_Ent[i].Vals.Texture=Copy_Textures(Default_Texture);
  2885.           break;
  2886.  
  2887.         case DENSITY_TYPE:
  2888.           Temp_Ent[i].Vals.Pigment=NULL;
  2889.           break;
  2890.  
  2891.      }
  2892.      Temp_Ent[i].value = (SNGL)i;
  2893.      i++;
  2894.    }
  2895.  
  2896.    New = Create_Blend_Map ();
  2897.    New->Number_Of_Entries = Count;
  2898.    New->Type=Type;
  2899.    New->Transparency_Flag=TRUE; /*Temp fix.  Really set in Post_???*/
  2900.    New->Blend_Map_Entries = Temp_Ent;
  2901.  
  2902.    return (New);
  2903.   }
  2904.  
  2905.  
  2906. /*****************************************************************************
  2907. *
  2908. * FUNCTION
  2909. *
  2910. *   Parse_Colour_Map
  2911. *
  2912. * INPUT
  2913. *   
  2914. * OUTPUT
  2915. *
  2916. * RETURNS
  2917. *
  2918. *   Pointer to newly created BLEND_MAP that has colors as all
  2919. *   its entries.
  2920. *   
  2921. * AUTHOR
  2922. *
  2923. *   POV-Ray Team
  2924. *   
  2925. * DESCRIPTION   : This seperate routine parses color_maps only.  It
  2926. *                 cannot be used for pigment_maps because it accomidates
  2927. *                 the old double entry color maps from vers 1.0
  2928. *
  2929. * CHANGES
  2930. *
  2931. ******************************************************************************/
  2932.  
  2933. BLEND_MAP *Parse_Colour_Map ()
  2934. {
  2935.    BLEND_MAP *New = NULL;
  2936.    int i,j,c,p,ii;
  2937.    EXPRESS Express;
  2938.    int Terms;
  2939.    BLEND_MAP_ENTRY *Temp_Ent;
  2940.  
  2941.    Parse_Begin ();
  2942.  
  2943.    EXPECT
  2944.      CASE (COLOUR_MAP_ID_TOKEN)
  2945.        New = Copy_Blend_Map ((BLEND_MAP *) Token.Data);
  2946.        EXIT
  2947.      END_CASE
  2948.  
  2949.      OTHERWISE
  2950.        UNGET
  2951.        Temp_Ent = Create_BMap_Entries(MAX_BLEND_MAP_ENTRIES);
  2952.        i = 0;
  2953.        j = 1;
  2954.  
  2955.        EXPECT
  2956.          CASE (LEFT_SQUARE_TOKEN)
  2957.            Temp_Ent[i].value = Parse_Float();  Parse_Comma();
  2958.  
  2959.            EXPECT
  2960.              /* After [ must be a float. If 2nd thing found is another
  2961.                 float then this is an old style color_map.
  2962.               */
  2963.              CASE_FLOAT
  2964.                Terms=1;
  2965.                Parse_Express(Express,&Terms);
  2966.                if (Terms==1)
  2967.                  {
  2968.                   Temp_Ent[j].value = Express[0];
  2969.                   Parse_Colour (Temp_Ent[i].Vals.Colour);
  2970.  
  2971.                   GET (COLOUR_TOKEN);
  2972.                   Parse_Colour (Temp_Ent[j].Vals.Colour);
  2973.                   i += 2;
  2974.                   j += 2;
  2975.                  }
  2976.                else
  2977.                  if (Terms==5)
  2978.                    {
  2979.                     for (ii=0;ii<5;ii++)
  2980.                       Temp_Ent[i].Vals.Colour[ii]=(COLC)Express[ii];
  2981.                     i++;
  2982.                     j++;
  2983.                    }
  2984.                  else
  2985.                    Error("Illegal expression syntax in color_map.");
  2986.                EXIT
  2987.              END_CASE
  2988.  
  2989.              CASE_COLOUR
  2990.                Parse_Colour (Temp_Ent[i].Vals.Colour);
  2991.                i++;
  2992.                j++;
  2993.                EXIT
  2994.              END_CASE
  2995.  
  2996.            END_EXPECT
  2997.  
  2998.            if (j > MAX_BLEND_MAP_ENTRIES)
  2999.              Error ("Blend_Map too long.");
  3000.  
  3001.            GET (RIGHT_SQUARE_TOKEN);
  3002.          END_CASE
  3003.  
  3004.          OTHERWISE
  3005.            UNGET
  3006.            if (i < 1)
  3007.              Error ("Must have at least one color in color map.");
  3008.  
  3009.            /* Eliminate duplicates */
  3010.            for (c = 1, p = 0; c<i; c++)
  3011.              {
  3012.               if (memcmp(&(Temp_Ent[p]),
  3013.                          &(Temp_Ent[c]),sizeof(BLEND_MAP_ENTRY)) == 0)
  3014.                 p--;
  3015.  
  3016.               Temp_Ent[++p] = Temp_Ent[c];
  3017.              }
  3018.            p++;
  3019.            New = Create_Blend_Map ();
  3020.            New->Number_Of_Entries = p;
  3021.            New->Type=COLOUR_TYPE;
  3022.            New->Transparency_Flag=TRUE; /*Temp fix.  Really set in Post_???*/
  3023.            New->Blend_Map_Entries = (BLEND_MAP_ENTRY *)POV_REALLOC(Temp_Ent,sizeof(BLEND_MAP_ENTRY)*p,"blend map entries");
  3024.            EXIT
  3025.          END_CASE
  3026.        END_EXPECT
  3027.        EXIT
  3028.      END_CASE
  3029.    END_EXPECT
  3030.  
  3031.    Parse_End ();
  3032.  
  3033.    return (New);
  3034.   }
  3035.  #ifdef SplinePatch
  3036.  
  3037. /*****************************************************************************
  3038. *
  3039. * FUNCTION
  3040. *
  3041. *   Parse_Spline
  3042. *
  3043. * INPUT
  3044. *   
  3045. * OUTPUT 
  3046. *
  3047. * RETURNS
  3048. *
  3049. *   Pointer to newly created SPLINE 
  3050. *
  3051. * AUTHOR
  3052. *
  3053. *   Wolfgang Ortmann
  3054. *   
  3055. * DESCRIPTION   : This seperate routine parses pure splines only. Splines in
  3056. *   lathe objects and SOR are similar but not identical 
  3057. *
  3058. * CHANGES
  3059. *
  3060. ******************************************************************************/
  3061.  
  3062. SPLINE2 *Parse_Spline()
  3063. {
  3064.   SPLINE2 *New = NULL;
  3065.   EXPRESS Express;
  3066.   int Type = LINEAR_SPLINE;
  3067.   int Terms;
  3068.   DBL par;
  3069.  
  3070.   /* check for spline identifier */
  3071.    EXPECT
  3072.      CASE (SPLINE_ID_TOKEN)
  3073.        New = Copy_Spline ((SPLINE2 *) Token.Data);
  3074.        EXIT
  3075.      END_CASE
  3076.  
  3077.      OTHERWISE
  3078.        UNGET
  3079.             EXIT
  3080.         END_CASE
  3081.     END_EXPECT
  3082.  
  3083.     /* Determine kind of spline */
  3084.        EXPECT
  3085.          CASE(LINEAR_SPLINE_TOKEN)
  3086.            Type = LINEAR_SPLINE;
  3087.          END_CASE
  3088.  
  3089.          CASE(QUADRATIC_SPLINE_TOKEN)
  3090.            Type = QUADRATIC_SPLINE;
  3091.          END_CASE
  3092.  
  3093.          CASE(CUBIC_SPLINE_TOKEN)
  3094.            Type = CUBIC_SPLINE;
  3095.          END_CASE
  3096.  
  3097.          OTHERWISE
  3098.            UNGET
  3099.            EXIT
  3100.          END_CASE
  3101.        END_EXPECT
  3102.  
  3103.     if ( New == NULL)    /* ys fix jan 14 2001*/
  3104.        New=Create_Spline(Type);    
  3105.  
  3106.        EXPECT
  3107.          CASE_FLOAT
  3108.            /* Entry has the form float,vector */
  3109.            par = Parse_Float();
  3110.            Parse_Comma();
  3111.            Terms=5;
  3112.            Parse_Express(Express,&Terms);
  3113.            if (Terms>5) 
  3114.                Error("Too much components");
  3115.            Parse_Comma();
  3116.  
  3117.            Insert_Spline_Entry(New,par,Express);
  3118.         END_CASE
  3119.  
  3120.         OTHERWISE
  3121.             UNGET
  3122.             EXIT
  3123.         END_CASE
  3124.     END_EXPECT
  3125.  
  3126.     if( New->Number_Of_Entries < 1 )
  3127.        Error("Spline must have at least one entry.");
  3128.    
  3129.   return New;
  3130. }
  3131. #endif
  3132.  
  3133. /*****************************************************************************
  3134. *
  3135. * FUNCTION
  3136. *
  3137. * INPUT
  3138. *
  3139. * OUTPUT
  3140. *
  3141. * RETURNS
  3142. *
  3143. * AUTHOR
  3144. *
  3145. * DESCRIPTION
  3146. *
  3147. * CHANGES
  3148. *
  3149. ******************************************************************************/
  3150.  
  3151. char *Parse_String()
  3152. {
  3153.   char *temp1, *temp2, *New = NULL, *p;
  3154.   char temp3[64];
  3155.   char temp4[64];
  3156.   DBL val;
  3157.   int l,l2,d;
  3158. #ifdef TimeDatePatch
  3159.   time_t timer;
  3160.   struct tm *date; 
  3161. #endif
  3162.  
  3163.   EXPECT
  3164.     CASE(STRING_LITERAL_TOKEN)
  3165.       New=(char *)POV_MALLOC(strlen(Token.Token_String) + 1, "temporary string");
  3166.       strcpy (New, Token.Token_String);
  3167.       EXIT
  3168.     END_CASE
  3169.  
  3170.     CASE(STR_TOKEN)
  3171.       GET (LEFT_PAREN_TOKEN);
  3172.       val = Parse_Float();
  3173.       Parse_Comma();
  3174.       l = (int)Parse_Float();
  3175.       Parse_Comma();
  3176.       d = (int)Parse_Float();
  3177.       GET (RIGHT_PAREN_TOKEN);
  3178.  
  3179.       p=temp3;
  3180.       *(p++) = '%';
  3181.       if (l>0)
  3182.       {
  3183.         sprintf(p,"%d",l);
  3184.         while (*(++p)){;}
  3185.         /* Could also be written for clarity as:
  3186.         while (*p != '\0')
  3187.           p++;
  3188.         */
  3189.       }
  3190.       else
  3191.       {
  3192.         if (l)
  3193.         {
  3194.           sprintf(p,"0%d",abs(l));
  3195.           while (*(++p)){;}
  3196.         }
  3197.       }
  3198.       
  3199.       if (d>=0)
  3200.       {
  3201.         *(p++) = '.';
  3202.         sprintf(p,"%d",d);
  3203.         while (*(++p)){;}
  3204.       }
  3205.       *(p++) = 'f';
  3206.       *p     = '\0';
  3207.             
  3208.       sprintf(temp4,temp3,val);
  3209.       
  3210.       FIX_WATCOM_BUG
  3211.  
  3212.       New=(char *)POV_MALLOC(strlen(temp4) + 1, "temporary string");
  3213.       strcpy (New, temp4);
  3214.       EXIT
  3215.     END_CASE
  3216.  
  3217.  
  3218.     CASE(CONCAT_TOKEN)
  3219.       GET (LEFT_PAREN_TOKEN);
  3220.       
  3221.       New=Parse_String();
  3222.       EXPECT
  3223.         CASE(RIGHT_PAREN_TOKEN)
  3224.           EXIT
  3225.         END_CASE
  3226.         
  3227.         OTHERWISE
  3228.           Parse_Comma();
  3229.           temp1=New;
  3230.           temp2=Parse_String();
  3231.           l2=strlen(temp1)+strlen(temp2)+2;
  3232.           New=(char *)POV_MALLOC(l2, "temporary string");
  3233.           strcpy(New,temp1);
  3234.           strcat(New,temp2);
  3235.           POV_FREE(temp1);
  3236.           POV_FREE(temp2);
  3237.         END_CASE
  3238.       END_EXPECT       
  3239.       EXIT
  3240.     END_CASE
  3241.     
  3242.     CASE(CHR_TOKEN)
  3243.       New=(char *)POV_MALLOC(2, "temporary string");
  3244.       d=(int)Parse_Float_Param();
  3245.       if ((d<0)||(d>255))
  3246.       {
  3247.         Error("Value %d cannot be used in chr(...).\n",d);
  3248.       }
  3249.       New[0]=d;
  3250.       New[1]='\0';
  3251.       EXIT
  3252.     END_CASE
  3253.     
  3254.     CASE(SUBSTR_TOKEN)
  3255.       GET (LEFT_PAREN_TOKEN);
  3256.       
  3257.       temp1=Parse_String();
  3258.       Parse_Comma();
  3259.       l=(int)Parse_Float();
  3260.       Parse_Comma();
  3261.       d=(int)Parse_Float();
  3262.       if ((l+d-1) > strlen(temp1))
  3263.       {
  3264.          Error("Illegal params in substr(%s,%d,%d).\n",temp1,l,d);
  3265.       }
  3266.       New=(char *)POV_MALLOC((size_t)(d+1), "temporary string");
  3267.       strncpy(New,&(temp1[l-1]),(unsigned)d);
  3268.       New[d]='\0';
  3269.       POV_FREE(temp1);
  3270.       GET (RIGHT_PAREN_TOKEN);
  3271.       EXIT
  3272.     END_CASE
  3273.     
  3274.     CASE(STRUPR_TOKEN)
  3275.       GET (LEFT_PAREN_TOKEN);
  3276.       New=Parse_String();
  3277.       POV_strupr(New);
  3278.       GET (RIGHT_PAREN_TOKEN);
  3279.       EXIT
  3280.     END_CASE
  3281.     
  3282.     CASE(STRLWR_TOKEN)
  3283.       GET (LEFT_PAREN_TOKEN);
  3284.       New=Parse_String();
  3285.       POV_strlwr(New);
  3286.       GET (RIGHT_PAREN_TOKEN);
  3287.       EXIT
  3288.     END_CASE
  3289.     
  3290.     CASE(STRING_ID_TOKEN)
  3291.       New=(char *)POV_MALLOC(strlen((char *)Token.Data) + 1, "temporary string");
  3292.       strcpy (New, (char *)Token.Data);
  3293.       EXIT
  3294.     END_CASE
  3295.       
  3296.  
  3297. #ifdef TimeDatePatch
  3298.     CASE(GET_DATE_TOKEN) /*YS 2000 get date and time string*/
  3299.       GET (LEFT_PAREN_TOKEN);
  3300.       
  3301.       temp1=Parse_String();
  3302.       New=(char *)POV_MALLOC(500 + 1, "time string");
  3303.  
  3304.       time(&timer);
  3305.       date=localtime(&timer); 
  3306.       strftime(New,500,temp1,date);
  3307.       POV_FREE(temp1);
  3308.       GET (RIGHT_PAREN_TOKEN);
  3309.       EXIT
  3310.     END_CASE
  3311. #endif
  3312.       
  3313.     OTHERWISE
  3314.       Parse_Error_Str ("string expression");
  3315.     END_CASE
  3316.   END_EXPECT
  3317.  
  3318.   return (New);
  3319. }
  3320.  
  3321.  
  3322.  
  3323. /*****************************************************************************
  3324. *
  3325. * FUNCTION
  3326. *
  3327. * INPUT
  3328. *
  3329. * OUTPUT
  3330. *
  3331. * RETURNS
  3332. *
  3333. * AUTHOR
  3334. *
  3335. * DESCRIPTION
  3336. *
  3337. * CHANGES
  3338. *
  3339. ******************************************************************************/
  3340.  
  3341. char *Parse_Formatted_String()
  3342. {
  3343.   char *New, *dest, *src, *temp;
  3344.   char buff[MAX_STRING_INDEX*2];
  3345.   
  3346.   dest = &buff[0];
  3347.  
  3348.   temp = src = Parse_String();
  3349.  
  3350.   while (*src != '\0')
  3351.   {
  3352.     switch(*src)
  3353.     {
  3354.       case '\\':
  3355.         switch(*(++src))
  3356.         {
  3357.           case 'a': *dest=0x07; break;
  3358.            
  3359.           case 'b': *dest=0x08; break;
  3360.  
  3361.           case 'f': *dest=0x0c; break;
  3362.  
  3363.           case 'n': *dest=0x0a; break;
  3364.  
  3365.           case 'r': *dest=0x0d; break;
  3366.  
  3367.           case 't': *dest=0x09; break;
  3368.  
  3369.           case 'v': *dest=0x0b; break;
  3370.  
  3371.           case '\0': *dest=0x5c; break;
  3372.  
  3373.           case '\'': *dest=0x27; break;
  3374.            
  3375.           default: *dest='\\'; dest++; *dest=*src; break;
  3376.         }
  3377.         break;
  3378.         
  3379.       case '%':
  3380.         *dest=*src; dest++; *dest=*src;
  3381.         break;
  3382.         
  3383.       default:
  3384.         *dest=*src;
  3385.         break;
  3386.     }
  3387.     src++;
  3388.     dest++;
  3389.   }
  3390.   *dest='\0';
  3391.   
  3392.   New=POV_STRDUP(buff);
  3393.   POV_FREE(temp);
  3394.   return (New);
  3395. }
  3396.  
  3397.  
  3398. /*****************************************************************************
  3399. *
  3400. * FUNCTION
  3401. *
  3402. * INPUT
  3403. *
  3404. * OUTPUT
  3405. *
  3406. * RETURNS
  3407. *
  3408. * AUTHOR
  3409. *
  3410. * DESCRIPTION
  3411. *
  3412. * CHANGES
  3413. *
  3414. ******************************************************************************/
  3415.  
  3416. static void POV_strupr(char *s)
  3417. {
  3418.   int i;
  3419.   
  3420.   for (i = 0; i < strlen(s); i++)
  3421.   {
  3422.     s[i] = (char)toupper((int)s[i]);
  3423.   }
  3424. }
  3425.  
  3426.  
  3427.  
  3428. /*****************************************************************************
  3429. *
  3430. * FUNCTION
  3431. *
  3432. * INPUT
  3433. *
  3434. * OUTPUT
  3435. *
  3436. * RETURNS
  3437. *
  3438. * AUTHOR
  3439. *
  3440. * DESCRIPTION
  3441. *
  3442. * CHANGES
  3443. *
  3444. ******************************************************************************/
  3445.  
  3446. static void POV_strlwr(char *s)
  3447. {
  3448.   int i;
  3449.   
  3450.   for (i = 0; i < strlen(s); i++)
  3451.   {
  3452.     s[i] = (char)tolower((int)s[i]);
  3453.   }
  3454. }
  3455.  
  3456.  
  3457. /*****************************************************************************
  3458. *
  3459. * FUNCTION
  3460. *
  3461. *   stream_rand
  3462. *
  3463. * INPUT
  3464. *
  3465. *   stream - number of random stream
  3466. *
  3467. * OUTPUT
  3468. *
  3469. * RETURNS
  3470. *
  3471. *   DBL - random value
  3472. *
  3473. * AUTHOR
  3474. *
  3475. *   Dieter Bayer
  3476. *
  3477. * DESCRIPTION
  3478. *
  3479. *   Standard pseudo-random function.
  3480. *
  3481. * CHANGES
  3482. *
  3483. *   Feb 1996 : Creation.
  3484. *   Mar 1996 : Return 2^32 random values instead of 2^16 [AED]
  3485. *
  3486. ******************************************************************************/
  3487.  
  3488. static DBL stream_rand(int stream)
  3489. {
  3490.   next_rand[stream] = next_rand[stream] * 1812433253L + 12345L;
  3491.  
  3492.   return((DBL)(next_rand[stream] & 0xFFFFFFFFUL) / 0xFFFFFFFFUL);
  3493. }
  3494.  
  3495.  
  3496.  
  3497. /*****************************************************************************
  3498. *
  3499. * FUNCTION
  3500. *
  3501. *   stream_seed
  3502. *
  3503. * INPUT
  3504. *
  3505. *   seed - Pseudo-random generator start value
  3506. *
  3507. * OUTPUT
  3508. *
  3509. * RETURNS
  3510. *
  3511. * AUTHOR
  3512. *
  3513. *   Dieter Bayer
  3514. *
  3515. * DESCRIPTION
  3516. *
  3517. *   Set start value for pseudo-random generator.
  3518. *
  3519. * CHANGES
  3520. *
  3521. *   Feb 1996 : Creation.
  3522. *
  3523. ******************************************************************************/
  3524.  
  3525. static int stream_seed(int seed)
  3526. {
  3527.   next_rand = (unsigned long *)POV_REALLOC(next_rand, (Number_Of_Random_Generators+1)*sizeof(unsigned long), "random number generator");
  3528.  
  3529.   next_rand[Number_Of_Random_Generators] = (unsigned long int)seed;
  3530.  
  3531.   Number_Of_Random_Generators++;
  3532.  
  3533.   return(Number_Of_Random_Generators-1);
  3534. }
  3535.  
  3536.  
  3537.  
  3538. /*****************************************************************************
  3539. *
  3540. * FUNCTION
  3541. *
  3542. *   Init_Random_Generators
  3543. *
  3544. * INPUT
  3545. *
  3546. * OUTPUT
  3547. *
  3548. * RETURNS
  3549. *
  3550. * AUTHOR
  3551. *
  3552. *   Dieter Bayer
  3553. *
  3554. * DESCRIPTION
  3555. *
  3556. * CHANGES
  3557. *
  3558. *   Feb 1996 : Creation.
  3559. *
  3560. ******************************************************************************/
  3561.  
  3562. void Init_Random_Generators()
  3563. {
  3564.   Number_Of_Random_Generators = 0;
  3565.  
  3566.   next_rand = NULL;
  3567. }
  3568.  
  3569.  
  3570.  
  3571. /*****************************************************************************
  3572. *
  3573. * FUNCTION
  3574. *
  3575. *   Destroy_Random_Generators
  3576. *
  3577. * INPUT
  3578. *
  3579. * OUTPUT
  3580. *
  3581. * RETURNS
  3582. *
  3583. * AUTHOR
  3584. *
  3585. *   Dieter Bayer
  3586. *
  3587. * DESCRIPTION
  3588. *
  3589. * CHANGES
  3590. *
  3591. *   Feb 1996 : Creation.
  3592. *
  3593. ******************************************************************************/
  3594.  
  3595. void Destroy_Random_Generators()
  3596. {
  3597.   if (next_rand != NULL)
  3598.   {
  3599.     POV_FREE(next_rand);
  3600.   }
  3601.  
  3602.   next_rand = NULL;
  3603.  
  3604.   Number_Of_Random_Generators = 0;
  3605. }
  3606.  
  3607. DBL Parse_Signed_Float(void)
  3608. {
  3609.    DBL Sign=1.0;
  3610.    DBL Val=0.0; /* tw */;
  3611.   
  3612.    EXPECT
  3613.      CASE (PLUS_TOKEN)
  3614.      END_CASE
  3615.      
  3616.      CASE (DASH_TOKEN) 
  3617.         Sign=-1.0;
  3618.         Get_Token();  
  3619.         /* Deliberate fall through with no END_CASE */
  3620.      CASE (FLOAT_FUNCT_TOKEN)
  3621.        if (Token.Function_Id==FLOAT_TOKEN)
  3622.        {
  3623.           Val = Sign * Token.Token_Float;
  3624.           EXIT
  3625.        }
  3626.        else
  3627.        {
  3628.           Parse_Error(FLOAT_TOKEN);
  3629.        }
  3630.      END_CASE
  3631.      
  3632.      OTHERWISE
  3633.        Parse_Error(FLOAT_TOKEN);
  3634.      END_CASE
  3635.    END_EXPECT
  3636.  
  3637.    return(Val);
  3638. }
  3639. #ifdef VtransformPatch
  3640. static void Parse_VTransform(VECTOR result, unsigned char inverse)
  3641. {
  3642.    MATRIX Local_Matrix;
  3643.    TRANSFORM *New, Local_Trans;
  3644.    VECTOR Local_Vector;
  3645.  VECTOR vect;
  3646.  
  3647.  GET (LEFT_PAREN_TOKEN);
  3648.  Parse_Vector(vect);
  3649.  Parse_Comma();
  3650.  New = Create_Transform();
  3651.  
  3652.    EXPECT
  3653.      CASE(TRANSFORM_ID_TOKEN)
  3654.        Compose_Transforms (New, (TRANSFORM *)Token.Data);
  3655.      END_CASE
  3656.  
  3657.      CASE (TRANSFORM_TOKEN)
  3658. #ifndef TransformPatch /* Chris Huff april 2000 */
  3659.        GET(TRANSFORM_ID_TOKEN)
  3660.        Compose_Transforms(New, (TRANSFORM *)Token.Data);
  3661. #else
  3662.        {
  3663.            TRANSFORM * Trans = Parse_Transform();
  3664.            Compose_Transforms(New, Trans);
  3665.             /*YS sept 17 2000 Memory leak*/
  3666.            POV_FREE(Trans);
  3667.        }
  3668. #endif
  3669.      END_CASE
  3670.  
  3671.      CASE (TRANSLATE_TOKEN)
  3672.        Parse_Vector (Local_Vector);
  3673.        Compute_Translation_Transform(&Local_Trans, Local_Vector);
  3674.        Compose_Transforms (New, &Local_Trans);
  3675.      END_CASE
  3676.  
  3677.      CASE (ROTATE_TOKEN)
  3678.        Parse_Vector (Local_Vector);
  3679.        Compute_Rotation_Transform(&Local_Trans, Local_Vector);
  3680.        Compose_Transforms (New, &Local_Trans);
  3681.      END_CASE
  3682.  
  3683.      CASE (SCALE_TOKEN)
  3684.        Parse_Scale_Vector (Local_Vector);
  3685.        Compute_Scaling_Transform(&Local_Trans, Local_Vector);
  3686.        Compose_Transforms (New, &Local_Trans);
  3687.      END_CASE
  3688.  
  3689.      CASE (MATRIX_TOKEN)
  3690.        Parse_Matrix(Local_Matrix);
  3691.        Compute_Matrix_Transform(&Local_Trans, Local_Matrix);
  3692.        Compose_Transforms (New, &Local_Trans);
  3693.      END_CASE
  3694.  
  3695.      OTHERWISE
  3696.        UNGET
  3697.        EXIT
  3698.      END_CASE
  3699.    END_EXPECT
  3700.  GET (RIGHT_PAREN_TOKEN);
  3701.   if ( inverse==IsInverse)
  3702.     MInvTransPoint(result, vect, New);
  3703.   else /*IsNotInverse*/
  3704.     MTransPoint(result, vect, New);
  3705.  Destroy_Transform(New);
  3706. }
  3707.  
  3708.  
  3709.  
  3710. #endif
  3711.  
  3712.