1 /****************************************************************************
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 *****************************************************************************/
44 /*****************************************************************************
45 * Local preprocessor defines
46 ******************************************************************************/
48 #define ftrue(f) ((int)(fabs(f)>EPSILON))
49 #ifndef FIX_WATCOM_BUG
50 #define FIX_WATCOM_BUG
54 /*****************************************************************************
56 ******************************************************************************/
60 /*****************************************************************************
62 ******************************************************************************/
64 static unsigned int Number_Of_Random_Generators
;
65 static unsigned long *next_rand
;
68 /*****************************************************************************
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 /*****************************************************************************
105 ******************************************************************************/
107 DBL
Parse_Float_Param()
113 GET(LEFT_PAREN_TOKEN
);
114 Parse_Express(Express
,&Terms
);
118 Error ("Float expected but vector or color expression found.");
123 GET(RIGHT_PAREN_TOKEN
);
130 /*****************************************************************************
146 ******************************************************************************/
148 void Parse_Float_Param2(DBL
*Val1
,DBL
*Val2
)
150 GET (LEFT_PAREN_TOKEN
);
151 *Val1
= Parse_Float();
153 *Val2
= Parse_Float();
154 GET (RIGHT_PAREN_TOKEN
);
159 /*****************************************************************************
175 ******************************************************************************/
177 static void Parse_Vector_Param(VECTOR Vector
)
179 GET(LEFT_PAREN_TOKEN
);
180 Parse_Vector(Vector
);
181 GET(RIGHT_PAREN_TOKEN
);
186 /*****************************************************************************
202 ******************************************************************************/
204 static void Parse_Vector_Param2(VECTOR Val1
,VECTOR Val2
)
206 GET (LEFT_PAREN_TOKEN
);
210 GET (RIGHT_PAREN_TOKEN
);
215 /*****************************************************************************
231 ******************************************************************************/
233 static void Parse_Num_Factor (EXPRESS Express
,int *Terms
)
237 VECTOR Vect
,Vect2
,Vect3
;
239 char *Local_String
, *Local_String2
;
242 int Old_Ok
=Ok_To_Declare
;
247 CASE (FLOAT_FUNCT_TOKEN
)
248 /* All of these functions return a DBL result */
249 switch(Token
.Function_Id
)
252 Val
= Parse_Float_Param();
257 Val
= acos(Parse_Float_Param());
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
);
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
);
277 Val
= asin(Parse_Float_Param());
281 Parse_Float_Param2(&Val
,&Val2
);
282 if (ftrue(Val
) || ftrue(Val2
))
288 Error("Domain error in atan2\n");
293 Val
= ceil(Parse_Float_Param());
297 Val
= opts
.FrameSeq
.Clock_Value
;
301 Val
= cos(Parse_Float_Param());
305 Val
= Parse_Ifdef_Param();
309 Val
= Parse_Float_Param()/M_PI_180
;
313 Parse_Float_Param2(&Val
,&Val2
);
314 Val
=(DBL
) ( (int)(Val
/Val2
) );
318 Val
= exp(Parse_Float_Param());
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;
329 POV_FREE(Local_String
);
330 GET (RIGHT_PAREN_TOKEN
);
334 Val
= *((DBL
*) Token
.Data
);
338 Val
= Token
.Token_Float
;
342 Val
= floor(Parse_Float_Param());
346 Val
= (DBL
) ((int) Parse_Float_Param());
350 Val
= Parse_Float_Param();
353 Error("Log of negative number %lf\n",Val
);
362 Parse_Float_Param2(&Val
,&Val2
);
367 Parse_Float_Param2(&Val
,&Val2
);
372 Parse_Float_Param2(&Val
,&Val2
);
373 Val
= fmod(Val
,Val2
);
381 Parse_Float_Param2(&Val
,&Val2
);
386 Val
= Parse_Float_Param()*M_PI_180
;
390 Val
= sin(Parse_Float_Param());
394 Val
= Parse_Float_Param();
397 Error("sqrt of negative number %lf\n",Val
);
406 GET (LEFT_PAREN_TOKEN
);
407 Local_String
=Parse_String();
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
);
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
);
425 Val
= tan(Parse_Float_Param());
429 Parse_Vector_Param2(Vect
,Vect2
);
430 VDot(Val
,Vect
,Vect2
);
434 Parse_Vector_Param(Vect
);
439 Val
= opts
.Language_Version
;
455 Val
= stream_seed((int)Parse_Float_Param());
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
);
467 case CLOCK_DELTA_TOKEN
:
471 case DIMENSIONS_TOKEN
:
472 GET(LEFT_PAREN_TOKEN
)
474 a
= (POV_ARRAY
*)(*(Token
.DataPtr
));
476 GET(RIGHT_PAREN_TOKEN
)
479 case DIMENSION_SIZE_TOKEN
:
480 GET(LEFT_PAREN_TOKEN
)
483 a
= (POV_ARRAY
*)(*(Token
.DataPtr
));
484 i
= (int)Parse_Float()-1.0;
485 if ((i
< 0) || (i
> a
->Dims
))
493 GET(RIGHT_PAREN_TOKEN
)
496 for (i
=0; i
< *Terms
; i
++)
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
);
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
);
518 Parse_Vector_Param2(Vect2
,Vect3
);
519 VCross(Vect
,Vect2
,Vect3
);
522 case VECTOR_ID_TOKEN
:
523 Assign_Vector(Vect
,Token
.Data
);
526 case VNORMALIZE_TOKEN
:
527 Parse_Vector_Param(Vect
);
531 Make_Vector(Vect
,0.0,0.0,0.0);
535 VInverseScaleEq(Vect
,Val
);
540 Parse_Vector_Param2(Vect2
,Vect3
);
541 Compute_Rotation_Transform (&Trans
, Vect3
);
542 MTransPoint(Vect
, Vect2
, &Trans
);
546 Make_Vector(Vect
,1.0,0.0,0.0)
550 Make_Vector(Vect
,0.0,1.0,0.0)
554 Make_Vector(Vect
,0.0,0.0,1.0)
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
565 for (i
=0; i
< 3; i
++)
570 CASE (COLOUR_ID_TOKEN
)
573 Express
[i
]=(DBL
)( ((COLC
*)(Token
.Data
))[i
] );
580 Express
[i
]=(DBL
)( ((DBL
*)(Token
.Data
))[i
] );
584 CASE (VECTOR_4D_ID_TOKEN
)
587 Express
[i
]=(DBL
)( ((DBL
*)(Token
.Data
))[i
] );
618 Ok_To_Declare
=Old_Ok
;
619 Parse_Num_Factor(Express
,Terms
);
620 Old_Ok
=Ok_To_Declare
;
622 for (i
=0; i
<*Terms
; i
++)
623 Express
[i
]=-Express
[i
];
627 CASE (EXCLAMATION_TOKEN
)
628 Ok_To_Declare
=Old_Ok
;
629 Parse_Num_Factor(Express
,Terms
);
630 Old_Ok
=Ok_To_Declare
;
632 for (i
=0; i
<*Terms
; i
++)
633 Express
[i
] = ftrue(Express
[i
])?0.0:1.0;
637 CASE (LEFT_PAREN_TOKEN
)
638 Parse_Express(Express
,Terms
);
639 GET(RIGHT_PAREN_TOKEN
);
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();
654 /* If a 3th float is found, parse it. */
655 Express
[2] = Parse_Float(); Parse_Comma();
659 /* If a 4th float is found, parse it. */
660 Express
[3] = Parse_Float(); Parse_Comma();
664 /* If a 5th float is found, parse it. */
665 Express
[4] = Parse_Float();
672 GET (RIGHT_ANGLE_TOKEN
)
682 GET (RIGHT_ANGLE_TOKEN
)
692 GET (RIGHT_ANGLE_TOKEN
)
700 Parse_Error_Str ("numeric expression");
704 Ok_To_Declare
=Old_Ok
;
706 /* Parse VECTOR.x or COLOR.red type things */
710 CASE (VECTOR_FUNCT_TOKEN
)
711 switch(Token
.Function_Id
)
726 Parse_Error_Str ("x, y, or z");
731 CASE (COLOUR_KEY_TOKEN
)
732 switch(Token
.Function_Id
)
755 Parse_Error_Str ("red, green, blue, filter, or transmit");
776 Parse_Error_Str ("x, y, z or color component");
782 Error("Bad operands for period operator.");
785 Express
[0]=Express
[i
];
798 /*****************************************************************************
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
)
827 if (*Old_Terms
>= New_Terms
)
832 for(i
=1;i
<New_Terms
;i
++)
834 Express
[i
]=Express
[0];
839 for(i
=(*Old_Terms
);i
<New_Terms
;i
++)
845 *Old_Terms
=New_Terms
;
851 /*****************************************************************************
867 ******************************************************************************/
869 static void Parse_Num_Term (EXPRESS Express
,int *Terms
)
872 EXPRESS Local_Express
;
875 Parse_Num_Factor(Express
,Terms
);
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
];
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 */
897 Warn(0.0,"Divide by zero.");
901 Express
[i
] /= Local_Express
[i
];
916 /*****************************************************************************
932 ******************************************************************************/
934 static void Parse_Rel_Factor (EXPRESS Express
,int *Terms
)
937 EXPRESS Local_Express
;
940 Parse_Num_Term(Express
,Terms
);
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
];
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
];
971 /*****************************************************************************
987 ******************************************************************************/
989 static void Parse_Rel_Term (EXPRESS Express
,int *Terms
)
992 EXPRESS Local_Express
;
995 Parse_Rel_Factor(Express
,Terms
);
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
]);
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
]);
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
]));
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
]);
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
]);
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
]);
1058 /*****************************************************************************
1074 ******************************************************************************/
1076 static void Parse_Logical (EXPRESS Express
,int *Terms
)
1079 EXPRESS Local_Express
;
1082 Parse_Rel_Term(Express
,Terms
);
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
]));
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
]));
1113 /*****************************************************************************
1129 ******************************************************************************/
1131 static void Parse_Express (EXPRESS Express
,int *Terms
)
1133 EXPRESS Local_Express1
, Local_Express2
;
1135 int Local_Terms1
, Local_Terms2
;
1139 Parse_Logical(Express
,&Local_Terms1
);
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
);
1148 Parse_Express(Local_Express2
,&Local_Terms2
);
1149 if (ftrue(Express
[0]))
1151 Chosen
= (EXPRESS
*)&Local_Express1
;
1152 *Terms
= Local_Terms1
;
1156 Chosen
= (EXPRESS
*)&Local_Express2
;
1157 *Terms
= Local_Terms2
;
1159 memcpy(Express
,Chosen
,sizeof(EXPRESS
));
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
;
1185 /*****************************************************************************
1201 ******************************************************************************/
1203 DBL
Parse_Raw_Number()
1211 Parse_Num_Factor(Express
, &Terms
);
1217 Error("Raw float expected but vector found instead.");
1225 /*****************************************************************************
1241 ******************************************************************************/
1250 if (opts
.Language_Version
< 1.5)
1251 Parse_Num_Factor(Express
,&Terms
);
1253 Parse_Rel_Factor(Express
,&Terms
);
1256 Error ("Float expected but vector or color expression found.");
1258 return (Express
[0]);
1263 /*****************************************************************************
1279 ******************************************************************************/
1281 DBL
Allow_Float (DBL defval
)
1287 retval
= Parse_Float();
1303 /*****************************************************************************
1319 ******************************************************************************/
1321 void Parse_Vector (VECTOR Vector
)
1326 /* Initialize expression. [DB 12/94] */
1328 for (Terms
= 0; Terms
< 5; Terms
++)
1330 Express
[Terms
] = 0.0;
1335 if (opts
.Language_Version
< 1.5)
1336 Parse_Num_Factor(Express
,&Terms
);
1338 Parse_Rel_Factor(Express
,&Terms
);
1341 Error ("Vector expected but color expression found.");
1343 for(Terms
=0;Terms
<3;Terms
++)
1344 Vector
[Terms
]=Express
[Terms
];
1348 /*****************************************************************************
1364 ******************************************************************************/
1366 void Parse_Vector4D (VECTOR Vector
)
1371 /* Initialize expression. [DB 12/94] */
1373 for (Terms
= 0; Terms
< 5; Terms
++)
1375 Express
[Terms
] = 0.0;
1380 if (opts
.Language_Version
< 1.5)
1381 Parse_Num_Factor(Express
,&Terms
);
1383 Parse_Rel_Factor(Express
,&Terms
);
1386 Error ("Vector expected but color expression found.");
1388 for(Terms
=0;Terms
<Dim
;Terms
++)
1389 Vector
[Terms
]=Express
[Terms
];
1395 /*****************************************************************************
1411 ******************************************************************************/
1413 void Parse_UV_Vect (UV_VECT UV_Vect
)
1418 /* Initialize expression. [DB 12/94] */
1420 for (Terms
= 0; Terms
< 5; Terms
++)
1422 Express
[Terms
] = 0.0;
1427 if (opts
.Language_Version
< 1.5)
1428 Parse_Num_Factor(Express
,&Terms
);
1430 Parse_Rel_Factor(Express
,&Terms
);
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 /*****************************************************************************
1457 ******************************************************************************/
1459 int Parse_Unknown_Vector(EXPRESS Express
)
1463 /* Initialize expression. [DB 12/94] */
1465 for (Terms
= 0; Terms
< 5; Terms
++)
1467 Express
[Terms
] = 0.0;
1472 if (opts
.Language_Version
< 1.5)
1474 Parse_Num_Factor(Express
,&Terms
);
1478 Parse_Rel_Factor(Express
,&Terms
);
1485 /*****************************************************************************
1501 ******************************************************************************/
1503 void Parse_Scale_Vector (VECTOR Vector
)
1505 Parse_Vector(Vector
);
1507 if (Vector
[X
] == 0.0)
1510 Warn(0.0, "Illegal Value: Scale X by 0.0. Changed to 1.0.");
1512 if (Vector
[Y
] == 0.0)
1515 Warn(0.0, "Illegal Value: Scale Y by 0.0. Changed to 1.0.");
1517 if (Vector
[Z
] == 0.0)
1520 Warn(0.0, "Illegal Value: Scale Z by 0.0. Changed to 1.0.");
1526 /*****************************************************************************
1542 ******************************************************************************/
1544 void Parse_Colour (COLOUR Colour
)
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);
1562 CASE (COLOUR_KEY_TOKEN
)
1563 switch(Token
.Function_Id
)
1566 Warn(1.55, "Keyword ALPHA discontinued. Use FILTER instead.");
1567 /* missing break deliberate */
1570 Colour
[FILTER
] = (COLC
)Parse_Float();
1574 Colour
[BLUE
] = (COLC
)Parse_Float();
1578 Colour
[GREEN
] = (COLC
)Parse_Float();
1582 Colour
[RED
] = (COLC
)Parse_Float();
1585 case TRANSMIT_TOKEN
:
1586 Colour
[TRANSM
] = (COLC
)Parse_Float();
1591 Parse_Express(Express
,&Terms
);
1593 Warn(0.0, "Suspicious expression after rgb.");
1594 for (i
=0;i
<Terms
;i
++)
1595 Colour
[i
]=(COLC
)Express
[i
];
1600 Parse_Express(Express
,&Terms
);
1602 Warn(0.0, "Suspicious expression after rgbf.");
1603 for (i
=0;i
<Terms
;i
++)
1604 Colour
[i
]=(COLC
)Express
[i
];
1609 Parse_Express(Express
,&Terms
);
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
];
1620 Parse_Express(Express
,&Terms
);
1622 Warn(0.0, "Suspicious expression after rgbft.");
1623 for (i
=0;i
<Terms
;i
++)
1624 Colour
[i
]=(COLC
)Express
[i
];
1629 CASE (COLOUR_ID_TOKEN
)
1632 Parse_Express(Express
,&Terms
);
1633 for (i
=0;i
<Terms
;i
++)
1634 Colour
[i
]=(COLC
)Express
[i
];
1640 Parse_Express(Express
,&Terms
);
1642 Error("Color expression expected but float or vector expression found.");
1643 for (i
=0;i
<Terms
;i
++)
1644 Colour
[i
]=(COLC
)Express
[i
];
1654 /*****************************************************************************
1662 * Type of map to parse: pigment_map, normal_map etc
1668 * Pointer to created blend map
1678 ******************************************************************************/
1680 BLEND_MAP
*Parse_Blend_Map (int Blend_Type
,int Pat_Type
)
1682 BLEND_MAP
*New
= NULL
;
1683 BLEND_MAP_ENTRY
*Temp_Ent
;
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");
1701 Temp_Ent
= Create_BMap_Entries(MAX_BLEND_MAP_ENTRIES
);
1705 CASE (LEFT_SQUARE_TOKEN
)
1708 case AVERAGE_PATTERN
:
1709 Temp_Ent
[i
].value
= Allow_Float(1.0);
1714 Temp_Ent
[i
].value
= Parse_Float();
1722 Temp_Ent
[i
].Vals
.Pigment
=Copy_Pigment(Default_Texture
->Pigment
);
1723 Parse_Pigment(&(Temp_Ent
[i
].Vals
.Pigment
));
1727 Temp_Ent
[i
].Vals
.Tnormal
=Copy_Tnormal(Default_Texture
->Tnormal
);
1728 Parse_Tnormal(&(Temp_Ent
[i
].Vals
.Tnormal
));
1732 Parse_UV_Vect(Temp_Ent
[i
].Vals
.Point_Slope
);
1736 Temp_Ent
[i
].Vals
.Texture
=Parse_Texture();
1740 Temp_Ent
[i
].Vals
.Pigment
=NULL
;
1741 Parse_Media_Density_Pattern (&(Temp_Ent
[i
].Vals
.Pigment
));
1745 Error("Type not implemented yet.");
1747 if (++i
> MAX_BLEND_MAP_ENTRIES
)
1748 Error ("Blend_Map too long");
1750 GET (RIGHT_SQUARE_TOKEN
);
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");
1776 /*****************************************************************************
1792 ******************************************************************************/
1794 BLEND_MAP
*Parse_Blend_List (int Count
,BLEND_MAP
*Def_Map
,int Blend_Type
)
1797 BLEND_MAP_ENTRY
*Temp_Ent
;
1802 if(Blend_Type
== PIGMENT_TYPE
)
1823 Temp_Ent
= Create_BMap_Entries(Count
);
1831 Parse_Colour (Temp_Ent
[i
].Vals
.Colour
);
1833 Temp_Ent
[i
].value
= (SNGL
)i
;
1849 Temp_Ent
[i
].Vals
.Pigment
=Copy_Pigment(Default_Texture
->Pigment
);
1850 Parse_Pigment(&(Temp_Ent
[i
].Vals
.Pigment
));
1853 Temp_Ent
[i
].value
= (SNGL
)i
;
1869 Temp_Ent
[i
].Vals
.Tnormal
=Copy_Tnormal(Default_Texture
->Tnormal
);
1870 Parse_Tnormal(&(Temp_Ent
[i
].Vals
.Tnormal
));
1873 Temp_Ent
[i
].value
= (SNGL
)i
;
1889 Temp_Ent
[i
].Vals
.Texture
=Parse_Texture();
1892 Temp_Ent
[i
].value
= (SNGL
)i
;
1908 Temp_Ent
[i
].Vals
.Pigment
=NULL
;
1909 Parse_Media_Density_Pattern (&(Temp_Ent
[i
].Vals
.Pigment
));
1912 Temp_Ent
[i
].value
= (SNGL
)i
;
1926 if ((Type
==NORMAL_TYPE
) && (i
==0))
1937 Assign_Colour(Temp_Ent
[i
].Vals
.Colour
,Def_Map
->Blend_Map_Entries
[i
].Vals
.Colour
);
1941 Temp_Ent
[i
].Vals
.Pigment
=Copy_Pigment(Default_Texture
->Pigment
);
1945 Temp_Ent
[i
].Vals
.Tnormal
=Copy_Tnormal(Default_Texture
->Tnormal
);
1949 Temp_Ent
[i
].Vals
.Texture
=Copy_Textures(Default_Texture
);
1953 Temp_Ent
[i
].Vals
.Pigment
=NULL
;
1957 Temp_Ent
[i
].value
= (SNGL
)i
;
1961 New
= Create_Blend_Map ();
1962 New
->Number_Of_Entries
= Count
;
1964 New
->Transparency_Flag
=TRUE
; /*Temp fix. Really set in Post_???*/
1965 New
->Blend_Map_Entries
= Temp_Ent
;
1971 /*****************************************************************************
1983 * Pointer to newly created BLEND_MAP that has colors as all
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
1996 ******************************************************************************/
1998 BLEND_MAP
*Parse_Colour_Map ()
2000 BLEND_MAP
*New
= NULL
;
2004 BLEND_MAP_ENTRY
*Temp_Ent
;
2009 CASE (COLOUR_MAP_ID_TOKEN
)
2010 New
= Copy_Blend_Map ((BLEND_MAP
*) Token
.Data
);
2016 Temp_Ent
= Create_BMap_Entries(MAX_BLEND_MAP_ENTRIES
);
2021 CASE (LEFT_SQUARE_TOKEN
)
2022 Temp_Ent
[i
].value
= Parse_Float(); Parse_Comma();
2025 /* After [ must be a float. If 2nd thing found is another
2026 float then this is an old style color_map.
2030 Parse_Express(Express
,&Terms
);
2033 Temp_Ent
[j
].value
= Express
[0];
2034 Parse_Colour (Temp_Ent
[i
].Vals
.Colour
);
2037 Parse_Colour (Temp_Ent
[j
].Vals
.Colour
);
2044 for (ii
=0;ii
<5;ii
++)
2045 Temp_Ent
[i
].Vals
.Colour
[ii
]=(COLC
)Express
[ii
];
2050 Error("Illegal expression syntax in color_map.");
2055 Parse_Colour (Temp_Ent
[i
].Vals
.Colour
);
2063 if (j
> MAX_BLEND_MAP_ENTRIES
)
2064 Error ("Blend_Map too long.");
2066 GET (RIGHT_SQUARE_TOKEN
);
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)
2081 Temp_Ent
[++p
] = Temp_Ent
[c
];
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");
2103 /*****************************************************************************
2119 ******************************************************************************/
2121 char *Parse_String()
2123 char *temp1
, *temp2
, *New
= NULL
, *p
;
2130 CASE(STRING_LITERAL_TOKEN
)
2131 New
=(char *)POV_MALLOC(strlen(Token
.Token_String
) + 1, "temporary string");
2132 strcpy (New
, Token
.Token_String
);
2137 GET (LEFT_PAREN_TOKEN
);
2138 val
= Parse_Float();
2140 l
= (int)Parse_Float();
2142 d
= (int)Parse_Float();
2143 GET (RIGHT_PAREN_TOKEN
);
2151 /* Could also be written for clarity as:
2160 sprintf(p
,"0%d",abs(l
));
2174 sprintf(temp4
,temp3
,val
);
2178 New
=(char *)POV_MALLOC(strlen(temp4
) + 1, "temporary string");
2179 strcpy (New
, temp4
);
2184 GET (LEFT_PAREN_TOKEN
);
2188 CASE(RIGHT_PAREN_TOKEN
)
2195 temp2
=Parse_String();
2196 l2
=strlen(temp1
)+strlen(temp2
)+2;
2197 New
=(char *)POV_MALLOC(l2
, "temporary string");
2208 New
=(char *)POV_MALLOC(2, "temporary string");
2209 d
=(int)Parse_Float_Param();
2212 Error("Value %d cannot be used in chr(...).\n",d
);
2220 GET (LEFT_PAREN_TOKEN
);
2222 temp1
=Parse_String();
2224 l
=(int)Parse_Float();
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
);
2235 GET (RIGHT_PAREN_TOKEN
);
2240 GET (LEFT_PAREN_TOKEN
);
2243 GET (RIGHT_PAREN_TOKEN
);
2248 GET (LEFT_PAREN_TOKEN
);
2251 GET (RIGHT_PAREN_TOKEN
);
2255 CASE(STRING_ID_TOKEN
)
2256 New
=(char *)POV_MALLOC(strlen((char *)Token
.Data
) + 1, "temporary string");
2257 strcpy (New
, (char *)Token
.Data
);
2262 Parse_Error_Str ("string expression");
2271 /*****************************************************************************
2287 ******************************************************************************/
2289 char *Parse_Formatted_String()
2291 char *New
, *dest
, *src
, *temp
;
2292 char buff
[MAX_STRING_INDEX
*2];
2296 temp
= src
= Parse_String();
2298 while (*src
!= '\0')
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;
2328 *dest
=*src
; dest
++; *dest
=*src
;
2340 New
=POV_STRDUP(buff
);
2346 /*****************************************************************************
2362 ******************************************************************************/
2364 static void POV_strupr(char *s
)
2368 for (i
= 0; i
< strlen(s
); i
++)
2370 s
[i
] = (char)toupper((int)s
[i
]);
2376 /*****************************************************************************
2392 ******************************************************************************/
2394 static void POV_strlwr(char *s
)
2398 for (i
= 0; i
< strlen(s
); i
++)
2400 s
[i
] = (char)tolower((int)s
[i
]);
2405 /*****************************************************************************
2413 * stream - number of random stream
2419 * DBL - random value
2427 * Standard pseudo-random function.
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 /*****************************************************************************
2453 * seed - Pseudo-random generator start value
2465 * Set start value for pseudo-random generator.
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 /*****************************************************************************
2490 * Init_Random_Generators
2506 * Feb 1996 : Creation.
2508 ******************************************************************************/
2510 void Init_Random_Generators()
2512 Number_Of_Random_Generators
= 0;
2519 /*****************************************************************************
2523 * Destroy_Random_Generators
2539 * Feb 1996 : Creation.
2541 ******************************************************************************/
2543 void Destroy_Random_Generators()
2545 if (next_rand
!= NULL
)
2547 POV_FREE(next_rand
);
2552 Number_Of_Random_Generators
= 0;
2555 DBL
Parse_Signed_Float(void)
2558 DBL Val
=0.0; /* tw */
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
;
2576 Parse_Error(FLOAT_TOKEN
);
2581 Parse_Error(FLOAT_TOKEN
);