1 /****************************************************************************
4 * This module contains functions for ini-file/command line parsing, streams.
6 * from Persistence of Vision(tm) Ray Tracer
7 * Copyright 1996,1999 Persistence of Vision Team
8 *---------------------------------------------------------------------------
9 * NOTICE: This source code file is provided so that users may experiment
10 * with enhancements to POV-Ray and to port the software to platforms other
11 * than those supported by the POV-Ray Team. There are strict rules under
12 * which you are permitted to use this file. The rules are in the file
13 * named POVLEGAL.DOC which should be distributed with this file.
14 * If POVLEGAL.DOC is not available or for more info please contact the POV-Ray
15 * Team Coordinator by email to team-coord@povray.org or visit us on the web at
16 * http://www.povray.org. The latest version of POV-Ray may be found at this site.
18 * This program is based on the popular DKB raytracer version 2.12.
19 * DKBTrace was originally written by David K. Buck.
20 * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
22 *****************************************************************************/
24 /****************************************************************************
26 * This file contains the routines to implement an .INI file parser that can
27 * parse options in the form "Variable=value" or traditional POV-Ray
28 * command-line switches. Values can come from POVRAYOPT, command-line,
31 * Written by CEY 4/94 based on existing code and INI code from CDW.
35 * Modification by Thomas Willhalm, March 1999, used with permission.
37 *****************************************************************************/
45 #include "mem.h" /*POV_FREE*/
62 /*****************************************************************************
63 * Local preprocessor defines
64 ******************************************************************************/
67 /*****************************************************************************
69 ******************************************************************************/
73 /*****************************************************************************
75 ******************************************************************************/
89 /* Quality constants */
91 long Quality_Values
[12]=
93 QUALITY_0
, QUALITY_1
, QUALITY_2
, QUALITY_3
, QUALITY_4
,
94 QUALITY_5
, QUALITY_6
, QUALITY_7
, QUALITY_8
, QUALITY_9
97 /* Keywords for the ini-file parser. */
99 struct Reserved_Word_Struct Option_Variable
[] =
101 { ALL_CONSOLE_OP
, "All_Console" },
102 { ALL_FILE_OP
, "All_File" },
103 { ANTIALIAS_DEPTH_OP
, "Antialias_Depth" },
104 { ANTIALIAS_OP
, "Antialias" },
105 { ANTIALIAS_THRESH_OP
, "Antialias_Threshold" },
106 { BOUNDING_OP
, "Bounding" },
107 { BOUNDING_THRESH_OP
, "Bounding_Threshold" },
108 { BUFFERED_OUTPUT_OP
,"Buffer_Output" },
109 { BUF_SIZE_OP
, "Buffer_Size" },
110 { CLOCK_OP
, "Clock" },
112 { CONTINUE_OP
, "Continue_Trace" },
113 { CREATE_INI_OP
, "Create_Ini" },
114 { CYCLIC_ANIMATION_OP
, "Cyclic_Animation" },
115 { DEBUG_CONSOLE_OP
, "Debug_Console" },
116 { DEBUG_FILE_OP
, "Debug_File" },
117 { DISPLAY_OP
, "Display" },
118 { DISPLAY_GAMMA_OP
, "Display_Gamma" },
119 { DRAW_VISTAS_OP
, "Draw_Vistas" },
120 { END_COLUMN_OP
, "End_Column" },
121 { END_ROW_OP
, "End_Row" },
122 { FATAL_CONSOLE_OP
, "Fatal_Console" },
124 { FATAL_ERROR_CMD_OP
, "Fatal_Error_Command" },
125 { FATAL_ERROR_RET_OP
, "Fatal_Error_Return" },
126 { FATAL_FILE_OP
, "Fatal_File" },
127 { FIELD_RENDER_OP
, "Field_Render" },
128 { FILE_OUTPUT_OP
, "Output_to_File" },
129 { FILE_OUTPUT_TYPE_OP
, "Output_File_Type" },
130 { FINAL_CLOCK_OP
, "Final_Clock" },
131 { FINAL_FRAME_OP
, "Final_Frame" },
132 { HEIGHT_OP
, "Height" },
133 { HIST_NAME_OP
, "Histogram_Name" },
135 { HIST_SIZE_OP
, "Histogram_Grid_Size" },
136 { HIST_TYPE_OP
, "Histogram_Type" },
137 { INITIAL_CLOCK_OP
, "Initial_Clock" },
138 { INITIAL_FRAME_OP
, "Initial_Frame" },
139 { INPUT_FILE_NAME_OP
, "Input_File_Name" },
140 { JITTER_AMOUNT_OP
, "Jitter_Amount" },
141 { JITTER_OP
, "Jitter" },
142 { LIBRARY_PATH_OP
, "Library_Path" },
143 { LIGHT_BUFFER_OP
, "Light_Buffer" },
144 { ODD_FIELD_OP
, "Odd_Field" },
146 { OUTPUT_ALPHA_OP
, "Output_Alpha" },
147 { OUTPUT_FILE_NAME_OP
, "Output_File_Name" },
148 { PALETTE_OP
, "Palette" },
149 { PAUSE_WHEN_DONE_OP
, "Pause_When_Done" },
150 { POST_FRAME_CMD_OP
, "Post_Frame_Command" },
151 { POST_FRAME_RET_OP
, "Post_Frame_Return" },
152 { POST_SCENE_CMD_OP
, "Post_Scene_Command" },
153 { POST_SCENE_RET_OP
, "Post_Scene_Return" },
154 { PREVIEW_E_OP
, "Preview_End_Size" },
155 { PREVIEW_S_OP
, "Preview_Start_Size" },
157 { PRE_FRAME_CMD_OP
, "Pre_Frame_Command" },
158 { PRE_FRAME_RET_OP
, "Pre_Frame_Return" },
159 { PRE_SCENE_CMD_OP
, "Pre_Scene_command" },
160 { PRE_SCENE_RET_OP
, "Pre_Scene_Return" },
161 { QUALITY_OP
, "Quality" },
162 { RAD_SWITCH_OP
, "Radiosity" },
163 { REMOVE_BOUNDS_OP
, "Remove_Bounds" },
164 { RENDER_CONSOLE_OP
, "Render_Console" },
165 { RENDER_FILE_OP
, "Render_File" },
166 { SAMPLING_METHOD_OP
, "Sampling_Method" },
168 { SPLIT_UNIONS_OP
, "Split_Unions" },
169 { START_COLUMN_OP
, "Start_Column" },
170 { START_ROW_OP
, "Start_Row" },
171 { STATISTIC_CONSOLE_OP
, "Statistic_Console" },
172 { STATISTIC_FILE_OP
, "Statistic_File" },
173 { SUBSET_END_FRAME_OP
, "Subset_End_Frame" },
174 { SUBSET_START_FRAME_OP
, "Subset_Start_Frame" },
175 { TEST_ABORT_COUNT_OP
, "Test_Abort_Count" },
176 { TEST_ABORT_OP
, "Test_Abort" },
177 { USER_ABORT_CMD_OP
, "User_Abort_Command" },
179 { USER_ABORT_RET_OP
, "User_Abort_Return" },
180 { VERBOSE_OP
, "Verbose" },
181 { VERSION_OP
, "Version" },
182 { VIDEO_MODE_OP
, "Video_Mode" },
183 { VISTA_BUFFER_OP
, "Vista_Buffer" },
184 { WARNING_CONSOLE_OP
, "Warning_Console" },
185 { WARNING_FILE_OP
, "Warning_File" },
186 { WIDTH_OP
, "Width" },
188 { BITS_PER_COLOR_OP
, "Bits_Per_Color" },
189 { BITS_PER_COLOUR_OP
, "Bits_Per_Colour" },
190 { INCLUDE_INI_OP
, "Include_Ini" }
193 static char temp_string
[3]="\0\0";
194 static char ret_string
[7]="IQUFSA";
196 /*****************************************************************************
198 ******************************************************************************/
200 static int matches ( char *v1
, char *v2
);
201 static int istrue ( char *value
);
202 static int isfalse ( char *value
);
204 /*****************************************************************************
212 * op - the .ini option's index
213 * libind - if op = LIBRARY_PATH_OP, the library's index
219 * char * pointing to a static string representation of the
228 * Returns a static string representation of an option's value.
234 ******************************************************************************/
236 char *get_ini_value(int op
, int libind
)
238 static char value
[128];
245 sprintf(value
,"%d", opts
.File_Buffer_Size
>>10);
248 case BUFFERED_OUTPUT_OP
:
249 return (opts
.Options
& BUFFERED_OUTPUT
? "On" : "Off");
252 return (opts
.Options
& CONTINUE_TRACE
? "On" : "Off");
255 return (opts
.Options
& DISPLAY
? "On" : "Off");
258 sprintf(value
,"%c",opts
.DisplayFormat
);
262 sprintf(value
,"%c",opts
.PaletteOption
);
266 return (opts
.Options
& VERBOSE
? "On" : "Off");
269 sprintf(value
,"%d",Frame
.Screen_Width
);
273 sprintf(value
,"%d",Frame
.Screen_Height
);
277 return (opts
.Options
& DISKWRITE
? "On" : "Off");
279 case FILE_OUTPUT_TYPE_OP
:
280 sprintf(value
,"%c",opts
.OutputFormat
);
283 case PAUSE_WHEN_DONE_OP
:
284 return (opts
.Options
& PROMPTEXIT
? "On" : "Off");
286 case INPUT_FILE_NAME_OP
:
287 return opts
.Input_File_Name
;
289 case OUTPUT_FILE_NAME_OP
:
290 return opts
.Output_File_Name
;
293 return (opts
.Options
& ANTIALIAS
? "On" : "Off");
295 case ANTIALIAS_THRESH_OP
:
296 sprintf(value
,"%g",opts
.Antialias_Threshold
);
299 case ANTIALIAS_DEPTH_OP
:
300 sprintf(value
,"%ld",opts
.AntialiasDepth
);
304 return (opts
.Options
& JITTER
? "On" : "Off");
306 case JITTER_AMOUNT_OP
:
307 sprintf(value
,"%g",opts
.JitterScale
);
311 return (opts
.Options
& EXITENABLE
? "On" : "Off");
313 case TEST_ABORT_COUNT_OP
:
314 sprintf(value
,"%d",opts
.Abort_Test_Counter
);
317 case LIBRARY_PATH_OP
:
318 return opts
.Library_Paths
[libind
];
320 case START_COLUMN_OP
:
321 if (opts
.First_Column
== -1)
322 sprintf(value
,"%g",opts
.First_Column_Percent
);
324 sprintf(value
,"%d",opts
.First_Column
);
328 if (opts
.First_Line
== -1)
329 sprintf(value
,"%g",opts
.First_Line_Percent
);
331 sprintf(value
,"%d",opts
.First_Line
);
335 if (opts
.Last_Column
== -1)
336 sprintf(value
,"%g",opts
.Last_Column_Percent
);
338 sprintf(value
,"%d",opts
.Last_Column
);
342 if (opts
.Last_Line
== -1)
343 sprintf(value
,"%g",opts
.Last_Line_Percent
);
345 sprintf(value
,"%d",opts
.Last_Line
);
349 sprintf(value
,"%g",opts
.Language_Version
);
353 return (opts
.Use_Slabs
? "On" : "Off");
355 case BOUNDING_THRESH_OP
:
356 sprintf(value
,"%ld",opts
.BBox_Threshold
);
360 sprintf(value
,"%d",opts
.Quality
);
364 sprintf(value
,"%d",opts
.PreviewGridSize_Start
);
368 sprintf(value
,"%d",opts
.PreviewGridSize_End
);
372 sprintf(value
,"%g",opts
.FrameSeq
.Clock_Value
);
375 case INITIAL_FRAME_OP
:
376 sprintf(value
,"%d",opts
.FrameSeq
.InitialFrame
);
379 case INITIAL_CLOCK_OP
:
380 sprintf(value
,"%g",opts
.FrameSeq
.InitialClock
);
384 sprintf(value
,"%d",opts
.FrameSeq
.FinalFrame
);
388 sprintf(value
,"%g",opts
.FrameSeq
.FinalClock
);
391 case SUBSET_START_FRAME_OP
:
392 sprintf(value
,"%d",opts
.FrameSeq
.SubsetStartFrame
);
395 case SUBSET_END_FRAME_OP
:
396 sprintf(value
,"%d",opts
.FrameSeq
.SubsetEndFrame
);
400 return opts
.Ini_Output_File_Name
;
403 return (Stream_Info
[ALL_STREAM
].do_console
? "On" : "Off");
406 return (Stream_Info
[ALL_STREAM
].name
? Stream_Info
[ALL_STREAM
].name
: "");
408 case DEBUG_CONSOLE_OP
:
409 return (Stream_Info
[DEBUG_STREAM
].do_console
? "On" : "Off");
412 return (Stream_Info
[DEBUG_STREAM
].name
? Stream_Info
[DEBUG_STREAM
].name
: "");
414 case RENDER_CONSOLE_OP
:
415 return (Stream_Info
[RENDER_STREAM
].do_console
? "On" : "Off");
418 return (Stream_Info
[RENDER_STREAM
].name
? Stream_Info
[RENDER_STREAM
].name
: "");
420 case STATISTIC_CONSOLE_OP
:
421 return (Stream_Info
[STATISTIC_STREAM
].do_console
? "On" : "Off");
423 case STATISTIC_FILE_OP
:
424 return (Stream_Info
[STATISTIC_STREAM
].name
? Stream_Info
[STATISTIC_STREAM
].name
: "");
426 case WARNING_CONSOLE_OP
:
427 return (Stream_Info
[WARNING_STREAM
].do_console
? "On" : "Off");
429 case WARNING_FILE_OP
:
430 return (Stream_Info
[WARNING_STREAM
].name
? Stream_Info
[WARNING_STREAM
].name
: "");
432 case FATAL_CONSOLE_OP
:
433 return (Stream_Info
[FATAL_STREAM
].do_console
? "On" : "Off");
436 return (Stream_Info
[FATAL_STREAM
].name
? Stream_Info
[FATAL_STREAM
].name
: "");
439 return (opts
.Options
& RADIOSITY
? "On" : "Off");
442 sprintf (value
, "%d.%d", opts
.histogram_x
, opts
.histogram_y
) ;
446 switch (opts
.histogram_type
)
458 return ("T ; TARGA") ;
464 return ("X ; NONE") ;
467 return ("X ; [UNKNOWN VALUE PASSED]") ;
470 return (opts
.Histogram_File_Name
) ;
472 case VISTA_BUFFER_OP
:
473 return ((opts
.Options
& USE_VISTA_BUFFER
) ? "On" : "Off");
475 case LIGHT_BUFFER_OP
:
476 return ((opts
.Options
& USE_LIGHT_BUFFER
) ? "On" : "Off");
479 return ((opts
.Options
& USE_VISTA_DRAW
) ? "On" : "Off");
481 case SPLIT_UNIONS_OP
:
482 return ((opts
.Options
& SPLIT_UNION
) ? "On" : "Off");
484 case REMOVE_BOUNDS_OP
:
485 return ((opts
.Options
& REMOVE_BOUNDS
) ? "On" : "Off");
487 case CYCLIC_ANIMATION_OP
:
488 return ((opts
.Options
& CYCLIC_ANIMATION
) ? "On" : "Off");
490 case PRE_SCENE_CMD_OP
:
491 return opts
.Shellouts
[PRE_SCENE_SHL
].Command
;
493 case PRE_FRAME_CMD_OP
:
494 return opts
.Shellouts
[PRE_FRAME_SHL
].Command
;
496 case POST_FRAME_CMD_OP
:
497 return opts
.Shellouts
[POST_FRAME_SHL
].Command
;
499 case POST_SCENE_CMD_OP
:
500 return opts
.Shellouts
[POST_SCENE_SHL
].Command
;
502 case USER_ABORT_CMD_OP
:
503 return opts
.Shellouts
[USER_ABORT_SHL
].Command
;
505 case FATAL_ERROR_CMD_OP
:
506 return opts
.Shellouts
[FATAL_SHL
].Command
;
508 case PRE_SCENE_RET_OP
:
509 temp_string
[0]=(opts
.Shellouts
[PRE_SCENE_SHL
].Inverse
)?'!':' ';
510 temp_string
[1]=ret_string
[opts
.Shellouts
[PRE_SCENE_SHL
].Ret
];
513 case PRE_FRAME_RET_OP
:
514 temp_string
[0]=(opts
.Shellouts
[PRE_FRAME_SHL
].Inverse
)?'!':' ';
515 temp_string
[1]=ret_string
[opts
.Shellouts
[PRE_FRAME_SHL
].Ret
];
518 case POST_FRAME_RET_OP
:
519 temp_string
[0]=(opts
.Shellouts
[POST_FRAME_SHL
].Inverse
)?'!':' ';
520 temp_string
[1]=ret_string
[opts
.Shellouts
[POST_FRAME_SHL
].Ret
];
523 case POST_SCENE_RET_OP
:
524 temp_string
[0]=(opts
.Shellouts
[POST_SCENE_SHL
].Inverse
)?'!':' ';
525 temp_string
[1]=ret_string
[opts
.Shellouts
[POST_SCENE_SHL
].Ret
];
528 case USER_ABORT_RET_OP
:
529 temp_string
[0]=(opts
.Shellouts
[USER_ABORT_SHL
].Inverse
)?'!':' ';
530 temp_string
[1]=ret_string
[opts
.Shellouts
[USER_ABORT_SHL
].Ret
];
533 case FATAL_ERROR_RET_OP
:
534 temp_string
[0]=(opts
.Shellouts
[FATAL_SHL
].Inverse
)?'!':' ';
535 temp_string
[1]=ret_string
[opts
.Shellouts
[FATAL_SHL
].Ret
];
538 case OUTPUT_ALPHA_OP
:
539 return ((opts
.Options
& OUTPUT_ALPHA
) ? "On" : "Off");
541 case FIELD_RENDER_OP
:
542 return (opts
.FrameSeq
.Field_Render_Flag
? "On" : "Off");
545 return (opts
.FrameSeq
.Odd_Field_Flag
? "On" : "Off");
547 case SAMPLING_METHOD_OP
:
548 sprintf(value
,"%d",opts
.Tracing_Method
);
551 case BITS_PER_COLOR_OP
:
552 case BITS_PER_COLOUR_OP
:
553 sprintf(value
,"%d",opts
.OutputQuality
);
556 case DISPLAY_GAMMA_OP
:
557 sprintf(value
,"%g",opts
.DisplayGamma
);
565 Error("Unknown INI option in Write_INI.");
573 /*****************************************************************************
591 * Parses a traditional POV-Ray command-line switch that starts
592 * with + or -. Whenever it seemed feasible, calls process_variable
593 * to perform the function rather than doing so itself. Although this
594 * requires another pass through a switch{case, case...}, it insures
595 * that command-line switches and variable=value options get treated
602 * Sep 1994 : Added options for union splitting, vista/light buffer. [DB]
603 * Jan 1995 : Added options for histogram grid. [CJC]
604 * Feb 1995 : Added options for console/file redirection and .INI writing [SCD]
606 ******************************************************************************/
608 void parse_switch (char *Option_String
)
611 unsigned long Add_Option
;
612 unsigned long Option_Number
;
616 if (*(Option_String
++) == '-')
627 switch (*Option_String
)
631 if (Option_String
[1] == '\0')
637 sscanf (&Option_String
[1], "%d", &i
);
639 if ((i
>= 0) && (i
<= MAX_HELP_PAGE
))
653 Warning(0.0,"The +@ switch no longer supported. Use +GS.\n");
660 switch (Option_String
[1])
665 switch (Option_String
[2])
669 opts
.Tracing_Method
= 1;
675 opts
.Tracing_Method
= 2;
681 Warning(0.0, "Unknown antialiasing method. Standard method used.\n");
683 opts
.Tracing_Method
= 1;
690 Option_Number
= ANTIALIAS
;
692 if (sscanf (&Option_String
[1], DBL_FORMAT_STRING
, &floatval
) != SCANF_EOF
)
694 opts
.Antialias_Threshold
= floatval
;
703 process_variable(BUF_SIZE_OP
, &Option_String
[1]);
705 if (opts
.File_Buffer_Size
> 0)
707 Option_Number
= BUFFERED_OUTPUT
;
715 Option_Number
= CONTINUE_TRACE
;
722 Option_Number
= DISPLAY
;
724 if (Option_String
[1] != '\0')
726 opts
.DisplayFormat
= (char)toupper(Option_String
[1]);
729 if (Option_String
[1] != '\0' && Option_String
[2] != '\0')
731 opts
.PaletteOption
= (char)toupper(Option_String
[2]);
739 switch (Option_String
[1])
744 process_variable(END_COLUMN_OP
,&Option_String
[2]);
750 if(isdigit((int)Option_String
[2])) /* tw */
751 process_variable(SUBSET_END_FRAME_OP
, &Option_String
[2]);
757 process_variable(END_ROW_OP
,&Option_String
[2]);
761 case 'p': /* Mosaic Preview Grid Size - End */
764 process_variable(PREVIEW_E_OP
,&Option_String
[2]);
770 process_variable(END_ROW_OP
,&Option_String
[1]);
778 Option_Number
= DISKWRITE
;
780 if (Option_String
[1] != '\0')
782 opts
.OutputFormat
= (char)tolower(Option_String
[1]);
785 if (sscanf(&Option_String
[2], "%d", &opts
.OutputQuality
) != 1)
787 opts
.OutputQuality
= 8;
792 /* Console/file redirection, .INI dump option - [SCD 2/95] */
797 switch (Option_String
[1])
802 process_variable(ALL_CONSOLE_OP
,Add_Option
? "On" : "Off");
803 process_variable(ALL_FILE_OP
,&Option_String
[2]);
807 case 'd': /* DebugInfo */
810 process_variable(DEBUG_CONSOLE_OP
,Add_Option
? "On" : "Off");
811 process_variable(DEBUG_FILE_OP
,&Option_String
[2]);
815 case 'f': /* Fatal */
818 process_variable(FATAL_CONSOLE_OP
,Add_Option
? "On" : "Off");
819 process_variable(FATAL_FILE_OP
,&Option_String
[2]);
823 case 'i': /* Create .INI containing all settings */
826 process_variable(CREATE_INI_OP
,&Option_String
[2]);
830 case 'r': /* RenderInfo */
833 process_variable(RENDER_CONSOLE_OP
,Add_Option
? "On" : "Off");
834 process_variable(RENDER_FILE_OP
,&Option_String
[2]);
838 case 's': /* Statistics */
841 process_variable(STATISTIC_CONSOLE_OP
,Add_Option
? "On" : "Off");
842 process_variable(STATISTIC_FILE_OP
,&Option_String
[2]);
846 case 'w': /* Warning */
849 process_variable(WARNING_CONSOLE_OP
,Add_Option
? "On" : "Off");
850 process_variable(WARNING_FILE_OP
,&Option_String
[2]);
863 if (Option_String
[1] == '\0')
869 sscanf (&Option_String
[1], "%d", &Frame
.Screen_Height
);
871 if ((Frame
.Screen_Height
>= 0) && (Frame
.Screen_Height
<= MAX_HELP_PAGE
))
873 Usage(Frame
.Screen_Height
, TRUE
);
879 if (!isdigit ((int)Option_String
[1])) /* tw */
881 switch (Option_String
[1])
883 case 'n': /* Histogram name */
885 process_variable(HIST_NAME_OP
,&Option_String
[2]);
888 case 's': /* Histogram size */
890 process_variable(HIST_SIZE_OP
,&Option_String
[2]);
893 case 't': /* Histogram type */
895 process_variable(HIST_TYPE_OP
,&Option_String
[2]);
901 sscanf (&Option_String
[1], "%d", &Frame
.Screen_Height
);
909 if (Option_String
[1] == '\0')
915 process_variable(INPUT_FILE_NAME_OP
, &Option_String
[1]);
923 Option_Number
= JITTER
;
925 if (sscanf (&Option_String
[1], DBL_FORMAT_STRING
, &floatval
) != SCANF_EOF
)
927 opts
.JitterScale
= floatval
;
930 if (opts
.JitterScale
<= 0.0)
940 /* Animation-type clock specification */
941 switch(Option_String
[1])
945 Option_Number
= CYCLIC_ANIMATION
;
950 process_variable(INITIAL_CLOCK_OP
, &Option_String
[2]);
955 /* Animation-type clock specification */
956 switch(Option_String
[2])
960 process_variable(INITIAL_FRAME_OP
, &Option_String
[3]);
965 process_variable(FINAL_FRAME_OP
, &Option_String
[3]);
969 process_variable(FINAL_CLOCK_OP
, &Option_String
[2]);
976 /* Standard clock specification */
977 process_variable(CLOCK_OP
,&Option_String
[1]);
985 process_variable(LIBRARY_PATH_OP
,&Option_String
[1]);
989 case 'M': /* Switch used so other max values can be inserted easily */
992 switch (Option_String
[1])
994 case 's': /* Max Symbols */
997 Warning(0.0,"+MS or -MS switch no longer needed.\n");
1000 case 'v': /* Max Version */
1003 sscanf (&Option_String
[2], DBL_FORMAT_STRING
, &opts
.Language_Version
);
1007 case 'b': /* Min Bounded */
1010 if (sscanf (&Option_String
[2], "%ld", &longval
) != SCANF_EOF
)
1012 opts
.BBox_Threshold
=longval
;
1015 opts
.Use_Slabs
= Add_Option
;
1026 /* "N" option flag is used by networking (multi-processor) options.
1038 if (Option_String
[1] == '\0')
1044 process_variable(OUTPUT_FILE_NAME_OP
, &Option_String
[1]);
1052 Option_Number
= PROMPTEXIT
;
1059 switch(Option_String
[1])
1063 Option_Number
= RADIOSITY
;
1075 process_variable(QUALITY_OP
,&Option_String
[1]);
1085 process_variable(ANTIALIAS_DEPTH_OP
,&Option_String
[1]);
1092 switch (Option_String
[1])
1097 process_variable(START_COLUMN_OP
,&Option_String
[2]);
1104 process_variable(START_ROW_OP
,&Option_String
[2]);
1110 process_variable(SUBSET_START_FRAME_OP
, &Option_String
[2]);
1113 case 'p': /* Mosaic Preview Grid Size - Start */
1116 process_variable(PREVIEW_S_OP
,&Option_String
[2]);
1120 /* Split unions option. [DB 9/94] */
1125 Option_Number
= SPLIT_UNION
;
1131 process_variable(START_ROW_OP
,&Option_String
[1]);
1136 /* Read vista/light buffer options. [DB 9/94] */
1141 switch (Option_String
[1])
1146 Option_Number
= USE_LIGHT_BUFFER
;
1153 Option_Number
= USE_VISTA_DRAW
;
1160 Option_Number
= REMOVE_BOUNDS
;
1167 Option_Number
= USE_VISTA_BUFFER
;
1174 Option_Number
= OUTPUT_ALPHA
;
1181 process_variable(FIELD_RENDER_OP
, Add_Option
? "True" : "False");
1188 process_variable(ODD_FIELD_OP
, Add_Option
? "True" : "False");
1198 Option_Number
= VERBOSE
;
1204 sscanf (&Option_String
[1], "%d", &Frame
.Screen_Width
);
1211 Option_Number
= EXITENABLE
;
1213 sscanf (&Option_String
[1], "%d", &Abort_Test_Every
);
1215 opts
.Abort_Test_Counter
= Abort_Test_Every
;
1221 Warning (0.0,"Invalid option: %s.\n", --Option_String
);
1224 if (Option_Number
!= 0)
1228 opts
.Options
|= Option_Number
;
1232 opts
.Options
&= ~Option_Number
;
1240 /*****************************************************************************
1258 * Given a token number representing an option variable and a string
1259 * that is the value to set, set one option. If its just an on/off
1260 * switch that takes a boolean value then just set Option_Number and
1261 * break. Otherwise process the value and return.
1267 ******************************************************************************/
1269 void process_variable(TOKEN variable
,char *value
)
1273 unsigned int Option_Number
= 0;
1279 if (sscanf (value
, "%d", &opts
.File_Buffer_Size
) != SCANF_EOF
)
1281 opts
.File_Buffer_Size
*= 1024;
1283 if (opts
.File_Buffer_Size
> MAX_BUFSIZE
)
1284 opts
.File_Buffer_Size
= MAX_BUFSIZE
;
1286 /* If 0 then no buffer, other low values use system default MIN */
1287 if ((opts
.File_Buffer_Size
> 0) && (opts
.File_Buffer_Size
< BUFSIZ
))
1289 opts
.File_Buffer_Size
= BUFSIZ
;
1291 if (opts
.File_Buffer_Size
<= 0)
1293 opts
.Options
&= ~BUFFERED_OUTPUT
;
1298 case BUFFERED_OUTPUT_OP
:
1299 Option_Number
= BUFFERED_OUTPUT
;
1303 Option_Number
= CONTINUE_TRACE
;
1307 Option_Number
= DISPLAY
;
1311 opts
.DisplayFormat
= (char)toupper(value
[0]);
1315 opts
.PaletteOption
= (char)toupper(value
[0]);
1319 Option_Number
= VERBOSE
;
1323 Frame
.Screen_Width
= atoi(value
);
1327 Frame
.Screen_Height
= atoi(value
);
1330 case FILE_OUTPUT_OP
:
1331 Option_Number
= DISKWRITE
;
1334 case FILE_OUTPUT_TYPE_OP
:
1335 opts
.OutputFormat
= (char)tolower(value
[0]);
1338 case PAUSE_WHEN_DONE_OP
:
1339 Option_Number
= PROMPTEXIT
;
1342 case INPUT_FILE_NAME_OP
:
1343 if (!strcmp(value
, "-") || !strcmp(value
, "stdin"))
1345 strcpy (opts
.Input_File_Name
, "stdin");
1346 opts
.Options
|= FROM_STDIN
;
1350 strncpy (opts
.Input_File_Name
, value
, FILE_NAME_LENGTH
);
1354 case OUTPUT_FILE_NAME_OP
:
1355 if (!strcmp(value
, "-") || !strcmp(value
, "stdout"))
1357 strcpy (opts
.Output_File_Name
, "stdout");
1358 opts
.Options
|= TO_STDOUT
;
1362 strncpy (opts
.Output_File_Name
, value
, FILE_NAME_LENGTH
);
1367 Option_Number
= ANTIALIAS
;
1370 case ANTIALIAS_THRESH_OP
:
1371 if (sscanf (value
, DBL_FORMAT_STRING
, &floatval
) != SCANF_EOF
)
1372 opts
.Antialias_Threshold
= floatval
;
1375 case ANTIALIAS_DEPTH_OP
:
1376 if (sscanf (value
, "%ld", &longval
) != SCANF_EOF
)
1377 opts
.AntialiasDepth
= longval
;
1378 if (opts
.AntialiasDepth
< 1)
1379 opts
.AntialiasDepth
= 1;
1380 if (opts
.AntialiasDepth
> 9)
1381 opts
.AntialiasDepth
= 9;
1385 Option_Number
= JITTER
;
1388 case JITTER_AMOUNT_OP
:
1389 if (sscanf (value
, DBL_FORMAT_STRING
, &floatval
) != SCANF_EOF
)
1390 opts
.JitterScale
= floatval
;
1391 if (opts
.JitterScale
<=0.0)
1392 opts
.Options
&= ~JITTER
;
1396 Option_Number
= EXITENABLE
;
1399 case TEST_ABORT_COUNT_OP
:
1400 sscanf (value
, "%d", &Abort_Test_Every
);
1401 opts
.Abort_Test_Counter
= Abort_Test_Every
;
1404 case LIBRARY_PATH_OP
:
1405 if (opts
.Library_Path_Index
>= MAX_LIBRARIES
)
1406 Error ("Too many library directories specified.");
1407 for (i
= 0; i
< opts
.Library_Path_Index
; i
++)
1408 if (strcmp(value
,opts
.Library_Paths
[i
])==0) return;
1409 opts
.Library_Paths
[opts
.Library_Path_Index
] = (char *)POV_MALLOC(strlen(value
)+1,
1411 strcpy (opts
.Library_Paths
[opts
.Library_Path_Index
], value
);
1412 opts
.Library_Path_Index
++;
1415 case START_COLUMN_OP
:
1416 if (sscanf (value
, DBL_FORMAT_STRING
, &floatval
) != SCANF_EOF
)
1418 if(floatval
> 0.0 && floatval
< 1.0)
1420 opts
.First_Column
= -1;
1421 opts
.First_Column_Percent
= floatval
;
1424 opts
.First_Column
= ((int) floatval
);
1425 /* The above used to have -1 but it messed up Write_INI_File.
1426 * Moved -1 fudge to fix_up_rendering_window
1432 if (sscanf (value
, DBL_FORMAT_STRING
, &floatval
) != SCANF_EOF
)
1434 if(floatval
> 0.0 && floatval
< 1.0)
1436 opts
.First_Line
= -1;
1437 opts
.First_Line_Percent
= floatval
;
1440 opts
.First_Line
= ((int) floatval
);
1441 /* The above used to have -1 but it messed up Write_INI_File
1442 * Moved -1 fudge to fix_up_rendering_window
1449 if (sscanf (value
, DBL_FORMAT_STRING
, &floatval
) != SCANF_EOF
)
1451 if(floatval
> 0.0 && floatval
<= 1.0)
1453 opts
.Last_Column
= -1;
1454 opts
.Last_Column_Percent
= floatval
;
1457 opts
.Last_Column
= (int) floatval
;
1464 if (sscanf (value
, DBL_FORMAT_STRING
, &floatval
) != SCANF_EOF
)
1466 if(floatval
> 0.0 && floatval
<= 1.0)
1468 opts
.Last_Line
= -1;
1469 opts
.Last_Line_Percent
= floatval
;
1472 opts
.Last_Line
= (int) floatval
;
1478 if (sscanf (value
, DBL_FORMAT_STRING
, &floatval
) != SCANF_EOF
)
1479 opts
.Language_Version
= floatval
;
1483 opts
.Use_Slabs
= istrue(value
);
1486 case BOUNDING_THRESH_OP
:
1487 opts
.BBox_Threshold
= atoi(value
);
1491 opts
.Quality
= atoi(value
);
1492 /* Emit a warning about the "radiosity" quality levels for
1493 * now. We can get rid of this some time in the future.
1495 if ((opts
.Quality
== 10) || (opts
.Quality
== 11))
1497 Warning(0.0, "Quality settings 10 and 11 are no longer valid.\n"
1498 "Use +QR if you need radiosity.\n");
1501 else if ((opts
.Quality
< 0) || (opts
.Quality
> 9))
1503 Error("Illegal Quality setting.");
1505 opts
.Quality_Flags
= Quality_Values
[opts
.Quality
];
1509 if(sscanf (value
, DBL_FORMAT_STRING
, &floatval
) != SCANF_EOF
)
1511 opts
.FrameSeq
.Clock_Value
= floatval
;
1515 case INITIAL_FRAME_OP
:
1516 if(sscanf(value
, "%ld", &longval
)!=SCANF_EOF
)
1518 opts
.FrameSeq
.InitialFrame
=longval
;
1522 case INITIAL_CLOCK_OP
:
1523 if(sscanf(value
, DBL_FORMAT_STRING
, &floatval
)!=SCANF_EOF
)
1525 opts
.FrameSeq
.InitialClock
=floatval
;
1529 case FINAL_FRAME_OP
:
1530 if(sscanf(value
, "%ld", &longval
)!=SCANF_EOF
)
1532 opts
.FrameSeq
.FinalFrame
=longval
;
1536 case FINAL_CLOCK_OP
:
1537 if(sscanf(value
, DBL_FORMAT_STRING
, &floatval
)!=SCANF_EOF
)
1539 opts
.FrameSeq
.FinalClock
=floatval
;
1543 case SUBSET_START_FRAME_OP
:
1544 if (sscanf (value
, DBL_FORMAT_STRING
, &floatval
) != SCANF_EOF
)
1546 if(floatval
> 0.0 && floatval
< 1.0)
1547 opts
.FrameSeq
.SubsetStartPercent
=floatval
;
1549 opts
.FrameSeq
.SubsetStartFrame
=(int)floatval
;
1553 case SUBSET_END_FRAME_OP
:
1554 if (sscanf (value
, DBL_FORMAT_STRING
, &floatval
) != SCANF_EOF
)
1556 if(floatval
> 0.0 && floatval
< 1.0)
1557 opts
.FrameSeq
.SubsetEndPercent
=floatval
;
1559 opts
.FrameSeq
.SubsetEndFrame
=(int)floatval
;
1564 opts
.PreviewGridSize_Start
= atoi(value
);
1568 opts
.PreviewGridSize_End
= atoi(value
);
1572 strcpy(opts
.Ini_Output_File_Name
,value
);
1575 case ALL_CONSOLE_OP
:
1576 Stream_Info
[ALL_STREAM
].do_console
=
1577 Stream_Info
[WARNING_STREAM
].do_console
=
1578 Stream_Info
[STATISTIC_STREAM
].do_console
=
1579 Stream_Info
[RENDER_STREAM
].do_console
=
1580 Stream_Info
[FATAL_STREAM
].do_console
=
1581 Stream_Info
[DEBUG_STREAM
].do_console
= istrue(value
);
1585 Do_Stream_Option(ALL_STREAM
,value
);
1588 case DEBUG_CONSOLE_OP
:
1589 Stream_Info
[DEBUG_STREAM
].do_console
= istrue(value
);
1593 Do_Stream_Option(DEBUG_STREAM
,value
);
1596 case FATAL_CONSOLE_OP
:
1597 Stream_Info
[FATAL_STREAM
].do_console
= istrue(value
);
1601 Do_Stream_Option(FATAL_STREAM
,value
);
1604 case RENDER_CONSOLE_OP
:
1605 Stream_Info
[RENDER_STREAM
].do_console
= istrue(value
);
1608 case RENDER_FILE_OP
:
1609 Do_Stream_Option(RENDER_STREAM
,value
);
1612 case STATISTIC_CONSOLE_OP
:
1613 Stream_Info
[STATISTIC_STREAM
].do_console
= istrue(value
);
1616 case STATISTIC_FILE_OP
:
1617 Do_Stream_Option(STATISTIC_STREAM
,value
);
1620 case WARNING_CONSOLE_OP
:
1621 Stream_Info
[WARNING_STREAM
].do_console
= istrue(value
);
1624 case WARNING_FILE_OP
:
1625 Do_Stream_Option(WARNING_STREAM
,value
);
1629 Option_Number
= RADIOSITY
;
1633 if (sscanf (value
, "%d.%d", &opts
.histogram_x
, &opts
.histogram_y
) == SCANF_EOF
)
1635 Warning (0.0, "Error occurred scanning histogram grid size '%s'.\n", value
) ;
1636 opts
.histogram_on
= FALSE
;
1641 #if PRECISION_TIMER_AVAILABLE
1643 char *def_ext
= NULL
;
1649 opts
.histogram_on
= TRUE
;
1650 opts
.histogram_type
= CSV
;
1655 opts
.histogram_on
= TRUE
;
1656 opts
.histogram_type
= SYS
;
1657 Histogram_File_Handle
= GET_SYS_FILE_HANDLE () ;
1658 def_ext
= SYS_DEF_EXT
;
1662 opts
.histogram_on
= TRUE
;
1663 opts
.histogram_type
= PPM
;
1664 Histogram_File_Handle
= Get_PPM_File_Handle () ;
1669 opts
.histogram_on
= TRUE
;
1670 opts
.histogram_type
= TARGA
;
1671 Histogram_File_Handle
= Get_Targa_File_Handle () ;
1676 opts
.histogram_on
= TRUE
;
1677 opts
.histogram_type
= PNG
;
1678 Histogram_File_Handle
= Get_Png_File_Handle () ;
1683 opts
.histogram_on
= FALSE
;
1686 Warning (0.0, "Unknown histogram output type '%c'.\n", *value
) ;
1687 opts
.histogram_on
= FALSE
;
1691 /* Process the histogram file name now, if it hasn't
1692 * yet been specified, and in case it isn't set later.
1694 if (opts
.histogram_on
&& opts
.Histogram_File_Name
[0] == '\0')
1696 sprintf(opts
.Histogram_File_Name
, "histgram%s", def_ext
);
1699 #else /* !PRECISION_TIMER_AVAILABLE */
1700 if (*value
!= 'x' && *value
!= 'X')
1701 Warning(0.0,"Histogram output unavailable in this compile of POV-Ray");
1702 opts
.histogram_on
= FALSE
;
1703 #endif /* PRECISION_TIMER_AVAILABLE */
1707 if (opts
.histogram_on
&& value
[0] == '\0')
1709 char *def_ext
= NULL
;
1711 switch (opts
.histogram_type
)
1713 case CSV
: def_ext
= ".csv"; break;
1714 case TARGA
: def_ext
= ".tga"; break;
1715 case PNG
: def_ext
= ".png"; break;
1716 case PPM
: def_ext
= ".ppm"; break;
1717 case SYS
: def_ext
= SYS_DEF_EXT
; break;
1718 case NONE
: def_ext
= ""; break; /* To quiet warnings */
1721 sprintf(opts
.Histogram_File_Name
, "histgram%s", def_ext
);
1725 strncpy (opts
.Histogram_File_Name
, value
, FILE_NAME_LENGTH
);
1729 case VISTA_BUFFER_OP
:
1730 Option_Number
= USE_VISTA_BUFFER
;
1733 case LIGHT_BUFFER_OP
:
1734 Option_Number
= USE_LIGHT_BUFFER
;
1737 case DRAW_VISTAS_OP
:
1738 Option_Number
= USE_VISTA_DRAW
;
1741 case SPLIT_UNIONS_OP
:
1742 Option_Number
= SPLIT_UNION
;
1745 case REMOVE_BOUNDS_OP
:
1746 Option_Number
= REMOVE_BOUNDS
;
1749 case CYCLIC_ANIMATION_OP
:
1750 Option_Number
= CYCLIC_ANIMATION
;
1753 case PRE_SCENE_CMD_OP
:
1754 strcpy(opts
.Shellouts
[PRE_SCENE_SHL
].Command
, value
);
1757 case PRE_FRAME_CMD_OP
:
1758 strcpy(opts
.Shellouts
[PRE_FRAME_SHL
].Command
, value
);
1761 case POST_FRAME_CMD_OP
:
1762 strcpy(opts
.Shellouts
[POST_FRAME_SHL
].Command
, value
);
1765 case POST_SCENE_CMD_OP
:
1766 strcpy(opts
.Shellouts
[POST_SCENE_SHL
].Command
, value
);
1769 case USER_ABORT_CMD_OP
:
1770 strcpy(opts
.Shellouts
[USER_ABORT_SHL
].Command
, value
);
1773 case FATAL_ERROR_CMD_OP
:
1774 strcpy(opts
.Shellouts
[FATAL_SHL
].Command
, value
);
1777 case PRE_SCENE_RET_OP
:
1778 Do_Return_Option(PRE_SCENE_SHL
, value
);
1781 case PRE_FRAME_RET_OP
:
1782 Do_Return_Option(PRE_FRAME_SHL
, value
);
1785 case POST_FRAME_RET_OP
:
1786 Do_Return_Option(POST_FRAME_SHL
, value
);
1789 case POST_SCENE_RET_OP
:
1790 Do_Return_Option(POST_SCENE_SHL
, value
);
1793 case USER_ABORT_RET_OP
:
1794 Do_Return_Option(USER_ABORT_SHL
, value
);
1797 case FATAL_ERROR_RET_OP
:
1798 Do_Return_Option(FATAL_SHL
, value
);
1801 case OUTPUT_ALPHA_OP
:
1802 Option_Number
= OUTPUT_ALPHA
;
1805 case FIELD_RENDER_OP
:
1806 opts
.FrameSeq
.Field_Render_Flag
= istrue(value
);
1810 opts
.FrameSeq
.Odd_Field_Flag
= istrue(value
);
1813 case SAMPLING_METHOD_OP
:
1814 opts
.Tracing_Method
= atoi(value
);
1817 case BITS_PER_COLOR_OP
:
1818 case BITS_PER_COLOUR_OP
:
1819 opts
.OutputQuality
= atoi(value
);
1820 opts
.OutputQuality
= max(5, opts
.OutputQuality
);
1821 opts
.OutputQuality
= min(16, opts
.OutputQuality
);
1824 case DISPLAY_GAMMA_OP
:
1825 if (sscanf (value
, DBL_FORMAT_STRING
, &floatval
) != SCANF_EOF
)
1828 opts
.DisplayGamma
= floatval
;
1832 case INCLUDE_INI_OP
:
1833 if (!parse_ini_file(value
))
1835 Error ("Could not open Include_Ini='%s'.\n", value
);
1840 Warning(0.0,"Unimplemented INI '%s'.\n",Option_Variable
[variable
].Token_Name
);
1845 if (Option_Number
!= 0)
1849 opts
.Options
|= Option_Number
;
1853 opts
.Options
&= ~Option_Number
;
1860 /*****************************************************************************
1884 ******************************************************************************/
1886 static int matches(char *v1
,char *v2
)
1891 while ((ans
) && (v1
[i
] != '\0') && (v2
[i
] != '\0'))
1893 ans
= ans
&& (v1
[i
] == tolower(v2
[i
]));
1900 static int istrue(char *value
)
1902 return (matches("on",value
) || matches("true",value
) ||
1903 matches("yes",value
) || matches("1",value
));
1906 static int isfalse(char *value
)
1908 return (matches("off",value
) || matches("false",value
) ||
1909 matches("no",value
) || matches("0",value
));
1913 /*****************************************************************************
1931 * Writes all options to an INI file with the current input filename's name
1932 * (by default), or using a specified filename.
1938 ******************************************************************************/
1940 void Write_INI_File()
1943 char ini_name
[FILE_NAME_LENGTH
];
1946 if (opts
.Ini_Output_File_Name
[0]=='\0')
1951 if (isfalse(opts
.Ini_Output_File_Name
))
1956 Status_Info("\nWriting INI file...");
1958 if (istrue(opts
.Ini_Output_File_Name
))
1960 strcpy(ini_name
,opts
.Scene_Name
);
1961 strcat(ini_name
,".ini");
1965 strcpy(ini_name
,opts
.Ini_Output_File_Name
);
1968 if ((ini_file
= fopen(ini_name
, WRITE_TXTFILE_STRING
)) == NULL
)
1970 Warning (0.0,"Error opening .INI output file '%s' - no file written.\n",
1976 for (op
= 0; op
< MAX_OPTION
; op
++)
1978 if (op
== LIBRARY_PATH_OP
)
1980 for (i
= 0; i
< opts
.Library_Path_Index
; i
++)
1982 fprintf(ini_file
,"%s=%s%s",Option_Variable
[op
].Token_Name
,
1983 get_ini_value(op
, i
),NEW_LINE_STRING
);
1986 /* So that we don't get both Bits_Per_Color and Bits_Per_Colour in
1988 else if ((op
!= BITS_PER_COLOUR_OP
) && (op
!= INCLUDE_INI_OP
))
1990 fprintf(ini_file
,"%s=%s%s",Option_Variable
[op
].Token_Name
,
1991 get_ini_value(op
, 0),NEW_LINE_STRING
);
2000 /*****************************************************************************
2018 * Given a file name, open it, parse options from it, close it.
2019 * Return 1 if file found, 0 if not found.
2025 ******************************************************************************/
2027 int parse_ini_file(char *File_Name
)
2029 char Option_Line
[512];
2030 char INI_Name
[FILE_NAME_LENGTH
];
2031 char Desired_Section
[FILE_NAME_LENGTH
];
2032 char Current_Section
[FILE_NAME_LENGTH
];
2033 char *source
, *dest
;
2035 int Matched
, Never_Matched
;
2037 Stage
=STAGE_INI_FILE
;
2039 /* File_Name can be of the for "FILE.INI[Section]" where everything
2040 * before the '[' is the actual name and "[Section]" is the title of
2041 * a section within that file that starts with the [Section] heading.
2042 * Only the specified section of the INI file is processed. If no
2043 * section is specified then only parts of the file without a section
2044 * header are processed.
2047 /* Copy the file name part */
2050 while ((*source
!= '\0') && (*source
!= '['))
2052 *(dest
++) = *(source
++);
2056 /* Copy the section name part */
2057 dest
= Desired_Section
;
2058 while ((*source
!= '\0') && (*source
!= ']'))
2060 *(dest
++) = *(source
++);
2065 if ((ini_file
= Locate_File(INI_Name
, READ_TXTFILE_STRING
,".ini",".INI",NULL
,FALSE
)) == NULL
)
2070 *Current_Section
='\0';
2072 Matched
= (*Desired_Section
== '\0');
2075 while (fgets(Option_Line
, 512, ini_file
) != NULL
)
2077 if (*Option_Line
== '[')
2080 dest
=Current_Section
;
2081 while ((*source
!= '\0') && (*source
!= ']'))
2083 *(dest
++) = *(source
++);
2087 Matched
= (pov_stricmp(Current_Section
, Desired_Section
) == 0);
2094 parse_option_line(Option_Line
);
2095 Never_Matched
=FALSE
;
2102 Warning(0.0,"Never found section %s in file %s.\n",Desired_Section
,INI_Name
);
2111 /*****************************************************************************
2129 * Given a string containing a line of text, split it into individual
2130 * switches or options and then pass them off to be parsed by parse_switch
2131 * or process_variable. This routine is called by parse_ini_file,
2132 * by the main with argv[] and by READ_ENV_VAR_????
2136 * Mar 1996 : Allow ';' in an option, if it is escaped [AED]
2138 ******************************************************************************/
2140 void parse_option_line(char *Option_Line
)
2142 char *source
, *dest
;
2143 char Option_String
[512];
2146 source
= Option_Line
;
2150 /* skip leading white space */
2151 while (((int)*source
> 0) && ((int)*source
< 33))
2156 /* Quit when finished or ignore if commented */
2157 if ((*source
== '\0') || (*source
== ';'))
2162 if ((*source
== '=') || (*source
== '#'))
2164 Error("'=' or '#' must be preceded by a keyword.");
2167 /* Copy everything that is not a space, an equals or a comment
2170 dest
= Option_String
;
2171 while ((isprint((int)*source
)) &&
2177 *(dest
++) = *(source
++);
2181 /* At this point, nearly all options that start with a "-" are
2182 * options. However the syntax for the +I and the +O
2183 * command-line switches, allows a space to appear between the
2184 * switch and the name. For example: "+I MYFILE.POV" is legal.
2185 * Since "-" is a legal input and output filename for stdin or
2186 * stdout we must parse this before we try to read other options.
2187 * If we encounter a "-" without a following option immediately
2188 * after a +I or +O switch, it must mean that. The flags
2189 * inflag and outflag indicate that there was a +I or +O switch
2190 * parsed just before this file name.
2196 if (pov_stricmp(Option_String
, "-") == 0 ||
2197 pov_stricmp(Option_String
, "stdin") == 0)
2199 strcpy (opts
.Input_File_Name
, "stdin");
2200 opts
.Options
|= FROM_STDIN
;
2203 else if ((*Option_String
!= '+') && (*Option_String
!= '-'))
2205 strncpy (opts
.Input_File_Name
, Option_String
, FILE_NAME_LENGTH
);
2213 if (pov_stricmp(Option_String
, "-") == 0 ||
2214 pov_stricmp(Option_String
, "stdout") == 0)
2216 strcpy (opts
.Output_File_Name
, "stdout");
2217 opts
.Options
|= TO_STDOUT
;
2220 else if ((*Option_String
!= '+') && (*Option_String
!= '-'))
2222 strncpy (opts
.Output_File_Name
, Option_String
, FILE_NAME_LENGTH
);
2227 /* If its a +/- style switch then just do it */
2228 if ((*Option_String
== '+') || (*Option_String
== '-'))
2230 parse_switch(Option_String
);
2234 /* Now search the Option_Variables to see if we find a match */
2237 for (i
= 0 ; i
< MAX_OPTION
; i
++)
2239 if (pov_stricmp(Option_Variable
[i
].Token_Name
, Option_String
) == 0)
2241 Found
=Option_Variable
[i
].Token_Number
;
2248 /* When an option string does not begin with a '+' or '-', and
2249 * is not in the list of valid keywords, then it is assumed to
2250 * be a file name. Any file names that appear at this point are
2251 * .INI/.DEF files to be parsed, or it is an error.
2254 if (++Number_Of_Files
> MAX_NESTED_INI
)
2256 Error ("Bad option syntax or too many nested .INI/.DEF files.");
2259 if (!parse_ini_file(Option_String
))
2261 Error ("Bad option syntax or error opening .INI/.DEF file '%s'.\n", Option_String
);
2266 /* If we make it this far, then it must be an .INI-style setting with
2267 * the keyword already verified in "Found". We now need to verify that
2268 * an equals sign follows.
2271 /* skip white space */
2272 while (((int)*source
> 0) && ((int)*source
< 33))
2277 if ((*source
!= '=') && (*source
!= '#'))
2279 Error("Missing '=' or '#' after %s in option.",Option_String
);
2284 /* Now the entire rest of Option_Line up to but excluding a comment,
2285 * becomes the variable part of the option.
2288 /* skip white space */
2289 while (((int)*source
> 0) && ((int)*source
< 33))
2296 /* Cut off comments and any unprintable characters */
2297 while (*source
!= '\0')
2299 /* If the comment character is escaped, pass it through */
2300 if ((*source
== '\\') && (*(source
+ 1) == ';'))
2307 else if ((*source
== ';') || (! isprint((int)*source
) ) )
2316 process_variable(Found
, dest
);
2323 /*****************************************************************************
2339 ******************************************************************************/
2341 void Do_Stream_Option (int i
, char *value
)
2353 if (Stream_Info
[i
].name
!= NULL
)
2355 POV_FREE(Stream_Info
[i
].name
);
2357 Stream_Info
[i
].name
= NULL
;
2362 Stream_Info
[i
].name
= (char *)POV_MALLOC(strlen(DefaultFile
[i
])+1, "stream name");
2364 strcpy(Stream_Info
[i
].name
, DefaultFile
[i
]);
2373 Stream_Info
[i
].name
= (char *)POV_MALLOC(strlen(value
)+1, "stream name");
2375 strcpy(Stream_Info
[i
].name
, value
);
2381 /*****************************************************************************
2397 ******************************************************************************/
2399 void Do_Return_Option (SHELLTYPE Type
, char *value
)
2403 SHELLDATA
*Shell
=&(opts
.Shellouts
[Type
]);
2405 Shell
->Inverse
=FALSE
;
2406 Shell
->Ret
=IGNORE_RET
;
2414 if ((*value
=='-') || (*value
=='!'))
2416 Shell
->Inverse
=TRUE
;
2423 if ((s
=strchr(ret_string
,toupper(*value
))) == NULL
)
2425 Warning(0.0,"Bad value in shellout return '%c'. Only '%s' are allowed.\n",*value
,ret_string
);
2426 Shell
->Ret
= IGNORE_RET
;
2430 Shell
->Ret
= (POV_SHELLOUT_CAST
)(s
-ret_string
);