Simple test for asyncio.library.
[AROS-Contrib.git] / gfx / povray / express.c
blob1f4ef33ea597d3614be2a5cb86158aababa557f7
1 /****************************************************************************
2 * express.c
4 * This module implements an expression parser for the floats, vectors and
5 * colours in scene description files.
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.
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.
23 * Modifications by Thomas Willhalm, March 1999, used with permission
25 *****************************************************************************/
27 #include <ctype.h>
28 #include "frame.h"
29 #include "vector.h"
30 #include "povproto.h"
31 #include "parse.h"
32 #include "parstxtr.h"
33 #include "colour.h"
34 #include "express.h"
35 #include "matrices.h"
36 #include "povray.h"
37 #include "tokenize.h"
38 #include "pattern.h"
39 #include "pigment.h"
40 #include "normal.h"
41 #include "texture.h"
44 /*****************************************************************************
45 * Local preprocessor defines
46 ******************************************************************************/
48 #define ftrue(f) ((int)(fabs(f)>EPSILON))
49 #ifndef FIX_WATCOM_BUG
50 #define FIX_WATCOM_BUG
51 #endif
54 /*****************************************************************************
55 * Local typedefs
56 ******************************************************************************/
60 /*****************************************************************************
61 * Local variables
62 ******************************************************************************/
64 static unsigned int Number_Of_Random_Generators;
65 static unsigned long *next_rand;
68 /*****************************************************************************
69 * Static functions
70 ******************************************************************************/
72 static void Parse_Vector_Param (VECTOR Vector);
73 static void Parse_Vector_Param2 (VECTOR Vect1, VECTOR Vect2);
74 static void Parse_Num_Factor (EXPRESS Express, int *Terms);
75 static void Parse_Num_Term (EXPRESS Express, int *Terms);
76 static void Parse_Rel_Factor (EXPRESS Express, int *Terms);
77 static void Parse_Rel_Term (EXPRESS Express, int *Terms);
78 static void Parse_Logical (EXPRESS Express, int *Terms);
79 static void Parse_Express (EXPRESS Express, int *Terms);
80 static void Promote_Express (EXPRESS Express,int *Old_Terms,int New_Terms);
81 static void POV_strupr (char *s);
82 static void POV_strlwr (char *s);
84 static DBL stream_rand (int stream);
85 static int stream_seed (int seed);
89 /*****************************************************************************
91 * FUNCTION
93 * INPUT
95 * OUTPUT
97 * RETURNS
99 * AUTHOR
101 * DESCRIPTION
103 * CHANGES
105 ******************************************************************************/
107 DBL Parse_Float_Param()
109 DBL Local;
110 EXPRESS Express;
111 int Terms = 1;
113 GET(LEFT_PAREN_TOKEN);
114 Parse_Express(Express,&Terms);
116 if (Terms>1)
118 Error ("Float expected but vector or color expression found.");
121 Local = Express[0];
123 GET(RIGHT_PAREN_TOKEN);
125 return (Local);
130 /*****************************************************************************
132 * FUNCTION
134 * INPUT
136 * OUTPUT
138 * RETURNS
140 * AUTHOR
142 * DESCRIPTION
144 * CHANGES
146 ******************************************************************************/
148 void Parse_Float_Param2(DBL *Val1,DBL *Val2)
150 GET (LEFT_PAREN_TOKEN);
151 *Val1 = Parse_Float();
152 Parse_Comma();
153 *Val2 = Parse_Float();
154 GET (RIGHT_PAREN_TOKEN);
159 /*****************************************************************************
161 * FUNCTION
163 * INPUT
165 * OUTPUT
167 * RETURNS
169 * AUTHOR
171 * DESCRIPTION
173 * CHANGES
175 ******************************************************************************/
177 static void Parse_Vector_Param(VECTOR Vector)
179 GET(LEFT_PAREN_TOKEN);
180 Parse_Vector(Vector);
181 GET(RIGHT_PAREN_TOKEN);
186 /*****************************************************************************
188 * FUNCTION
190 * INPUT
192 * OUTPUT
194 * RETURNS
196 * AUTHOR
198 * DESCRIPTION
200 * CHANGES
202 ******************************************************************************/
204 static void Parse_Vector_Param2(VECTOR Val1,VECTOR Val2)
206 GET (LEFT_PAREN_TOKEN);
207 Parse_Vector(Val1);
208 Parse_Comma();
209 Parse_Vector(Val2);
210 GET (RIGHT_PAREN_TOKEN);
215 /*****************************************************************************
217 * FUNCTION
219 * INPUT
221 * OUTPUT
223 * RETURNS
225 * AUTHOR
227 * DESCRIPTION
229 * CHANGES
231 ******************************************************************************/
233 static void Parse_Num_Factor (EXPRESS Express,int *Terms)
235 int i = 0;
236 DBL Val,Val2;
237 VECTOR Vect,Vect2,Vect3;
238 TRANSFORM Trans;
239 char *Local_String, *Local_String2;
240 FILE *f;
241 POV_ARRAY *a;
242 int Old_Ok=Ok_To_Declare;
244 Ok_To_Declare=TRUE;
246 EXPECT
247 CASE (FLOAT_FUNCT_TOKEN)
248 /* All of these functions return a DBL result */
249 switch(Token.Function_Id)
251 case ABS_TOKEN:
252 Val = Parse_Float_Param();
253 Val = fabs(Val);
254 break;
256 case ACOS_TOKEN:
257 Val = acos(Parse_Float_Param());
258 break;
260 case VAL_TOKEN:
261 GET (LEFT_PAREN_TOKEN);
262 Local_String=Parse_String();
263 Val = atof(Local_String);
264 POV_FREE(Local_String);
265 GET (RIGHT_PAREN_TOKEN);
266 break;
268 case ASC_TOKEN:
269 GET (LEFT_PAREN_TOKEN);
270 Local_String=Parse_String();
271 Val = (DBL)Local_String[0];
272 POV_FREE(Local_String);
273 GET (RIGHT_PAREN_TOKEN);
274 break;
276 case ASIN_TOKEN:
277 Val = asin(Parse_Float_Param());
278 break;
280 case ATAN2_TOKEN:
281 Parse_Float_Param2(&Val,&Val2);
282 if (ftrue(Val) || ftrue(Val2))
284 Val=atan2(Val,Val2);
286 else
288 Error("Domain error in atan2\n");
290 break;
292 case CEIL_TOKEN:
293 Val = ceil(Parse_Float_Param());
294 break;
296 case CLOCK_TOKEN:
297 Val = opts.FrameSeq.Clock_Value;
298 break;
300 case COS_TOKEN:
301 Val = cos(Parse_Float_Param());
302 break;
304 case DEFINED_TOKEN:
305 Val = Parse_Ifdef_Param();
306 break;
308 case DEGREES_TOKEN:
309 Val = Parse_Float_Param()/M_PI_180;
310 break;
312 case DIV_TOKEN:
313 Parse_Float_Param2(&Val,&Val2);
314 Val=(DBL) ( (int)(Val/Val2) );
315 break;
317 case EXP_TOKEN:
318 Val = exp(Parse_Float_Param());
319 break;
321 case FILE_EXISTS_TOKEN:
322 GET (LEFT_PAREN_TOKEN);
323 Local_String=Parse_String();
324 Val = ((f=Locate_File(Local_String,READ_BINFILE_STRING,"","",NULL,FALSE))==NULL) ? 0.0 : 1.0;
325 if (f != NULL)
327 fclose(f);
329 POV_FREE(Local_String);
330 GET (RIGHT_PAREN_TOKEN);
331 break;
333 case FLOAT_ID_TOKEN:
334 Val = *((DBL *) Token.Data);
335 break;
337 case FLOAT_TOKEN:
338 Val = Token.Token_Float;
339 break;
341 case FLOOR_TOKEN:
342 Val = floor(Parse_Float_Param());
343 break;
345 case INT_TOKEN:
346 Val = (DBL) ((int) Parse_Float_Param());
347 break;
349 case LOG_TOKEN:
350 Val = Parse_Float_Param();
351 if (Val<=0.0)
353 Error("Log of negative number %lf\n",Val);
355 else
357 Val = log(Val);
359 break;
361 case MAX_TOKEN:
362 Parse_Float_Param2(&Val,&Val2);
363 Val = max(Val,Val2);
364 break;
366 case MIN_TOKEN:
367 Parse_Float_Param2(&Val,&Val2);
368 Val = min(Val,Val2);
369 break;
371 case MOD_TOKEN:
372 Parse_Float_Param2(&Val,&Val2);
373 Val = fmod(Val,Val2);
374 break;
376 case PI_TOKEN:
377 Val = M_PI;
378 break;
380 case POW_TOKEN:
381 Parse_Float_Param2(&Val,&Val2);
382 Val=pow(Val,Val2);
383 break;
385 case RADIANS_TOKEN:
386 Val = Parse_Float_Param()*M_PI_180;
387 break;
389 case SIN_TOKEN:
390 Val = sin(Parse_Float_Param());
391 break;
393 case SQRT_TOKEN:
394 Val = Parse_Float_Param();
395 if (Val<0.0)
397 Error("sqrt of negative number %lf\n",Val);
399 else
401 Val = sqrt(Val);
403 break;
405 case STRCMP_TOKEN:
406 GET (LEFT_PAREN_TOKEN);
407 Local_String=Parse_String();
408 Parse_Comma();
409 Local_String2=Parse_String();
410 Val = (DBL)strcmp(Local_String,Local_String2);
411 POV_FREE(Local_String);
412 POV_FREE(Local_String2);
413 GET (RIGHT_PAREN_TOKEN);
414 break;
416 case STRLEN_TOKEN:
417 GET (LEFT_PAREN_TOKEN);
418 Local_String=Parse_String();
419 Val = (DBL)strlen(Local_String);
420 POV_FREE(Local_String);
421 GET (RIGHT_PAREN_TOKEN);
422 break;
424 case TAN_TOKEN:
425 Val = tan(Parse_Float_Param());
426 break;
428 case VDOT_TOKEN:
429 Parse_Vector_Param2(Vect,Vect2);
430 VDot(Val,Vect,Vect2);
431 break;
433 case VLENGTH_TOKEN:
434 Parse_Vector_Param(Vect);
435 VLength(Val,Vect);
436 break;
438 case VERSION_TOKEN:
439 Val = opts.Language_Version;
440 break;
442 case TRUE_TOKEN:
443 case YES_TOKEN:
444 case ON_TOKEN:
445 Val = 1.0;
446 break;
448 case FALSE_TOKEN:
449 case NO_TOKEN:
450 case OFF_TOKEN:
451 Val = 0.0;
452 break;
454 case SEED_TOKEN:
455 Val = stream_seed((int)Parse_Float_Param());
456 break;
458 case RAND_TOKEN:
459 i = (int)Parse_Float_Param();
460 if ((i < 0) || (i >= Number_Of_Random_Generators))
462 Error("Illegal random number generator.");
464 Val = stream_rand(i);
465 break;
467 case CLOCK_DELTA_TOKEN:
468 Val = Clock_Delta;
469 break;
471 case DIMENSIONS_TOKEN:
472 GET(LEFT_PAREN_TOKEN)
473 GET(ARRAY_ID_TOKEN)
474 a = (POV_ARRAY *)(*(Token.DataPtr));
475 Val = a->Dims+1;
476 GET(RIGHT_PAREN_TOKEN)
477 break;
479 case DIMENSION_SIZE_TOKEN:
480 GET(LEFT_PAREN_TOKEN)
481 GET(ARRAY_ID_TOKEN)
482 Parse_Comma();
483 a = (POV_ARRAY *)(*(Token.DataPtr));
484 i = (int)Parse_Float()-1.0;
485 if ((i < 0) || (i > a->Dims))
487 Val = 0.0;
489 else
491 Val = a->Sizes[i];
493 GET(RIGHT_PAREN_TOKEN)
494 break;
496 for (i=0; i < *Terms; i++)
497 Express[i]=Val;
498 EXIT
499 END_CASE
501 CASE (VECTOR_FUNCT_TOKEN)
502 /* All of these functions return a VECTOR result */
503 switch(Token.Function_Id)
505 case VAXIS_ROTATE_TOKEN:
506 GET (LEFT_PAREN_TOKEN);
507 Parse_Vector(Vect2);
508 Parse_Comma();
509 Parse_Vector(Vect3);
510 Parse_Comma();
511 Val=Parse_Float()*M_PI_180;
512 GET (RIGHT_PAREN_TOKEN);
513 Compute_Axis_Rotation_Transform(&Trans,Vect3,Val);
514 MTransPoint(Vect, Vect2, &Trans);
515 break;
517 case VCROSS_TOKEN:
518 Parse_Vector_Param2(Vect2,Vect3);
519 VCross(Vect,Vect2,Vect3);
520 break;
522 case VECTOR_ID_TOKEN:
523 Assign_Vector(Vect,Token.Data);
524 break;
526 case VNORMALIZE_TOKEN:
527 Parse_Vector_Param(Vect);
528 VLength(Val,Vect);
529 if (Val==0.0)
531 Make_Vector(Vect,0.0,0.0,0.0);
533 else
535 VInverseScaleEq(Vect,Val);
537 break;
539 case VROTATE_TOKEN:
540 Parse_Vector_Param2(Vect2,Vect3);
541 Compute_Rotation_Transform (&Trans, Vect3);
542 MTransPoint(Vect, Vect2, &Trans);
543 break;
545 case X_TOKEN:
546 Make_Vector(Vect,1.0,0.0,0.0)
547 break;
549 case Y_TOKEN:
550 Make_Vector(Vect,0.0,1.0,0.0)
551 break;
553 case Z_TOKEN:
554 Make_Vector(Vect,0.0,0.0,1.0)
555 break;
558 /* If it was expecting a DBL, promote it to a VECTOR.
559 I haven't yet figured out what to do if it was expecting
560 a COLOUR value with Terms>3
562 if (*Terms==1)
563 *Terms=3;
565 for (i=0; i < 3; i++)
566 Express[i]=Vect[i];
567 EXIT
568 END_CASE
570 CASE (COLOUR_ID_TOKEN)
571 *Terms=5;
572 for (i=0; i<5; i++)
573 Express[i]=(DBL)( ((COLC *)(Token.Data))[i] );
574 EXIT
575 END_CASE
577 CASE (UV_ID_TOKEN)
578 *Terms=2;
579 for (i=0; i<2; i++)
580 Express[i]=(DBL)( ((DBL *)(Token.Data))[i] );
581 EXIT
582 END_CASE
584 CASE (VECTOR_4D_ID_TOKEN)
585 *Terms=4;
586 for (i=0; i<4; i++)
587 Express[i]=(DBL)( ((DBL *)(Token.Data))[i] );
588 EXIT
589 END_CASE
591 CASE (T_TOKEN)
592 *Terms=4;
593 Express[0]=0.0;
594 Express[1]=0.0;
595 Express[2]=0.0;
596 Express[3]=1.0;
597 EXIT
598 END_CASE
600 CASE (U_TOKEN)
601 *Terms=2;
602 Express[0]=1.0;
603 Express[1]=0.0;
604 EXIT
605 END_CASE
607 CASE (V_TOKEN)
608 *Terms=2;
609 Express[0]=0.0;
610 Express[1]=1.0;
611 EXIT
612 END_CASE
614 CASE (PLUS_TOKEN)
615 END_CASE
617 CASE (DASH_TOKEN)
618 Ok_To_Declare=Old_Ok;
619 Parse_Num_Factor(Express,Terms);
620 Old_Ok=Ok_To_Declare;
621 Ok_To_Declare=TRUE;
622 for (i=0; i<*Terms; i++)
623 Express[i]=-Express[i];
624 EXIT
625 END_CASE
627 CASE (EXCLAMATION_TOKEN)
628 Ok_To_Declare=Old_Ok;
629 Parse_Num_Factor(Express,Terms);
630 Old_Ok=Ok_To_Declare;
631 Ok_To_Declare=TRUE;
632 for (i=0; i<*Terms; i++)
633 Express[i] = ftrue(Express[i])?0.0:1.0;
634 EXIT
635 END_CASE
637 CASE (LEFT_PAREN_TOKEN)
638 Parse_Express(Express,Terms);
639 GET(RIGHT_PAREN_TOKEN);
640 EXIT
641 END_CASE
643 /* This case parses a 2, 3, 4, or 5 term vector. First parse 2 terms.
644 Note Parse_Comma won't crash if it doesn't find one.
647 CASE (LEFT_ANGLE_TOKEN)
648 Express[X] = Parse_Float(); Parse_Comma();
649 Express[Y] = Parse_Float(); Parse_Comma();
650 *Terms=2;
652 EXPECT
653 CASE_EXPRESS
654 /* If a 3th float is found, parse it. */
655 Express[2] = Parse_Float(); Parse_Comma();
656 *Terms=3;
657 EXPECT
658 CASE_EXPRESS
659 /* If a 4th float is found, parse it. */
660 Express[3] = Parse_Float(); Parse_Comma();
661 *Terms=4;
662 EXPECT
663 CASE_EXPRESS
664 /* If a 5th float is found, parse it. */
665 Express[4] = Parse_Float();
666 *Terms=5;
667 END_CASE
669 OTHERWISE
670 /* Only 4 found. */
671 UNGET
672 GET (RIGHT_ANGLE_TOKEN)
673 EXIT
674 END_CASE
675 END_EXPECT
676 EXIT
677 END_CASE
679 OTHERWISE
680 /* Only 3 found. */
681 UNGET
682 GET (RIGHT_ANGLE_TOKEN)
683 EXIT
684 END_CASE
685 END_EXPECT
686 EXIT
687 END_CASE
689 OTHERWISE
690 /* Only 2 found. */
691 UNGET
692 GET (RIGHT_ANGLE_TOKEN)
693 EXIT
694 END_CASE
695 END_EXPECT
696 EXIT
697 END_CASE
699 OTHERWISE
700 Parse_Error_Str ("numeric expression");
701 END_CASE
702 END_EXPECT
704 Ok_To_Declare=Old_Ok;
706 /* Parse VECTOR.x or COLOR.red type things */
707 EXPECT
708 CASE(PERIOD_TOKEN)
709 EXPECT
710 CASE (VECTOR_FUNCT_TOKEN)
711 switch(Token.Function_Id)
713 case X_TOKEN:
714 i=X;
715 break;
717 case Y_TOKEN:
718 i=Y;
719 break;
721 case Z_TOKEN:
722 i=Z;
723 break;
725 default:
726 Parse_Error_Str ("x, y, or z");
728 EXIT
729 END_CASE
731 CASE (COLOUR_KEY_TOKEN)
732 switch(Token.Function_Id)
734 case RED_TOKEN:
735 i=RED;
736 break;
738 case GREEN_TOKEN:
739 i=GREEN;
740 break;
742 case BLUE_TOKEN:
743 i=BLUE;
744 break;
746 case FILTER_TOKEN:
747 i=FILTER;
748 break;
750 case TRANSMIT_TOKEN:
751 i=TRANSM;
752 break;
754 default:
755 Parse_Error_Str ("red, green, blue, filter, or transmit");
757 EXIT
758 END_CASE
760 CASE(U_TOKEN)
761 i=U;
762 EXIT
763 END_CASE
765 CASE(V_TOKEN)
766 i=V;
767 EXIT
768 END_CASE
770 CASE(T_TOKEN)
771 i=T;
772 EXIT
773 END_CASE
775 OTHERWISE
776 Parse_Error_Str ("x, y, z or color component");
777 END_CASE
778 END_EXPECT
780 if (i>=*Terms)
782 Error("Bad operands for period operator.");
784 *Terms=1;
785 Express[0]=Express[i];
786 EXIT
787 END_CASE
789 OTHERWISE
790 UNGET
791 EXIT
792 END_CASE
793 END_EXPECT
798 /*****************************************************************************
800 * FUNCTION
802 * INPUT
804 * OUTPUT
806 * RETURNS
808 * AUTHOR
810 * DESCRIPTION
812 * CHANGES
814 ******************************************************************************/
816 /* If first operand of a 2-operand function had more terms than the second,
817 then the parsing of the 2nd operand would have automatically promoted it.
818 But if 2nd operand has more terms then we must go back promote the 1st
819 operand before combining them Promote_Express does it. If Old_Terms=1
820 then set all terms to Express[0]. Otherwise pad extra terms with 0.0.
823 static void Promote_Express(EXPRESS Express,int *Old_Terms,int New_Terms)
825 register int i;
827 if (*Old_Terms >= New_Terms)
828 return;
830 if (*Old_Terms==1)
832 for(i=1;i<New_Terms;i++)
834 Express[i]=Express[0];
837 else
839 for(i=(*Old_Terms);i<New_Terms;i++)
841 Express[i]=0.0;
845 *Old_Terms=New_Terms;
851 /*****************************************************************************
853 * FUNCTION
855 * INPUT
857 * OUTPUT
859 * RETURNS
861 * AUTHOR
863 * DESCRIPTION
865 * CHANGES
867 ******************************************************************************/
869 static void Parse_Num_Term (EXPRESS Express,int *Terms)
871 register int i;
872 EXPRESS Local_Express;
873 int Local_Terms;
875 Parse_Num_Factor(Express,Terms);
877 Local_Terms=*Terms;
879 EXPECT
880 CASE (STAR_TOKEN)
881 Parse_Num_Factor(Local_Express,&Local_Terms);
882 Promote_Express(Express,Terms,Local_Terms);
884 for(i=0;i<*Terms;i++)
885 Express[i] *= Local_Express[i];
886 END_CASE
888 CASE (SLASH_TOKEN)
889 Parse_Num_Factor(Local_Express,&Local_Terms);
890 Promote_Express(Express,Terms,Local_Terms);
892 for(i=0;i<*Terms;i++)
894 if (Local_Express[i]==0.0) /* must be 0.0, not EPSILON */
896 Express[i]=HUGE_VAL;
897 Warn(0.0,"Divide by zero.");
899 else
901 Express[i] /= Local_Express[i];
904 END_CASE
906 OTHERWISE
907 UNGET
908 EXIT
909 END_CASE
910 END_EXPECT
916 /*****************************************************************************
918 * FUNCTION
920 * INPUT
922 * OUTPUT
924 * RETURNS
926 * AUTHOR
928 * DESCRIPTION
930 * CHANGES
932 ******************************************************************************/
934 static void Parse_Rel_Factor (EXPRESS Express,int *Terms)
936 register int i;
937 EXPRESS Local_Express;
938 int Local_Terms;
940 Parse_Num_Term(Express,Terms);
942 Local_Terms=*Terms;
944 EXPECT
945 CASE (PLUS_TOKEN)
946 Parse_Num_Term(Local_Express,&Local_Terms);
947 Promote_Express(Express,Terms,Local_Terms);
949 for(i=0;i<*Terms;i++)
950 Express[i] += Local_Express[i];
951 END_CASE
953 CASE (DASH_TOKEN)
954 Parse_Num_Term(Local_Express,&Local_Terms);
955 Promote_Express(Express,Terms,Local_Terms);
957 for(i=0;i<*Terms;i++)
958 Express[i] -= Local_Express[i];
959 END_CASE
961 OTHERWISE
962 UNGET
963 EXIT
964 END_CASE
965 END_EXPECT
971 /*****************************************************************************
973 * FUNCTION
975 * INPUT
977 * OUTPUT
979 * RETURNS
981 * AUTHOR
983 * DESCRIPTION
985 * CHANGES
987 ******************************************************************************/
989 static void Parse_Rel_Term (EXPRESS Express,int *Terms)
991 register int i;
992 EXPRESS Local_Express;
993 int Local_Terms;
995 Parse_Rel_Factor(Express,Terms);
997 Local_Terms=*Terms;
999 EXPECT
1000 CASE (LEFT_ANGLE_TOKEN)
1001 Parse_Rel_Factor(Local_Express,&Local_Terms);
1002 Promote_Express(Express,Terms,Local_Terms);
1004 for(i=0;i<*Terms;i++)
1005 Express[i] = (DBL)(Express[i] < Local_Express[i]);
1006 END_CASE
1008 CASE (REL_LE_TOKEN)
1009 Parse_Rel_Factor(Local_Express,&Local_Terms);
1010 Promote_Express(Express,Terms,Local_Terms);
1012 for(i=0;i<*Terms;i++)
1013 Express[i] = (DBL)(Express[i] <= Local_Express[i]);
1014 END_CASE
1016 CASE (EQUALS_TOKEN)
1017 Parse_Rel_Factor(Local_Express,&Local_Terms);
1018 Promote_Express(Express,Terms,Local_Terms);
1020 for(i=0;i<*Terms;i++)
1021 Express[i] = (DBL)(!ftrue(Express[i]-Local_Express[i]));
1022 END_CASE
1024 CASE (REL_NE_TOKEN)
1025 Parse_Rel_Factor(Local_Express,&Local_Terms);
1026 Promote_Express(Express,Terms,Local_Terms);
1028 for(i=0;i<*Terms;i++)
1029 Express[i] = (DBL)ftrue(Express[i]-Local_Express[i]);
1030 END_CASE
1032 CASE (REL_GE_TOKEN)
1033 Parse_Rel_Factor(Local_Express,&Local_Terms);
1034 Promote_Express(Express,Terms,Local_Terms);
1036 for(i=0;i<*Terms;i++)
1037 Express[i] = (DBL)(Express[i] >= Local_Express[i]);
1038 END_CASE
1040 CASE (RIGHT_ANGLE_TOKEN)
1041 Parse_Rel_Factor(Local_Express,&Local_Terms);
1042 Promote_Express(Express,Terms,Local_Terms);
1044 for(i=0;i<*Terms;i++)
1045 Express[i] = (DBL)(Express[i] > Local_Express[i]);
1046 END_CASE
1048 OTHERWISE
1049 UNGET
1050 EXIT
1051 END_CASE
1052 END_EXPECT
1058 /*****************************************************************************
1060 * FUNCTION
1062 * INPUT
1064 * OUTPUT
1066 * RETURNS
1068 * AUTHOR
1070 * DESCRIPTION
1072 * CHANGES
1074 ******************************************************************************/
1076 static void Parse_Logical (EXPRESS Express,int *Terms)
1078 register int i;
1079 EXPRESS Local_Express;
1080 int Local_Terms;
1082 Parse_Rel_Term(Express,Terms);
1084 Local_Terms=*Terms;
1086 EXPECT
1087 CASE (AMPERSAND_TOKEN)
1088 Parse_Rel_Term(Local_Express,&Local_Terms);
1089 Promote_Express(Express,Terms,Local_Terms);
1091 for(i=0;i<*Terms;i++)
1092 Express[i] = (DBL)(ftrue(Express[i]) && ftrue(Local_Express[i]));
1093 END_CASE
1095 CASE (BAR_TOKEN)
1096 Parse_Rel_Term(Local_Express,&Local_Terms);
1097 Promote_Express(Express,Terms,Local_Terms);
1099 for(i=0;i<*Terms;i++)
1100 Express[i] = (DBL)(ftrue(Express[i]) || ftrue(Local_Express[i]));
1101 END_CASE
1103 OTHERWISE
1104 UNGET
1105 EXIT
1106 END_CASE
1107 END_EXPECT
1113 /*****************************************************************************
1115 * FUNCTION
1117 * INPUT
1119 * OUTPUT
1121 * RETURNS
1123 * AUTHOR
1125 * DESCRIPTION
1127 * CHANGES
1129 ******************************************************************************/
1131 static void Parse_Express (EXPRESS Express,int *Terms)
1133 EXPRESS Local_Express1, Local_Express2;
1134 EXPRESS *Chosen;
1135 int Local_Terms1, Local_Terms2;
1137 Local_Terms1 = 1;
1139 Parse_Logical(Express,&Local_Terms1);
1141 EXPECT
1142 CASE (QUESTION_TOKEN)
1143 if (Local_Terms1 != 1)
1144 Error("Conditional must evaluate to a float.");
1145 Local_Terms1 = Local_Terms2 = *Terms;
1146 Parse_Express(Local_Express1,&Local_Terms1);
1147 GET(COLON_TOKEN);
1148 Parse_Express(Local_Express2,&Local_Terms2);
1149 if (ftrue(Express[0]))
1151 Chosen = (EXPRESS *)&Local_Express1;
1152 *Terms = Local_Terms1;
1154 else
1156 Chosen = (EXPRESS *)&Local_Express2;
1157 *Terms = Local_Terms2;
1159 memcpy(Express,Chosen,sizeof(EXPRESS));
1160 EXIT
1161 END_CASE
1163 OTHERWISE
1164 /* Not a (c)?a:b expression. Since Express was parsed with
1165 Local_Terms1=1 then we may have to promote this. Suppose
1166 Terms=3 but Local_Terms1=1. If this had been a (c)?a:b
1167 then a float is ok but since it is not a condition then
1168 it must be promoted to Terms=3. Note that the parameters
1169 below look wrong but they are not.
1171 Promote_Express (Express,&Local_Terms1,*Terms);
1172 /* On the other hand, Local_Terms1 may be bigger than Terms.
1173 If so, Express already is promoted and Terms must reflect that.
1175 *Terms=Local_Terms1;
1176 UNGET
1177 EXIT
1178 END_CASE
1179 END_EXPECT
1185 /*****************************************************************************
1187 * FUNCTION
1189 * INPUT
1191 * OUTPUT
1193 * RETURNS
1195 * AUTHOR
1197 * DESCRIPTION
1199 * CHANGES
1201 ******************************************************************************/
1203 DBL Parse_Raw_Number()
1205 int Terms;
1206 DBL Val;
1207 EXPRESS Express;
1209 Terms = 1;
1211 Parse_Num_Factor(Express, &Terms);
1213 Val = Express[0];
1215 if (Terms != 1)
1217 Error("Raw float expected but vector found instead.");
1220 return (Val);
1225 /*****************************************************************************
1227 * FUNCTION
1229 * INPUT
1231 * OUTPUT
1233 * RETURNS
1235 * AUTHOR
1237 * DESCRIPTION
1239 * CHANGES
1241 ******************************************************************************/
1243 DBL Parse_Float ()
1245 EXPRESS Express;
1246 int Terms;
1248 Terms=1;
1250 if (opts.Language_Version < 1.5)
1251 Parse_Num_Factor(Express,&Terms);
1252 else
1253 Parse_Rel_Factor(Express,&Terms);
1255 if (Terms>1)
1256 Error ("Float expected but vector or color expression found.");
1258 return (Express[0]);
1263 /*****************************************************************************
1265 * FUNCTION
1267 * INPUT
1269 * OUTPUT
1271 * RETURNS
1273 * AUTHOR
1275 * DESCRIPTION
1277 * CHANGES
1279 ******************************************************************************/
1281 DBL Allow_Float (DBL defval)
1283 DBL retval;
1285 EXPECT
1286 CASE_EXPRESS
1287 retval = Parse_Float();
1288 EXIT
1289 END_CASE
1291 OTHERWISE
1292 UNGET
1293 retval = defval;
1294 EXIT
1295 END_CASE
1296 END_EXPECT
1298 return (retval);
1303 /*****************************************************************************
1305 * FUNCTION
1307 * INPUT
1309 * OUTPUT
1311 * RETURNS
1313 * AUTHOR
1315 * DESCRIPTION
1317 * CHANGES
1319 ******************************************************************************/
1321 void Parse_Vector (VECTOR Vector)
1323 EXPRESS Express;
1324 int Terms;
1326 /* Initialize expression. [DB 12/94] */
1328 for (Terms = 0; Terms < 5; Terms++)
1330 Express[Terms] = 0.0;
1333 Terms=3;
1335 if (opts.Language_Version < 1.5)
1336 Parse_Num_Factor(Express,&Terms);
1337 else
1338 Parse_Rel_Factor(Express,&Terms);
1340 if (Terms>3)
1341 Error ("Vector expected but color expression found.");
1343 for(Terms=0;Terms<3;Terms++)
1344 Vector[Terms]=Express[Terms];
1348 /*****************************************************************************
1350 * FUNCTION
1352 * INPUT
1354 * OUTPUT
1356 * RETURNS
1358 * AUTHOR
1360 * DESCRIPTION
1362 * CHANGES
1364 ******************************************************************************/
1366 void Parse_Vector4D (VECTOR Vector)
1368 EXPRESS Express;
1369 int Terms;
1370 int Dim = 4;
1371 /* Initialize expression. [DB 12/94] */
1373 for (Terms = 0; Terms < 5; Terms++)
1375 Express[Terms] = 0.0;
1378 Terms=Dim;
1380 if (opts.Language_Version < 1.5)
1381 Parse_Num_Factor(Express,&Terms);
1382 else
1383 Parse_Rel_Factor(Express,&Terms);
1385 if (Terms>Dim)
1386 Error ("Vector expected but color expression found.");
1388 for(Terms=0;Terms<Dim;Terms++)
1389 Vector[Terms]=Express[Terms];
1395 /*****************************************************************************
1397 * FUNCTION
1399 * INPUT
1401 * OUTPUT
1403 * RETURNS
1405 * AUTHOR
1407 * DESCRIPTION
1409 * CHANGES
1411 ******************************************************************************/
1413 void Parse_UV_Vect (UV_VECT UV_Vect)
1415 EXPRESS Express;
1416 int Terms;
1418 /* Initialize expression. [DB 12/94] */
1420 for (Terms = 0; Terms < 5; Terms++)
1422 Express[Terms] = 0.0;
1425 Terms=2;
1427 if (opts.Language_Version < 1.5)
1428 Parse_Num_Factor(Express,&Terms);
1429 else
1430 Parse_Rel_Factor(Express,&Terms);
1432 if (Terms>2)
1433 Error ("UV_Vector expected but vector or color expression found.");
1435 for(Terms=0;Terms<2;Terms++)
1436 UV_Vect[Terms]=Express[Terms];
1441 /*****************************************************************************
1443 * FUNCTION
1445 * INPUT
1447 * OUTPUT
1449 * RETURNS
1451 * AUTHOR
1453 * DESCRIPTION
1455 * CHANGES
1457 ******************************************************************************/
1459 int Parse_Unknown_Vector(EXPRESS Express)
1461 int Terms;
1463 /* Initialize expression. [DB 12/94] */
1465 for (Terms = 0; Terms < 5; Terms++)
1467 Express[Terms] = 0.0;
1470 Terms=1;
1472 if (opts.Language_Version < 1.5)
1474 Parse_Num_Factor(Express,&Terms);
1476 else
1478 Parse_Rel_Factor(Express,&Terms);
1481 return(Terms);
1485 /*****************************************************************************
1487 * FUNCTION
1489 * INPUT
1491 * OUTPUT
1493 * RETURNS
1495 * AUTHOR
1497 * DESCRIPTION
1499 * CHANGES
1501 ******************************************************************************/
1503 void Parse_Scale_Vector (VECTOR Vector)
1505 Parse_Vector(Vector);
1507 if (Vector[X] == 0.0)
1509 Vector[X] = 1.0;
1510 Warn(0.0, "Illegal Value: Scale X by 0.0. Changed to 1.0.");
1512 if (Vector[Y] == 0.0)
1514 Vector[Y] = 1.0;
1515 Warn(0.0, "Illegal Value: Scale Y by 0.0. Changed to 1.0.");
1517 if (Vector[Z] == 0.0)
1519 Vector[Z] = 1.0;
1520 Warn(0.0, "Illegal Value: Scale Z by 0.0. Changed to 1.0.");
1526 /*****************************************************************************
1528 * FUNCTION
1530 * INPUT
1532 * OUTPUT
1534 * RETURNS
1536 * AUTHOR
1538 * DESCRIPTION
1540 * CHANGES
1542 ******************************************************************************/
1544 void Parse_Colour (COLOUR Colour)
1546 EXPRESS Express;
1547 int Terms;
1548 register int i;
1550 /* Initialize expression. [DB 12/94] */
1552 for (Terms = 0; Terms < 5; Terms++)
1554 Express[Terms] = 0.0;
1557 Make_Colour (Colour, 0.0, 0.0, 0.0);
1559 ALLOW(COLOUR_TOKEN)
1561 EXPECT
1562 CASE (COLOUR_KEY_TOKEN)
1563 switch(Token.Function_Id)
1565 case ALPHA_TOKEN:
1566 Warn(1.55, "Keyword ALPHA discontinued. Use FILTER instead.");
1567 /* missing break deliberate */
1569 case FILTER_TOKEN:
1570 Colour[FILTER] = (COLC)Parse_Float();
1571 break;
1573 case BLUE_TOKEN:
1574 Colour[BLUE] = (COLC)Parse_Float();
1575 break;
1577 case GREEN_TOKEN:
1578 Colour[GREEN] = (COLC)Parse_Float();
1579 break;
1581 case RED_TOKEN:
1582 Colour[RED] = (COLC)Parse_Float();
1583 break;
1585 case TRANSMIT_TOKEN:
1586 Colour[TRANSM] = (COLC)Parse_Float();
1587 break;
1589 case RGB_TOKEN:
1590 Terms=3;
1591 Parse_Express(Express,&Terms);
1592 if (Terms != 3)
1593 Warn(0.0, "Suspicious expression after rgb.");
1594 for (i=0;i<Terms;i++)
1595 Colour[i]=(COLC)Express[i];
1596 break;
1598 case RGBF_TOKEN:
1599 Terms=4;
1600 Parse_Express(Express,&Terms);
1601 if (Terms != 4)
1602 Warn(0.0, "Suspicious expression after rgbf.");
1603 for (i=0;i<Terms;i++)
1604 Colour[i]=(COLC)Express[i];
1605 break;
1607 case RGBT_TOKEN:
1608 Terms=4;
1609 Parse_Express(Express,&Terms);
1610 if (Terms != 4)
1611 Warn(0.0, "Suspicious expression after rgbt.");
1612 for (i=0;i<Terms;i++)
1613 Colour[i]=(COLC)Express[i];
1614 Colour[TRANSM]=Colour[FILTER];
1615 Colour[FILTER]=0.0;
1616 break;
1618 case RGBFT_TOKEN:
1619 Terms=5;
1620 Parse_Express(Express,&Terms);
1621 if (Terms != 5)
1622 Warn(0.0, "Suspicious expression after rgbft.");
1623 for (i=0;i<Terms;i++)
1624 Colour[i]=(COLC)Express[i];
1625 break;
1627 END_CASE
1629 CASE (COLOUR_ID_TOKEN)
1630 UNGET
1631 Terms=5;
1632 Parse_Express(Express,&Terms);
1633 for (i=0;i<Terms;i++)
1634 Colour[i]=(COLC)Express[i];
1635 END_CASE
1637 CASE_EXPRESS
1638 UNGET
1639 Terms=5;
1640 Parse_Express(Express,&Terms);
1641 if (Terms != 5)
1642 Error("Color expression expected but float or vector expression found.");
1643 for (i=0;i<Terms;i++)
1644 Colour[i]=(COLC)Express[i];
1645 END_CASE
1647 OTHERWISE
1648 UNGET
1649 EXIT
1650 END_CASE
1651 END_EXPECT
1654 /*****************************************************************************
1656 * FUNCTION
1658 * Parse_Blend_Map
1660 * INPUT
1662 * Type of map to parse: pigment_map, normal_map etc
1664 * OUTPUT
1666 * RETURNS
1668 * Pointer to created blend map
1670 * AUTHOR
1672 * Chris Young 11/94
1674 * DESCRIPTION :
1676 * CHANGES
1678 ******************************************************************************/
1680 BLEND_MAP *Parse_Blend_Map (int Blend_Type,int Pat_Type)
1682 BLEND_MAP *New = NULL;
1683 BLEND_MAP_ENTRY *Temp_Ent;
1684 int i;
1686 Parse_Begin ();
1688 EXPECT
1689 CASE2 (COLOUR_MAP_ID_TOKEN, PIGMENT_MAP_ID_TOKEN)
1690 CASE3 (NORMAL_MAP_ID_TOKEN, TEXTURE_MAP_ID_TOKEN, SLOPE_MAP_ID_TOKEN)
1691 New = Copy_Blend_Map ((BLEND_MAP *) Token.Data);
1692 if (Blend_Type != New->Type)
1694 Error("Wrong identifier type\n");
1696 EXIT
1697 END_CASE
1699 OTHERWISE
1700 UNGET
1701 Temp_Ent = Create_BMap_Entries(MAX_BLEND_MAP_ENTRIES);
1702 i = 0;
1704 EXPECT
1705 CASE (LEFT_SQUARE_TOKEN)
1706 switch (Pat_Type)
1708 case AVERAGE_PATTERN:
1709 Temp_Ent[i].value = Allow_Float(1.0);
1710 Parse_Comma();
1711 break;
1713 default:
1714 Temp_Ent[i].value = Parse_Float();
1715 Parse_Comma();
1716 break;
1719 switch (Blend_Type)
1721 case PIGMENT_TYPE:
1722 Temp_Ent[i].Vals.Pigment=Copy_Pigment(Default_Texture->Pigment);
1723 Parse_Pigment(&(Temp_Ent[i].Vals.Pigment));
1724 break;
1726 case NORMAL_TYPE:
1727 Temp_Ent[i].Vals.Tnormal=Copy_Tnormal(Default_Texture->Tnormal);
1728 Parse_Tnormal(&(Temp_Ent[i].Vals.Tnormal));
1729 break;
1731 case SLOPE_TYPE:
1732 Parse_UV_Vect(Temp_Ent[i].Vals.Point_Slope);
1733 break;
1735 case TEXTURE_TYPE:
1736 Temp_Ent[i].Vals.Texture=Parse_Texture();
1737 break;
1739 case DENSITY_TYPE:
1740 Temp_Ent[i].Vals.Pigment=NULL;
1741 Parse_Media_Density_Pattern (&(Temp_Ent[i].Vals.Pigment));
1742 break;
1744 default:
1745 Error("Type not implemented yet.");
1747 if (++i > MAX_BLEND_MAP_ENTRIES)
1748 Error ("Blend_Map too long");
1750 GET (RIGHT_SQUARE_TOKEN);
1751 END_CASE
1753 OTHERWISE
1754 UNGET
1755 if (i < 1)
1756 Error ("Must have at least one entry in map.");
1757 New = Create_Blend_Map ();
1758 New->Number_Of_Entries = i;
1759 New->Type=Blend_Type;
1760 New->Transparency_Flag=TRUE; /*Temp fix. Really set in Post_???*/
1761 New->Blend_Map_Entries = (BLEND_MAP_ENTRY *)POV_REALLOC(Temp_Ent,sizeof(BLEND_MAP_ENTRY)*i,"blend map entries");
1762 EXIT
1763 END_CASE
1764 END_EXPECT
1765 EXIT
1766 END_CASE
1767 END_EXPECT
1769 Parse_End ();
1771 return (New);
1776 /*****************************************************************************
1778 * FUNCTION
1780 * INPUT
1782 * OUTPUT
1784 * RETURNS
1786 * AUTHOR
1788 * DESCRIPTION
1790 * CHANGES
1792 ******************************************************************************/
1794 BLEND_MAP *Parse_Blend_List (int Count,BLEND_MAP *Def_Map,int Blend_Type)
1796 BLEND_MAP *New;
1797 BLEND_MAP_ENTRY *Temp_Ent;
1798 int Type, i;
1800 i = 0;
1802 if(Blend_Type == PIGMENT_TYPE)
1804 EXPECT
1805 CASE(PIGMENT_TOKEN)
1806 UNGET
1807 Type=PIGMENT_TYPE;
1808 EXIT
1809 END_CASE
1811 OTHERWISE
1812 UNGET
1813 Type=COLOUR_TYPE;
1814 EXIT
1815 END_CASE
1816 END_EXPECT
1818 else
1820 Type=Blend_Type;
1823 Temp_Ent = Create_BMap_Entries(Count);
1825 switch(Type)
1827 case COLOUR_TYPE:
1828 EXPECT
1829 CASE_COLOUR
1830 CASE_EXPRESS
1831 Parse_Colour (Temp_Ent[i].Vals.Colour);
1832 Parse_Comma ();
1833 Temp_Ent[i].value = (SNGL)i;
1834 if (++i >= Count)
1835 EXIT
1836 END_CASE
1838 OTHERWISE
1839 UNGET
1840 EXIT
1841 END_CASE
1842 END_EXPECT
1843 break;
1845 case PIGMENT_TYPE:
1846 EXPECT
1847 CASE(PIGMENT_TOKEN)
1848 Parse_Begin ();
1849 Temp_Ent[i].Vals.Pigment=Copy_Pigment(Default_Texture->Pigment);
1850 Parse_Pigment(&(Temp_Ent[i].Vals.Pigment));
1851 Parse_End ();
1852 Parse_Comma ();
1853 Temp_Ent[i].value = (SNGL)i;
1854 if (++i >= Count)
1855 EXIT
1856 END_CASE
1858 OTHERWISE
1859 UNGET
1860 EXIT
1861 END_CASE
1862 END_EXPECT
1863 break;
1865 case NORMAL_TYPE:
1866 EXPECT
1867 CASE(TNORMAL_TOKEN)
1868 Parse_Begin ();
1869 Temp_Ent[i].Vals.Tnormal=Copy_Tnormal(Default_Texture->Tnormal);
1870 Parse_Tnormal(&(Temp_Ent[i].Vals.Tnormal));
1871 Parse_End ();
1872 Parse_Comma ();
1873 Temp_Ent[i].value = (SNGL)i;
1874 if (++i >= Count)
1875 EXIT
1876 END_CASE
1878 OTHERWISE
1879 UNGET
1880 EXIT
1881 END_CASE
1882 END_EXPECT
1883 break;
1885 case TEXTURE_TYPE:
1886 EXPECT
1887 CASE(TEXTURE_TOKEN)
1888 Parse_Begin ();
1889 Temp_Ent[i].Vals.Texture=Parse_Texture();
1890 Parse_End ();
1891 Parse_Comma ();
1892 Temp_Ent[i].value = (SNGL)i;
1893 if (++i >= Count)
1894 EXIT
1895 END_CASE
1897 OTHERWISE
1898 UNGET
1899 EXIT
1900 END_CASE
1901 END_EXPECT
1902 break;
1904 case DENSITY_TYPE:
1905 EXPECT
1906 CASE(DENSITY_TOKEN)
1907 Parse_Begin ();
1908 Temp_Ent[i].Vals.Pigment=NULL;
1909 Parse_Media_Density_Pattern (&(Temp_Ent[i].Vals.Pigment));
1910 Parse_End ();
1911 Parse_Comma ();
1912 Temp_Ent[i].value = (SNGL)i;
1913 if (++i >= Count)
1914 EXIT
1915 END_CASE
1917 OTHERWISE
1918 UNGET
1919 EXIT
1920 END_CASE
1921 END_EXPECT
1922 break;
1926 if ((Type==NORMAL_TYPE) && (i==0))
1928 POV_FREE(Temp_Ent);
1929 return (NULL);
1932 while (i < Count)
1934 switch (Type)
1936 case COLOUR_TYPE:
1937 Assign_Colour(Temp_Ent[i].Vals.Colour,Def_Map->Blend_Map_Entries[i].Vals.Colour);
1938 break;
1940 case PIGMENT_TYPE:
1941 Temp_Ent[i].Vals.Pigment=Copy_Pigment(Default_Texture->Pigment);
1942 break;
1944 case NORMAL_TYPE:
1945 Temp_Ent[i].Vals.Tnormal=Copy_Tnormal(Default_Texture->Tnormal);
1946 break;
1948 case TEXTURE_TYPE:
1949 Temp_Ent[i].Vals.Texture=Copy_Textures(Default_Texture);
1950 break;
1952 case DENSITY_TYPE:
1953 Temp_Ent[i].Vals.Pigment=NULL;
1954 break;
1957 Temp_Ent[i].value = (SNGL)i;
1958 i++;
1961 New = Create_Blend_Map ();
1962 New->Number_Of_Entries = Count;
1963 New->Type=Type;
1964 New->Transparency_Flag=TRUE; /*Temp fix. Really set in Post_???*/
1965 New->Blend_Map_Entries = Temp_Ent;
1967 return (New);
1971 /*****************************************************************************
1973 * FUNCTION
1975 * Parse_Colour_Map
1977 * INPUT
1979 * OUTPUT
1981 * RETURNS
1983 * Pointer to newly created BLEND_MAP that has colors as all
1984 * its entries.
1986 * AUTHOR
1988 * POV-Ray Team
1990 * DESCRIPTION : This seperate routine parses color_maps only. It
1991 * cannot be used for pigment_maps because it accomidates
1992 * the old double entry color maps from vers 1.0
1994 * CHANGES
1996 ******************************************************************************/
1998 BLEND_MAP *Parse_Colour_Map ()
2000 BLEND_MAP *New = NULL;
2001 int i,j,c,p,ii;
2002 EXPRESS Express;
2003 int Terms;
2004 BLEND_MAP_ENTRY *Temp_Ent;
2006 Parse_Begin ();
2008 EXPECT
2009 CASE (COLOUR_MAP_ID_TOKEN)
2010 New = Copy_Blend_Map ((BLEND_MAP *) Token.Data);
2011 EXIT
2012 END_CASE
2014 OTHERWISE
2015 UNGET
2016 Temp_Ent = Create_BMap_Entries(MAX_BLEND_MAP_ENTRIES);
2017 i = 0;
2018 j = 1;
2020 EXPECT
2021 CASE (LEFT_SQUARE_TOKEN)
2022 Temp_Ent[i].value = Parse_Float(); Parse_Comma();
2024 EXPECT
2025 /* After [ must be a float. If 2nd thing found is another
2026 float then this is an old style color_map.
2028 CASE_FLOAT
2029 Terms=1;
2030 Parse_Express(Express,&Terms);
2031 if (Terms==1)
2033 Temp_Ent[j].value = Express[0];
2034 Parse_Colour (Temp_Ent[i].Vals.Colour);
2036 GET (COLOUR_TOKEN);
2037 Parse_Colour (Temp_Ent[j].Vals.Colour);
2038 i += 2;
2039 j += 2;
2041 else
2042 if (Terms==5)
2044 for (ii=0;ii<5;ii++)
2045 Temp_Ent[i].Vals.Colour[ii]=(COLC)Express[ii];
2046 i++;
2047 j++;
2049 else
2050 Error("Illegal expression syntax in color_map.");
2051 EXIT
2052 END_CASE
2054 CASE_COLOUR
2055 Parse_Colour (Temp_Ent[i].Vals.Colour);
2056 i++;
2057 j++;
2058 EXIT
2059 END_CASE
2061 END_EXPECT
2063 if (j > MAX_BLEND_MAP_ENTRIES)
2064 Error ("Blend_Map too long.");
2066 GET (RIGHT_SQUARE_TOKEN);
2067 END_CASE
2069 OTHERWISE
2070 UNGET
2071 if (i < 1)
2072 Error ("Must have at least one color in color map.");
2074 /* Eliminate duplicates */
2075 for (c = 1, p = 0; c<i; c++)
2077 if (memcmp(&(Temp_Ent[p]),
2078 &(Temp_Ent[c]),sizeof(BLEND_MAP_ENTRY)) == 0)
2079 p--;
2081 Temp_Ent[++p] = Temp_Ent[c];
2083 p++;
2084 New = Create_Blend_Map ();
2085 New->Number_Of_Entries = p;
2086 New->Type=COLOUR_TYPE;
2087 New->Transparency_Flag=TRUE; /*Temp fix. Really set in Post_???*/
2088 New->Blend_Map_Entries = (BLEND_MAP_ENTRY *)POV_REALLOC(Temp_Ent,sizeof(BLEND_MAP_ENTRY)*p,"blend map entries");
2089 EXIT
2090 END_CASE
2091 END_EXPECT
2092 EXIT
2093 END_CASE
2094 END_EXPECT
2096 Parse_End ();
2098 return (New);
2103 /*****************************************************************************
2105 * FUNCTION
2107 * INPUT
2109 * OUTPUT
2111 * RETURNS
2113 * AUTHOR
2115 * DESCRIPTION
2117 * CHANGES
2119 ******************************************************************************/
2121 char *Parse_String()
2123 char *temp1, *temp2, *New = NULL, *p;
2124 char temp3[64];
2125 char temp4[64];
2126 DBL val;
2127 int l,l2,d;
2129 EXPECT
2130 CASE(STRING_LITERAL_TOKEN)
2131 New=(char *)POV_MALLOC(strlen(Token.Token_String) + 1, "temporary string");
2132 strcpy (New, Token.Token_String);
2133 EXIT
2134 END_CASE
2136 CASE(STR_TOKEN)
2137 GET (LEFT_PAREN_TOKEN);
2138 val = Parse_Float();
2139 Parse_Comma();
2140 l = (int)Parse_Float();
2141 Parse_Comma();
2142 d = (int)Parse_Float();
2143 GET (RIGHT_PAREN_TOKEN);
2145 p=temp3;
2146 *(p++) = '%';
2147 if (l>0)
2149 sprintf(p,"%d",l);
2150 while (*(++p));
2151 /* Could also be written for clarity as:
2152 while (*p != '\0')
2153 p++;
2156 else
2158 if (l)
2160 sprintf(p,"0%d",abs(l));
2161 while (*(++p));
2165 if (d>=0)
2167 *(p++) = '.';
2168 sprintf(p,"%d",d);
2169 while (*(++p));
2171 *(p++) = 'f';
2172 *p = '\0';
2174 sprintf(temp4,temp3,val);
2176 FIX_WATCOM_BUG
2178 New=(char *)POV_MALLOC(strlen(temp4) + 1, "temporary string");
2179 strcpy (New, temp4);
2180 EXIT
2181 END_CASE
2183 CASE(CONCAT_TOKEN)
2184 GET (LEFT_PAREN_TOKEN);
2186 New=Parse_String();
2187 EXPECT
2188 CASE(RIGHT_PAREN_TOKEN)
2189 EXIT
2190 END_CASE
2192 OTHERWISE
2193 Parse_Comma();
2194 temp1=New;
2195 temp2=Parse_String();
2196 l2=strlen(temp1)+strlen(temp2)+2;
2197 New=(char *)POV_MALLOC(l2, "temporary string");
2198 strcpy(New,temp1);
2199 strcat(New,temp2);
2200 POV_FREE(temp1);
2201 POV_FREE(temp2);
2202 END_CASE
2203 END_EXPECT
2204 EXIT
2205 END_CASE
2207 CASE(CHR_TOKEN)
2208 New=(char *)POV_MALLOC(2, "temporary string");
2209 d=(int)Parse_Float_Param();
2210 if ((d<0)||(d>255))
2212 Error("Value %d cannot be used in chr(...).\n",d);
2214 New[0]=d;
2215 New[1]='\0';
2216 EXIT
2217 END_CASE
2219 CASE(SUBSTR_TOKEN)
2220 GET (LEFT_PAREN_TOKEN);
2222 temp1=Parse_String();
2223 Parse_Comma();
2224 l=(int)Parse_Float();
2225 Parse_Comma();
2226 d=(int)Parse_Float();
2227 if ((l+d-1) > strlen(temp1))
2229 Error("Illegal params in substr(%s,%d,%d).\n",temp1,l,d);
2231 New=(char *)POV_MALLOC((size_t)(d+1), "temporary string");
2232 strncpy(New,&(temp1[l-1]),(unsigned)d);
2233 New[d]='\0';
2234 POV_FREE(temp1);
2235 GET (RIGHT_PAREN_TOKEN);
2236 EXIT
2237 END_CASE
2239 CASE(STRUPR_TOKEN)
2240 GET (LEFT_PAREN_TOKEN);
2241 New=Parse_String();
2242 POV_strupr(New);
2243 GET (RIGHT_PAREN_TOKEN);
2244 EXIT
2245 END_CASE
2247 CASE(STRLWR_TOKEN)
2248 GET (LEFT_PAREN_TOKEN);
2249 New=Parse_String();
2250 POV_strlwr(New);
2251 GET (RIGHT_PAREN_TOKEN);
2252 EXIT
2253 END_CASE
2255 CASE(STRING_ID_TOKEN)
2256 New=(char *)POV_MALLOC(strlen((char *)Token.Data) + 1, "temporary string");
2257 strcpy (New, (char *)Token.Data);
2258 EXIT
2259 END_CASE
2261 OTHERWISE
2262 Parse_Error_Str ("string expression");
2263 END_CASE
2264 END_EXPECT
2266 return (New);
2271 /*****************************************************************************
2273 * FUNCTION
2275 * INPUT
2277 * OUTPUT
2279 * RETURNS
2281 * AUTHOR
2283 * DESCRIPTION
2285 * CHANGES
2287 ******************************************************************************/
2289 char *Parse_Formatted_String()
2291 char *New, *dest, *src, *temp;
2292 char buff[MAX_STRING_INDEX*2];
2294 dest = &buff[0];
2296 temp = src = Parse_String();
2298 while (*src != '\0')
2300 switch(*src)
2302 case '\\':
2303 switch(*(++src))
2305 case 'a': *dest=0x07; break;
2307 case 'b': *dest=0x08; break;
2309 case 'f': *dest=0x0c; break;
2311 case 'n': *dest=0x0a; break;
2313 case 'r': *dest=0x0d; break;
2315 case 't': *dest=0x09; break;
2317 case 'v': *dest=0x0b; break;
2319 case '\0': *dest=0x5c; break;
2321 case '\'': *dest=0x27; break;
2323 default: *dest='\\'; dest++; *dest=*src; break;
2325 break;
2327 case '%':
2328 *dest=*src; dest++; *dest=*src;
2329 break;
2331 default:
2332 *dest=*src;
2333 break;
2335 src++;
2336 dest++;
2338 *dest='\0';
2340 New=POV_STRDUP(buff);
2341 POV_FREE(temp);
2342 return (New);
2346 /*****************************************************************************
2348 * FUNCTION
2350 * INPUT
2352 * OUTPUT
2354 * RETURNS
2356 * AUTHOR
2358 * DESCRIPTION
2360 * CHANGES
2362 ******************************************************************************/
2364 static void POV_strupr(char *s)
2366 int i;
2368 for (i = 0; i < strlen(s); i++)
2370 s[i] = (char)toupper((int)s[i]);
2376 /*****************************************************************************
2378 * FUNCTION
2380 * INPUT
2382 * OUTPUT
2384 * RETURNS
2386 * AUTHOR
2388 * DESCRIPTION
2390 * CHANGES
2392 ******************************************************************************/
2394 static void POV_strlwr(char *s)
2396 int i;
2398 for (i = 0; i < strlen(s); i++)
2400 s[i] = (char)tolower((int)s[i]);
2405 /*****************************************************************************
2407 * FUNCTION
2409 * stream_rand
2411 * INPUT
2413 * stream - number of random stream
2415 * OUTPUT
2417 * RETURNS
2419 * DBL - random value
2421 * AUTHOR
2423 * Dieter Bayer
2425 * DESCRIPTION
2427 * Standard pseudo-random function.
2429 * CHANGES
2431 * Feb 1996 : Creation.
2432 * Mar 1996 : Return 2^32 random values instead of 2^16 [AED]
2434 ******************************************************************************/
2436 static DBL stream_rand(int stream)
2438 next_rand[stream] = next_rand[stream] * 1812433253L + 12345L;
2440 return((DBL)(next_rand[stream] & 0xFFFFFFFFUL) / 0xFFFFFFFFUL);
2445 /*****************************************************************************
2447 * FUNCTION
2449 * stream_seed
2451 * INPUT
2453 * seed - Pseudo-random generator start value
2455 * OUTPUT
2457 * RETURNS
2459 * AUTHOR
2461 * Dieter Bayer
2463 * DESCRIPTION
2465 * Set start value for pseudo-random generator.
2467 * CHANGES
2469 * Feb 1996 : Creation.
2471 ******************************************************************************/
2473 static int stream_seed(int seed)
2475 next_rand = (unsigned long *)POV_REALLOC(next_rand, (Number_Of_Random_Generators+1)*sizeof(unsigned long), "random number generator");
2477 next_rand[Number_Of_Random_Generators] = (unsigned long int)seed;
2479 Number_Of_Random_Generators++;
2481 return(Number_Of_Random_Generators-1);
2486 /*****************************************************************************
2488 * FUNCTION
2490 * Init_Random_Generators
2492 * INPUT
2494 * OUTPUT
2496 * RETURNS
2498 * AUTHOR
2500 * Dieter Bayer
2502 * DESCRIPTION
2504 * CHANGES
2506 * Feb 1996 : Creation.
2508 ******************************************************************************/
2510 void Init_Random_Generators()
2512 Number_Of_Random_Generators = 0;
2514 next_rand = NULL;
2519 /*****************************************************************************
2521 * FUNCTION
2523 * Destroy_Random_Generators
2525 * INPUT
2527 * OUTPUT
2529 * RETURNS
2531 * AUTHOR
2533 * Dieter Bayer
2535 * DESCRIPTION
2537 * CHANGES
2539 * Feb 1996 : Creation.
2541 ******************************************************************************/
2543 void Destroy_Random_Generators()
2545 if (next_rand != NULL)
2547 POV_FREE(next_rand);
2550 next_rand = NULL;
2552 Number_Of_Random_Generators = 0;
2555 DBL Parse_Signed_Float(void)
2557 DBL Sign=1.0;
2558 DBL Val=0.0; /* tw */
2560 EXPECT
2561 CASE (PLUS_TOKEN)
2562 END_CASE
2564 CASE (DASH_TOKEN)
2565 Sign=-1.0;
2566 Get_Token();
2567 /* Deliberate fall through with no END_CASE */
2568 CASE (FLOAT_FUNCT_TOKEN)
2569 if (Token.Function_Id==FLOAT_TOKEN)
2571 Val = Sign * Token.Token_Float;
2572 EXIT
2574 else
2576 Parse_Error(FLOAT_TOKEN);
2578 END_CASE
2580 OTHERWISE
2581 Parse_Error(FLOAT_TOKEN);
2582 END_CASE
2583 END_EXPECT
2585 return(Val);