home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: Graphics / Graphics.zip / povsrc31.zip / optin.c < prev    next >
C/C++ Source or Header  |  2000-11-26  |  60KB  |  2,450 lines

  1. /****************************************************************************
  2. *                   optin.c
  3. *
  4. *  This module contains functions for ini-file/command line parsing, streams.
  5. *
  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.
  17. *
  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.
  21. *
  22. * Modification by Thomas Willhalm, March 1999.
  23. *
  24. *****************************************************************************/
  25.  
  26. /****************************************************************************
  27. *
  28. *  This file contains the routines to implement an .INI file parser that can
  29. *  parse options in the form "Variable=value" or traditional POV-Ray
  30. *  command-line switches.  Values can come from POVRAYOPT, command-line,
  31. *  .DEF or .INI files.
  32. *
  33. *  Written by CEY 4/94 based on existing code and INI code from CDW.
  34. *
  35. *  ---
  36. *
  37. *****************************************************************************/
  38.  
  39. #include <ctype.h>
  40. #include <time.h>
  41. #include "frame.h"
  42. #include "povproto.h"
  43. #include "bbox.h"
  44. #include "lighting.h"
  45. #include "mem.h"        /*POV_FREE*/
  46. #include "octree.h"
  47. #include "povray.h"
  48. #include "optin.h"
  49. #include "optout.h"
  50. #include "parse.h"
  51. #include "radiosit.h"
  52. #include "render.h"
  53. #include "tokenize.h"
  54. #include "vlbuffer.h"
  55. #include "ppm.h"
  56. #include "targa.h"
  57. #include "userio.h"
  58. #include "png_pov.h"
  59.  
  60.  
  61.  
  62. /*****************************************************************************
  63. * Local preprocessor defines
  64. ******************************************************************************/
  65.  
  66.  
  67. /*****************************************************************************
  68. * Local typedefs
  69. ******************************************************************************/
  70.  
  71.  
  72.  
  73. /*****************************************************************************
  74. * Local variables
  75. ******************************************************************************/
  76.  
  77. char *DefaultFile[] =
  78. {
  79.   "debug.out",
  80.   "fatal.out",
  81.   "render.out",
  82.   "stats.out",
  83.   "warning.out",
  84.   "alltext.out"
  85. };
  86.  
  87. int inflag, outflag;
  88.  
  89. /* Quality constants */
  90.  
  91. long Quality_Values[12]=
  92. {
  93.   QUALITY_0, QUALITY_1, QUALITY_2, QUALITY_3, QUALITY_4,
  94.   QUALITY_5, QUALITY_6, QUALITY_7, QUALITY_8, QUALITY_9
  95. };
  96.  
  97. /* Keywords for the ini-file parser. */
  98.  
  99. struct Reserved_Word_Struct Option_Variable [] =
  100. {
  101.   { ALL_CONSOLE_OP, "All_Console" },
  102.   { ALL_FILE_OP, "All_File" },
  103.   { BUFFERED_OUTPUT_OP,"Buffer_Output" },
  104.   { BUF_SIZE_OP, "Buffer_Size" },
  105.   { CREATE_INI_OP, "Create_Ini" },
  106.   { CYCLIC_ANIMATION_OP, "Cyclic_Animation" },
  107.   { DEBUG_CONSOLE_OP, "Debug_Console" },
  108.   { DEBUG_FILE_OP, "Debug_File" },
  109.   { DISPLAY_OP, "Display" },
  110.   { DISPLAY_GAMMA_OP, "Display_Gamma" },
  111.   { FATAL_CONSOLE_OP, "Fatal_Console" },
  112.   { FATAL_ERROR_CMD_OP, "Fatal_Error_Command" },
  113.   { FATAL_ERROR_RET_OP, "Fatal_Error_Return" },
  114.   { FATAL_FILE_OP, "Fatal_File" },
  115.   { FINAL_CLOCK_OP, "Final_Clock" },
  116.   { FINAL_FRAME_OP, "Final_Frame" },
  117.   { INCLUDE_INI_OP, "Include_Ini" },
  118.   { INITIAL_CLOCK_OP, "Initial_Clock" },
  119.   { INITIAL_FRAME_OP, "Initial_Frame" },
  120.   { INPUT_FILE_NAME_OP, "Input_File_Name" },
  121.   { FILE_OUTPUT_OP, "Output_to_File" },
  122.   { FILE_OUTPUT_TYPE_OP, "Output_File_Type" },
  123.   { OUTPUT_FILE_NAME_OP, "Output_File_Name" },
  124.   { PALETTE_OP, "Palette" },
  125.   { PAUSE_WHEN_DONE_OP, "Pause_When_Done" },
  126.   /* NK persist - Nov 1999 */
  127.   { PERSISTENT_ANIMATION_OP, "Persistent_Animation" },
  128.   { POST_FRAME_CMD_OP, "Post_Frame_Command" },
  129.   { POST_FRAME_RET_OP, "Post_Frame_Return" },
  130.   { POST_SCENE_CMD_OP, "Post_Scene_Command" },
  131.   { POST_SCENE_RET_OP, "Post_Scene_Return" },
  132.   { PRE_FRAME_CMD_OP, "Pre_Frame_Command" },
  133.   { PRE_FRAME_RET_OP, "Pre_Frame_Return" },
  134.   { PRE_SCENE_CMD_OP, "Pre_Scene_command" },
  135.   { PRE_SCENE_RET_OP, "Pre_Scene_Return" },
  136.   { RENDER_CONSOLE_OP, "Render_Console" },
  137.   { RENDER_FILE_OP, "Render_File" },
  138.   { STATISTIC_CONSOLE_OP, "Statistic_Console" },
  139.   { STATISTIC_FILE_OP, "Statistic_File" },
  140.   { SUBSET_END_FRAME_OP, "Subset_End_Frame" },
  141.   { SUBSET_START_FRAME_OP, "Subset_Start_Frame" },
  142.   { TEST_ABORT_COUNT_OP, "Test_Abort_Count" },
  143.   { TEST_ABORT_OP, "Test_Abort" },
  144.   { USER_ABORT_CMD_OP, "User_Abort_Command" },
  145.   { USER_ABORT_RET_OP, "User_Abort_Return" },
  146.   { VERBOSE_OP, "Verbose" },
  147.   { VERSION_OP, "Version" },
  148.   { VIDEO_MODE_OP, "Video_Mode" },
  149.   { WARNING_CONSOLE_OP, "Warning_Console" },
  150.   { WARNING_FILE_OP, "Warning_File" },
  151.  
  152.   { ANTIALIAS_DEPTH_OP, "Antialias_Depth" },
  153.   { ANTIALIAS_OP, "Antialias" },
  154.   { ANTIALIAS_THRESH_OP, "Antialias_Threshold" },
  155.   { BOUNDING_OP, "Bounding" },
  156.   { BOUNDING_THRESH_OP, "Bounding_Threshold" },
  157.  
  158.   { CLOCK_OP, "Clock" },
  159.   { CONTINUE_OP, "Continue_Trace" },
  160.   { DRAW_VISTAS_OP, "Draw_Vistas" },
  161.   { END_COLUMN_OP, "End_Column" },
  162.   { END_ROW_OP, "End_Row" },
  163.  
  164.   { FIELD_RENDER_OP, "Field_Render" },
  165.   { HEIGHT_OP, "Height" },
  166.  
  167.   { HIST_NAME_OP, "Histogram_Name" },
  168.   { HIST_SIZE_OP, "Histogram_Grid_Size" },
  169.   { HIST_TYPE_OP, "Histogram_Type" },
  170.   { JITTER_AMOUNT_OP, "Jitter_Amount" },
  171.   { JITTER_OP, "Jitter" },
  172.   { LIBRARY_PATH_OP, "Library_Path" },
  173.   { LIGHT_BUFFER_OP, "Light_Buffer" },
  174.  
  175.   { ODD_FIELD_OP, "Odd_Field" },
  176.   { OUTPUT_ALPHA_OP, "Output_Alpha" },
  177.   { PREVIEW_E_OP, "Preview_End_Size" },
  178.  
  179.   { PREVIEW_S_OP, "Preview_Start_Size" },
  180.   { QUALITY_OP, "Quality" },
  181.   { RAD_SWITCH_OP, "Radiosity" },
  182.   { REMOVE_BOUNDS_OP, "Remove_Bounds" },
  183.  
  184.   { SAMPLING_METHOD_OP, "Sampling_Method" },
  185.   { SPLIT_UNIONS_OP, "Split_Unions" },
  186.   { START_COLUMN_OP, "Start_Column" },
  187.   { START_ROW_OP, "Start_Row" },
  188.  
  189.   { VISTA_BUFFER_OP, "Vista_Buffer" },
  190.   { WIDTH_OP, "Width" },
  191.  
  192.   { BITS_PER_COLOR_OP, "Bits_Per_Color" },
  193.   { BITS_PER_COLOUR_OP, "Bits_Per_Colour" }
  194. };
  195.  
  196. static char temp_string[3]="\0\0";
  197. static char ret_string[7]="IQUFSA";
  198.  
  199. /*****************************************************************************
  200. * static functions
  201. ******************************************************************************/
  202.  
  203. static int matches ( const char *v1, const char *v2 );
  204. static int istrue ( const char *value );
  205. static int isfalse ( const char *value );
  206.  
  207. /*****************************************************************************
  208. *
  209. * FUNCTION
  210. *
  211. *   get_ini_value
  212. *
  213. * INPUT
  214. *
  215. *   op - the .ini option's index
  216. *   libind - if op = LIBRARY_PATH_OP, the library's index
  217. *   
  218. * OUTPUT
  219. *   
  220. * RETURNS
  221. *
  222. *   char * pointing to a static string representation of the
  223. *   option's value.
  224. *   
  225. * AUTHOR
  226. *
  227. *   SCD, 2/95
  228. *   
  229. * DESCRIPTION
  230. *
  231. *   Returns a static string representation of an option's value.
  232. *
  233. * CHANGES
  234. *
  235. *   -
  236. *
  237. ******************************************************************************/
  238.  
  239. const char *get_ini_value(int op, int  libind)
  240. {
  241.   static char value[128];
  242.  
  243.   value[0] = '\0';
  244.  
  245.   switch (op)
  246.   {
  247.     case BUF_SIZE_OP:
  248.       sprintf(value,"%d", opts.File_Buffer_Size>>10);
  249.       return(value);
  250.  
  251.     case BUFFERED_OUTPUT_OP:
  252.       return (opts.Options & BUFFERED_OUTPUT ? "On" : "Off");
  253.  
  254.     case CONTINUE_OP:
  255.       return (opts.Options & CONTINUE_TRACE ? "On" : "Off");
  256.  
  257.     case DISPLAY_OP:
  258.       return (opts.Options & DISPLAY ? "On" : "Off");
  259.  
  260.     case VIDEO_MODE_OP:
  261.       sprintf(value,"%c",opts.DisplayFormat);
  262.       return(value);
  263.  
  264.     case PALETTE_OP:
  265.       sprintf(value,"%c",opts.PaletteOption);
  266.       return(value);
  267.  
  268.     case VERBOSE_OP:
  269.       return (opts.Options & VERBOSE ? "On" : "Off");
  270.  
  271.     case WIDTH_OP:
  272.       sprintf(value,"%d",Frame.Screen_Width);
  273.       return(value);
  274.  
  275.     case HEIGHT_OP:
  276.       sprintf(value,"%d",Frame.Screen_Height);
  277.       return(value);
  278.  
  279.     case FILE_OUTPUT_OP:
  280.       return (opts.Options & DISKWRITE ? "On" : "Off");
  281.  
  282.     case FILE_OUTPUT_TYPE_OP:
  283.       sprintf(value,"%c",opts.OutputFormat);
  284.       return(value);
  285.  
  286.     case PAUSE_WHEN_DONE_OP:
  287.       return (opts.Options & PROMPTEXIT ? "On" : "Off");
  288.  
  289.     case INPUT_FILE_NAME_OP:
  290.       return opts.Input_File_Name;
  291.  
  292.     case OUTPUT_FILE_NAME_OP:
  293.       return opts.Output_File_Name;
  294.  
  295.     case ANTIALIAS_OP:
  296.       return (opts.Options & ANTIALIAS ? "On" : "Off");
  297.  
  298.     case ANTIALIAS_THRESH_OP:
  299.       sprintf(value,"%g",opts.Antialias_Threshold);
  300.       return(value);
  301.  
  302.     case ANTIALIAS_DEPTH_OP:
  303.       sprintf(value,"%ld",opts.AntialiasDepth);
  304.       return(value);
  305.  
  306.     case JITTER_OP:
  307.       return (opts.Options & JITTER ? "On" : "Off");
  308.  
  309.     case JITTER_AMOUNT_OP:
  310.       sprintf(value,"%g",opts.JitterScale);
  311.       return(value);
  312.  
  313.     case TEST_ABORT_OP:
  314.       return (opts.Options & EXITENABLE ? "On" : "Off");
  315.  
  316.     case TEST_ABORT_COUNT_OP:
  317.       sprintf(value,"%d",opts.Abort_Test_Counter);
  318.       return(value);
  319.  
  320.     case LIBRARY_PATH_OP:
  321.       return opts.Library_Paths[libind];
  322.  
  323.     case START_COLUMN_OP:
  324.       if (opts.First_Column == -1)
  325.         sprintf(value,"%g",opts.First_Column_Percent);
  326.       else
  327.         sprintf(value,"%d",opts.First_Column);
  328.       return(value);
  329.  
  330.     case START_ROW_OP:
  331.       if (opts.First_Line == -1)
  332.         sprintf(value,"%g",opts.First_Line_Percent);
  333.       else
  334.         sprintf(value,"%d",opts.First_Line);
  335.       return(value);
  336.  
  337.     case END_COLUMN_OP:
  338.       if (opts.Last_Column == -1)
  339.         sprintf(value,"%g",opts.Last_Column_Percent);
  340.       else
  341.         sprintf(value,"%d",opts.Last_Column);
  342.       return(value);
  343.  
  344.     case END_ROW_OP:
  345.       if (opts.Last_Line == -1)
  346.         sprintf(value,"%g",opts.Last_Line_Percent);
  347.       else
  348.         sprintf(value,"%d",opts.Last_Line);
  349.       return(value);
  350.  
  351.     case VERSION_OP:
  352.       sprintf(value,"%g",(DBL)opts.Language_Version/100.0);
  353.       return(value);
  354.  
  355.     case BOUNDING_OP:
  356.       return (opts.Use_Slabs ? "On" : "Off");
  357.  
  358.     case BOUNDING_THRESH_OP:
  359.       sprintf(value,"%ld",opts.BBox_Threshold);
  360.       return(value);
  361.  
  362.     case QUALITY_OP:
  363.       sprintf(value,"%d",opts.Quality);
  364.       return(value);
  365.  
  366.     case PREVIEW_S_OP:
  367.       sprintf(value,"%d",opts.PreviewGridSize_Start);
  368.       return value;
  369.  
  370.     case PREVIEW_E_OP:
  371.       sprintf(value,"%d",opts.PreviewGridSize_End);
  372.       return value;
  373.  
  374.     case CLOCK_OP:
  375.       sprintf(value,"%g",opts.FrameSeq.Clock_Value);
  376.       return value;
  377.  
  378.     case INITIAL_FRAME_OP:
  379.       sprintf(value,"%d",opts.FrameSeq.InitialFrame);
  380.       return value;
  381.  
  382.     case INITIAL_CLOCK_OP:
  383.       sprintf(value,"%g",opts.FrameSeq.InitialClock);
  384.       return value;
  385.  
  386.     case FINAL_FRAME_OP:
  387.       sprintf(value,"%d",opts.FrameSeq.FinalFrame);
  388.       return value;
  389.  
  390.     case FINAL_CLOCK_OP:
  391.       sprintf(value,"%g",opts.FrameSeq.FinalClock);
  392.       return value;
  393.  
  394.     case SUBSET_START_FRAME_OP:
  395.       sprintf(value,"%d",opts.FrameSeq.SubsetStartFrame);
  396.       return value;
  397.  
  398.     case SUBSET_END_FRAME_OP:
  399.       sprintf(value,"%d",opts.FrameSeq.SubsetEndFrame);
  400.       return value;
  401.  
  402.     case CREATE_INI_OP:
  403.       return opts.Ini_Output_File_Name;
  404.  
  405.     case ALL_CONSOLE_OP:
  406.       return (Stream_Info[ALL_STREAM].do_console ? "On" : "Off");
  407.  
  408.     case ALL_FILE_OP:
  409.       return (Stream_Info[ALL_STREAM].name ? Stream_Info[ALL_STREAM].name : "");
  410.  
  411.     case DEBUG_CONSOLE_OP:
  412.       return (Stream_Info[DEBUG_STREAM].do_console ? "On" : "Off");
  413.  
  414.     case DEBUG_FILE_OP:
  415.       return (Stream_Info[DEBUG_STREAM].name ? Stream_Info[DEBUG_STREAM].name : "");
  416.  
  417.     case RENDER_CONSOLE_OP:
  418.       return (Stream_Info[RENDER_STREAM].do_console ? "On" : "Off");
  419.  
  420.     case RENDER_FILE_OP:
  421.       return (Stream_Info[RENDER_STREAM].name ? Stream_Info[RENDER_STREAM].name : "");
  422.  
  423.     case STATISTIC_CONSOLE_OP:
  424.       return (Stream_Info[STATISTIC_STREAM].do_console ? "On" : "Off");
  425.  
  426.     case STATISTIC_FILE_OP:
  427.       return (Stream_Info[STATISTIC_STREAM].name ? Stream_Info[STATISTIC_STREAM].name : "");
  428.  
  429.     case WARNING_CONSOLE_OP:
  430.       return (Stream_Info[WARNING_STREAM].do_console ? "On" : "Off");
  431.  
  432.     case WARNING_FILE_OP:
  433.       return (Stream_Info[WARNING_STREAM].name ? Stream_Info[WARNING_STREAM].name : "");
  434.  
  435.     case FATAL_CONSOLE_OP:
  436.       return (Stream_Info[FATAL_STREAM].do_console ? "On" : "Off");
  437.  
  438.     case FATAL_FILE_OP:
  439.       return (Stream_Info[FATAL_STREAM].name ? Stream_Info[FATAL_STREAM].name : "");
  440.  
  441.     case RAD_SWITCH_OP:
  442.       return (opts.Options & RADIOSITY ? "On" : "Off");
  443.  
  444.     case HIST_SIZE_OP:
  445.       sprintf (value, "%d.%d", opts.histogram_x, opts.histogram_y) ;
  446.       return (value) ;
  447.  
  448.     case HIST_TYPE_OP:
  449.       switch (opts.histogram_type)
  450.       {
  451.         case CSV :
  452.           return ("C ; CSV") ;
  453.  
  454.         case SYS :
  455.           return ("S ; SYS") ;
  456.  
  457.         case PPM :
  458.           return ("P ; PPM") ;
  459.  
  460.         case TARGA :
  461.           return ("T ; TARGA") ;
  462.  
  463.         case PNG :
  464.           return ("N ; PNG") ;
  465.  
  466.         case NONE :
  467.           return ("X ; NONE") ;
  468.  
  469.       }
  470.       return ("X ; [UNKNOWN VALUE PASSED]") ;
  471.  
  472.     case HIST_NAME_OP:
  473.       return (opts.Histogram_File_Name) ;
  474.  
  475.     case VISTA_BUFFER_OP:
  476.       return ((opts.Options & USE_VISTA_BUFFER) ? "On" : "Off");
  477.  
  478.     case LIGHT_BUFFER_OP:
  479.       return ((opts.Options & USE_LIGHT_BUFFER) ? "On" : "Off");
  480.  
  481.     case DRAW_VISTAS_OP:
  482.       return ((opts.Options & USE_VISTA_DRAW) ? "On" : "Off");
  483.  
  484.     case SPLIT_UNIONS_OP:
  485.       return ((opts.Options & SPLIT_UNION) ? "On" : "Off");
  486.  
  487.     case REMOVE_BOUNDS_OP:
  488.       return ((opts.Options & REMOVE_BOUNDS) ? "On" : "Off");
  489.  
  490.     case CYCLIC_ANIMATION_OP:
  491.       return ((opts.Options & CYCLIC_ANIMATION) ? "On" : "Off");
  492.  
  493.     case PRE_SCENE_CMD_OP:
  494.       return opts.Shellouts[PRE_SCENE_SHL].Command;
  495.  
  496.     case PRE_FRAME_CMD_OP:
  497.       return opts.Shellouts[PRE_FRAME_SHL].Command;
  498.  
  499.     case POST_FRAME_CMD_OP:
  500.       return opts.Shellouts[POST_FRAME_SHL].Command;
  501.  
  502.     case POST_SCENE_CMD_OP:
  503.       return opts.Shellouts[POST_SCENE_SHL].Command;
  504.  
  505.     case USER_ABORT_CMD_OP:
  506.       return opts.Shellouts[USER_ABORT_SHL].Command;
  507.  
  508.     case FATAL_ERROR_CMD_OP:
  509.       return opts.Shellouts[FATAL_SHL].Command;
  510.  
  511.     case PRE_SCENE_RET_OP:
  512.       temp_string[0]=(opts.Shellouts[PRE_SCENE_SHL].Inverse)?'!':' ';
  513.       temp_string[1]=ret_string[opts.Shellouts[PRE_SCENE_SHL].Ret];
  514.       return temp_string;
  515.  
  516.     case PRE_FRAME_RET_OP:
  517.       temp_string[0]=(opts.Shellouts[PRE_FRAME_SHL].Inverse)?'!':' ';
  518.       temp_string[1]=ret_string[opts.Shellouts[PRE_FRAME_SHL].Ret];
  519.       return temp_string;
  520.  
  521.     case POST_FRAME_RET_OP:
  522.       temp_string[0]=(opts.Shellouts[POST_FRAME_SHL].Inverse)?'!':' ';
  523.       temp_string[1]=ret_string[opts.Shellouts[POST_FRAME_SHL].Ret];
  524.       return temp_string;
  525.  
  526.     case POST_SCENE_RET_OP:
  527.       temp_string[0]=(opts.Shellouts[POST_SCENE_SHL].Inverse)?'!':' ';
  528.       temp_string[1]=ret_string[opts.Shellouts[POST_SCENE_SHL].Ret];
  529.       return temp_string;
  530.  
  531.     case USER_ABORT_RET_OP:
  532.       temp_string[0]=(opts.Shellouts[USER_ABORT_SHL].Inverse)?'!':' ';
  533.       temp_string[1]=ret_string[opts.Shellouts[USER_ABORT_SHL].Ret];
  534.       return temp_string;
  535.  
  536.     case FATAL_ERROR_RET_OP:
  537.       temp_string[0]=(opts.Shellouts[FATAL_SHL].Inverse)?'!':' ';
  538.       temp_string[1]=ret_string[opts.Shellouts[FATAL_SHL].Ret];
  539.       return temp_string;
  540.  
  541.     case OUTPUT_ALPHA_OP:
  542.       return ((opts.Options & OUTPUT_ALPHA) ? "On" : "Off");
  543.  
  544.     case FIELD_RENDER_OP:
  545.       return (opts.FrameSeq.Field_Render_Flag ? "On" : "Off");
  546.  
  547.     case ODD_FIELD_OP:
  548.       return (opts.FrameSeq.Odd_Field_Flag ? "On" : "Off");
  549.       
  550.     case SAMPLING_METHOD_OP:
  551.       sprintf(value,"%d",opts.Tracing_Method);
  552.       return value;
  553.  
  554.     case BITS_PER_COLOR_OP:
  555.     case BITS_PER_COLOUR_OP:
  556.       sprintf(value,"%d",opts.OutputQuality);
  557.       return value;
  558.  
  559.     case DISPLAY_GAMMA_OP:
  560.       sprintf(value,"%g",opts.DisplayGamma);
  561.       return value;
  562.  
  563.     case INCLUDE_INI_OP:
  564.       value[0] = '\0';
  565.       return value;
  566.  
  567.     /* NK persist - Nov 1999 */
  568.     case PERSISTENT_ANIMATION_OP:
  569.       return ((opts.persistentAnimation) ? "On" : "Off");
  570.  
  571.     default:
  572.       Error("Unknown INI option in Write_INI.");
  573.   }
  574.  
  575.   return(value);
  576. }
  577.  
  578.  
  579.  
  580. /*****************************************************************************
  581. *
  582. * FUNCTION
  583. *
  584. *   parse_switch
  585. *
  586. * INPUT
  587. *   
  588. * OUTPUT
  589. *   
  590. * RETURNS
  591. *   
  592. * AUTHOR
  593. *
  594. *   POV-Ray Team
  595. *   
  596. * DESCRIPTION
  597. *
  598. *   Parses a traditional POV-Ray command-line switch that starts
  599. *   with + or -.  Whenever it seemed feasible, calls process_variable
  600. *   to perform the function rather than doing so itself.  Although this
  601. *   requires another pass through a switch{case, case...}, it insures
  602. *   that command-line switches and variable=value options get treated
  603. *   identically.
  604. *
  605. * CHANGES
  606. *
  607. *   -
  608. *
  609. *   Sep 1994 : Added options for union splitting, vista/light buffer. [DB]
  610. *   Jan 1995 : Added options for histogram grid. [CJC]
  611. *   Feb 1995 : Added options for console/file redirection and .INI writing [SCD]
  612. *
  613. ******************************************************************************/
  614.  
  615. void parse_switch (char *Option_String)
  616. {
  617.   int i;
  618.   unsigned long Add_Option;
  619.   unsigned long Option_Number;
  620.   long longval;
  621.   DBL floatval;
  622.  
  623.   if (*(Option_String++) == '-')
  624.   {
  625.     Add_Option = FALSE;
  626.   }
  627.   else
  628.   {
  629.     Add_Option = TRUE;
  630.   }
  631.  
  632.   Option_Number = 0;
  633.  
  634.   switch (*Option_String)
  635.   {
  636.     case '?':
  637.  
  638.       if (Option_String[1] == '\0')
  639.       {
  640.         Usage(0, TRUE);
  641.       }
  642.       else
  643.       {
  644.         sscanf (&Option_String[1], "%d", &i);
  645.  
  646.         if ((i >= 0) && (i <= MAX_HELP_PAGE))
  647.         {
  648.           Usage(i, TRUE);
  649.         }
  650.         else
  651.         {
  652.           Usage(0, TRUE);
  653.         }
  654.       }
  655.  
  656.       break;
  657.  
  658.     case '@':
  659.  
  660.       Warning(0,"The +@ switch no longer supported. Use +GS.\n");
  661.  
  662.       break;
  663.  
  664.     case 'A':
  665.     case 'a':
  666.  
  667.       switch (Option_String[1])
  668.       {
  669.         case 'm':
  670.         case 'M':
  671.  
  672.           switch (Option_String[2])
  673.           {
  674.             case '1':
  675.  
  676.               opts.Tracing_Method = 1;
  677.  
  678.               break;
  679.  
  680.             case '2':
  681.  
  682.               opts.Tracing_Method = 2;
  683.  
  684.               break;
  685.  
  686.             default:
  687.  
  688.               Warning(0, "Unknown antialiasing method. Standard method used.\n");
  689.  
  690.               opts.Tracing_Method = 1;
  691.           }
  692.  
  693.           break;
  694.  
  695.         default:
  696.  
  697.           Option_Number = ANTIALIAS;
  698.  
  699.           if (sscanf (&Option_String[1], DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  700.           {
  701.             opts.Antialias_Threshold = floatval;
  702.           }
  703.       }
  704.  
  705.       break;
  706.  
  707.     case 'B':
  708.     case 'b':
  709.  
  710.       process_variable(BUF_SIZE_OP, &Option_String[1]);
  711.  
  712.       if (opts.File_Buffer_Size > 0)
  713.       {
  714.         Option_Number = BUFFERED_OUTPUT;
  715.       }
  716.  
  717.       break;
  718.  
  719.     case 'C':
  720.     case 'c':
  721.  
  722.       Option_Number = CONTINUE_TRACE;
  723.  
  724.       break;
  725.  
  726.     case 'D':
  727.     case 'd':
  728.  
  729.       Option_Number = DISPLAY;
  730.  
  731.       if (Option_String[1] != '\0')
  732.       {
  733.         opts.DisplayFormat = (char)toupper(Option_String[1]);
  734.       }
  735.  
  736.       if (Option_String[1] != '\0' && Option_String[2] != '\0')
  737.       {
  738.         opts.PaletteOption = (char)toupper(Option_String[2]);
  739.       }
  740.  
  741.       break;
  742.  
  743.     case 'E':
  744.     case 'e':
  745.  
  746.       switch (Option_String[1])
  747.       {
  748.         case 'c':
  749.         case 'C':
  750.  
  751.           process_variable(END_COLUMN_OP,&Option_String[2]);
  752.  
  753.           break;
  754.  
  755.         case 'f':
  756.         case 'F':
  757.           if(isdigit((int)Option_String[2])) /* tw */
  758.             process_variable(SUBSET_END_FRAME_OP, &Option_String[2]);
  759.           break;
  760.  
  761.         case 'r':
  762.         case 'R':
  763.  
  764.           process_variable(END_ROW_OP,&Option_String[2]);
  765.  
  766.           break;
  767.  
  768.         case 'p': /* Mosaic Preview Grid Size - End */
  769.         case 'P':
  770.  
  771.           process_variable(PREVIEW_E_OP,&Option_String[2]);
  772.  
  773.           break;
  774.  
  775.         default:
  776.  
  777.           process_variable(END_ROW_OP,&Option_String[1]);
  778.       }
  779.  
  780.       break;
  781.  
  782.     case 'F':
  783.     case 'f':
  784.  
  785.       Option_Number = DISKWRITE;
  786.       
  787.       if (Option_String[1] != '\0')
  788.       {
  789.         opts.OutputFormat = (char)tolower(Option_String[1]);
  790.       }
  791.  
  792.       if (sscanf(&Option_String[2], "%d", &opts.OutputQuality) != 1)
  793.       {
  794.         opts.OutputQuality = 8;
  795.       }
  796.  
  797.       break;
  798.  
  799.     /* Console/file redirection, .INI dump option - [SCD 2/95] */
  800.  
  801.     case 'G':
  802.     case 'g':
  803.  
  804.       switch (Option_String[1])
  805.       {
  806.         case 'a':  /* All */
  807.         case 'A':
  808.  
  809.           process_variable(ALL_CONSOLE_OP,Add_Option ? "On" : "Off");
  810.           process_variable(ALL_FILE_OP,&Option_String[2]);
  811.  
  812.           break;
  813.  
  814.         case 'd':  /* DebugInfo */
  815.         case 'D':
  816.  
  817.           process_variable(DEBUG_CONSOLE_OP,Add_Option ? "On" : "Off");
  818.           process_variable(DEBUG_FILE_OP,&Option_String[2]);
  819.  
  820.           break;
  821.  
  822.         case 'f':  /* Fatal */
  823.         case 'F':
  824.  
  825.           process_variable(FATAL_CONSOLE_OP,Add_Option ? "On" : "Off");
  826.           process_variable(FATAL_FILE_OP,&Option_String[2]);
  827.  
  828.           break;
  829.  
  830.         case 'i':  /* Create .INI containing all settings */
  831.         case 'I':
  832.  
  833.           process_variable(CREATE_INI_OP,&Option_String[2]);
  834.  
  835.           break;
  836.  
  837.         case 'r':  /* RenderInfo */
  838.         case 'R':
  839.  
  840.           process_variable(RENDER_CONSOLE_OP,Add_Option ? "On" : "Off");
  841.           process_variable(RENDER_FILE_OP,&Option_String[2]);
  842.  
  843.           break;
  844.  
  845.         case 's':  /* Statistics */
  846.         case 'S':
  847.  
  848.           process_variable(STATISTIC_CONSOLE_OP,Add_Option ? "On" : "Off");
  849.           process_variable(STATISTIC_FILE_OP,&Option_String[2]);
  850.  
  851.           break;
  852.  
  853.         case 'w':  /* Warning */
  854.         case 'W':
  855.  
  856.           process_variable(WARNING_CONSOLE_OP,Add_Option ? "On" : "Off");
  857.           process_variable(WARNING_FILE_OP,&Option_String[2]);
  858.  
  859.           break;
  860.  
  861.       }
  862.  
  863.       break;
  864.  
  865.     case 'H':
  866.     case 'h':
  867.  
  868.       if (Help_Available)
  869.       {
  870.         if (Option_String[1] == '\0')
  871.         {
  872.           Usage(0, TRUE);
  873.         }
  874.         else
  875.         {
  876.           sscanf (&Option_String[1], "%d", &Frame.Screen_Height);
  877.  
  878.           if ((Frame.Screen_Height >= 0) &&  (Frame.Screen_Height <= MAX_HELP_PAGE))
  879.           {
  880.             Usage(Frame.Screen_Height, TRUE);
  881.           }
  882.         }
  883.       }
  884.       else
  885.       {
  886.         if (!isdigit ((int)Option_String [1])) /* tw */
  887.         {
  888.           switch (Option_String [1])
  889.           {
  890.             case 'n':  /* Histogram name */
  891.             case 'N':
  892.                  process_variable(HIST_NAME_OP,&Option_String[2]);
  893.                  break ;
  894.  
  895.             case 's':  /* Histogram size */
  896.             case 'S':
  897.                  process_variable(HIST_SIZE_OP,&Option_String[2]);
  898.                  break ;
  899.  
  900.             case 't':  /* Histogram type */
  901.             case 'T':
  902.                  process_variable(HIST_TYPE_OP,&Option_String[2]);
  903.                  break ;
  904.           }
  905.         }
  906.         else
  907.         {
  908.           sscanf (&Option_String[1], "%d", &Frame.Screen_Height);
  909.         }
  910.       }
  911.       break;
  912.  
  913.     case 'I':
  914.     case 'i':
  915.  
  916.       if (Option_String[1] == '\0')
  917.       {
  918.         inflag = TRUE;
  919.       }
  920.       else
  921.       {
  922.         process_variable(INPUT_FILE_NAME_OP, &Option_String[1]);
  923.       }
  924.  
  925.       break;
  926.  
  927.     case 'J':
  928.     case 'j':
  929.  
  930.       Option_Number = JITTER;
  931.  
  932.       if (sscanf (&Option_String[1], DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  933.       {
  934.         opts.JitterScale = floatval;
  935.       }
  936.  
  937.       if (opts.JitterScale <= 0.0)
  938.       {
  939.         Add_Option = FALSE;
  940.       }
  941.  
  942.       break;
  943.  
  944.     case 'K':
  945.     case 'k':
  946.  
  947.       /* Animation-type clock specification */
  948.       switch(Option_String[1])
  949.       {
  950.         case 'c':
  951.         case 'C':
  952.           Option_Number = CYCLIC_ANIMATION;
  953.           break;
  954.  
  955.         case 'i':
  956.         case 'I':
  957.           process_variable(INITIAL_CLOCK_OP, &Option_String[2]);
  958.           break;
  959.  
  960.         case 'f':
  961.         case 'F':
  962.           /* Animation-type clock specification */
  963.           switch(Option_String[2])
  964.           {
  965.             case 'i':
  966.             case 'I':
  967.               process_variable(INITIAL_FRAME_OP, &Option_String[3]);
  968.               break;
  969.  
  970.             case 'f':
  971.             case 'F':
  972.               process_variable(FINAL_FRAME_OP, &Option_String[3]);
  973.               break;
  974.                
  975.             default:
  976.               process_variable(FINAL_CLOCK_OP, &Option_String[2]);
  977.               break;
  978.  
  979.           }
  980.           break;
  981.  
  982.         default:
  983.           /* Standard clock specification */
  984.           process_variable(CLOCK_OP,&Option_String[1]);
  985.           break;
  986.       }
  987.       break;
  988.  
  989.     case 'L':
  990.     case 'l':
  991.  
  992.       process_variable(LIBRARY_PATH_OP,&Option_String[1]);
  993.  
  994.       break;
  995.  
  996.     case 'M': /* Switch used so other max values can be inserted easily */
  997.     case 'm':
  998.  
  999.       switch (Option_String[1])
  1000.       {
  1001.         case 's': /* Max Symbols */
  1002.         case 'S':
  1003.  
  1004.           Warning(0,"+MS or -MS switch no longer needed.\n");
  1005.           break;
  1006.  
  1007.         case 'v': /* Max Version */
  1008.         case 'V':
  1009.  
  1010.           sscanf (&Option_String[2], DBL_FORMAT_STRING, &opts.Language_Version);
  1011.           opts.Language_Version = (int)(opts.Language_Version*100.0+0.5);
  1012.  
  1013.           break;
  1014.  
  1015.         case 'b': /* Min Bounded */
  1016.         case 'B':
  1017.  
  1018.           if (sscanf (&Option_String[2], "%ld", &longval) != SCANF_EOF)
  1019.           {
  1020.             opts.BBox_Threshold=longval;
  1021.           }
  1022.  
  1023.           opts.Use_Slabs = Add_Option;
  1024.  
  1025.           break;
  1026.  
  1027.         default:
  1028.  
  1029.           break;
  1030.       }
  1031.  
  1032.       break;
  1033.  
  1034.     /*  "N" option flag is used by networking (multi-processor) options.
  1035.  
  1036.     case 'N':
  1037.     case 'n':
  1038.  
  1039.       break;
  1040.  
  1041.      */
  1042.  
  1043.     case 'O':
  1044.     case 'o':
  1045.  
  1046.       if (Option_String[1] == '\0')
  1047.       {
  1048.         outflag = TRUE;
  1049.       }
  1050.       else
  1051.       {
  1052.         process_variable(OUTPUT_FILE_NAME_OP, &Option_String[1]);
  1053.       }
  1054.  
  1055.       break;
  1056.  
  1057.     case 'P':
  1058.     case 'p':
  1059.  
  1060.       Option_Number = PROMPTEXIT;
  1061.  
  1062.       break;
  1063.  
  1064.     case 'Q':
  1065.     case 'q':
  1066.  
  1067.       switch(Option_String[1])
  1068.       {
  1069.         case 'r':
  1070.         case 'R':
  1071.           Option_Number = RADIOSITY;
  1072.           break;
  1073.         case '0':
  1074.         case '1':
  1075.         case '2':
  1076.         case '3':
  1077.         case '4':
  1078.         case '5':
  1079.         case '6':
  1080.         case '7':
  1081.         case '8':
  1082.         case '9':
  1083.           process_variable(QUALITY_OP,&Option_String[1]);
  1084.           break;
  1085.         default:
  1086.           break;
  1087.       }
  1088.       break;
  1089.  
  1090.     case 'R':
  1091.     case 'r':
  1092.  
  1093.       process_variable(ANTIALIAS_DEPTH_OP,&Option_String[1]);
  1094.  
  1095.       break;
  1096.  
  1097.     case 'S':
  1098.     case 's':
  1099.  
  1100.       switch (Option_String[1])
  1101.       {
  1102.         case 'c':
  1103.         case 'C':
  1104.  
  1105.           process_variable(START_COLUMN_OP,&Option_String[2]);
  1106.  
  1107.           break;
  1108.  
  1109.         case 'r':
  1110.         case 'R':
  1111.  
  1112.           process_variable(START_ROW_OP,&Option_String[2]);
  1113.  
  1114.           break;
  1115.  
  1116.         case 'f':
  1117.         case 'F':
  1118.           process_variable(SUBSET_START_FRAME_OP, &Option_String[2]);
  1119.           break;
  1120.  
  1121.         case 'p': /* Mosaic Preview Grid Size - Start */
  1122.         case 'P':
  1123.  
  1124.           process_variable(PREVIEW_S_OP,&Option_String[2]);
  1125.  
  1126.           break;
  1127.  
  1128.         /* Split unions option. [DB 9/94] */
  1129.  
  1130.         case 'U':
  1131.         case 'u':
  1132.  
  1133.           Option_Number = SPLIT_UNION;
  1134.  
  1135.           break;
  1136.  
  1137.         default:
  1138.  
  1139.           process_variable(START_ROW_OP,&Option_String[1]);
  1140.       }
  1141.  
  1142.       break;
  1143.  
  1144.     /* Read vista/light buffer options. [DB 9/94] */
  1145.  
  1146.     case 'U':
  1147.     case 'u':
  1148.  
  1149.       switch (Option_String[1])
  1150.       {
  1151.         case 'l':
  1152.         case 'L':
  1153.  
  1154.           Option_Number = USE_LIGHT_BUFFER;
  1155.  
  1156.           break;
  1157.  
  1158.         case 'd':
  1159.         case 'D':
  1160.  
  1161.           Option_Number = USE_VISTA_DRAW;
  1162.  
  1163.           break;
  1164.  
  1165.         case 'r':
  1166.         case 'R':
  1167.  
  1168.            Option_Number = REMOVE_BOUNDS;
  1169.  
  1170.            break;
  1171.  
  1172.         case 'v':
  1173.         case 'V':
  1174.  
  1175.           Option_Number = USE_VISTA_BUFFER;
  1176.  
  1177.           break;
  1178.  
  1179.         case 'a':
  1180.         case 'A':
  1181.  
  1182.           Option_Number = OUTPUT_ALPHA;
  1183.  
  1184.           break;
  1185.  
  1186.         case 'f':
  1187.         case 'F':
  1188.  
  1189.           process_variable(FIELD_RENDER_OP, Add_Option ? "True" : "False");
  1190.  
  1191.           break;
  1192.  
  1193.         case 'o':
  1194.         case 'O':
  1195.  
  1196.           process_variable(ODD_FIELD_OP, Add_Option ? "True" : "False");
  1197.  
  1198.           break;
  1199.       }
  1200.  
  1201.       break;
  1202.  
  1203.     case 'V':
  1204.     case 'v':
  1205.  
  1206.       Option_Number = VERBOSE;
  1207.       break;
  1208.  
  1209.     case 'W':
  1210.     case 'w':
  1211.  
  1212.       sscanf (&Option_String[1], "%d", &Frame.Screen_Width);
  1213.  
  1214.       break;
  1215.  
  1216.     case 'X':
  1217.     case 'x':
  1218.  
  1219.       Option_Number = EXITENABLE;
  1220.  
  1221.       sscanf (&Option_String[1], "%d", &Abort_Test_Every);
  1222.  
  1223.       opts.Abort_Test_Counter = Abort_Test_Every;
  1224.  
  1225.       break;
  1226.  
  1227.     default:
  1228.  
  1229.       Warning (0,"Invalid option: %s.\n", --Option_String);
  1230.   }
  1231.  
  1232.   if (Option_Number != 0)
  1233.   {
  1234.     if (Add_Option)
  1235.     {
  1236.       opts.Options |= Option_Number;
  1237.     }
  1238.     else
  1239.     {
  1240.       opts.Options &= ~Option_Number;
  1241.     }
  1242.   }
  1243. }
  1244.  
  1245.  
  1246.  
  1247.  
  1248. /*****************************************************************************
  1249. *
  1250. * FUNCTION
  1251. *
  1252. *   process_variable
  1253. *
  1254. * INPUT
  1255. *
  1256. * OUTPUT
  1257. *   
  1258. * RETURNS
  1259. *   
  1260. * AUTHOR
  1261. *
  1262. *   POV-Ray Team
  1263. *   
  1264. * DESCRIPTION
  1265. *
  1266. *   Given a token number representing an option variable and a string
  1267. *   that is the value to set, set one option.  If its just an on/off
  1268. *   switch that takes a boolean value then just set Option_Number and
  1269. *   break.  Otherwise process the value and return. 
  1270. *
  1271. * CHANGES
  1272. *
  1273. *   -
  1274. *
  1275. ******************************************************************************/
  1276.  
  1277. void process_variable(TOKEN variable,const char *value)
  1278. {
  1279.   int i;
  1280.   long longval;
  1281.   unsigned int Option_Number = 0;
  1282.   DBL floatval;
  1283.  
  1284.   /* NK ini */
  1285.   if (Stage!=STAGE_INI_FILE && Stage!=STAGE_COMMAND_LINE)
  1286.   {
  1287.     if (variable<=LAST_INI_ONLY_OP)
  1288.       Error("The ini option is not allowed in a POV file.\n");
  1289.   }
  1290.   /* NK ---- */
  1291.  
  1292.   switch (variable)
  1293.   {
  1294.     case BUF_SIZE_OP:
  1295.       if (sscanf (value, "%d", &opts.File_Buffer_Size) != SCANF_EOF)
  1296.       {
  1297.         opts.File_Buffer_Size *= 1024;
  1298.  
  1299.         if (opts.File_Buffer_Size > MAX_BUFSIZE)
  1300.           opts.File_Buffer_Size = MAX_BUFSIZE;
  1301.  
  1302.         /* If 0 then no buffer, other low values use system default MIN */
  1303.         if ((opts.File_Buffer_Size > 0) && (opts.File_Buffer_Size < BUFSIZ))
  1304.         {
  1305.           opts.File_Buffer_Size = BUFSIZ;
  1306.         }
  1307.         if (opts.File_Buffer_Size <= 0)
  1308.         {
  1309.           opts.Options &= ~BUFFERED_OUTPUT;
  1310.         }
  1311.       }
  1312.       return;
  1313.  
  1314.     case BUFFERED_OUTPUT_OP:
  1315.       Option_Number = BUFFERED_OUTPUT;
  1316.       break;
  1317.  
  1318.     case CONTINUE_OP:
  1319.       Option_Number = CONTINUE_TRACE;
  1320.       break;
  1321.  
  1322.     case DISPLAY_OP:
  1323.       Option_Number = DISPLAY;
  1324.       break;
  1325.  
  1326.     case VIDEO_MODE_OP:
  1327.       opts.DisplayFormat = (char)toupper(value[0]);
  1328.       return;
  1329.  
  1330.     case PALETTE_OP:
  1331.       opts.PaletteOption = (char)toupper(value[0]);
  1332.       return;
  1333.  
  1334.     case VERBOSE_OP:
  1335.       Option_Number = VERBOSE;
  1336.       break;
  1337.  
  1338.     case WIDTH_OP:
  1339.       Frame.Screen_Width = atoi(value);
  1340.       return;
  1341.  
  1342.     case HEIGHT_OP:
  1343.       Frame.Screen_Height = atoi(value);
  1344.       return;
  1345.  
  1346.     case FILE_OUTPUT_OP:
  1347.       Option_Number = DISKWRITE;
  1348.       break;
  1349.  
  1350.     case FILE_OUTPUT_TYPE_OP:
  1351.       opts.OutputFormat = (char)tolower(value[0]);
  1352.       return;
  1353.  
  1354.     case PAUSE_WHEN_DONE_OP:
  1355.       Option_Number = PROMPTEXIT;
  1356.       break;
  1357.  
  1358.     case INPUT_FILE_NAME_OP:
  1359.       if (!strcmp(value, "-") || !strcmp(value, "stdin"))
  1360.       {
  1361.         strcpy (opts.Input_File_Name, "stdin");
  1362.         opts.Options |= FROM_STDIN;
  1363.       }
  1364.       else
  1365.       {
  1366.         strncpy (opts.Input_File_Name, value, FILE_NAME_LENGTH);
  1367.       }
  1368.       return;
  1369.  
  1370.     case OUTPUT_FILE_NAME_OP:
  1371.       if (!strcmp(value, "-") || !strcmp(value, "stdout"))
  1372.       {
  1373.         strcpy (opts.Output_File_Name, "stdout");
  1374.         opts.Options |= TO_STDOUT;
  1375.       }
  1376.       else
  1377.       {
  1378.         strncpy (opts.Output_File_Name, value, FILE_NAME_LENGTH);
  1379.       }
  1380.       return;
  1381.  
  1382.     case ANTIALIAS_OP:
  1383.       Option_Number = ANTIALIAS;
  1384.       break;
  1385.  
  1386.     case ANTIALIAS_THRESH_OP:
  1387.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1388.         opts.Antialias_Threshold = floatval;
  1389.       return;
  1390.  
  1391.     case ANTIALIAS_DEPTH_OP:
  1392.       if (sscanf (value, "%ld", &longval) != SCANF_EOF)
  1393.         opts.AntialiasDepth = longval;
  1394.       if (opts.AntialiasDepth < 1)
  1395.         opts.AntialiasDepth = 1;
  1396.       if (opts.AntialiasDepth > 9)
  1397.         opts.AntialiasDepth = 9;
  1398.       return;
  1399.  
  1400.     case JITTER_OP:
  1401.       Option_Number = JITTER;
  1402.       break;
  1403.  
  1404.     case JITTER_AMOUNT_OP:
  1405.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1406.         opts.JitterScale = floatval;
  1407.       if (opts.JitterScale<=0.0)
  1408.         opts.Options &= ~JITTER;
  1409.       return;
  1410.  
  1411.     case TEST_ABORT_OP:
  1412.       Option_Number = EXITENABLE;
  1413.       break;
  1414.  
  1415.     case TEST_ABORT_COUNT_OP:
  1416.       sscanf (value, "%d", &Abort_Test_Every);
  1417.       opts.Abort_Test_Counter = Abort_Test_Every;
  1418.       break;
  1419.  
  1420.     case LIBRARY_PATH_OP:
  1421.       if (opts.Library_Path_Index >= MAX_LIBRARIES)
  1422.         Error ("Too many library directories specified.");
  1423.       for (i = 0; i < opts.Library_Path_Index; i++)
  1424.         if (strcmp(value,opts.Library_Paths[i])==0) return;
  1425.       opts.Library_Paths[opts.Library_Path_Index] = (char *)POV_MALLOC(strlen(value)+1,
  1426.                  "library paths");
  1427.       strcpy (opts.Library_Paths [opts.Library_Path_Index], value);
  1428.       opts.Library_Path_Index++;
  1429.       return;
  1430.  
  1431.     case START_COLUMN_OP:
  1432.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1433.       { /* tw */
  1434.         if(floatval > 0.0 && floatval < 1.0)
  1435.         {
  1436.           opts.First_Column = -1;
  1437.           opts.First_Column_Percent = floatval;
  1438.         }
  1439.         else
  1440.           opts.First_Column = ((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 
  1443.            */
  1444.       } /* tw */
  1445.       return;
  1446.  
  1447.     case START_ROW_OP:
  1448.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1449.       { /* tw */
  1450.         if(floatval > 0.0 && floatval < 1.0)
  1451.         {
  1452.           opts.First_Line = -1;
  1453.           opts.First_Line_Percent = floatval;
  1454.         }
  1455.         else
  1456.           opts.First_Line = ((int) floatval);
  1457.           /* The above used to have -1 but it messed up Write_INI_File
  1458.           * Moved -1 fudge to fix_up_rendering_window 
  1459.           */
  1460.       } /* tw */
  1461.       return;
  1462.  
  1463.     case END_COLUMN_OP:
  1464.       { /* tw */
  1465.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1466.         if(floatval > 0.0 && floatval <= 1.0)
  1467.         {
  1468.           opts.Last_Column = -1;
  1469.           opts.Last_Column_Percent = floatval;
  1470.         }
  1471.         else
  1472.           opts.Last_Column = (int) floatval;
  1473.       } /* tw */
  1474.       return;
  1475.  
  1476.     case END_ROW_OP:
  1477.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1478.       { /* tw */
  1479.         if(floatval > 0.0 && floatval <= 1.0)
  1480.         {
  1481.           opts.Last_Line = -1;
  1482.           opts.Last_Line_Percent = floatval;
  1483.         }
  1484.         else
  1485.           opts.Last_Line = (int) floatval;
  1486.       } /* tw */
  1487.       return;
  1488.  
  1489.     case VERSION_OP:
  1490.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1491.         opts.Language_Version = (int)(floatval*100.0+0.5);
  1492.       return;
  1493.  
  1494.     case BOUNDING_OP:
  1495.       opts.Use_Slabs = istrue(value);
  1496.       return;
  1497.  
  1498.     case BOUNDING_THRESH_OP:
  1499.       opts.BBox_Threshold = atoi(value);
  1500.       return;
  1501.  
  1502.     case QUALITY_OP:
  1503.       opts.Quality = atoi(value);
  1504.       /* Emit a warning about the "radiosity" quality levels for
  1505.        * now.  We can get rid of this some time in the future.
  1506.        */
  1507.       if ((opts.Quality == 10) || (opts.Quality == 11))
  1508.       {
  1509.          Warning(0, "Quality settings 10 and 11 are no longer valid.\n"
  1510.                       "Use +QR if you need radiosity.\n");
  1511.          opts.Quality = 9;
  1512.       }
  1513.       else if ((opts.Quality < 0) || (opts.Quality > 9))
  1514.       {
  1515.          Error("Illegal Quality setting.");
  1516.       }
  1517.       opts.Quality_Flags = Quality_Values[opts.Quality];
  1518.       return;
  1519.  
  1520.     case CLOCK_OP:
  1521.       if(sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1522.       {
  1523.         opts.FrameSeq.Clock_Value = floatval;
  1524.       }
  1525.       return;
  1526.  
  1527.     case INITIAL_FRAME_OP:
  1528.       if(sscanf(value, "%ld", &longval)!=SCANF_EOF)
  1529.       {
  1530.         opts.FrameSeq.InitialFrame=longval;
  1531.       }
  1532.       return;
  1533.  
  1534.     case INITIAL_CLOCK_OP:
  1535.       if(sscanf(value, DBL_FORMAT_STRING, &floatval)!=SCANF_EOF)
  1536.       {
  1537.         opts.FrameSeq.InitialClock=floatval;
  1538.       }
  1539.       return;
  1540.  
  1541.     case FINAL_FRAME_OP:
  1542.       if(sscanf(value, "%ld", &longval)!=SCANF_EOF)
  1543.       {
  1544.         opts.FrameSeq.FinalFrame=longval;
  1545.       }
  1546.       return;
  1547.  
  1548.     case FINAL_CLOCK_OP:
  1549.       if(sscanf(value, DBL_FORMAT_STRING, &floatval)!=SCANF_EOF)
  1550.       {
  1551.         opts.FrameSeq.FinalClock=floatval;
  1552.       }
  1553.       return;
  1554.  
  1555.     case SUBSET_START_FRAME_OP:
  1556.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1557.       {
  1558.         if(floatval > 0.0 && floatval < 1.0)
  1559.           opts.FrameSeq.SubsetStartPercent=floatval;
  1560.         else
  1561.           opts.FrameSeq.SubsetStartFrame=(int)floatval;
  1562.       }
  1563.       return;
  1564.  
  1565.     case SUBSET_END_FRAME_OP:
  1566.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1567.       {
  1568.         if(floatval > 0.0 && floatval < 1.0)
  1569.           opts.FrameSeq.SubsetEndPercent=floatval;
  1570.         else
  1571.           opts.FrameSeq.SubsetEndFrame=(int)floatval;
  1572.       }
  1573.       return;
  1574.  
  1575.     case PREVIEW_S_OP:
  1576.       opts.PreviewGridSize_Start = atoi(value);
  1577.       return;
  1578.  
  1579.     case PREVIEW_E_OP:
  1580.       opts.PreviewGridSize_End = atoi(value);
  1581.       return;
  1582.  
  1583.     case CREATE_INI_OP:
  1584.       strcpy(opts.Ini_Output_File_Name,value);
  1585.       return;
  1586.  
  1587.     case ALL_CONSOLE_OP:
  1588.       Stream_Info[ALL_STREAM].do_console =
  1589.       Stream_Info[WARNING_STREAM].do_console =
  1590.       Stream_Info[STATISTIC_STREAM].do_console =
  1591.       Stream_Info[RENDER_STREAM].do_console = 
  1592.       Stream_Info[FATAL_STREAM].do_console = 
  1593.       Stream_Info[DEBUG_STREAM].do_console = istrue(value);
  1594.       return;
  1595.  
  1596.     case ALL_FILE_OP:
  1597.       Do_Stream_Option(ALL_STREAM,value);
  1598.       return;
  1599.  
  1600.     case DEBUG_CONSOLE_OP:
  1601.       Stream_Info[DEBUG_STREAM].do_console = istrue(value);
  1602.       return;
  1603.  
  1604.     case DEBUG_FILE_OP:
  1605.       Do_Stream_Option(DEBUG_STREAM,value);
  1606.       return;
  1607.  
  1608.     case FATAL_CONSOLE_OP:
  1609.       Stream_Info[FATAL_STREAM].do_console = istrue(value);
  1610.       return;
  1611.  
  1612.     case FATAL_FILE_OP:
  1613.       Do_Stream_Option(FATAL_STREAM,value);
  1614.       return;
  1615.  
  1616.     case RENDER_CONSOLE_OP:
  1617.       Stream_Info[RENDER_STREAM].do_console = istrue(value);
  1618.       return;
  1619.  
  1620.     case RENDER_FILE_OP:
  1621.       Do_Stream_Option(RENDER_STREAM,value);
  1622.       return;
  1623.  
  1624.     case STATISTIC_CONSOLE_OP:
  1625.       Stream_Info[STATISTIC_STREAM].do_console = istrue(value);
  1626.       return;
  1627.  
  1628.     case STATISTIC_FILE_OP:
  1629.       Do_Stream_Option(STATISTIC_STREAM,value);
  1630.       return;
  1631.  
  1632.     case WARNING_CONSOLE_OP:
  1633.       Stream_Info[WARNING_STREAM].do_console = istrue(value);
  1634.       return;
  1635.  
  1636.     case WARNING_FILE_OP:
  1637.       Do_Stream_Option(WARNING_STREAM,value);
  1638.       return;
  1639.  
  1640.     case RAD_SWITCH_OP:
  1641.       Option_Number = RADIOSITY;
  1642.       break;
  1643.  
  1644.     case HIST_SIZE_OP:
  1645.       if (sscanf (value, "%d.%d", &opts.histogram_x, &opts.histogram_y) == SCANF_EOF)
  1646.       {
  1647.         Warning (0, "Error occurred scanning histogram grid size '%s'.\n", value) ;
  1648.         opts.histogram_on = FALSE ;
  1649.       }
  1650.       break ;
  1651.  
  1652.     case HIST_TYPE_OP:
  1653. #if PRECISION_TIMER_AVAILABLE
  1654.     {
  1655.       char *def_ext = NULL;
  1656.  
  1657.       switch (*value)
  1658.       {
  1659.         case 'C' :
  1660.         case 'c' :
  1661.              opts.histogram_on = TRUE ;
  1662.              opts.histogram_type = CSV ;
  1663.              def_ext = ".csv";
  1664.              break ;
  1665.         case 'S' :
  1666.         case 's' :
  1667.              opts.histogram_on = TRUE ;
  1668.              opts.histogram_type = SYS ;
  1669.              Histogram_File_Handle = GET_SYS_FILE_HANDLE () ;
  1670.              def_ext = SYS_DEF_EXT;
  1671.              break ;
  1672.         case 'P' :
  1673.         case 'p' :
  1674.              opts.histogram_on = TRUE ;
  1675.              opts.histogram_type = PPM ;
  1676.              Histogram_File_Handle = Get_PPM_File_Handle () ;
  1677.              def_ext = ".ppm";
  1678.              break ;
  1679.         case 'T' :
  1680.         case 't' :
  1681.              opts.histogram_on = TRUE ;
  1682.              opts.histogram_type = TARGA ;
  1683.              Histogram_File_Handle = Get_Targa_File_Handle () ;
  1684.              def_ext = ".tga";
  1685.              break ;
  1686.         case 'n':
  1687.         case 'N':
  1688.              opts.histogram_on = TRUE ;
  1689.              opts.histogram_type = PNG ;
  1690.              Histogram_File_Handle = Get_Png_File_Handle () ;
  1691.              def_ext = ".png";
  1692.              break ;
  1693.         case 'x':
  1694.         case 'X':
  1695.              opts.histogram_on = FALSE ;
  1696.              break ;
  1697.         default :
  1698.              Warning (0, "Unknown histogram output type '%c'.\n", *value) ;
  1699.              opts.histogram_on = FALSE ;
  1700.              break ;
  1701.       }
  1702.  
  1703.       /* Process the histogram file name now, if it hasn't
  1704.        * yet been specified, and in case it isn't set later.
  1705.        */
  1706.       if (opts.histogram_on && opts.Histogram_File_Name[0] == '\0')
  1707.       {
  1708.         sprintf(opts.Histogram_File_Name, "histgram%s", def_ext);
  1709.       }
  1710.     }
  1711. #else  /* !PRECISION_TIMER_AVAILABLE */
  1712.       if (*value != 'x' && *value != 'X')
  1713.         Warning(0,"Histogram output unavailable in this compile of POV-Ray");
  1714.       opts.histogram_on = FALSE;
  1715. #endif /* PRECISION_TIMER_AVAILABLE */
  1716.       break ;
  1717.  
  1718.     case HIST_NAME_OP:
  1719.       if (opts.histogram_on && value[0] == '\0')
  1720.       {
  1721.         char *def_ext = NULL;
  1722.  
  1723.         switch (opts.histogram_type)
  1724.         {
  1725.           case CSV:   def_ext = ".csv"; break;
  1726.           case TARGA: def_ext = ".tga"; break;
  1727.           case PNG:   def_ext = ".png"; break;
  1728.           case PPM:   def_ext = ".ppm"; break;
  1729.           case SYS:   def_ext = SYS_DEF_EXT; break;
  1730.           case NONE:  def_ext = "";     break;  /* To quiet warnings */
  1731.         }
  1732.  
  1733.         sprintf(opts.Histogram_File_Name, "histgram%s", def_ext);
  1734.       }
  1735.       else
  1736.       {
  1737.         strncpy (opts.Histogram_File_Name, value, FILE_NAME_LENGTH);
  1738.       }
  1739.       break ;
  1740.  
  1741.     case VISTA_BUFFER_OP:
  1742.       Option_Number = USE_VISTA_BUFFER;
  1743.       break;
  1744.  
  1745.     case LIGHT_BUFFER_OP:
  1746.       Option_Number = USE_LIGHT_BUFFER;
  1747.       break;
  1748.  
  1749.     case DRAW_VISTAS_OP:
  1750.       Option_Number = USE_VISTA_DRAW;
  1751.       break;
  1752.  
  1753.     case SPLIT_UNIONS_OP:
  1754.       Option_Number = SPLIT_UNION;
  1755.       break;
  1756.  
  1757.     case REMOVE_BOUNDS_OP:
  1758.       Option_Number = REMOVE_BOUNDS;
  1759.       break;
  1760.  
  1761.     case CYCLIC_ANIMATION_OP:
  1762.       Option_Number = CYCLIC_ANIMATION;
  1763.       break;
  1764.  
  1765.     case PRE_SCENE_CMD_OP:
  1766.       strcpy(opts.Shellouts[PRE_SCENE_SHL].Command, value);
  1767.       break;
  1768.  
  1769.     case PRE_FRAME_CMD_OP:
  1770.       strcpy(opts.Shellouts[PRE_FRAME_SHL].Command, value);
  1771.       break;
  1772.  
  1773.     case POST_FRAME_CMD_OP:
  1774.       strcpy(opts.Shellouts[POST_FRAME_SHL].Command, value);
  1775.       break;
  1776.  
  1777.     case POST_SCENE_CMD_OP:
  1778.       strcpy(opts.Shellouts[POST_SCENE_SHL].Command, value);
  1779.       break;
  1780.  
  1781.     case USER_ABORT_CMD_OP:
  1782.       strcpy(opts.Shellouts[USER_ABORT_SHL].Command, value);
  1783.       break;
  1784.  
  1785.     case FATAL_ERROR_CMD_OP:
  1786.       strcpy(opts.Shellouts[FATAL_SHL].Command, value);
  1787.       break;
  1788.  
  1789.     case PRE_SCENE_RET_OP:
  1790.       Do_Return_Option(PRE_SCENE_SHL, value);
  1791.       break;
  1792.  
  1793.     case PRE_FRAME_RET_OP:
  1794.       Do_Return_Option(PRE_FRAME_SHL, value);
  1795.       break;
  1796.  
  1797.     case POST_FRAME_RET_OP:
  1798.       Do_Return_Option(POST_FRAME_SHL, value);
  1799.       break;
  1800.  
  1801.     case POST_SCENE_RET_OP:
  1802.       Do_Return_Option(POST_SCENE_SHL, value);
  1803.       break;
  1804.  
  1805.     case USER_ABORT_RET_OP:
  1806.       Do_Return_Option(USER_ABORT_SHL, value);
  1807.       break;
  1808.  
  1809.     case FATAL_ERROR_RET_OP:
  1810.       Do_Return_Option(FATAL_SHL, value);
  1811.       break;
  1812.  
  1813.     case OUTPUT_ALPHA_OP:
  1814.       Option_Number = OUTPUT_ALPHA;
  1815.       break;
  1816.  
  1817.     case FIELD_RENDER_OP:
  1818.       opts.FrameSeq.Field_Render_Flag = istrue(value);
  1819.       return;
  1820.  
  1821.     case ODD_FIELD_OP:
  1822.       opts.FrameSeq.Odd_Field_Flag = istrue(value);
  1823.       return;
  1824.  
  1825.     case SAMPLING_METHOD_OP:
  1826.       opts.Tracing_Method = atoi(value);
  1827.       return;
  1828.  
  1829.     case BITS_PER_COLOR_OP:
  1830.     case BITS_PER_COLOUR_OP:
  1831.       opts.OutputQuality = atoi(value);
  1832.       opts.OutputQuality = max(5,  opts.OutputQuality);
  1833.       opts.OutputQuality = min(16, opts.OutputQuality);
  1834.       return;
  1835.  
  1836.     case DISPLAY_GAMMA_OP:
  1837.       if (sscanf (value, DBL_FORMAT_STRING, &floatval) != SCANF_EOF)
  1838.       {
  1839.         if (floatval > 0.0)
  1840.           opts.DisplayGamma = floatval;
  1841.       }
  1842.       return;
  1843.  
  1844.     case INCLUDE_INI_OP:
  1845.       if (!parse_ini_file(value))
  1846.       {
  1847.         Error ("Could not open Include_Ini='%s'.\n", value);
  1848.       }
  1849.       return;
  1850.  
  1851.     /* NK persist - Nov 1999 */
  1852.     case PERSISTENT_ANIMATION_OP:
  1853.       opts.persistentAnimation = istrue(value);
  1854.       return;
  1855.  
  1856.     default:
  1857.       Warning(0,"Unimplemented INI '%s'.\n",Option_Variable[variable].Token_Name);
  1858.       return;
  1859.  
  1860.   }
  1861.  
  1862.   if (Option_Number != 0)
  1863.   {
  1864.     if (istrue(value))
  1865.     {
  1866.       opts.Options |= Option_Number;
  1867.     }
  1868.     else
  1869.     {
  1870.       opts.Options &= ~Option_Number;
  1871.     }
  1872.   }
  1873. }
  1874.  
  1875.  
  1876.  
  1877. /*****************************************************************************
  1878. *
  1879. * FUNCTION
  1880. *
  1881. *   istrue
  1882. *
  1883. * INPUT
  1884. *   
  1885. * OUTPUT
  1886. *   
  1887. * RETURNS
  1888. *   
  1889. * AUTHOR
  1890. *
  1891. *   POV-Ray Team
  1892. *   
  1893. * DESCRIPTION
  1894. *
  1895. *   -
  1896. *
  1897. * CHANGES
  1898. *
  1899. *   -
  1900. *
  1901. ******************************************************************************/
  1902.  
  1903. static int matches(const char *v1,const char  *v2)
  1904. {
  1905.   int i=0;
  1906.   int ans=TRUE;
  1907.   
  1908.   while ((ans) && (v1[i] != '\0') && (v2[i] != '\0'))
  1909.   {
  1910.     ans = ans && (v1[i] == tolower(v2[i]));
  1911.     i++;
  1912.   }
  1913.   
  1914.   return(ans);
  1915. }
  1916.  
  1917. static int istrue(const char *value)
  1918. {
  1919.    return (matches("on",value)  || matches("true",value) || 
  1920.            matches("yes",value) || matches("1",value));
  1921. }
  1922.  
  1923. static int isfalse(const char *value)
  1924. {
  1925.    return (matches("off",value)  || matches("false",value) || 
  1926.            matches("no",value)   || matches("0",value));
  1927. }
  1928.  
  1929.  
  1930. /*****************************************************************************
  1931. *
  1932. * FUNCTION
  1933. *
  1934. *   Write_INI_File
  1935. *
  1936. * INPUT
  1937. *   
  1938. * OUTPUT
  1939. *   
  1940. * RETURNS
  1941. *   
  1942. * AUTHOR
  1943. *
  1944. *   SCD, 2/95
  1945. *   
  1946. * DESCRIPTION
  1947. *
  1948. *   Writes all options to an INI file with the current input filename's name
  1949. *   (by default), or using a specified filename.
  1950. *
  1951. * CHANGES
  1952. *
  1953. *   -
  1954. *
  1955. ******************************************************************************/
  1956.  
  1957. void Write_INI_File()
  1958. {
  1959.   int  op, i;
  1960.   char ini_name[FILE_NAME_LENGTH];
  1961.   FILE *ini_file;
  1962.  
  1963.   if (opts.Ini_Output_File_Name[0]=='\0')
  1964.   {
  1965.     return;
  1966.   }
  1967.  
  1968.   if (isfalse(opts.Ini_Output_File_Name))
  1969.   {
  1970.     return;
  1971.     }
  1972.  
  1973.   Status_Info("\nWriting INI file...");
  1974.  
  1975.   if (istrue(opts.Ini_Output_File_Name))
  1976.       {
  1977.     strcpy(ini_name,opts.Scene_Name);
  1978.     strcat(ini_name,".ini");
  1979.       }
  1980.       else
  1981.       {
  1982.     strcpy(ini_name,opts.Ini_Output_File_Name);
  1983.   }
  1984.  
  1985.   if ((ini_file = fopen(ini_name, WRITE_TXTFILE_STRING)) == NULL)
  1986.   {
  1987.     Warning (0,"Error opening .INI output file '%s' - no file written.\n",
  1988.                     ini_name);
  1989.  
  1990.     return;
  1991.   }
  1992.  
  1993.   for (op = 0; op < MAX_OPTION; op++)
  1994.   {
  1995.     if (op == LIBRARY_PATH_OP)
  1996.     {
  1997.       for (i = 0; i < opts.Library_Path_Index; i++)
  1998.       {
  1999.         fprintf(ini_file,"%s=%s%s",Option_Variable[op].Token_Name,
  2000.                    get_ini_value(op, i),NEW_LINE_STRING);
  2001.       }
  2002.     }
  2003.     /* So that we don't get both Bits_Per_Color and Bits_Per_Colour in
  2004.      * the INI file. */
  2005.     else if ((op != BITS_PER_COLOUR_OP) && (op != INCLUDE_INI_OP))
  2006.     {
  2007.       fprintf(ini_file,"%s=%s%s",Option_Variable[op].Token_Name,
  2008.                    get_ini_value(op, 0),NEW_LINE_STRING);
  2009.     }
  2010.   }
  2011.  
  2012.   fclose(ini_file);
  2013. }
  2014.  
  2015.  
  2016.  
  2017. /*****************************************************************************
  2018. *
  2019. * FUNCTION
  2020. *
  2021. *   parse_ini_file
  2022. *
  2023. * INPUT
  2024. *   
  2025. * OUTPUT
  2026. *   
  2027. * RETURNS
  2028. *   
  2029. * AUTHOR
  2030. *
  2031. *   POV-Ray Team
  2032. *   
  2033. * DESCRIPTION
  2034. *
  2035. *   Given a file name, open it, parse options from it, close it.
  2036. *   Return 1 if file found, 0 if not found.
  2037. *
  2038. * CHANGES
  2039. *
  2040. *   -
  2041. *
  2042. ******************************************************************************/
  2043.  
  2044. int parse_ini_file(const char *File_Name)
  2045. {
  2046.   char Option_Line[512];
  2047.   char INI_Name[FILE_NAME_LENGTH];
  2048.   char Desired_Section[FILE_NAME_LENGTH];
  2049.   char Current_Section[FILE_NAME_LENGTH];
  2050.   char *source, *dest;
  2051.   FILE *ini_file;
  2052.   int Matched, Never_Matched;
  2053.  
  2054.   Stage=STAGE_INI_FILE;
  2055.   
  2056.   /* File_Name can be of the for "FILE.INI[Section]" where everything
  2057.    * before the '[' is the actual name and "[Section]" is the title of
  2058.    * a section within that file that starts with the [Section] heading.  
  2059.    * Only the specified section of the INI file is processed.  If no
  2060.    * section is specified then only parts of the file without a section
  2061.    * header are processed.
  2062.    */
  2063.    
  2064.   /* Copy the file name part */
  2065.   source=(char*)File_Name;
  2066.   dest=INI_Name;
  2067.   while ((*source != '\0') && (*source != '['))
  2068.   {
  2069.     *(dest++) = *(source++);
  2070.   }
  2071.   *dest = '\0';
  2072.  
  2073.   /* Copy the section name part */
  2074.   dest = Desired_Section;
  2075.   while ((*source != '\0') && (*source != ']'))
  2076.   {
  2077.     *(dest++) = *(source++);
  2078.   }
  2079.   *dest = *source;
  2080.   *(++dest)='\0';
  2081.  
  2082.   if ((ini_file = Locate_File(INI_Name, READ_TXTFILE_STRING,".ini",".INI",NULL,FALSE)) == NULL)
  2083.   {
  2084.     return(FALSE);
  2085.   }
  2086.   
  2087.   *Current_Section='\0';
  2088.   
  2089.   Matched = (*Desired_Section == '\0');
  2090.   Never_Matched=TRUE;
  2091.   
  2092.   while (fgets(Option_Line, 512, ini_file) != NULL)
  2093.   {
  2094.     if (*Option_Line == '[')
  2095.     {
  2096.       source=Option_Line;
  2097.       dest=Current_Section;
  2098.       while ((*source != '\0') && (*source != ']'))
  2099.       {
  2100.         *(dest++) = *(source++);
  2101.       }
  2102.       *dest = *source;
  2103.       *(++dest)='\0';
  2104.       Matched = (pov_stricmp(Current_Section, Desired_Section) == 0);
  2105.       
  2106.     }
  2107.     else
  2108.     {    
  2109.        if (Matched)
  2110.        {
  2111.           parse_option_line(Option_Line);
  2112.           Never_Matched=FALSE;
  2113.        }
  2114.     }
  2115.   }
  2116.  
  2117.   if (Never_Matched)
  2118.   {
  2119.      Warning(0,"Never found section %s in file %s.\n",Desired_Section,INI_Name);
  2120.   }
  2121.   
  2122.   fclose(ini_file);
  2123.  
  2124.   return(TRUE);
  2125. }
  2126.  
  2127.  
  2128. /*****************************************************************************
  2129. *
  2130. * FUNCTION
  2131. *
  2132. *   parse_option_line
  2133. *
  2134. * INPUT
  2135. *   
  2136. * OUTPUT
  2137. *   
  2138. * RETURNS
  2139. *   
  2140. * AUTHOR
  2141. *
  2142. *   POV-Ray Team
  2143. *   
  2144. * DESCRIPTION
  2145. *
  2146. *   Given a string containing a line of text, split it into individual
  2147. *   switches or options and then pass them off to be parsed by parse_switch
  2148. *   or process_variable.  This routine is called by parse_ini_file,
  2149. *   by the main with argv[] and by READ_ENV_VAR_????
  2150. *
  2151. * CHANGES
  2152. *
  2153. *   Mar 1996 : Allow ';' in an option, if it is escaped  [AED]
  2154. *
  2155. ******************************************************************************/
  2156.  
  2157. void parse_option_line(const char *Option_Line)
  2158. {
  2159.   char *source, *dest;
  2160.   char Option_String[512];
  2161.   int i,Found;
  2162.  
  2163.   source = (char*) Option_Line;
  2164.  
  2165.   while (TRUE)
  2166.   {
  2167.     /* skip leading white space */
  2168.     while (((int)*source > 0) && ((int)*source < 33))
  2169.     {
  2170.       source++;
  2171.     }
  2172.  
  2173.     /* Quit when finished or ignore if commented */
  2174.     if ((*source == '\0') || (*source == ';'))
  2175.     {
  2176.       return;
  2177.     }
  2178.     
  2179.     if ((*source == '=') || (*source == '#'))
  2180.     {
  2181.       Error("'=' or '#' must be preceded by a keyword.");
  2182.     }
  2183.  
  2184.     /* Copy everything that is not a space, an equals or a comment 
  2185.        into Option_String 
  2186.     */
  2187.     dest = Option_String;
  2188.     while ((isprint((int)*source)) && 
  2189.            (*source != ' ') && 
  2190.            (*source != '=') && 
  2191.            (*source != '#') && 
  2192.            (*source != ';'))
  2193.     {
  2194.       *(dest++) = *(source++);
  2195.     }
  2196.     *dest = '\0';
  2197.  
  2198.     /* At this point, nearly all options that start with a "-" are
  2199.      * options. However the syntax for the +I and the +O 
  2200.      * command-line switches, allows a space to appear between the 
  2201.      * switch and the name.  For example: "+I MYFILE.POV" is legal.  
  2202.      * Since "-" is a legal input and output filename for stdin or
  2203.      * stdout we must parse this before we try to read other options.
  2204.      * If we encounter a "-" without a following option immediately
  2205.      * after a +I or +O switch, it must mean that.  The flags
  2206.      * inflag and outflag indicate that there was a +I or +O switch
  2207.      * parsed just before this file name.
  2208.      */
  2209.  
  2210.     if (inflag)
  2211.     {
  2212.       inflag = FALSE;
  2213.       if (pov_stricmp(Option_String, "-") == 0 ||
  2214.           pov_stricmp(Option_String, "stdin") == 0)
  2215.       {
  2216.         strcpy (opts.Input_File_Name, "stdin");
  2217.         opts.Options |= FROM_STDIN;
  2218.         continue;
  2219.       }
  2220.       else if ((*Option_String != '+') && (*Option_String != '-'))
  2221.       {
  2222.         strncpy (opts.Input_File_Name, Option_String, FILE_NAME_LENGTH);
  2223.         continue;
  2224.       }
  2225.     }
  2226.  
  2227.     if (outflag)
  2228.     {
  2229.       outflag = FALSE;
  2230.       if (pov_stricmp(Option_String, "-") == 0 ||
  2231.           pov_stricmp(Option_String, "stdout") == 0)
  2232.       {
  2233.         strcpy (opts.Output_File_Name, "stdout");
  2234.         opts.Options |= TO_STDOUT;
  2235.         continue;
  2236.       }
  2237.       else if ((*Option_String != '+') && (*Option_String != '-'))
  2238.       {
  2239.         strncpy (opts.Output_File_Name, Option_String, FILE_NAME_LENGTH);
  2240.         continue;
  2241.       }
  2242.     }
  2243.     
  2244.     /* If its a +/- style switch then just do it */
  2245.     if ((*Option_String == '+') || (*Option_String == '-'))
  2246.     {
  2247.       parse_switch(Option_String);
  2248.       continue;
  2249.     }
  2250.  
  2251.     /* Now search the Option_Variables to see if we find a match */
  2252.  
  2253.     Found=-1;
  2254.     for (i = 0 ; i < MAX_OPTION; i++)
  2255.     {
  2256.       if (pov_stricmp(Option_Variable[i].Token_Name, Option_String) == 0)
  2257.       {
  2258.         Found=Option_Variable[i].Token_Number;
  2259.         break;
  2260.       }
  2261.     }
  2262.     
  2263.     if (Found < 0)
  2264.     {
  2265.       /* When an option string does not begin with a '+' or '-', and
  2266.        * is not in the list of valid keywords, then it is assumed to 
  2267.        * be a file name.  Any file names that appear at this point are
  2268.        * .INI/.DEF files to be parsed, or it is an error.
  2269.        */
  2270.        
  2271.       if (++Number_Of_Files > MAX_NESTED_INI)
  2272.       {
  2273.         Error ("Bad option syntax or too many nested .INI/.DEF files.");
  2274.       }
  2275.  
  2276.       if (!parse_ini_file(Option_String))
  2277.       {
  2278.         Error ("Bad option syntax or error opening .INI/.DEF file '%s'.\n", Option_String);
  2279.       }
  2280.       continue;
  2281.     }
  2282.     
  2283.     /* If we make it this far, then it must be an .INI-style setting with
  2284.      * the keyword already verified in "Found".  We now need to verify that
  2285.      * an equals sign follows.  
  2286.      */
  2287.  
  2288.     /* skip white space */
  2289.     while (((int)*source > 0) && ((int)*source < 33))
  2290.     {
  2291.       source++;
  2292.     }
  2293.     
  2294.     if ((*source != '=') && (*source != '#'))
  2295.     {
  2296.       Error("Missing '=' or '#' after %s in option.",Option_String);
  2297.     }
  2298.     
  2299.     source++;
  2300.  
  2301.     /* Now the entire rest of Option_Line up to but excluding a comment, 
  2302.      * becomes the variable part of the option. 
  2303.      */
  2304.  
  2305.     /* skip white space */
  2306.     while (((int)*source > 0) && ((int)*source < 33))
  2307.     {
  2308.       source++;
  2309.     }
  2310.     
  2311.     dest=source;
  2312.     
  2313.     /* Cut off comments and any unprintable characters */
  2314.     while (*source != '\0') 
  2315.     {
  2316.        /* If the comment character is escaped, pass it through */
  2317.        if ((*source == '\\') && (*(source + 1) == ';'))
  2318.        {
  2319.          *source = ';';
  2320.          source++;
  2321.          *source = ' ';
  2322.          source++;
  2323.        }
  2324.        else if ((*source == ';') || (! isprint((int)*source) ) )
  2325.        {
  2326.          *source = '\0';
  2327.        }
  2328.        else
  2329.        {
  2330.          source++;
  2331.        }
  2332.     }
  2333.     process_variable(Found, dest);
  2334.     return;
  2335.   }
  2336. }
  2337.  
  2338.  
  2339.  
  2340. /*****************************************************************************
  2341. *
  2342. * FUNCTION
  2343. *
  2344. * INPUT
  2345. *   
  2346. * OUTPUT
  2347. *   
  2348. * RETURNS
  2349. *   
  2350. * AUTHOR
  2351. *   
  2352. * DESCRIPTION
  2353. *
  2354. * CHANGES
  2355. *
  2356. ******************************************************************************/
  2357.  
  2358. void Do_Stream_Option (int i, const char *value)
  2359. {
  2360.   if (value==NULL)
  2361.   {
  2362.     return;
  2363.   }
  2364.  
  2365.   if (*value == '\0')
  2366.   {
  2367.     return;
  2368.   }
  2369.  
  2370.   if (Stream_Info[i].name != NULL)
  2371.   {
  2372.     POV_FREE(Stream_Info[i].name);
  2373.  
  2374.     Stream_Info[i].name = NULL;
  2375.   }
  2376.  
  2377.   if (istrue(value))
  2378.   {
  2379.     Stream_Info[i].name = (char *)POV_MALLOC(strlen(DefaultFile[i])+1, "stream name");
  2380.  
  2381.     strcpy(Stream_Info[i].name, DefaultFile[i]);
  2382.   }
  2383.   else
  2384.   {
  2385.     if (isfalse(value))
  2386.     {
  2387.       return;
  2388.     }
  2389.  
  2390.     Stream_Info[i].name = (char *)POV_MALLOC(strlen(value)+1, "stream name");
  2391.  
  2392.     strcpy(Stream_Info[i].name, value);
  2393.  }
  2394. }
  2395.  
  2396.  
  2397.  
  2398. /*****************************************************************************
  2399. *
  2400. * FUNCTION
  2401. *
  2402. * INPUT
  2403. *   
  2404. * OUTPUT
  2405. *   
  2406. * RETURNS
  2407. *   
  2408. * AUTHOR
  2409. *   
  2410. * DESCRIPTION
  2411. *
  2412. * CHANGES
  2413. *
  2414. ******************************************************************************/
  2415.  
  2416. void Do_Return_Option (SHELLTYPE Type, const char *value)
  2417. {
  2418.    char *s;
  2419.    
  2420.    SHELLDATA *Shell=&(opts.Shellouts[Type]);
  2421.    
  2422.    Shell->Inverse=FALSE;
  2423.    Shell->Ret=IGNORE_RET;
  2424.    
  2425.    if (value==NULL)
  2426.      return;
  2427.      
  2428.    if (*value=='\0')
  2429.      return;
  2430.      
  2431.    if ((*value=='-') || (*value=='!'))
  2432.    {
  2433.       Shell->Inverse=TRUE;
  2434.       value++;
  2435.    }
  2436.  
  2437.    if (*value=='\0')
  2438.      return;
  2439.  
  2440.    if ((s=strchr(ret_string,toupper(*value))) == NULL)
  2441.    {
  2442.      Warning(0,"Bad value in shellout return '%c'. Only '%s' are allowed.\n",*value,ret_string);
  2443.      Shell->Ret = IGNORE_RET;
  2444.    }
  2445.    else
  2446.    {
  2447.      Shell->Ret = (POV_SHELLOUT_CAST)(s-ret_string);
  2448.    }
  2449. }
  2450.