home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 7 / Apprentice-Release7.iso / Source Code / C / Applications / POV-Ray 3.0.2 / src / SOURCE / tokenize.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-06-24  |  54.1 KB  |  2,729 lines  |  [TEXT/MPS ]

  1. /****************************************************************************
  2. *                tokenize.c
  3. *
  4. *  This module implements the first part of a two part parser for the scene
  5. *  description files.  This phase changes the input file into tokens.
  6. *
  7. *  This module tokenizes the input file and sends the tokens created
  8. *  to the parser (the second stage).  Tokens sent to the parser contain a
  9. *  token ID, the line number of the token, and if necessary, some data for
  10. *  the token.
  11. *
  12. *  from Persistence of Vision(tm) Ray Tracer
  13. *  Copyright 1996 Persistence of Vision Team
  14. *---------------------------------------------------------------------------
  15. *  NOTICE: This source code file is provided so that users may experiment
  16. *  with enhancements to POV-Ray and to port the software to platforms other
  17. *  than those supported by the POV-Ray Team.  There are strict rules under
  18. *  which you are permitted to use this file.  The rules are in the file
  19. *  named POVLEGAL.DOC which should be distributed with this file. If
  20. *  POVLEGAL.DOC is not available or for more info please contact the POV-Ray
  21. *  Team Coordinator by leaving a message in CompuServe's Graphics Developer's
  22. *  Forum.  The latest version of POV-Ray may be found there as well.
  23. *
  24. * This program is based on the popular DKB raytracer version 2.12.
  25. * DKBTrace was originally written by David K. Buck.
  26. * DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
  27. *
  28. *****************************************************************************/
  29.  
  30. #include <ctype.h>
  31. #include "frame.h"
  32. #include "povray.h"
  33. #include "povproto.h"
  34. #include "parse.h"
  35. #include "povray.h"
  36. #include "render.h"
  37. #include "tokenize.h"
  38. #include "express.h"
  39.  
  40.  
  41.  
  42. /*****************************************************************************
  43. * Local preprocessor defines
  44. ******************************************************************************/
  45.  
  46.  
  47.  
  48. /*****************************************************************************
  49. * Local typedefs
  50. ******************************************************************************/
  51.  
  52. #define MAX_INCLUDE_FILES 10
  53.  
  54. #define CALL(x) { if (!(x)) return (FALSE); }
  55.  
  56. #define COND_STACK_SIZE 200
  57.  
  58. typedef enum cond_type
  59. {
  60.   ROOT_COND=0,
  61.   WHILE_COND,
  62.   IF_TRUE_COND,
  63.   IF_FALSE_COND,
  64.   ELSE_COND,
  65.   SWITCH_COND,
  66.   CASE_TRUE_COND,
  67.   CASE_FALSE_COND,
  68.   SKIP_TIL_END_COND
  69. } COND_TYPE;
  70.  
  71.  
  72. typedef struct Reserved_Word_Struct RESERVED_WORD;
  73.  
  74. #define HASH_TABLE_SIZE 257
  75.  
  76. typedef struct Pov_Hash_Table_Struct HASH_TABLE;
  77.  
  78. struct Pov_Hash_Table_Struct
  79. {
  80.   RESERVED_WORD Entry;
  81.   HASH_TABLE *next;
  82. };
  83.  
  84.  
  85.  
  86.  
  87. /*****************************************************************************
  88. * Local variables
  89. ******************************************************************************/
  90.  
  91. /* Hash tables */
  92.  
  93. HASH_TABLE *Reserved_Words_Hash_Table[HASH_TABLE_SIZE];
  94. HASH_TABLE *Symbol_Table_Hash_Table[HASH_TABLE_SIZE];
  95.  
  96. int Max_Symbols, Max_Constants;
  97.  
  98. static int String_Index;
  99. char String[MAX_STRING_INDEX];
  100. char String2[MAX_STRING_INDEX];
  101.  
  102. int Number_Of_Constants;
  103.  
  104. /* moved here to allow reinitialization */
  105.  
  106. static int token_count = 0, line_count = 10;
  107.  
  108. static int Number_Of_Symbols;
  109. struct Constant_Struct *Constants;
  110.  
  111. static int Include_File_Index;
  112. static DATA_FILE *Data_File;
  113. static DATA_FILE Include_Files[MAX_INCLUDE_FILES];
  114.  
  115. struct Token_Struct Token;
  116.  
  117. static char **Echo_Buff;
  118. static char  *Echo_Ptr;
  119. static int    Echo_Indx;
  120. static int    Echo_Line;
  121. static int    Echo_Unget_Flag;
  122. static int    Echo_Unget_Char;
  123.  
  124. typedef struct Cond_Stack_Entry CS_ENTRY;
  125.  
  126. struct Cond_Stack_Entry
  127. {
  128.   COND_TYPE Cond_Type;
  129.   DBL Switch_Value;
  130.   FILE *While_File;
  131.   long While_Pos,While_Line_No;
  132. };
  133.  
  134. static CS_ENTRY *Cond_Stack;
  135. static int CS_Index, Skipping, Inside_Ifdef;
  136.  
  137. int input_file_in_memory = 0 ;
  138.  
  139. /*
  140.  * Here are the reserved words.  If you need to add new words,
  141.  * be sure to declare them in parse.h
  142.  */
  143.  
  144. RESERVED_WORD Reserved_Words [LAST_TOKEN] = {
  145.   {AA_LEVEL_TOKEN, "aa_level"},
  146.   {AA_THRESHOLD_TOKEN, "aa_threshold"},
  147.   {ABS_TOKEN, "abs"},
  148.   {ACOS_TOKEN, "acos"},
  149.   {ACOSH_TOKEN,"acosh"},
  150.   {ADAPTIVE_TOKEN, "adaptive"},
  151.   {ADC_BAILOUT_TOKEN, "adc_bailout"},
  152.   {AGATE_TOKEN, "agate"},
  153.   {AGATE_TURB_TOKEN, "agate_turb"},
  154.   {ALL_TOKEN, "all"},
  155.   {ALPHA_TOKEN, "alpha"},
  156.   {AMBIENT_LIGHT_TOKEN, "ambient_light"},
  157.   {AMBIENT_TOKEN, "ambient"},
  158.   {AMPERSAND_TOKEN, "&"},
  159.   {ANGLE_TOKEN, "angle"},
  160.   {APERTURE_TOKEN, "aperture"},
  161.   {ARC_ANGLE_TOKEN, "arc_angle"},
  162.   {AREA_LIGHT_TOKEN, "area_light"},
  163.   {ASC_TOKEN, "asc"},
  164.   {ASIN_TOKEN, "asin"},
  165.   {ASINH_TOKEN,"asinh"},
  166.   {ASSUMED_GAMMA_TOKEN, "assumed_gamma"},
  167.   {ATAN_TOKEN,"atan"},
  168.   {ATAN2_TOKEN,"atan2"},
  169.   {ATANH_TOKEN,"atanh"},
  170.   {ATMOSPHERE_ID_TOKEN, "atmosphere identifier"},
  171.   {ATMOSPHERE_TOKEN, "atmosphere"},
  172.   {ATMOSPHERIC_ATTENUATION_TOKEN, "atmospheric_attenuation"},
  173.   {ATTENUATING_TOKEN, "attenuating"},
  174.   {AT_TOKEN, "@"},
  175.   {AVERAGE_TOKEN, "average"},
  176.   {BACKGROUND_TOKEN, "background"},
  177.   {BACK_QUOTE_TOKEN, "`"},
  178.   {BACK_SLASH_TOKEN, "\\"},
  179.   {BAR_TOKEN, "|"},
  180.   {BICUBIC_PATCH_TOKEN, "bicubic_patch"},
  181.   {BLACK_HOLE_TOKEN, "black_hole"},
  182.   {BLOB_TOKEN, "blob"},
  183.   {BLUE_TOKEN, "blue"},
  184.   {BLUR_SAMPLES_TOKEN, "blur_samples"},
  185.   {BOUNDED_BY_TOKEN, "bounded_by"},
  186.   {BOX_MAPPING_TOKEN, "box_mapping"},
  187.   {BOX_TOKEN, "box"},
  188.   {BOZO_TOKEN, "bozo"},
  189.   {BREAK_TOKEN, "break"},
  190.   {BRICK_SIZE_TOKEN, "brick_size"},
  191.   {BRICK_TOKEN, "brick"},
  192.   {BRIGHTNESS_TOKEN, "brightness" },
  193.   {BRILLIANCE_TOKEN, "brilliance"},
  194.   {BUMPS_TOKEN, "bumps"},
  195.   {BUMPY1_TOKEN, "bumpy1"},
  196.   {BUMPY2_TOKEN, "bumpy2"},
  197.   {BUMPY3_TOKEN, "bumpy3"},
  198.   {BUMP_MAP_TOKEN, "bump_map"},
  199.   {BUMP_SIZE_TOKEN, "bump_size"},
  200.   {CAMERA_ID_TOKEN, "camera identifier"},
  201.   {CAMERA_TOKEN, "camera"},
  202.   {CASE_TOKEN, "case"},
  203.   {CAUSTICS_TOKEN, "caustics"},
  204.   {CEIL_TOKEN, "ceil"},
  205.   {CHECKER_TOKEN, "checker"},
  206.   {CHR_TOKEN, "chr"},
  207.   {CLIPPED_BY_TOKEN, "clipped_by"},
  208.   {CLOCK_TOKEN,"clock"},
  209.   {COLON_TOKEN, ":"},
  210.   {COLOUR_ID_TOKEN, "colour identifier"},
  211.   {COLOUR_KEY_TOKEN,"color keyword"},
  212.   {COLOUR_MAP_ID_TOKEN, "colour map identifier"},
  213.   {COLOUR_MAP_TOKEN, "color_map"},
  214.   {COLOUR_MAP_TOKEN, "colour_map"},
  215.   {COLOUR_TOKEN, "color"},
  216.   {COLOUR_TOKEN, "colour"},
  217.   {COMMA_TOKEN, ","},
  218.   {COMPONENT_TOKEN, "component"},
  219.   {COMPOSITE_TOKEN, "composite"},
  220.   {CONCAT_TOKEN, "concat"},
  221.   {CONE_TOKEN, "cone"},
  222.   {CONFIDENCE_TOKEN, "confidence"},
  223.   {CONIC_SWEEP_TOKEN, "conic_sweep"},
  224.   {CONSTANT_TOKEN,"constant"},
  225.   {CONTROL0_TOKEN,"control0"},
  226.   {CONTROL1_TOKEN,"control1"},
  227.   {COS_TOKEN,"cos"},
  228.   {COSH_TOKEN,"cosh"},
  229.   {COUNT_TOKEN, "count" },
  230.   {CRACKLE_TOKEN, "crackle"},
  231.   {CRAND_TOKEN, "crand"},
  232.   {CUBE_TOKEN, "cube"},
  233.   {CUBIC_SPLINE_TOKEN, "cubic_spline"},
  234.   {CUBIC_TOKEN, "cubic"},
  235.   {CYLINDER_TOKEN, "cylinder"},
  236.   {CYLINDRICAL_MAPPING_TOKEN, "cylindrical_mapping"},
  237.   {DASH_TOKEN, "-"},
  238.   {DEBUG_TOKEN, "debug"},
  239.   {DECLARE_TOKEN, "declare"},
  240.   {DEFAULT_TOKEN, "default"},
  241.   {DEGREES_TOKEN, "degrees"},
  242.   {DENTS_TOKEN, "dents"},
  243.   {DIFFERENCE_TOKEN, "difference"},
  244.   {DIFFUSE_TOKEN, "diffuse"},
  245.   {DIRECTION_TOKEN, "direction"},
  246.   {DISC_TOKEN, "disc"},
  247.   {DISTANCE_MAXIMUM_TOKEN, "distance_maximum" },
  248.   {DISTANCE_TOKEN, "distance"},
  249.   {DIV_TOKEN, "div"},
  250.   {DOLLAR_TOKEN, "$"},
  251.   {DUST_TOKEN, "dust"},
  252.   {DUST_TYPE_TOKEN, "dust_type"},
  253.   {ELSE_TOKEN, "else"},
  254.   {EMITTING_TOKEN, "emitting"},
  255.   {END_OF_FILE_TOKEN, "End of File"},
  256.   {END_TOKEN, "end"},
  257.   {EQUALS_TOKEN, "="},
  258.   {ERROR_BOUND_TOKEN, "error_bound" },
  259.   {ERROR_TOKEN, "error"},
  260.   {ECCENTRICITY_TOKEN, "eccentricity"},
  261.   {EXCLAMATION_TOKEN, "!"},
  262.   {EXPONENT_TOKEN, "exponent"},
  263.   {EXP_TOKEN,"exp"},
  264.   {FADE_DISTANCE_TOKEN, "fade_distance"},
  265.   {FADE_POWER_TOKEN, "fade_power"},
  266.   {FALLOFF_ANGLE_TOKEN, "falloff_angle"},
  267.   {FALLOFF_TOKEN, "falloff"},
  268.   {FALSE_TOKEN, "false"},
  269.   {FILE_EXISTS_TOKEN, "file_exists"},
  270.   {FILL_LIGHT_TOKEN, "shadowless"},
  271.   {FILTER_TOKEN, "filter"},
  272.   {FINISH_ID_TOKEN, "finish identifier"},
  273.   {FINISH_TOKEN, "finish"},
  274.   {FISHEYE_TOKEN, "fisheye"},
  275.   {FLATNESS_TOKEN, "flatness"},
  276.   {FLIP_TOKEN, "flip"},
  277.   {FLOAT_FUNCT_TOKEN,"float function"},
  278.   {FLOAT_ID_TOKEN, "float identifier"},
  279.   {FLOAT_TOKEN, "float constant"},
  280.   {FLOOR_TOKEN, "floor"},
  281.   {FOCAL_POINT_TOKEN, "focal_point"},
  282.   {FOG_ALT_TOKEN, "fog_alt"},
  283.   {FOG_ID_TOKEN, "fog identifier"},
  284.   {FOG_OFFSET_TOKEN, "fog_offset"},
  285.   {FOG_TOKEN, "fog"},
  286.   {FOG_TYPE_TOKEN, "fog_type"},
  287.   {FREQUENCY_TOKEN, "frequency"},
  288.   {GIF_TOKEN, "gif"},
  289.   {GLOBAL_SETTINGS_TOKEN, "global_settings" },
  290.   {GLOWING_TOKEN, "glowing"},
  291.   {GRADIENT_TOKEN, "gradient"},
  292.   {GRANITE_TOKEN, "granite"},
  293.   {GRAY_THRESHOLD_TOKEN, "gray_threshold" },
  294.   {GREEN_TOKEN, "green"},
  295.   {HALO_ID_TOKEN, "halo identifier"},
  296.   {HALO_TOKEN, "halo"},
  297.   {HASH_TOKEN, "#"},
  298.   {HAT_TOKEN, "^"},
  299.   {HEIGHT_FIELD_TOKEN, "height_field"},
  300.   {HEXAGON_TOKEN, "hexagon"},
  301.   {HF_GRAY_16_TOKEN, "hf_gray_16" },
  302.   {HIERARCHY_TOKEN, "hierarchy"},
  303.   {HOLLOW_TOKEN, "hollow"},
  304.   {HYPERCOMPLEX_TOKEN, "hypercomplex"},
  305.   {IDENTIFIER_TOKEN, "undeclared identifier"},
  306.   {IFDEF_TOKEN, "ifdef"},
  307.   {IFNDEF_TOKEN, "ifndef"},
  308.   {IFF_TOKEN, "iff"},
  309.   {IF_TOKEN, "if"},
  310.   {IMAGE_MAP_TOKEN, "image_map"},
  311.   {INCIDENCE_TOKEN, "incidence"},
  312.   {INCLUDE_TOKEN, "include"},
  313.   {INTERPOLATE_TOKEN, "interpolate"},
  314.   {INTERSECTION_TOKEN, "intersection"},
  315.   {INT_TOKEN,"int"},
  316.   {INVERSE_TOKEN, "inverse"},
  317.   {IOR_TOKEN, "ior"},
  318.   {IRID_TOKEN, "irid"},
  319.   {IRID_WAVELENGTH_TOKEN,"irid_wavelength"},
  320.   {JITTER_TOKEN, "jitter"},
  321.   {JULIA_FRACTAL_TOKEN, "julia_fractal"},
  322.   {LAMBDA_TOKEN, "lambda"},
  323.   {LATHE_TOKEN, "lathe"},
  324.   {LEFT_ANGLE_TOKEN, "<"},
  325.   {LEFT_CURLY_TOKEN, "{"},
  326.   {LEFT_PAREN_TOKEN, "("},
  327.   {LEFT_SQUARE_TOKEN, "["},
  328.   {LEOPARD_TOKEN, "leopard"},
  329.   {LIGHT_SOURCE_TOKEN, "light_source"},
  330.   {LINEAR_SPLINE_TOKEN, "linear_spline"},
  331.   {LINEAR_SWEEP_TOKEN, "linear_sweep"},
  332.   {LINEAR_TOKEN, "linear"},
  333.   {LOCATION_TOKEN, "location"},
  334.   {LOG_TOKEN,"log"},
  335.   {LOOKS_LIKE_TOKEN, "looks_like"},
  336.   {LOOK_AT_TOKEN, "look_at"},
  337.   {LOW_ERROR_FACTOR_TOKEN, "low_error_factor" },
  338.   {MANDEL_TOKEN,"mandel"},
  339.   {MAP_TYPE_TOKEN, "map_type"},
  340.   {MARBLE_TOKEN, "marble"},
  341.   {MATERIAL_MAP_TOKEN, "material_map"},
  342.   {MATRIX_TOKEN, "matrix"},
  343.   {MAX_INTERSECTIONS, "max_intersections"},
  344.   {MAX_ITERATION_TOKEN, "max_iteration"},
  345.   {MAX_TOKEN, "max"},
  346.   {MAX_TRACE_LEVEL_TOKEN, "max_trace_level"},
  347.   {MAX_VALUE_TOKEN, "max_value"},
  348.   {MERGE_TOKEN,"merge"},
  349.   {MESH_TOKEN, "mesh"},
  350.   {METALLIC_TOKEN, "metallic"},
  351.   {MINIMUM_REUSE_TOKEN, "minimum_reuse" },
  352.   {MIN_TOKEN, "min"},
  353.   {MOD_TOKEN,"mod"},
  354.   {MORTAR_TOKEN, "mortar"},
  355.   {NEAREST_COUNT_TOKEN, "nearest_count" },
  356.   {NORMAL_MAP_ID_TOKEN,"normal_map identifier"},
  357.   {NORMAL_MAP_TOKEN, "normal_map"},
  358.   {NO_SHADOW_TOKEN, "no_shadow"},
  359.   {NO_TOKEN, "no"},
  360.   {NUMBER_OF_WAVES_TOKEN, "number_of_waves"},
  361.   {OBJECT_ID_TOKEN, "object identifier"},
  362.   {OBJECT_TOKEN, "object"},
  363.   {OCTAVES_TOKEN, "octaves"},
  364.   {OFFSET_TOKEN, "offset"},
  365.   {OFF_TOKEN, "off"},
  366.   {OMEGA_TOKEN, "omega"},
  367.   {OMNIMAX_TOKEN, "omnimax"},
  368.   {ONCE_TOKEN, "once"},
  369.   {ONION_TOKEN, "onion"},
  370.   {ON_TOKEN, "on"},
  371.   {OPEN_TOKEN, "open"},
  372.   {ORTHOGRAPHIC_TOKEN, "orthographic"},
  373.   {PANORAMIC_TOKEN, "panoramic"},
  374.   {PATTERN1_TOKEN, "pattern1"},
  375.   {PATTERN2_TOKEN, "pattern2"},
  376.   {PATTERN3_TOKEN, "pattern3"},
  377.   {PERCENT_TOKEN, "%"},
  378.   {PERIOD_TOKEN, ". (period)"},
  379.   {PERSPECTIVE_TOKEN, "perspective"},
  380.   {PGM_TOKEN, "pgm"},
  381.   {PHASE_TOKEN, "phase"},
  382.   {PHONG_SIZE_TOKEN, "phong_size"},
  383.   {PHONG_TOKEN, "phong"},
  384.   {PIGMENT_ID_TOKEN, "pigment identifier"},
  385.   {PIGMENT_MAP_ID_TOKEN,"pigment_map identifier"},
  386.   {PIGMENT_MAP_TOKEN, "pigment_map"},
  387.   {PIGMENT_TOKEN, "pigment"},
  388.   {PI_TOKEN,"pi"},
  389.   {PLANAR_MAPPING_TOKEN, "planar_mapping"},
  390.   {PLANE_TOKEN, "plane"},
  391.   {PLUS_TOKEN, "+"},
  392.   {PNG_TOKEN, "png"},
  393.   {POINT_AT_TOKEN, "point_at"},
  394.   {POLYGON_TOKEN, "polygon"},
  395.   {POLY_TOKEN, "poly"},
  396.   {POT_TOKEN, "pot"},
  397.   {POW_TOKEN,"pow"},
  398.   {PPM_TOKEN, "ppm"},
  399.   {PRECISION_TOKEN, "precision"},
  400.   {PRISM_TOKEN, "prism"},
  401.   {PWR_TOKEN,"pwr"},
  402.   {QUADRATIC_SPLINE_TOKEN, "quadratic_spline"},
  403.   {QUADRIC_TOKEN, "quadric"},
  404.   {QUARTIC_TOKEN, "quartic"},
  405.   {QUATERNION_TOKEN, "quaternion"},
  406.   {QUESTION_TOKEN, "?"},
  407.   {QUICK_COLOUR_TOKEN,"quick_color"},
  408.   {QUICK_COLOUR_TOKEN,"quick_colour"},
  409.   {QUILTED_TOKEN,"quilted"},
  410.   {RADIAL_TOKEN, "radial"},
  411.   {RADIANS_TOKEN, "radians"},
  412.   {RADIOSITY_TOKEN, "radiosity" },
  413.   {RADIUS_TOKEN, "radius"},
  414.   {RAINBOW_ID_TOKEN, "rainbow identifier"},
  415.   {RAINBOW_TOKEN, "rainbow"},
  416.   {RAMP_WAVE_TOKEN, "ramp_wave"},
  417.   {RAND_TOKEN, "rand"},
  418.   {RANGE_TOKEN, "range"},
  419.   {RECIPROCAL_TOKEN, "reciprocal" },
  420.   {RECURSION_LIMIT_TOKEN, "recursion_limit" },
  421.   {RED_TOKEN, "red"},
  422.   {REFLECTION_TOKEN, "reflection"},
  423.   {REFRACTION_TOKEN, "refraction"},
  424.   {REL_GE_TOKEN,">="},
  425.   {REL_LE_TOKEN,"<="},
  426.   {REL_NE_TOKEN,"!="},
  427.   {RENDER_TOKEN, "render"},
  428.   {REPEAT_TOKEN, "repeat"},
  429.   {RGBFT_TOKEN, "rgbft"},
  430.   {RGBF_TOKEN,"rgbf"},
  431.   {RGBT_TOKEN, "rgbt"},
  432.   {RGB_TOKEN,"rgb"},
  433.   {RIGHT_ANGLE_TOKEN, ">"},
  434.   {RIGHT_CURLY_TOKEN, "}"},
  435.   {RIGHT_PAREN_TOKEN, ")"},
  436.   {RIGHT_SQUARE_TOKEN, "]"},
  437.   {RIGHT_TOKEN, "right"},
  438.   {RIPPLES_TOKEN, "ripples"},
  439.   {ROTATE_TOKEN, "rotate"},
  440.   {ROUGHNESS_TOKEN, "roughness"},
  441.   {SAMPLES_TOKEN, "samples"},
  442.   {SCALE_TOKEN, "scale"},
  443.   {SCALLOP_WAVE_TOKEN, "scallop_wave"},
  444.   {SCATTERING_TOKEN, "scattering"},
  445.   {SEED_TOKEN, "seed"},
  446.   {SEMI_COLON_TOKEN, ";"},
  447.   {SINE_WAVE_TOKEN, "sine_wave"},
  448.   {SINGLE_QUOTE_TOKEN, "'"},
  449.   {SIN_TOKEN,"sin"},
  450.   {SINH_TOKEN,"sinh"},
  451.   {SKYSPHERE_ID_TOKEN, "sky_sphere identifier"},
  452.   {SKYSPHERE_TOKEN, "sky_sphere"},
  453.   {SKY_TOKEN, "sky"},
  454.   {SLASH_TOKEN, "/"},
  455.   {SLICE_TOKEN, "slice"},
  456.   {SLOPE_MAP_ID_TOKEN,"slope_map identifier"},
  457.   {SLOPE_MAP_TOKEN, "slope_map"},
  458.   {SMOOTH_TOKEN,"smooth"},
  459.   {SMOOTH_TRIANGLE_TOKEN, "smooth_triangle"},
  460.   {SOR_TOKEN, "sor"},
  461.   {SPECULAR_TOKEN, "specular"},
  462.   {SPHERE_TOKEN, "sphere"},
  463.   {SPHERICAL_MAPPING_TOKEN, "spherical_mapping"},
  464.   {SPIRAL1_TOKEN, "spiral1"},
  465.   {SPIRAL2_TOKEN, "spiral2"},
  466.   {SPIRAL_TOKEN, "spiral"},
  467.   {SPOTLIGHT_TOKEN, "spotlight"},
  468.   {SPOTTED_TOKEN, "spotted"},
  469.   {SQR_TOKEN,"sqr"},
  470.   {SQRT_TOKEN,"sqrt"},
  471.   {STAR_TOKEN, "*"},
  472.   {STATISTICS_TOKEN, "statistics"},
  473.   {STRCMP_TOKEN, "strcmp"},
  474.   {STRENGTH_TOKEN, "strength"},
  475.   {STRING_ID_TOKEN, "string identifier"},
  476.   {STRING_LITERAL_TOKEN, "string literal"},
  477.   {STRLEN_TOKEN, "strlen"},
  478.   {STRLWR_TOKEN, "strlwr"},
  479.   {STRUPR_TOKEN, "strupr"},
  480.   {STR_TOKEN, "str"},
  481.   {STURM_TOKEN, "sturm"},
  482.   {SUBSTR_TOKEN, "substr"},
  483.   {SUPERELLIPSOID_TOKEN, "superellipsoid"},
  484.   {SWITCH_TOKEN, "switch"},
  485.   {SYS_TOKEN, "sys"},
  486.   {T_TOKEN, "t"},
  487.   {TAN_TOKEN, "tan"},
  488.   {TANH_TOKEN,"tanh"},
  489.   {TEST_CAMERA_1_TOKEN, "test_camera_1"},
  490.   {TEST_CAMERA_2_TOKEN, "test_camera_2"},
  491.   {TEST_CAMERA_3_TOKEN, "test_camera_3"},
  492.   {TEST_CAMERA_4_TOKEN, "test_camera_4"},
  493.   {TEXTURE_ID_TOKEN, "texture identifier"},
  494.   {TEXTURE_MAP_ID_TOKEN,"texture_map identifier"},
  495.   {TEXTURE_MAP_TOKEN, "texture_map"},
  496.   {TEXTURE_TOKEN, "texture"},
  497.   {TEXT_TOKEN, "text"},
  498.   {TGA_TOKEN, "tga"},
  499.   {THICKNESS_TOKEN, "thickness"},
  500.   {THRESHOLD_TOKEN, "threshold"},
  501.   {TIGHTNESS_TOKEN, "tightness"},
  502.   {TILDE_TOKEN, "~"},
  503.   {TILE2_TOKEN, "tile2"},
  504.   {TILES_TOKEN, "tiles"},
  505.   {TNORMAL_ID_TOKEN, "normal identifier"},
  506.   {TNORMAL_TOKEN, "normal"},
  507.   {TORUS_TOKEN, "torus"},
  508.   {TRACK_TOKEN, "track"},
  509.   {TRANSFORM_ID_TOKEN, "transform identifier"},
  510.   {TRANSFORM_TOKEN, "transform"},
  511.   {TRANSLATE_TOKEN, "translate"},
  512.   {TRANSMIT_TOKEN, "transmit"},
  513.   {TRIANGLE_TOKEN, "triangle"},
  514.   {TRIANGLE_WAVE_TOKEN, "triangle_wave"},
  515.   {TRUE_TOKEN, "true"},
  516.   {TTF_TOKEN, "ttf"},
  517.   {TURBULENCE_TOKEN, "turbulence"},
  518.   {TURB_DEPTH_TOKEN, "turb_depth"},
  519.   {TYPE_TOKEN, "type"},
  520.   {ULTRA_WIDE_ANGLE_TOKEN, "ultra_wide_angle"},
  521.   {UNION_TOKEN, "union"},
  522.   {UP_TOKEN, "up"},
  523.   {USE_COLOUR_TOKEN,"use_color"},
  524.   {USE_COLOUR_TOKEN,"use_colour"},
  525.   {USE_INDEX_TOKEN,"use_index"},
  526.   {U_STEPS_TOKEN, "u_steps"},
  527.   {U_TOKEN, "u"},
  528.   {VAL_TOKEN, "val"},
  529.   {VARIANCE_TOKEN, "variance"},
  530.   {VAXIS_ROTATE_TOKEN,"vaxis_rotate"},
  531.   {VCROSS_TOKEN,"vcross"},
  532.   {VDOT_TOKEN,"vdot"},
  533.   {VECTOR_FUNCT_TOKEN,"vector function"},
  534.   {VECTOR_ID_TOKEN, "vector identifier"},
  535.   {VERSION_TOKEN, "version"},
  536.   {VLENGTH_TOKEN,"vlength"},
  537.   {VNORMALIZE_TOKEN,"vnormalize"},
  538.   {VOLUME_OBJECT_TOKEN, "volume_object"},
  539.   {VOLUME_RENDERED_TOKEN, "volume_rendered"},
  540.   {VOL_WITH_LIGHT_TOKEN, "vol_with_light"},
  541.   {VROTATE_TOKEN,"vrotate"},
  542.   {V_STEPS_TOKEN, "v_steps"},
  543.   {V_TOKEN, "v"},
  544.   {WARNING_TOKEN, "warning"},
  545.   {WARP_TOKEN, "warp"},
  546.   {WATER_LEVEL_TOKEN, "water_level"},
  547.   {WAVES_TOKEN, "waves"},
  548.   {WHILE_TOKEN, "while"},
  549.   {WIDTH_TOKEN, "width"},
  550.   {WOOD_TOKEN, "wood"},
  551.   {WRINKLES_TOKEN, "wrinkles"},
  552.   {X_TOKEN,"x"},
  553.   {YES_TOKEN, "yes"},
  554.   {Y_TOKEN,"y"},
  555.   {Z_TOKEN,"z"}
  556. };
  557.  
  558.  
  559.  
  560. /*****************************************************************************
  561. * Static functions
  562. ******************************************************************************/
  563.  
  564. static int Echo_ungetc PARAMS((int c));
  565. static int Echo_getc PARAMS((void));
  566. static int Skip_Spaces PARAMS((void));
  567. static int Parse_C_Comments PARAMS((void));
  568. static void Begin_String PARAMS((void));
  569. static void Stuff_Character PARAMS((int c));
  570. static void End_String PARAMS((void));
  571. static int Read_Float PARAMS((void));
  572. static void Parse_String_Literal PARAMS((void));
  573. static void Read_Symbol PARAMS((void));
  574. static int Find_Reserved PARAMS((char *s, int hash_value));
  575. static int Find_Symbol PARAMS((char *s, int hash_value));
  576. static void Skip_Tokens PARAMS((COND_TYPE cond));
  577.  
  578. static int get_hash_value PARAMS((char *s));
  579. static void init_reserved_words_hash_table PARAMS((void));
  580.  
  581.  
  582.  
  583.  
  584. /*****************************************************************************
  585. *
  586. * FUNCTION
  587. *
  588. * INPUT
  589. *
  590. * OUTPUT
  591. *
  592. * RETURNS
  593. *
  594. * AUTHOR
  595. *
  596. * DESCRIPTION
  597. *
  598. * CHANGES
  599. *
  600. ******************************************************************************/
  601.  
  602. void Initialize_Tokenizer()
  603. {
  604.   int i;
  605.  
  606.   Stage = STAGE_TOKEN_INIT;
  607.  
  608.   pre_init_tokenizer ();
  609.  
  610.   if (opts.Options & FROM_STDIN)
  611.   {
  612.     Data_File->File = stdin;
  613.   }
  614.   else
  615.   {
  616.      if (input_file_in_memory)
  617.      {
  618.         /* Note platforms which use this feature will
  619.          * trap fopen so the NULL is ok [C.Cason 7/3/96]
  620.          */
  621.         Data_File->File = fopen (NULL, "rt") ;
  622.      }
  623.      else
  624.      {
  625.         Data_File->File = Locate_File (opts.Input_File_Name, READ_TEXT_FILE_STRING,".pov",".POV",TRUE);
  626.      }
  627.   }
  628.  
  629.   if (Data_File->File == NULL)
  630.   {
  631.     Error ("Cannot open input file.");
  632.   }
  633.  
  634.   Data_File->Filename = POV_MALLOC(strlen(opts.Input_File_Name)+1, "filename");
  635.  
  636.   strcpy (Data_File->Filename, opts.Input_File_Name);
  637.  
  638.   Data_File->Line_Number = 0;
  639.  
  640.   /* Allocate constants table. */
  641.  
  642.   Constants = (struct Constant_Struct *)POV_MALLOC((Max_Constants+1) * sizeof (struct Constant_Struct), "constants table");
  643.  
  644.   /* Init echo buffer. */
  645.  
  646.   Echo_Buff = (char **)POV_MALLOC(sizeof(char *) * Num_Echo_Lines, "echo buffer");
  647.  
  648.   for (Echo_Line = 0; Echo_Line < Num_Echo_Lines; Echo_Line++)
  649.   {
  650.     Echo_Buff[Echo_Line] = (char *)POV_MALLOC((size_t)Echo_Line_Length+10, "echo buffer");
  651.  
  652.     Echo_Buff[Echo_Line][0]='\0';
  653.   }
  654.  
  655.   Echo_Line = 0;
  656.   Echo_Ptr = Echo_Buff[0];
  657.  
  658.   /* Init conditional stack. */
  659.  
  660.   Cond_Stack = (CS_ENTRY*)POV_MALLOC(sizeof(CS_ENTRY*) * COND_STACK_SIZE, "conditional stack");
  661.  
  662.   Cond_Stack[0].Cond_Type    = ROOT_COND;
  663.   Cond_Stack[0].Switch_Value = 0.0;
  664.  
  665.   /* Init token hash tables. */
  666.  
  667.   init_reserved_words_hash_table();
  668.  
  669.   for (i = 0; i < HASH_TABLE_SIZE; i++)
  670.   {
  671.     Symbol_Table_Hash_Table[i] = NULL;
  672.   }
  673. }
  674.  
  675.  
  676.  
  677. /*****************************************************************************
  678. *
  679. * FUNCTION
  680. *
  681. * INPUT
  682. *
  683. * OUTPUT
  684. *
  685. * RETURNS
  686. *
  687. * AUTHOR
  688. *
  689. * DESCRIPTION
  690. *
  691. * CHANGES
  692. *
  693. ******************************************************************************/
  694.  
  695. void pre_init_tokenizer ()
  696. {
  697.   Token.Token_Line_No = 0;
  698.   Token.Token_String  = NULL;
  699.   Token.Unget_Token   = FALSE;
  700.   Token.End_Of_File   = FALSE;
  701.   Token.Filename      = NULL;
  702.   Token.Constant_Data = NULL;
  703.  
  704.   Constants = NULL;
  705.   Data_File = NULL;
  706.  
  707.   Number_Of_Constants = 0;
  708.   line_count = 10;
  709.   token_count = 0;
  710.   Include_File_Index = 0;
  711.   Echo_Indx=0;
  712.   Echo_Line=0;
  713.   Echo_Ptr=NULL;
  714.   Echo_Buff=NULL;
  715.   Echo_Unget_Flag=FALSE;
  716.   Echo_Unget_Char='\0';
  717.  
  718.   Number_Of_Symbols = 0;
  719.  
  720.   CS_Index            = 0;
  721.   Skipping            = FALSE;
  722.   Inside_Ifdef        = FALSE;
  723.   Cond_Stack          = NULL;
  724.   Data_File = &Include_Files[0];
  725.   Data_File->Filename = NULL;
  726. }
  727.  
  728.  
  729. /*****************************************************************************
  730. *
  731. * FUNCTION
  732. *
  733. * INPUT
  734. *
  735. * OUTPUT
  736. *
  737. * RETURNS
  738. *
  739. * AUTHOR
  740. *
  741. * DESCRIPTION
  742. *
  743. * CHANGES
  744. *
  745. ******************************************************************************/
  746.  
  747. void Terminate_Tokenizer()
  748. {
  749.   int i;
  750.   HASH_TABLE *p, *temp;
  751.  
  752.   for (i = 0 ; i < HASH_TABLE_SIZE; i++)
  753.   {
  754.     p = Symbol_Table_Hash_Table[i];
  755.  
  756.     while (p)
  757.     {
  758.       temp = p->next;
  759.  
  760.       POV_FREE(p->Entry.Token_Name);
  761.  
  762.       POV_FREE(p);
  763.  
  764.       p = temp;
  765.     }
  766.  
  767.     Symbol_Table_Hash_Table[i] = NULL;
  768.   }
  769.  
  770.   for (i = 0 ; i < HASH_TABLE_SIZE; i++)
  771.   {
  772.     p = Reserved_Words_Hash_Table[i];
  773.  
  774.     while (p)
  775.     {
  776.       temp = p->next;
  777.  
  778.       POV_FREE(p);
  779.  
  780.       p = temp;
  781.     }
  782.  
  783.     Reserved_Words_Hash_Table[i] = NULL;
  784.   }
  785.  
  786.   if (Data_File->Filename != NULL)
  787.   {
  788.     fclose (Data_File->File);
  789.  
  790.     POV_FREE (Data_File->Filename);
  791.  
  792.     Data_File->Filename = NULL;
  793.   }
  794.  
  795.   if (Echo_Buff != NULL)
  796.   {
  797.     for (Echo_Line = 0; Echo_Line < Num_Echo_Lines; Echo_Line++)
  798.     {
  799.       if (Echo_Buff[Echo_Line]!=NULL)
  800.       {
  801.         POV_FREE (Echo_Buff[Echo_Line]);
  802.  
  803.         Echo_Buff[Echo_Line]=NULL;
  804.       }
  805.     }
  806.  
  807.     POV_FREE (Echo_Buff);
  808.  
  809.     Echo_Buff = NULL;
  810.   }
  811.  
  812.   if (Cond_Stack!=NULL)
  813.   {
  814.     POV_FREE (Cond_Stack);
  815.  
  816.     Cond_Stack = NULL;
  817.   }
  818. }
  819.  
  820.  
  821.  
  822. /*****************************************************************************
  823. *
  824. * FUNCTION
  825. *
  826. * INPUT
  827. *
  828. * OUTPUT
  829. *
  830. * RETURNS
  831. *
  832. * AUTHOR
  833. *
  834. * DESCRIPTION
  835. *
  836. *   The main tokenizing routine.  Set up the files and continue parsing
  837. *   until the end of file
  838. *
  839. *   Read a token from the input file and store it in the Token variable.
  840. *   If the token is an INCLUDE token, then set the include file name and
  841. *   read another token.
  842. *
  843. *   This function performs most of the work involved in tokenizing.  It
  844. *   reads the first character of the token and decides which function to
  845. *   call to tokenize the rest.  For simple tokens, it simply writes them
  846. *   out to the token buffer.
  847. *
  848. * CHANGES
  849. *
  850. ******************************************************************************/
  851.  
  852. void Get_Token ()
  853. {
  854.   register int c,c2;
  855.  
  856.   if (Token.Unget_Token)
  857.   {
  858.     Token.Unget_Token = FALSE;
  859.  
  860.     return;
  861.   }
  862.  
  863.   if (Token.End_Of_File)
  864.   {
  865.     return;
  866.   }
  867.  
  868.  
  869.   Token.Token_Id = END_OF_FILE_TOKEN;
  870.  
  871.   while (Token.Token_Id == END_OF_FILE_TOKEN)
  872.   {
  873.     Skip_Spaces();
  874.  
  875.     c = Echo_getc();
  876.  
  877.     if (c == EOF)
  878.     {
  879.       if (Include_File_Index == 0)
  880.       {
  881.         if (CS_Index !=0)
  882.           Error("End of file reached but #end expected.");
  883.  
  884.         Token.Token_Id = END_OF_FILE_TOKEN;
  885.  
  886.         Token.End_Of_File = TRUE;
  887.  
  888.         Status_Info("\n");
  889.  
  890.         return;
  891.       }
  892.  
  893.       fclose(Data_File->File); /* added to fix open file buildup JLN 12/91 */
  894.  
  895.       POV_FREE (Data_File->Filename);
  896.  
  897.       Data_File = &Include_Files[--Include_File_Index];
  898.  
  899.       continue;
  900.     }
  901.  
  902.     String[0] = c; /* This isn't necessar but helps debugging */
  903.  
  904.     String[1] = '\0';
  905.  
  906.     String_Index = 0;
  907.  
  908.     switch (c)
  909.     {
  910.       case '\n':
  911.         Data_File->Line_Number++;
  912.         COOPERATE_0
  913.         break;
  914.  
  915.       case '{' :
  916.         Write_Token (LEFT_CURLY_TOKEN, Data_File);
  917.         break;
  918.   
  919.       case '}' :
  920.         Write_Token (RIGHT_CURLY_TOKEN, Data_File);
  921.         break;
  922.   
  923.       case '@' :
  924.         Write_Token (AT_TOKEN, Data_File);
  925.         break;
  926.   
  927.       case '&' :
  928.         Write_Token (AMPERSAND_TOKEN, Data_File);
  929.         break;
  930.   
  931.       case '`' :
  932.         Write_Token (BACK_QUOTE_TOKEN, Data_File);
  933.         break;
  934.   
  935.       case '\\':
  936.         Write_Token (BACK_SLASH_TOKEN, Data_File);
  937.         break;
  938.  
  939.       case '|' :
  940.         Write_Token (BAR_TOKEN, Data_File);
  941.         break;
  942.   
  943.       case ':' :
  944.         Write_Token (COLON_TOKEN, Data_File);
  945.         break;
  946.   
  947.       case ',' :
  948.         Write_Token (COMMA_TOKEN, Data_File);
  949.         break;
  950.   
  951.       case '-' :
  952.         Write_Token (DASH_TOKEN, Data_File);
  953.         break;
  954.   
  955.       case '$' :
  956.         Write_Token (DOLLAR_TOKEN, Data_File);
  957.         break;
  958.   
  959.       case '=' :
  960.         Write_Token (EQUALS_TOKEN, Data_File);
  961.         break;
  962.   
  963.       case '!' :
  964.         c2 = Echo_getc();
  965.         if (c2 == (int)'=')
  966.         {
  967.           Write_Token (REL_NE_TOKEN, Data_File);
  968.         }
  969.         else
  970.         {
  971.           Echo_ungetc(c2);
  972.           Write_Token (EXCLAMATION_TOKEN, Data_File);
  973.         }
  974.         break;
  975.   
  976.       case '#' : 
  977.         Parse_Directive(TRUE);
  978.         /* Write_Token (HASH_TOKEN, Data_File);*/
  979.         break;
  980.   
  981.       case '^' :
  982.         Write_Token (HAT_TOKEN, Data_File);
  983.         break;
  984.   
  985.       case '<' :
  986.         c2 = Echo_getc();
  987.         if (c2 == (int)'=')
  988.         {
  989.           Write_Token (REL_LE_TOKEN, Data_File);
  990.         }
  991.         else
  992.         {
  993.           Echo_ungetc(c2);
  994.           Write_Token (LEFT_ANGLE_TOKEN, Data_File);
  995.         }
  996.         break;
  997.   
  998.       case '(' :
  999.         Write_Token (LEFT_PAREN_TOKEN, Data_File);
  1000.         break;
  1001.   
  1002.       case '[' :
  1003.         Write_Token (LEFT_SQUARE_TOKEN, Data_File);
  1004.         break;
  1005.   
  1006.       case '%' :
  1007.         Write_Token (PERCENT_TOKEN, Data_File);
  1008.         break;
  1009.   
  1010.       case '+' :
  1011.         Write_Token (PLUS_TOKEN, Data_File);
  1012.         break;
  1013.   
  1014.       case '?' :
  1015.         Write_Token (QUESTION_TOKEN, Data_File);
  1016.         break;
  1017.   
  1018.       case '>' :
  1019.         c2 = Echo_getc();
  1020.         if (c2 == (int)'=')
  1021.         {
  1022.           Write_Token (REL_GE_TOKEN, Data_File);
  1023.         }
  1024.         else
  1025.         {
  1026.           Echo_ungetc(c2);
  1027.           Write_Token (RIGHT_ANGLE_TOKEN, Data_File);
  1028.         }
  1029.         break;
  1030.   
  1031.       case ')' :
  1032.         Write_Token (RIGHT_PAREN_TOKEN, Data_File);
  1033.         break;
  1034.   
  1035.       case ']' :
  1036.         Write_Token (RIGHT_SQUARE_TOKEN, Data_File);
  1037.         break;
  1038.   
  1039.       case ';' : /* Parser doesn't use it, so let's ignore it */
  1040.         /* Write_Token (SEMI_COLON_TOKEN, Data_File); */
  1041.         break;
  1042.   
  1043.       case '\'':
  1044.         Write_Token (SINGLE_QUOTE_TOKEN, Data_File);
  1045.         break;
  1046.   
  1047.         /* enable C++ style commenting */
  1048.       case '/' :
  1049.         c2 = Echo_getc();
  1050.         if(c2 != (int) '/' && c2 != (int) '*')
  1051.         {
  1052.           Echo_ungetc(c2);
  1053.           Write_Token (SLASH_TOKEN, Data_File);
  1054.           break;
  1055.         }
  1056.         if(c2 == (int)'*')
  1057.         {
  1058.           Parse_C_Comments();
  1059.           break;
  1060.         }
  1061.         while((c2 != (int)'\n') && (c2 != (int)'\r'))
  1062.         {
  1063.           c2=Echo_getc();
  1064.           if(c2==EOF)
  1065.           {
  1066.             Echo_ungetc(c2);
  1067.             break;
  1068.           }
  1069.         }
  1070.         if (c2 =='\n')
  1071.         {
  1072.           Data_File->Line_Number++;
  1073.         }
  1074.         COOPERATE_0
  1075.         break;
  1076.  
  1077.       case '*' :
  1078.         Write_Token (STAR_TOKEN, Data_File);
  1079.         break;
  1080.   
  1081.       case '~' :
  1082.         Write_Token (TILDE_TOKEN, Data_File);
  1083.         break;
  1084.   
  1085.       case '"' :
  1086.         Parse_String_Literal ();
  1087.         break;
  1088.   
  1089.       case '0':
  1090.       case '1':
  1091.       case '2':
  1092.       case '3':
  1093.       case '4':
  1094.       case '5':
  1095.       case '6':
  1096.       case '7':
  1097.       case '8':
  1098.       case '9':
  1099.       case '.':
  1100.         Echo_ungetc(c);
  1101.         if (Read_Float () != TRUE)
  1102.           return;
  1103.         break;
  1104.   
  1105.       case 'a':
  1106.       case 'b':
  1107.       case 'c':
  1108.       case 'd':
  1109.       case 'e':
  1110.       case 'f':
  1111.       case 'g':
  1112.       case 'h':
  1113.       case 'i':
  1114.       case 'j':
  1115.       case 'k':
  1116.       case 'l':
  1117.       case 'm':
  1118.       case 'n':
  1119.       case 'o':
  1120.       case 'p':
  1121.       case 'q':
  1122.       case 'r':
  1123.       case 's':
  1124.       case 't':
  1125.       case 'u':
  1126.       case 'v':
  1127.       case 'w':
  1128.       case 'x':
  1129.       case 'y':
  1130.       case 'z':
  1131.   
  1132.       case 'A':
  1133.       case 'B':
  1134.       case 'C':
  1135.       case 'D':
  1136.       case 'E':
  1137.       case 'F':
  1138.       case 'G':
  1139.       case 'H':
  1140.       case 'I':
  1141.       case 'J':
  1142.       case 'K':
  1143.       case 'L':
  1144.       case 'M':
  1145.       case 'N':
  1146.       case 'O':
  1147.       case 'P':
  1148.       case 'Q':
  1149.       case 'R':
  1150.       case 'S':
  1151.       case 'T':
  1152.       case 'U':
  1153.       case 'V':
  1154.       case 'W':
  1155.       case 'X':
  1156.       case 'Y':
  1157.       case 'Z':
  1158.       case '_':
  1159.         Echo_ungetc(c);
  1160.         Read_Symbol ();
  1161.         break;
  1162.       case '\t':
  1163.       case '\r':
  1164.       case '\032':   /* Control Z - EOF on many systems */
  1165.       case '\0':
  1166.         break;
  1167.   
  1168.       default:
  1169.         Error("Illegal character in input file, value is %02x.\n", c);
  1170.         break;
  1171.     }
  1172.   }
  1173.  
  1174.   token_count++;
  1175.  
  1176.   if (token_count > 1000)
  1177.   {
  1178.     token_count = 0;
  1179.  
  1180.     COOPERATE_0
  1181.  
  1182.     Check_User_Abort(FALSE);
  1183.  
  1184.     Status_Info(".");
  1185.  
  1186.     line_count++;
  1187.  
  1188.     if (line_count > 78)
  1189.     {
  1190.       line_count = 0;
  1191.  
  1192.       Status_Info ("\n");
  1193.     }
  1194.   }
  1195. }
  1196.  
  1197.  
  1198.  
  1199. /*****************************************************************************
  1200. *
  1201. * FUNCTION
  1202. *
  1203. * INPUT
  1204. *
  1205. * OUTPUT
  1206. *
  1207. * RETURNS
  1208. *
  1209. * AUTHOR
  1210. *
  1211. * DESCRIPTION
  1212. *
  1213. *   Mark that the token has been put back into the input stream.  The next
  1214. *   call to Get_Token will return the last-read token instead of reading a
  1215. *   new one from the file.
  1216. *
  1217. * CHANGES
  1218. *
  1219. ******************************************************************************/
  1220.  
  1221. void Unget_Token ()
  1222. {
  1223.   Token.Unget_Token = TRUE;
  1224. }
  1225.  
  1226.  
  1227.  
  1228. /*****************************************************************************
  1229. *
  1230. * FUNCTION
  1231. *
  1232. * INPUT
  1233. *
  1234. * OUTPUT
  1235. *
  1236. * RETURNS
  1237. *
  1238. * AUTHOR
  1239. *
  1240. * DESCRIPTION
  1241. *
  1242. *   Skip over spaces in the input file.
  1243. *
  1244. * CHANGES
  1245. *
  1246. ******************************************************************************/
  1247.  
  1248. static int Skip_Spaces ()
  1249. {
  1250.   register int c;
  1251.  
  1252.   while (TRUE)
  1253.   {
  1254.     c = Echo_getc();
  1255.  
  1256.     if (c == EOF)
  1257.     {
  1258.       return (FALSE);
  1259.     }
  1260.  
  1261.     if (!(isspace(c) || c == 0x0A))
  1262.     {
  1263.       break;
  1264.     }
  1265.  
  1266.     if (c == '\n')
  1267.     {
  1268.       Data_File->Line_Number++;
  1269.  
  1270.       COOPERATE_0
  1271.     }
  1272.   }
  1273.  
  1274.   Echo_ungetc(c);
  1275.  
  1276.   return (TRUE);
  1277. }
  1278.  
  1279.  
  1280.  
  1281. /*****************************************************************************
  1282. *
  1283. * FUNCTION
  1284. *
  1285. * INPUT
  1286. *
  1287. * OUTPUT
  1288. *
  1289. * RETURNS
  1290. *
  1291. * AUTHOR
  1292. *
  1293. * DESCRIPTION
  1294. *
  1295. *   C style comments with asterik and slash - CdW 8/91.
  1296. *
  1297. * CHANGES
  1298. *
  1299. ******************************************************************************/
  1300.  
  1301. static int Parse_C_Comments()
  1302. {
  1303.   register int c, c2;
  1304.   int End_Of_Comment;
  1305.  
  1306.   End_Of_Comment = FALSE;
  1307.  
  1308.   while (!End_Of_Comment)
  1309.   {
  1310.     c = Echo_getc();
  1311.  
  1312.     if (c == EOF)
  1313.     {
  1314.       Error ("No */ closing comment found.");
  1315.     }
  1316.  
  1317.     if (c == (int) '\n')
  1318.     {
  1319.       Data_File->Line_Number++;
  1320.  
  1321.       COOPERATE_0
  1322.     }
  1323.  
  1324.     if (c == (int) '*')
  1325.     {
  1326.       c2 = Echo_getc();
  1327.  
  1328.       if (c2 != (int) '/')
  1329.       {
  1330.         Echo_ungetc(c2);
  1331.       }
  1332.       else
  1333.       {
  1334.         End_Of_Comment = TRUE;
  1335.       }
  1336.     }
  1337.  
  1338.     /* Check for and handle nested comments */
  1339.  
  1340.     if (c == (int) '/')
  1341.     {
  1342.       c2 = Echo_getc();
  1343.  
  1344.       if (c2 != (int) '*')
  1345.       {
  1346.         Echo_ungetc(c2);
  1347.       }
  1348.       else
  1349.       {
  1350.         Parse_C_Comments();
  1351.       }
  1352.     }
  1353.   }
  1354.  
  1355.   return (TRUE);
  1356. }
  1357.  
  1358.  
  1359.  
  1360. /* The following routines make it easier to handle strings.  They stuff
  1361.    characters into a string buffer one at a time making all the proper
  1362.    range checks.  Call Begin_String to start, Stuff_Character to put
  1363.    characters in, and End_String to finish.  The String variable contains
  1364.    the final string. */
  1365.  
  1366. /*****************************************************************************
  1367. *
  1368. * FUNCTION
  1369. *
  1370. * INPUT
  1371. *
  1372. * OUTPUT
  1373. *
  1374. * RETURNS
  1375. *
  1376. * AUTHOR
  1377. *
  1378. * DESCRIPTION
  1379. *
  1380. * CHANGES
  1381. *
  1382. ******************************************************************************/
  1383.  
  1384. static void Begin_String()
  1385. {
  1386.   String_Index = 0;
  1387. }
  1388.  
  1389.  
  1390.  
  1391. /*****************************************************************************
  1392. *
  1393. * FUNCTION
  1394. *
  1395. * INPUT
  1396. *
  1397. * OUTPUT
  1398. *
  1399. * RETURNS
  1400. *
  1401. * AUTHOR
  1402. *
  1403. * DESCRIPTION
  1404. *
  1405. * CHANGES
  1406. *
  1407. ******************************************************************************/
  1408.  
  1409. static void Stuff_Character(c)
  1410. int c;
  1411. {
  1412.   if (String_Index < MAX_STRING_INDEX)
  1413.   {
  1414.     String[String_Index++] = (char)c;
  1415.  
  1416.     if (String_Index >= MAX_STRING_INDEX)
  1417.     {
  1418.       Error ("String too long.");
  1419.     }
  1420.   }
  1421. }
  1422.  
  1423.  
  1424.  
  1425. /*****************************************************************************
  1426. *
  1427. * FUNCTION
  1428. *
  1429. * INPUT
  1430. *
  1431. * OUTPUT
  1432. *
  1433. * RETURNS
  1434. *
  1435. * AUTHOR
  1436. *
  1437. * DESCRIPTION
  1438. *
  1439. * CHANGES
  1440. *
  1441. ******************************************************************************/
  1442.  
  1443. static void End_String()
  1444. {
  1445.   Stuff_Character((int)'\0');
  1446. }
  1447.  
  1448.  
  1449.  
  1450. /*****************************************************************************
  1451. *
  1452. * FUNCTION
  1453. *
  1454. * INPUT
  1455. *
  1456. * OUTPUT
  1457. *
  1458. * RETURNS
  1459. *
  1460. * AUTHOR
  1461. *
  1462. * DESCRIPTION
  1463. *
  1464. *   Read a float from the input file and tokenize it as one token. The phase
  1465. *   variable is 0 for the first character, 1 for all subsequent characters
  1466. *   up to the decimal point, 2 for all characters after the decimal
  1467. *   point, 3 for the E+/- and 4 for the exponent.  This helps to insure
  1468. *   that the number is formatted properly. E format added 9/91 CEY
  1469. *
  1470. * CHANGES
  1471. *
  1472. ******************************************************************************/
  1473.  
  1474. static int Read_Float()
  1475. {
  1476.   register int c, Finished, Phase;
  1477.  
  1478.   Finished = FALSE;
  1479.  
  1480.   Phase = 0;
  1481.  
  1482.   Begin_String();
  1483.  
  1484.   while (!Finished)
  1485.   {
  1486.     c = Echo_getc();
  1487.  
  1488.     if (c == EOF)
  1489.     {
  1490.       Error ("Unexpected end of file.");
  1491.     }
  1492.  
  1493.     switch (Phase)
  1494.     {
  1495.       case 0:
  1496.  
  1497.         Phase = 1;
  1498.  
  1499.         if (isdigit(c))
  1500.         {
  1501.           Stuff_Character(c);
  1502.         }
  1503.         else
  1504.         {
  1505.           if (c == '.')
  1506.           {
  1507.             c = Echo_getc();
  1508.  
  1509.             if (c == EOF)
  1510.             {
  1511.               Error ("Unexpected end of file");
  1512.             }
  1513.  
  1514.             if (isdigit(c))
  1515.             {
  1516.               Stuff_Character('0');
  1517.               Stuff_Character('.');
  1518.               Stuff_Character(c);
  1519.  
  1520.               Phase = 2;
  1521.             }
  1522.             else
  1523.             {
  1524.               Echo_ungetc(c);
  1525.  
  1526.               Write_Token (PERIOD_TOKEN, Data_File);
  1527.  
  1528.               return(TRUE);
  1529.             }
  1530.           }
  1531.           else
  1532.           {
  1533.             Error ("Error in decimal number");
  1534.           }
  1535.         }
  1536.  
  1537.         break;
  1538.  
  1539.       case 1:
  1540.         if (isdigit(c))
  1541.         {
  1542.           Stuff_Character(c);
  1543.         }
  1544.         else
  1545.         {
  1546.           if (c == (int) '.')
  1547.           {
  1548.             Stuff_Character(c); Phase = 2;
  1549.           }
  1550.           else
  1551.           {
  1552.             if ((c == 'e') || (c == 'E'))
  1553.             {
  1554.               Stuff_Character(c); Phase = 3;
  1555.             }
  1556.             else
  1557.             {
  1558.               Finished = TRUE;
  1559.             }
  1560.           }
  1561.         }
  1562.  
  1563.         break;
  1564.  
  1565.       case 2:
  1566.  
  1567.         if (isdigit(c))
  1568.         {
  1569.           Stuff_Character(c);
  1570.         }
  1571.         else
  1572.         {
  1573.           if ((c == 'e') || (c == 'E'))
  1574.           {
  1575.             Stuff_Character(c); Phase = 3;
  1576.           }
  1577.           else
  1578.           {
  1579.             Finished = TRUE;
  1580.           }
  1581.         }
  1582.  
  1583.         break;
  1584.  
  1585.       case 3:
  1586.  
  1587.         if (isdigit(c) || (c == '+') || (c == '-'))
  1588.         {
  1589.           Stuff_Character(c); Phase = 4;
  1590.         }
  1591.         else
  1592.         {
  1593.           Finished = TRUE;
  1594.         }
  1595.  
  1596.         break;
  1597.  
  1598.       case 4:
  1599.  
  1600.         if (isdigit(c))
  1601.         {
  1602.           Stuff_Character(c);
  1603.         }
  1604.         else
  1605.         {
  1606.           Finished = TRUE;
  1607.         }
  1608.  
  1609.         break;
  1610.     }
  1611.   }
  1612.  
  1613.   Echo_ungetc(c);
  1614.  
  1615.   End_String();
  1616.  
  1617.   Write_Token (FLOAT_TOKEN, Data_File);
  1618.  
  1619.   if (sscanf (String, DBL_FORMAT_STRING, &Token.Token_Float) == 0)
  1620.   {
  1621.     return (FALSE);
  1622.   }
  1623.  
  1624.   return (TRUE);
  1625. }
  1626.  
  1627.  
  1628.  
  1629. /*****************************************************************************
  1630. *
  1631. * FUNCTION
  1632. *
  1633. * INPUT
  1634. *
  1635. * OUTPUT
  1636. *
  1637. * RETURNS
  1638. *
  1639. * AUTHOR
  1640. *
  1641. * DESCRIPTION
  1642. *
  1643. *   Parse a string from the input file into a token.
  1644. *
  1645. * CHANGES
  1646. *
  1647. ******************************************************************************/
  1648.  
  1649. static void Parse_String_Literal()
  1650. {
  1651.   register int c;
  1652.  
  1653.   Begin_String();
  1654.  
  1655.   while (TRUE)
  1656.   {
  1657.     c = Echo_getc();
  1658.  
  1659.     if (c == EOF)
  1660.     {
  1661.       Error ("No end quote for string.");
  1662.     }
  1663.  
  1664.     if (c == '\\')
  1665.     {
  1666.       switch(c = Echo_getc())
  1667.       {
  1668.         case '\n':
  1669.         case '\r':
  1670.  
  1671.           Error("Unterminated string literal.");
  1672.  
  1673.           break;
  1674.  
  1675.         case '\"':
  1676.  
  1677.           c = 0x22;
  1678.  
  1679.           break;
  1680.  
  1681.         case EOF:
  1682.  
  1683.           Error ("No end quote for string.");
  1684.  
  1685.           break;
  1686.  
  1687.         case '\\' :
  1688.           c='\\';
  1689.           break;
  1690.  
  1691.         default:
  1692.  
  1693.           Stuff_Character ('\\');
  1694.       }
  1695.  
  1696.       Stuff_Character (c);
  1697.     }
  1698.     else
  1699.     {
  1700.       if (c != (int) '"')
  1701.       {
  1702.         Stuff_Character (c);
  1703.       }
  1704.       else
  1705.       {
  1706.         break;
  1707.       }
  1708.     }
  1709.   }
  1710.  
  1711.   End_String();
  1712.  
  1713.   Write_Token (STRING_LITERAL_TOKEN, Data_File);
  1714.  
  1715.   Token.Token_String = String;
  1716. }
  1717.  
  1718.  
  1719.  
  1720. /*****************************************************************************
  1721. *
  1722. * FUNCTION
  1723. *
  1724. * INPUT
  1725. *
  1726. * OUTPUT
  1727. *
  1728. * RETURNS
  1729. *
  1730. * AUTHOR
  1731. *
  1732. * DESCRIPTION
  1733. *
  1734. *   Read in a symbol from the input file. Check to see if it is a reserved
  1735. *   word. If it is, write out the appropriate token. Otherwise, write the
  1736. *   symbol out to the symbol table and write out an IDENTIFIER token. An
  1737. *   identifier token is a token whose token number is greater than the
  1738. *   highest reserved word.
  1739. *
  1740. * CHANGES
  1741. *
  1742. ******************************************************************************/
  1743.  
  1744. static void Read_Symbol()
  1745. {
  1746.   register int c, Symbol_Id;
  1747.   register int hash_value;
  1748.   HASH_TABLE *New_Entry;
  1749.  
  1750.   Begin_String();
  1751.  
  1752.   while (TRUE)
  1753.   {
  1754.     c = Echo_getc();
  1755.  
  1756.     if (c == EOF)
  1757.     {
  1758.       Error ("Unexpected end of file.");
  1759.     }
  1760.  
  1761.     if (isalpha(c) || isdigit(c) || c == (int) '_')
  1762.     {
  1763.       Stuff_Character(c);
  1764.     }
  1765.     else
  1766.     {
  1767.       Echo_ungetc(c);
  1768.  
  1769.       break;
  1770.     }
  1771.   }
  1772.  
  1773.   End_String();
  1774.  
  1775.   if (Inside_Ifdef)
  1776.   {
  1777.     Token.Token_Id = IDENTIFIER_TOKEN;
  1778.  
  1779.     return;
  1780.   }
  1781.  
  1782.   /* If its a reserved keyword, write it and return */
  1783.  
  1784.   if ((Symbol_Id = Find_Reserved(String, get_hash_value(String))) != -1)
  1785.   {
  1786.     Write_Token (Symbol_Id, Data_File);
  1787.   }
  1788.   else
  1789.   {
  1790.     if ((Symbol_Id = Find_Symbol(String, get_hash_value(String))) == -1)
  1791.     {
  1792.       /* Here its an unknown symbol. */
  1793.  
  1794.       if (Skipping)
  1795.       {
  1796.         Write_Token(IDENTIFIER_TOKEN, Data_File);
  1797.         return;
  1798.       }
  1799.       else
  1800.       {
  1801.         Number_Of_Symbols++;
  1802.  
  1803.         /* Add it to the table. */
  1804.  
  1805.         New_Entry = (HASH_TABLE *)POV_MALLOC(sizeof(HASH_TABLE), "hash table entry");
  1806.  
  1807.         New_Entry->Entry.Token_Number = Symbol_Id = Number_Of_Symbols;
  1808.  
  1809.         New_Entry->Entry.Token_Name = POV_MALLOC(strlen(String)+1, "identifier");
  1810.  
  1811.         strcpy(New_Entry->Entry.Token_Name, String);
  1812.  
  1813.         hash_value = get_hash_value(String);
  1814.  
  1815.         New_Entry->next = Symbol_Table_Hash_Table[hash_value];
  1816.  
  1817.         Symbol_Table_Hash_Table[hash_value] = New_Entry;
  1818.       }
  1819.     }
  1820.  
  1821.     Write_Token (LAST_TOKEN + Symbol_Id, Data_File);
  1822.   }
  1823. }
  1824.  
  1825.  
  1826.  
  1827. /*****************************************************************************
  1828. *
  1829. * FUNCTION
  1830. *
  1831. * INPUT
  1832. *
  1833. * OUTPUT
  1834. *
  1835. * RETURNS
  1836. *
  1837. *   int - Index of the token in the reserved words table or -1 if it isn't there.
  1838. *
  1839. * AUTHOR
  1840. *
  1841. * DESCRIPTION
  1842. *
  1843. *   Use a hash table look-up to find a keyword given in the variable String.
  1844. *
  1845. * CHANGES
  1846. *
  1847. ******************************************************************************/
  1848.  
  1849. static int Find_Reserved(s, hash_value)
  1850. char *s;
  1851. int hash_value;
  1852. {
  1853.   HASH_TABLE *p;
  1854.  
  1855.   p = Reserved_Words_Hash_Table[hash_value];
  1856.  
  1857.   while (p)
  1858.   {
  1859.     if (strcmp(s, p->Entry.Token_Name) == 0)
  1860.     {
  1861.       return(p->Entry.Token_Number);
  1862.     }
  1863.  
  1864.     p = p->next;
  1865.   }
  1866.  
  1867.   return(-1);
  1868. }
  1869.  
  1870.  
  1871.  
  1872. /*****************************************************************************
  1873. *
  1874. * FUNCTION
  1875. *
  1876. * INPUT
  1877. *
  1878. * OUTPUT
  1879. *
  1880. * RETURNS
  1881. *
  1882. *   int - Symbol ID, -1 if not found.
  1883. *
  1884. * AUTHOR
  1885. *
  1886. * DESCRIPTION
  1887. *
  1888. *   Use a hash table look-up to find symbol given in string s.
  1889. *
  1890. * CHANGES
  1891. *
  1892. ******************************************************************************/
  1893.  
  1894. static int Find_Symbol(s, hash_value)
  1895. char *s;
  1896. int hash_value;
  1897. {
  1898.   HASH_TABLE *p;
  1899.  
  1900.   p = Symbol_Table_Hash_Table[hash_value];
  1901.  
  1902.   while (p)
  1903.   {
  1904.     if (strcmp(s, p->Entry.Token_Name) == 0)
  1905.     {
  1906.       return(p->Entry.Token_Number);
  1907.     }
  1908.  
  1909.     p = p->next;
  1910.   }
  1911.  
  1912.   return(-1);
  1913. }
  1914.  
  1915.  
  1916.  
  1917. /*****************************************************************************
  1918. *
  1919. * FUNCTION
  1920. *
  1921. * INPUT
  1922. *
  1923. * OUTPUT
  1924. *
  1925. * RETURNS
  1926. *
  1927. * AUTHOR
  1928. *
  1929. * DESCRIPTION
  1930. *
  1931. * CHANGES
  1932. *
  1933. ******************************************************************************/
  1934.  
  1935. static int Echo_getc()
  1936. {
  1937.   register int c;
  1938.  
  1939.   if (Echo_Unget_Flag)
  1940.   {
  1941.     Echo_Unget_Flag = FALSE;
  1942.  
  1943.     return(Echo_Unget_Char);
  1944.   }
  1945.  
  1946.   Echo_Ptr[Echo_Indx++] = c = getc(Data_File->File);
  1947.  
  1948.   if ((Echo_Indx > Echo_Line_Length) || (c == '\n'))
  1949.   {
  1950.     Echo_Ptr[Echo_Indx] = '\0';
  1951.  
  1952.     Echo_Indx = 0;
  1953.  
  1954.     Echo_Line++;
  1955.  
  1956.     if (Echo_Line == Num_Echo_Lines)
  1957.       Echo_Line = 0;
  1958.  
  1959.     Echo_Ptr=Echo_Buff[Echo_Line];
  1960.   }
  1961.  
  1962.   return(c);
  1963. }
  1964.  
  1965.  
  1966.  
  1967. /*****************************************************************************
  1968. *
  1969. * FUNCTION
  1970. *
  1971. * INPUT
  1972. *
  1973. * OUTPUT
  1974. *
  1975. * RETURNS
  1976. *
  1977. * AUTHOR
  1978. *
  1979. * DESCRIPTION
  1980. *
  1981. * CHANGES
  1982. *
  1983. ******************************************************************************/
  1984.  
  1985. static int Echo_ungetc(int c)
  1986. {
  1987.   Echo_Unget_Flag = TRUE;
  1988.  
  1989.   return(Echo_Unget_Char = c);
  1990. }
  1991.  
  1992.  
  1993.  
  1994. /*****************************************************************************
  1995. *
  1996. * FUNCTION
  1997. *
  1998. * INPUT
  1999. *
  2000. * OUTPUT
  2001. *
  2002. * RETURNS
  2003. *
  2004. * AUTHOR
  2005. *
  2006. * DESCRIPTION
  2007. *
  2008. * CHANGES
  2009. *
  2010. ******************************************************************************/
  2011.  
  2012. void Where_Error ()
  2013. {
  2014.   int i;
  2015.  
  2016.   /* Return if no filename is specified. [DB 8/94] */
  2017.  
  2018.   if (Token.Filename == NULL)
  2019.   {
  2020.     return;
  2021.   }
  2022.  
  2023.   strcpy (&(Echo_Ptr[Echo_Indx])," <----ERROR\n");
  2024.  
  2025.   for (i=0;i<Num_Echo_Lines;i++)
  2026.   {
  2027.     Echo_Line++;
  2028.  
  2029.     if (Echo_Line==Num_Echo_Lines)
  2030.     {
  2031.       Echo_Line=0;
  2032.     }
  2033.  
  2034.     Error_Line(Echo_Buff[Echo_Line]);
  2035.   }
  2036.  
  2037.   Error_Line("\n%s:%d: error: ", Token.Filename, Token.Token_Line_No+1);
  2038. }
  2039.  
  2040.  
  2041.  
  2042.  
  2043. /*****************************************************************************
  2044. *
  2045. * FUNCTION    Parse_Directive
  2046. *
  2047. * INPUT
  2048. *
  2049. * OUTPUT
  2050. *
  2051. * RETURNS
  2052. *
  2053. * AUTHOR      Chris Young
  2054. *
  2055. * DESCRIPTION
  2056. *
  2057. * CHANGES
  2058. *
  2059. ******************************************************************************/
  2060.  
  2061. void Parse_Directive(After_Hash)
  2062. int After_Hash;
  2063. {
  2064.   DBL Value, Value2;
  2065.   int Flag;
  2066.   char *ts;
  2067.   COND_TYPE Curr_Type = Cond_Stack[CS_Index].Cond_Type;
  2068.   
  2069.   if (!Ok_To_Declare)
  2070.   {
  2071.     if (After_Hash)
  2072.     {
  2073.        Token.Token_Id=HASH_TOKEN; 
  2074.     }
  2075.     Token.Unget_Token = FALSE;
  2076.  
  2077.     return;
  2078.   }
  2079.  
  2080.   EXPECT
  2081.     CASE(IFDEF_TOKEN)
  2082.       CS_Index++;
  2083.  
  2084.       if (Skipping)
  2085.       {
  2086.         Cond_Stack[CS_Index].Cond_Type = SKIP_TIL_END_COND;
  2087.         Skip_Tokens(SKIP_TIL_END_COND);
  2088.       }
  2089.       else
  2090.       {
  2091.         GET(LEFT_PAREN_TOKEN)
  2092.         Inside_Ifdef=TRUE;
  2093.         Get_Token();
  2094.         strcpy(String2,String);
  2095.         Inside_Ifdef=FALSE;
  2096.         GET(RIGHT_PAREN_TOKEN)
  2097.         
  2098.         if (Find_Symbol(String2, get_hash_value(String2)) != -1)
  2099.         {
  2100.            Cond_Stack[CS_Index].Cond_Type=IF_TRUE_COND;
  2101.         }
  2102.         else
  2103.         {
  2104.            Cond_Stack[CS_Index].Cond_Type=IF_FALSE_COND;
  2105.            Skip_Tokens(IF_FALSE_COND);
  2106.         }
  2107.       }
  2108.       EXIT
  2109.     END_CASE
  2110.     
  2111.     CASE(IFNDEF_TOKEN)
  2112.       CS_Index++;
  2113.  
  2114.       if (Skipping)
  2115.       {
  2116.         Cond_Stack[CS_Index].Cond_Type = SKIP_TIL_END_COND;
  2117.         Skip_Tokens(SKIP_TIL_END_COND);
  2118.       }
  2119.       else
  2120.       {
  2121.         GET(LEFT_PAREN_TOKEN)
  2122.         Inside_Ifdef=TRUE;
  2123.         Get_Token();
  2124.         strcpy(String2,String);
  2125.         Inside_Ifdef=FALSE;
  2126.         GET(RIGHT_PAREN_TOKEN)
  2127.         
  2128.         if (Find_Symbol(String2, get_hash_value(String2)) != -1)
  2129.         {
  2130.            Cond_Stack[CS_Index].Cond_Type=IF_FALSE_COND;
  2131.            Skip_Tokens(IF_FALSE_COND);
  2132.         }
  2133.         else
  2134.         {
  2135.            Cond_Stack[CS_Index].Cond_Type=IF_TRUE_COND;
  2136.         }
  2137.       }
  2138.       EXIT
  2139.     END_CASE
  2140.     
  2141.     CASE(IF_TOKEN)
  2142.       CS_Index++;
  2143.  
  2144.       if (Skipping)
  2145.       {
  2146.         Cond_Stack[CS_Index].Cond_Type = SKIP_TIL_END_COND;
  2147.         Skip_Tokens(SKIP_TIL_END_COND);
  2148.       }
  2149.       else
  2150.       {
  2151.         Value=Parse_Float_Param();
  2152.       
  2153.         if (fabs(Value)>EPSILON)
  2154.         {
  2155.            Cond_Stack[CS_Index].Cond_Type=IF_TRUE_COND;
  2156.         }
  2157.         else
  2158.         {
  2159.            Cond_Stack[CS_Index].Cond_Type=IF_FALSE_COND;
  2160.            Skip_Tokens(IF_FALSE_COND);
  2161.         }
  2162.       }
  2163.       EXIT
  2164.     END_CASE
  2165.  
  2166.  
  2167.     CASE(WHILE_TOKEN)
  2168.       CS_Index++;
  2169.  
  2170.       if (Skipping)
  2171.       {
  2172.         Cond_Stack[CS_Index].Cond_Type = SKIP_TIL_END_COND;
  2173.         Skip_Tokens(SKIP_TIL_END_COND);
  2174.       }
  2175.       else
  2176.       {
  2177.         Cond_Stack[CS_Index].While_File    = Data_File->File;
  2178.         Cond_Stack[CS_Index].While_Pos     = ftell(Data_File->File);
  2179.         Cond_Stack[CS_Index].While_Line_No = Data_File->Line_Number;
  2180.  
  2181.         if (Echo_Unget_Flag)
  2182.         {
  2183.            Cond_Stack[CS_Index].While_Pos--;
  2184.         }
  2185.  
  2186.         Value=Parse_Float_Param();
  2187.        
  2188.         if (fabs(Value)>EPSILON)
  2189.         {
  2190.            Cond_Stack[CS_Index].Cond_Type = WHILE_COND;
  2191.         }
  2192.         else
  2193.         {
  2194.            Cond_Stack[CS_Index].Cond_Type = SKIP_TIL_END_COND;
  2195.            Skip_Tokens(SKIP_TIL_END_COND);
  2196.         }
  2197.       }
  2198.       EXIT
  2199.     END_CASE
  2200.     
  2201.  
  2202.     CASE(ELSE_TOKEN)
  2203.       switch (Curr_Type)
  2204.       {
  2205.          case IF_TRUE_COND:
  2206.            Cond_Stack[CS_Index].Cond_Type = SKIP_TIL_END_COND;
  2207.            Skip_Tokens(SKIP_TIL_END_COND);
  2208.            break;
  2209.            
  2210.          case IF_FALSE_COND:
  2211.            Cond_Stack[CS_Index].Cond_Type = ELSE_COND;
  2212.            Token.Token_Id=HASH_TOKEN; /*insures Skip_Token takes notice*/
  2213.            UNGET
  2214.            break;
  2215.          
  2216.          case CASE_TRUE_COND:
  2217.          case SKIP_TIL_END_COND:
  2218.            break;
  2219.  
  2220.          case CASE_FALSE_COND:
  2221.            Cond_Stack[CS_Index].Cond_Type = CASE_TRUE_COND;
  2222.            if (Skipping)
  2223.            {
  2224.               Token.Token_Id=HASH_TOKEN; /*insures Skip_Token takes notice*/
  2225.               UNGET
  2226.            }
  2227.            break;
  2228.  
  2229.          default:
  2230.            Error("Mis-matched '#else'.");
  2231.       }
  2232.       EXIT
  2233.     END_CASE
  2234.  
  2235.     CASE(SWITCH_TOKEN)
  2236.       CS_Index++;
  2237.  
  2238.       if (Skipping)
  2239.       {
  2240.         Cond_Stack[CS_Index].Cond_Type = SKIP_TIL_END_COND;
  2241.         Skip_Tokens(SKIP_TIL_END_COND);
  2242.       }
  2243.       else
  2244.       {
  2245.         Cond_Stack[CS_Index].Switch_Value=Parse_Float_Param();
  2246.         Cond_Stack[CS_Index].Cond_Type=SWITCH_COND;
  2247.         EXPECT
  2248.           CASE2(CASE_TOKEN,RANGE_TOKEN)
  2249.             if (Token.Token_Id==CASE_TOKEN)
  2250.             {
  2251.               Value=Parse_Float_Param();
  2252.               Flag = (fabs(Value-Cond_Stack[CS_Index].Switch_Value)<EPSILON);
  2253.             }
  2254.             else
  2255.             {
  2256.               Parse_Float_Param2(&Value,&Value2);
  2257.               Flag = ((Cond_Stack[CS_Index].Switch_Value >= Value) &&
  2258.                       (Cond_Stack[CS_Index].Switch_Value <= Value2));
  2259.             }
  2260.  
  2261.             if(Flag)
  2262.             {
  2263.               Cond_Stack[CS_Index].Cond_Type=CASE_TRUE_COND;
  2264.             }
  2265.             else
  2266.             {
  2267.               Cond_Stack[CS_Index].Cond_Type=CASE_FALSE_COND;
  2268.               Skip_Tokens(CASE_FALSE_COND);
  2269.             }
  2270.             EXIT
  2271.           END_CASE
  2272.  
  2273.           OTHERWISE
  2274.             Error("#switch not followed by #case or #range.");
  2275.           END_CASE
  2276.         END_EXPECT
  2277.       }
  2278.       EXIT
  2279.     END_CASE
  2280.  
  2281.     CASE(BREAK_TOKEN)
  2282.       if (Curr_Type==CASE_TRUE_COND)
  2283.       {
  2284.         Cond_Stack[CS_Index].Cond_Type=SKIP_TIL_END_COND;
  2285.         Skip_Tokens(SKIP_TIL_END_COND);
  2286.       }          
  2287.       EXIT
  2288.     END_CASE
  2289.     
  2290.     CASE2(CASE_TOKEN,RANGE_TOKEN)
  2291.       switch(Curr_Type)
  2292.       {
  2293.         case CASE_TRUE_COND:
  2294.         case CASE_FALSE_COND:
  2295.           if (Token.Token_Id==CASE_TOKEN)
  2296.           {
  2297.             Value=Parse_Float_Param();
  2298.             Flag = (fabs(Value-Cond_Stack[CS_Index].Switch_Value)<EPSILON);
  2299.           }
  2300.           else
  2301.           {
  2302.             Parse_Float_Param2(&Value,&Value2);
  2303.             Flag = ((Cond_Stack[CS_Index].Switch_Value >= Value) &&
  2304.                     (Cond_Stack[CS_Index].Switch_Value <= Value2));
  2305.           }
  2306.           
  2307.           if(Flag && (Curr_Type==CASE_FALSE_COND))
  2308.           {
  2309.             Cond_Stack[CS_Index].Cond_Type=CASE_TRUE_COND;
  2310.             if (Skipping)
  2311.             {
  2312.                Token.Token_Id=HASH_TOKEN; /*insures Skip_Token takes notice*/
  2313.                UNGET
  2314.             }
  2315.           }
  2316.           break;           
  2317.  
  2318.         case SWITCH_COND:
  2319.           UNGET
  2320.         case SKIP_TIL_END_COND:
  2321.           break;
  2322.  
  2323.         default:
  2324.           Error("Mis-matched '#case' or '#range'.");
  2325.       }
  2326.       EXIT
  2327.     END_CASE
  2328.     
  2329.     CASE(END_TOKEN)
  2330.       switch (Curr_Type)
  2331.       {
  2332.          case IF_FALSE_COND:
  2333.            Token.Token_Id=HASH_TOKEN; /*insures Skip_Token takes notice*/
  2334.            UNGET
  2335.          case IF_TRUE_COND:
  2336.          case ELSE_COND:
  2337.          case CASE_TRUE_COND:
  2338.          case CASE_FALSE_COND:
  2339.          case SKIP_TIL_END_COND:
  2340.            if (--CS_Index < 0)
  2341.            {
  2342.               Error("Mis-matched '#end'.");
  2343.            }
  2344.            if (Skipping)
  2345.            {
  2346.               Token.Token_Id=HASH_TOKEN; /*insures Skip_Token takes notice*/
  2347.               UNGET
  2348.            }
  2349.            EXIT
  2350.            break;
  2351.          
  2352.          case WHILE_COND:
  2353.            if (Cond_Stack[CS_Index].While_File != Data_File->File)
  2354.            { 
  2355.               Error("#while loop didn't end in file where it started.");
  2356.            }
  2357.            
  2358.            if (fseek(Data_File->File, Cond_Stack[CS_Index].While_Pos,0) < 0)
  2359.            {
  2360.               Error("Unable to seek in input file for #while directive.\n");
  2361.            }
  2362.  
  2363.            Data_File->Line_Number = Cond_Stack[CS_Index].While_Line_No;
  2364.  
  2365.            Value=Parse_Float_Param();
  2366.       
  2367.            if (fabs(Value)<EPSILON)
  2368.            {
  2369.              Cond_Stack[CS_Index].Cond_Type = SKIP_TIL_END_COND;
  2370.              Skip_Tokens(SKIP_TIL_END_COND);
  2371.            }
  2372.            break;
  2373.  
  2374.          default:
  2375.            Error("Mis-matched '#end'.");
  2376.       }
  2377.       EXIT
  2378.     END_CASE
  2379.  
  2380.     CASE (DECLARE_TOKEN)
  2381.       if (Skipping)
  2382.       {
  2383.          UNGET
  2384.          EXIT
  2385.       }
  2386.       else
  2387.       {
  2388.          Parse_Declare ();
  2389.          if (Token.Unget_Token && (Token.Token_Id==HASH_TOKEN))
  2390.          {
  2391.             Token.Unget_Token=FALSE;
  2392.          }
  2393.          else
  2394.          {
  2395.             EXIT
  2396.          }
  2397.       }
  2398.     END_CASE
  2399.     
  2400.     CASE (DEFAULT_TOKEN)
  2401.       Parse_Default();
  2402.       EXIT
  2403.     END_CASE
  2404.  
  2405.     CASE (INCLUDE_TOKEN)
  2406.       if (Skipping)
  2407.       {
  2408.          UNGET
  2409.       }
  2410.       else
  2411.       {
  2412.          Open_Include();
  2413.       }
  2414.       EXIT
  2415.     END_CASE
  2416.  
  2417.     CASE (FLOAT_FUNCT_TOKEN)
  2418.       if (Skipping)
  2419.       {
  2420.         UNGET
  2421.         EXIT
  2422.       }
  2423.       else
  2424.       {
  2425.         switch(Token.Function_Id)
  2426.         {
  2427.            case VERSION_TOKEN:
  2428.              Ok_To_Declare = FALSE;
  2429.              opts.Language_Version = Parse_Float ();
  2430.              Ok_To_Declare = TRUE;
  2431.              if (Token.Unget_Token && (Token.Token_Id==HASH_TOKEN))
  2432.              {
  2433.                 Token.Unget_Token=FALSE;
  2434.              }
  2435.              else
  2436.              {
  2437.                 EXIT
  2438.              }
  2439.              break;
  2440.  
  2441.            default:
  2442.              UNGET
  2443.              Parse_Error_Str ("object or directive.");
  2444.              break;
  2445.         }
  2446.       }
  2447.     END_CASE
  2448.  
  2449.     CASE(WARNING_TOKEN)
  2450.       if (Skipping)
  2451.       {
  2452.         UNGET
  2453.         EXIT
  2454.       }
  2455.       else
  2456.       {     
  2457.         ts=Parse_Formatted_String();
  2458.         Warning(0.0,ts);
  2459.         POV_FREE(ts);
  2460.       }
  2461.       EXIT
  2462.     END_CASE
  2463.       
  2464.     CASE(ERROR_TOKEN)
  2465.       if (Skipping)
  2466.       {
  2467.         UNGET
  2468.         EXIT
  2469.       }
  2470.       else
  2471.       {     
  2472.         ts=Parse_Formatted_String();
  2473.         POV_FREE(ts);
  2474.         Error("User error directive hit.");
  2475.       }
  2476.       EXIT
  2477.     END_CASE
  2478.       
  2479.     CASE(RENDER_TOKEN)
  2480.       if (Skipping)
  2481.       {
  2482.         UNGET
  2483.         EXIT
  2484.       }
  2485.       else
  2486.       {     
  2487.         ts=Parse_Formatted_String();
  2488.         Render_Info(ts);
  2489.         POV_FREE(ts);
  2490.       }
  2491.       EXIT
  2492.     END_CASE
  2493.       
  2494.     CASE(STATISTICS_TOKEN)
  2495.       if (Skipping)
  2496.       {
  2497.         UNGET
  2498.         EXIT
  2499.       }
  2500.       else
  2501.       {     
  2502.         ts=Parse_Formatted_String();
  2503.         Statistics(ts);
  2504.         POV_FREE(ts);
  2505.       }
  2506.       EXIT
  2507.     END_CASE
  2508.       
  2509.     CASE(DEBUG_TOKEN)
  2510.       if (Skipping)
  2511.       {
  2512.         UNGET
  2513.         EXIT
  2514.       }
  2515.       else
  2516.       {     
  2517.         ts=Parse_Formatted_String();
  2518.         Debug_Info(ts);
  2519.         POV_FREE(ts);
  2520.       }
  2521.       EXIT
  2522.     END_CASE
  2523.  
  2524.     OTHERWISE
  2525.       UNGET
  2526.       EXIT
  2527.     END_CASE
  2528.   END_EXPECT
  2529.   
  2530.   if (Token.Unget_Token)
  2531.   {
  2532.     Token.Unget_Token = FALSE;
  2533.   }
  2534.   else
  2535.   {
  2536.     Token.Token_Id = END_OF_FILE_TOKEN;
  2537.   }
  2538. }
  2539.  
  2540.  
  2541.  
  2542. /*****************************************************************************
  2543. *
  2544. * FUNCTION
  2545. *
  2546. * INPUT
  2547. *
  2548. * OUTPUT
  2549. *
  2550. * RETURNS
  2551. *
  2552. * AUTHOR
  2553. *
  2554. * DESCRIPTION
  2555. *
  2556. * CHANGES
  2557. *
  2558. ******************************************************************************/
  2559.  
  2560. void Open_Include()
  2561. {
  2562.    char *temp;
  2563.  
  2564.    if (Skip_Spaces () != TRUE)
  2565.      Error ("Expecting a string after INCLUDE.\n");
  2566.  
  2567.    Include_File_Index++;
  2568.  
  2569.    if (Include_File_Index > MAX_INCLUDE_FILES)
  2570.      Error ("Too many nested include files.\n");
  2571.  
  2572.    temp = Parse_String();
  2573.  
  2574.    Data_File = &Include_Files[Include_File_Index];
  2575.    Data_File->Line_Number = 0;
  2576.    Data_File->Filename = temp;
  2577.  
  2578.    if ((Data_File->File = Locate_File (Data_File->Filename, READ_TEXT_FILE_STRING,".inc",".INC",TRUE)) == NULL)
  2579.    {
  2580.       temp = Data_File->Filename;
  2581.       Data_File->Filename = NULL;  /* Keeps from closing failed file. */
  2582.       Stage=STAGE_INCLUDE_ERR;
  2583.       Error ("Cannot open include file %s.\n", temp);
  2584.    }
  2585.  
  2586.    Token.Token_Id = END_OF_FILE_TOKEN;
  2587. }
  2588.  
  2589.  
  2590.  
  2591. /*****************************************************************************
  2592. *
  2593. * FUNCTION
  2594. *
  2595. * INPUT
  2596. *
  2597. * OUTPUT
  2598. *
  2599. * RETURNS
  2600. *
  2601. * AUTHOR
  2602. *
  2603. * DESCRIPTION
  2604. *
  2605. * CHANGES
  2606. *
  2607. ******************************************************************************/
  2608.  
  2609. static void Skip_Tokens(cond)
  2610. COND_TYPE cond;
  2611. {
  2612.   int Temp      = CS_Index;
  2613.   int Prev_Skip = Skipping;
  2614.  
  2615.   Skipping=TRUE;
  2616.  
  2617.   while ((CS_Index > Temp) || ((CS_Index == Temp) && (Cond_Stack[CS_Index].Cond_Type == cond)))
  2618.   {
  2619.     Get_Token();
  2620.   }
  2621.  
  2622.   Skipping=Prev_Skip;
  2623.  
  2624.   if (Token.Token_Id==HASH_TOKEN)
  2625.   {
  2626.      Token.Token_Id=END_OF_FILE_TOKEN;
  2627.      Token.Unget_Token=FALSE;
  2628.   }
  2629.   else
  2630.   {
  2631.      UNGET
  2632.   }
  2633. }
  2634.  
  2635.  
  2636.  
  2637. /*****************************************************************************
  2638. *
  2639. * FUNCTION
  2640. *
  2641. *   get_hash_value
  2642. *
  2643. * INPUT
  2644. *
  2645. * OUTPUT
  2646. *
  2647. * RETURNS
  2648. *
  2649. * AUTHOR
  2650. *
  2651. *   Dieter Bayer
  2652. *
  2653. * DESCRIPTION
  2654. *
  2655. *   Calculate hash value for a given string.
  2656. *
  2657. * CHANGES
  2658. *
  2659. *   Apr 1996 : Creation.
  2660. *
  2661. ******************************************************************************/
  2662.  
  2663. static int get_hash_value(s)
  2664. char *s;
  2665. {
  2666.   unsigned int i = 0;
  2667.  
  2668.   while (*s)
  2669.   {
  2670.     i = (i << 1) ^ *s++;
  2671.   }
  2672.  
  2673.   return((int)(i % HASH_TABLE_SIZE));
  2674. }
  2675.  
  2676.  
  2677.  
  2678. /*****************************************************************************
  2679. *
  2680. * FUNCTION
  2681. *
  2682. *   init_reserved_words_hash_table
  2683. *
  2684. * INPUT
  2685. *
  2686. * OUTPUT
  2687. *
  2688. * RETURNS
  2689. *
  2690. * AUTHOR
  2691. *
  2692. *   Dieter Bayer
  2693. *
  2694. * DESCRIPTION
  2695. *
  2696. *   Sort token list.
  2697. *
  2698. * CHANGES
  2699. *
  2700. *   Apr 1996 : Creation.
  2701. *
  2702. ******************************************************************************/
  2703.  
  2704. static void init_reserved_words_hash_table()
  2705. {
  2706.   int i;
  2707.   unsigned int hash_value;
  2708.   HASH_TABLE *New_Entry;
  2709.  
  2710.   for (i = 0; i < HASH_TABLE_SIZE; i++)
  2711.   {
  2712.     Reserved_Words_Hash_Table[i] = NULL;
  2713.   }
  2714.  
  2715.   for (i = 0; i < LAST_TOKEN; i++)
  2716.   {
  2717.     hash_value = get_hash_value(Reserved_Words[i].Token_Name);
  2718.  
  2719.     New_Entry = (HASH_TABLE *)POV_MALLOC(sizeof(HASH_TABLE), "hash table entry");
  2720.  
  2721.     New_Entry->Entry = Reserved_Words[i];
  2722.  
  2723.     New_Entry->next = Reserved_Words_Hash_Table[hash_value];
  2724.  
  2725.     Reserved_Words_Hash_Table[hash_value] = New_Entry;
  2726.   }
  2727. }
  2728.  
  2729.