Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  1. /**********************************************************
  2.  * Copyright 2008-2009 VMware, Inc.  All rights reserved.
  3.  *
  4.  * Permission is hereby granted, free of charge, to any person
  5.  * obtaining a copy of this software and associated documentation
  6.  * files (the "Software"), to deal in the Software without
  7.  * restriction, including without limitation the rights to use, copy,
  8.  * modify, merge, publish, distribute, sublicense, and/or sell copies
  9.  * of the Software, and to permit persons to whom the Software is
  10.  * furnished to do so, subject to the following conditions:
  11.  *
  12.  * The above copyright notice and this permission notice shall be
  13.  * included in all copies or substantial portions of the Software.
  14.  *
  15.  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  16.  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  17.  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  18.  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
  19.  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
  20.  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
  21.  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
  22.  * SOFTWARE.
  23.  *
  24.  **********************************************************/
  25.  
  26.  
  27. #include "pipe/p_shader_tokens.h"
  28. #include "tgsi/tgsi_parse.h"
  29. #include "util/u_memory.h"
  30.  
  31. #include "svga_tgsi_emit.h"
  32.  
  33.  
  34. /**
  35.  * Translate TGSI semantic info into SVGA3d semantic info.
  36.  * This is called for VS outputs and PS inputs only.
  37.  */
  38. static boolean
  39. translate_vs_ps_semantic(struct svga_shader_emitter *emit,
  40.                          struct tgsi_declaration_semantic semantic,
  41.                          unsigned *usage,
  42.                          unsigned *idx)
  43. {
  44.    switch (semantic.Name) {
  45.    case TGSI_SEMANTIC_POSITION:  
  46.       *idx = semantic.Index;
  47.       *usage = SVGA3D_DECLUSAGE_POSITION;
  48.       break;
  49.    case TGSI_SEMANTIC_COLOR:    
  50.       *idx = semantic.Index;
  51.       *usage = SVGA3D_DECLUSAGE_COLOR;
  52.       break;
  53.    case TGSI_SEMANTIC_BCOLOR:
  54.       *idx = semantic.Index + 2; /* sharing with COLOR */
  55.       *usage = SVGA3D_DECLUSAGE_COLOR;
  56.       break;
  57.    case TGSI_SEMANTIC_FOG:      
  58.       *idx = 0;
  59.       assert(semantic.Index == 0);
  60.       *usage = SVGA3D_DECLUSAGE_TEXCOORD;
  61.       break;
  62.    case TGSI_SEMANTIC_PSIZE:    
  63.       *idx = semantic.Index;
  64.       *usage = SVGA3D_DECLUSAGE_PSIZE;
  65.       break;
  66.    case TGSI_SEMANTIC_GENERIC:  
  67.       *idx = svga_remap_generic_index(emit->key.generic_remap_table,
  68.                                       semantic.Index);
  69.       *usage = SVGA3D_DECLUSAGE_TEXCOORD;
  70.       break;
  71.    case TGSI_SEMANTIC_NORMAL:    
  72.       *idx = semantic.Index;
  73.       *usage = SVGA3D_DECLUSAGE_NORMAL;
  74.       break;
  75.    case TGSI_SEMANTIC_CLIPDIST:
  76.    case TGSI_SEMANTIC_CLIPVERTEX:
  77.       /* XXX at this time we don't support clip distance or clip vertices */
  78.       debug_warn_once("unsupported clip distance/vertex attribute\n");
  79.       *usage = SVGA3D_DECLUSAGE_TEXCOORD;
  80.       *idx = 0;
  81.       return TRUE;
  82.    default:
  83.       assert(0);
  84.       *usage = SVGA3D_DECLUSAGE_TEXCOORD;
  85.       *idx = 0;
  86.       return FALSE;
  87.    }
  88.  
  89.    return TRUE;
  90. }
  91.  
  92.  
  93. /**
  94.  * Emit a PS input (or VS depth/fog output) register declaration.
  95.  * For example, if usage = SVGA3D_DECLUSAGE_TEXCOORD, reg.num = 1, and
  96.  * index = 3, we'll emit "dcl_texcoord3 v1".
  97.  */
  98. static boolean
  99. emit_decl(struct svga_shader_emitter *emit,
  100.           SVGA3dShaderDestToken reg,
  101.           unsigned usage,
  102.           unsigned index)
  103. {
  104.    SVGA3DOpDclArgs dcl;
  105.    SVGA3dShaderInstToken opcode;
  106.  
  107.    /* check values against bitfield sizes */
  108.    assert(index < 16);
  109.    assert(usage <= SVGA3D_DECLUSAGE_MAX);
  110.  
  111.    opcode = inst_token( SVGA3DOP_DCL );
  112.    dcl.values[0] = 0;
  113.    dcl.values[1] = 0;
  114.  
  115.    dcl.dst = reg;
  116.    dcl.usage = usage;
  117.    dcl.index = index;
  118.    dcl.values[0] |= 1<<31;
  119.  
  120.    return (emit_instruction(emit, opcode) &&
  121.            svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
  122. }
  123.  
  124.  
  125. /**
  126.  * Emit declaration for PS front/back-face input register.
  127.  */
  128. static boolean
  129. emit_vface_decl(struct svga_shader_emitter *emit)
  130. {
  131.    if (!emit->emitted_vface) {
  132.       SVGA3dShaderDestToken reg =
  133.          dst_register(SVGA3DREG_MISCTYPE, SVGA3DMISCREG_FACE);
  134.  
  135.       if (!emit_decl( emit, reg, 0, 0 ))
  136.          return FALSE;
  137.  
  138.       emit->emitted_vface = TRUE;
  139.    }
  140.    return TRUE;
  141. }
  142.  
  143.  
  144. /**
  145.  * Emit PS input register to pass depth/fog coordinates.
  146.  * Note that this always goes into texcoord[0].
  147.  */
  148. static boolean
  149. ps30_input_emit_depth_fog( struct svga_shader_emitter *emit,
  150.                            struct src_register *out )
  151. {
  152.    struct src_register reg;
  153.  
  154.    if (emit->emitted_depth_fog) {
  155.       *out = emit->ps_depth_fog;
  156.       return TRUE;
  157.    }
  158.  
  159.    if (emit->ps30_input_count >= SVGA3D_INPUTREG_MAX)
  160.       return FALSE;
  161.  
  162.    reg = src_register( SVGA3DREG_INPUT,
  163.                        emit->ps30_input_count++ );
  164.  
  165.    *out = emit->ps_depth_fog = reg;
  166.  
  167.    emit->emitted_depth_fog = TRUE;
  168.  
  169.    return emit_decl( emit, dst( reg ), SVGA3D_DECLUSAGE_TEXCOORD, 0 );
  170. }
  171.  
  172.  
  173. /**
  174.  * Process a PS input declaration.
  175.  * We'll emit a declaration like "dcl_texcoord1 v2"
  176.  */
  177. static boolean
  178. ps30_input(struct svga_shader_emitter *emit,
  179.            struct tgsi_declaration_semantic semantic,
  180.            unsigned idx)
  181. {
  182.    unsigned usage, index;
  183.    SVGA3dShaderDestToken reg;
  184.  
  185.    if (semantic.Name == TGSI_SEMANTIC_POSITION) {
  186.  
  187.       emit->ps_true_pos = src_register( SVGA3DREG_MISCTYPE,
  188.                                         SVGA3DMISCREG_POSITION );
  189.       emit->ps_true_pos.base.swizzle = TRANSLATE_SWIZZLE( TGSI_SWIZZLE_X,
  190.                                                           TGSI_SWIZZLE_Y,
  191.                                                           TGSI_SWIZZLE_Y,
  192.                                                           TGSI_SWIZZLE_Y );
  193.       reg = writemask( dst(emit->ps_true_pos),
  194.                        TGSI_WRITEMASK_XY );
  195.       emit->ps_reads_pos = TRUE;
  196.  
  197.       if (emit->info.reads_z) {
  198.          emit->ps_temp_pos = dst_register( SVGA3DREG_TEMP,
  199.                                            emit->nr_hw_temp );
  200.  
  201.          emit->input_map[idx] = src_register( SVGA3DREG_TEMP,
  202.                                               emit->nr_hw_temp );
  203.          emit->nr_hw_temp++;
  204.  
  205.          if (!ps30_input_emit_depth_fog( emit, &emit->ps_depth_pos ))
  206.             return FALSE;
  207.  
  208.          emit->ps_depth_pos.base.swizzle = TRANSLATE_SWIZZLE( TGSI_SWIZZLE_Z,
  209.                                                               TGSI_SWIZZLE_Z,
  210.                                                               TGSI_SWIZZLE_Z,
  211.                                                               TGSI_SWIZZLE_W );
  212.       }
  213.       else {
  214.          emit->input_map[idx] = emit->ps_true_pos;
  215.       }
  216.  
  217.       return emit_decl( emit, reg, 0, 0 );
  218.    }
  219.    else if (emit->key.fkey.light_twoside &&
  220.             (semantic.Name == TGSI_SEMANTIC_COLOR)) {
  221.  
  222.       if (!translate_vs_ps_semantic( emit, semantic, &usage, &index ))
  223.          return FALSE;
  224.  
  225.       emit->internal_color_idx[emit->internal_color_count] = idx;
  226.       emit->input_map[idx] = src_register( SVGA3DREG_INPUT, emit->ps30_input_count );
  227.       emit->ps30_input_count++;
  228.       emit->internal_color_count++;
  229.  
  230.       reg = dst( emit->input_map[idx] );
  231.  
  232.       if (!emit_decl( emit, reg, usage, index ))
  233.          return FALSE;
  234.  
  235.       semantic.Name = TGSI_SEMANTIC_BCOLOR;
  236.       if (!translate_vs_ps_semantic( emit, semantic, &usage, &index ))
  237.          return FALSE;
  238.  
  239.       if (emit->ps30_input_count >= SVGA3D_INPUTREG_MAX)
  240.          return FALSE;
  241.  
  242.       reg = dst_register( SVGA3DREG_INPUT, emit->ps30_input_count++ );
  243.  
  244.       if (!emit_decl( emit, reg, usage, index ))
  245.          return FALSE;
  246.  
  247.       if (!emit_vface_decl( emit ))
  248.          return FALSE;
  249.  
  250.       return TRUE;
  251.    }
  252.    else if (semantic.Name == TGSI_SEMANTIC_FACE) {
  253.       if (!emit_vface_decl( emit ))
  254.          return FALSE;
  255.       emit->emit_frontface = TRUE;
  256.       emit->internal_frontface_idx = idx;
  257.       return TRUE;
  258.    }
  259.    else if (semantic.Name == TGSI_SEMANTIC_FOG) {
  260.  
  261.       assert(semantic.Index == 0);
  262.  
  263.       if (!ps30_input_emit_depth_fog( emit, &emit->input_map[idx] ))
  264.          return FALSE;
  265.  
  266.       emit->input_map[idx].base.swizzle = TRANSLATE_SWIZZLE( TGSI_SWIZZLE_X,
  267.                                                              TGSI_SWIZZLE_X,
  268.                                                              TGSI_SWIZZLE_X,
  269.                                                              TGSI_SWIZZLE_X );
  270.  
  271.       return TRUE;
  272.    }
  273.    else {
  274.  
  275.       if (!translate_vs_ps_semantic( emit, semantic, &usage, &index ))
  276.          return FALSE;
  277.  
  278.       if (emit->ps30_input_count >= SVGA3D_INPUTREG_MAX)
  279.          return FALSE;
  280.  
  281.       emit->input_map[idx] = src_register( SVGA3DREG_INPUT, emit->ps30_input_count++ );
  282.       reg = dst( emit->input_map[idx] );
  283.  
  284.       if (!emit_decl( emit, reg, usage, index ))
  285.          return FALSE;
  286.  
  287.       if (semantic.Name == TGSI_SEMANTIC_GENERIC &&
  288.           emit->key.fkey.sprite_origin_lower_left &&
  289.           index >= 1 &&
  290.           emit->key.fkey.tex[index - 1].sprite_texgen) {
  291.          /* This is a sprite texture coord with lower-left origin.
  292.           * We need to invert the texture T coordinate since the SVGA3D
  293.           * device only supports an upper-left origin.
  294.           */
  295.          unsigned unit = index - 1;
  296.  
  297.          emit->inverted_texcoords |= (1 << unit);
  298.  
  299.          /* save original texcoord reg */
  300.          emit->ps_true_texcoord[unit] = emit->input_map[idx];
  301.  
  302.          /* this temp register will be the results of the MAD instruction */
  303.          emit->ps_inverted_texcoord[unit] =
  304.             src_register(SVGA3DREG_TEMP, emit->nr_hw_temp);
  305.          emit->nr_hw_temp++;
  306.  
  307.          emit->ps_inverted_texcoord_input[unit] = idx;
  308.  
  309.          /* replace input_map entry with the temp register */
  310.          emit->input_map[idx] = emit->ps_inverted_texcoord[unit];
  311.       }
  312.  
  313.       return TRUE;
  314.    }
  315.  
  316. }
  317.  
  318.  
  319. /**
  320.  * Process a PS output declaration.
  321.  * Note that we don't actually emit a SVGA3DOpDcl for PS outputs.
  322.  * \idx  register index, such as OUT[2] (not semantic index)
  323.  */
  324. static boolean
  325. ps30_output(struct svga_shader_emitter *emit,
  326.             struct tgsi_declaration_semantic semantic,
  327.             unsigned idx)
  328. {
  329.    switch (semantic.Name) {
  330.    case TGSI_SEMANTIC_COLOR:
  331.       if (emit->unit == PIPE_SHADER_FRAGMENT) {
  332.          if (emit->key.fkey.white_fragments) {
  333.             /* Used for XOR logicop mode */
  334.             emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
  335.                                                   emit->nr_hw_temp++ );
  336.             emit->temp_color_output[idx] = emit->output_map[idx];
  337.             emit->true_color_output[idx] = dst_register(SVGA3DREG_COLOROUT,
  338.                                                         semantic.Index);
  339.          }
  340.          else if (emit->key.fkey.write_color0_to_n_cbufs) {
  341.             /* We'll write color output [0] to all render targets.
  342.              * Prepare all the output registers here, but only when the
  343.              * semantic.Index == 0 so we don't do this more than once.
  344.              */
  345.             if (semantic.Index == 0) {
  346.                unsigned i;
  347.                for (i = 0; i < emit->key.fkey.write_color0_to_n_cbufs; i++) {
  348.                   emit->output_map[idx+i] = dst_register(SVGA3DREG_TEMP,
  349.                                                      emit->nr_hw_temp++);
  350.                   emit->temp_color_output[i] = emit->output_map[idx+i];
  351.                   emit->true_color_output[i] = dst_register(SVGA3DREG_COLOROUT,
  352.                                                             i);
  353.                }
  354.             }
  355.          }
  356.          else {
  357.             emit->output_map[idx] =
  358.                dst_register(SVGA3DREG_COLOROUT, semantic.Index);
  359.          }
  360.       }
  361.       else {
  362.          emit->output_map[idx] = dst_register( SVGA3DREG_COLOROUT,
  363.                                                semantic.Index );
  364.       }
  365.       break;
  366.    case TGSI_SEMANTIC_POSITION:
  367.       emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
  368.                                             emit->nr_hw_temp++ );
  369.       emit->temp_pos = emit->output_map[idx];
  370.       emit->true_pos = dst_register( SVGA3DREG_DEPTHOUT,
  371.                                      semantic.Index );
  372.       break;
  373.    default:
  374.       assert(0);
  375.       /* A wild stab in the dark. */
  376.       emit->output_map[idx] = dst_register( SVGA3DREG_COLOROUT, 0 );
  377.       break;
  378.    }
  379.  
  380.    return TRUE;
  381. }
  382.  
  383.  
  384. /**
  385.  * Declare a VS input register.
  386.  * We still make up the input semantics the same as in 2.0
  387.  */
  388. static boolean
  389. vs30_input(struct svga_shader_emitter *emit,
  390.            struct tgsi_declaration_semantic semantic,
  391.            unsigned idx)
  392. {
  393.    SVGA3DOpDclArgs dcl;
  394.    SVGA3dShaderInstToken opcode;
  395.    unsigned usage, index;
  396.  
  397.    opcode = inst_token( SVGA3DOP_DCL );
  398.    dcl.values[0] = 0;
  399.    dcl.values[1] = 0;
  400.  
  401.    emit->input_map[idx] = src_register( SVGA3DREG_INPUT, idx );
  402.    dcl.dst = dst_register( SVGA3DREG_INPUT, idx );
  403.  
  404.    assert(dcl.dst.reserved0);
  405.  
  406.    svga_generate_vdecl_semantics( idx, &usage, &index );
  407.  
  408.    dcl.usage = usage;
  409.    dcl.index = index;
  410.    dcl.values[0] |= 1<<31;
  411.  
  412.    return (emit_instruction(emit, opcode) &&
  413.            svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
  414. }
  415.  
  416.  
  417. /**
  418.  * Declare VS output for holding depth/fog.
  419.  */
  420. static boolean
  421. vs30_output_emit_depth_fog(struct svga_shader_emitter *emit,
  422.                            SVGA3dShaderDestToken *out)
  423. {
  424.    SVGA3dShaderDestToken reg;
  425.  
  426.    if (emit->emitted_depth_fog) {
  427.       *out = emit->vs_depth_fog;
  428.       return TRUE;
  429.    }
  430.  
  431.    reg = dst_register( SVGA3DREG_OUTPUT, emit->vs30_output_count++ );
  432.  
  433.    *out = emit->vs_depth_fog = reg;
  434.  
  435.    emit->emitted_depth_fog = TRUE;
  436.  
  437.    return emit_decl( emit, reg, SVGA3D_DECLUSAGE_TEXCOORD, 0 );
  438. }
  439.  
  440.  
  441. /**
  442.  * Declare a VS output.
  443.  * VS3.0 outputs have proper declarations and semantic info for
  444.  * matching against PS inputs.
  445.  */
  446. static boolean
  447. vs30_output(struct svga_shader_emitter *emit,
  448.             struct tgsi_declaration_semantic semantic,
  449.             unsigned idx)
  450. {
  451.    SVGA3DOpDclArgs dcl;
  452.    SVGA3dShaderInstToken opcode;
  453.    unsigned usage, index;
  454.  
  455.    opcode = inst_token( SVGA3DOP_DCL );
  456.    dcl.values[0] = 0;
  457.    dcl.values[1] = 0;
  458.  
  459.    if (!translate_vs_ps_semantic( emit, semantic, &usage, &index ))
  460.       return FALSE;
  461.  
  462.    if (emit->vs30_output_count >= SVGA3D_OUTPUTREG_MAX)
  463.       return FALSE;
  464.  
  465.    dcl.dst = dst_register( SVGA3DREG_OUTPUT, emit->vs30_output_count++ );
  466.    dcl.usage = usage;
  467.    dcl.index = index;
  468.    dcl.values[0] |= 1<<31;
  469.  
  470.    if (semantic.Name == TGSI_SEMANTIC_POSITION) {
  471.       assert(idx == 0);
  472.       emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
  473.                                             emit->nr_hw_temp++ );
  474.       emit->temp_pos = emit->output_map[idx];
  475.       emit->true_pos = dcl.dst;
  476.  
  477.       /* Grab an extra output for the depth output */
  478.       if (!vs30_output_emit_depth_fog( emit, &emit->depth_pos ))
  479.          return FALSE;
  480.  
  481.    }
  482.    else if (semantic.Name == TGSI_SEMANTIC_PSIZE) {
  483.       emit->output_map[idx] = dst_register( SVGA3DREG_TEMP,
  484.                                             emit->nr_hw_temp++ );
  485.       emit->temp_psiz = emit->output_map[idx];
  486.  
  487.       /* This has the effect of not declaring psiz (below) and not
  488.        * emitting the final MOV to true_psiz in the postamble.
  489.        */
  490.       if (!emit->key.vkey.allow_psiz)
  491.          return TRUE;
  492.  
  493.       emit->true_psiz = dcl.dst;
  494.    }
  495.    else if (semantic.Name == TGSI_SEMANTIC_FOG) {
  496.       /*
  497.        * Fog is shared with depth.
  498.        * So we need to decrement out_count since emit_depth_fog will increment it.
  499.        */
  500.       emit->vs30_output_count--;
  501.  
  502.       if (!vs30_output_emit_depth_fog( emit, &emit->output_map[idx] ))
  503.          return FALSE;
  504.  
  505.       return TRUE;
  506.    }
  507.    else {
  508.       emit->output_map[idx] = dcl.dst;
  509.    }
  510.  
  511.    return (emit_instruction(emit, opcode) &&
  512.            svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
  513. }
  514.  
  515.  
  516. /** Translate PIPE_TEXTURE_x to SVGA3DSAMP_x */
  517. static ubyte
  518. svga_tgsi_sampler_type(const struct svga_shader_emitter *emit, int idx)
  519. {
  520.    switch (emit->key.fkey.tex[idx].texture_target) {
  521.    case PIPE_TEXTURE_1D:
  522.       return SVGA3DSAMP_2D;
  523.    case PIPE_TEXTURE_2D:
  524.    case PIPE_TEXTURE_RECT:
  525.       return SVGA3DSAMP_2D;
  526.    case PIPE_TEXTURE_3D:
  527.       return SVGA3DSAMP_VOLUME;
  528.    case PIPE_TEXTURE_CUBE:
  529.       return SVGA3DSAMP_CUBE;
  530.    }
  531.  
  532.    return SVGA3DSAMP_UNKNOWN;
  533. }
  534.  
  535.  
  536. static boolean
  537. ps30_sampler( struct svga_shader_emitter *emit,
  538.               struct tgsi_declaration_semantic semantic,
  539.               unsigned idx )
  540. {
  541.    SVGA3DOpDclArgs dcl;
  542.    SVGA3dShaderInstToken opcode;
  543.  
  544.    opcode = inst_token( SVGA3DOP_DCL );
  545.    dcl.values[0] = 0;
  546.    dcl.values[1] = 0;
  547.  
  548.    dcl.dst = dst_register( SVGA3DREG_SAMPLER, idx );
  549.    dcl.type = svga_tgsi_sampler_type( emit, idx );
  550.    dcl.values[0] |= 1<<31;
  551.  
  552.    return (emit_instruction(emit, opcode) &&
  553.            svga_shader_emit_dwords( emit, dcl.values, Elements(dcl.values)));
  554. }
  555.  
  556.  
  557. boolean
  558. svga_translate_decl_sm30( struct svga_shader_emitter *emit,
  559.                           const struct tgsi_full_declaration *decl )
  560. {
  561.    unsigned first = decl->Range.First;
  562.    unsigned last = decl->Range.Last;
  563.    unsigned idx;
  564.  
  565.    for( idx = first; idx <= last; idx++ ) {
  566.       boolean ok;
  567.  
  568.       switch (decl->Declaration.File) {
  569.       case TGSI_FILE_SAMPLER:
  570.          assert (emit->unit == PIPE_SHADER_FRAGMENT);
  571.          ok = ps30_sampler( emit, decl->Semantic, idx );
  572.          break;
  573.  
  574.       case TGSI_FILE_INPUT:
  575.          if (emit->unit == PIPE_SHADER_VERTEX)
  576.             ok = vs30_input( emit, decl->Semantic, idx );
  577.          else
  578.             ok = ps30_input( emit, decl->Semantic, idx );
  579.          break;
  580.  
  581.       case TGSI_FILE_OUTPUT:
  582.          if (emit->unit == PIPE_SHADER_VERTEX)
  583.             ok = vs30_output( emit, decl->Semantic, idx );
  584.          else
  585.             ok = ps30_output( emit, decl->Semantic, idx );
  586.          break;
  587.  
  588.       default:
  589.          /* don't need to declare other vars */
  590.          ok = TRUE;
  591.       }
  592.  
  593.       if (!ok)
  594.          return FALSE;
  595.    }
  596.  
  597.    return TRUE;
  598. }
  599.