示例#1
0
static void cellToQString( const UCell* val, QString& str )
{
    switch( ur_type(val) )
    {
        case UT_NONE:
            str.clear();
            break;

        case UT_CHAR:
            str = QChar( ur_int(val) );
            break;

        case UT_INT:
            str.setNum( ur_int(val) );
            break;

        case UT_DECIMAL:
            str.setNum( ur_decimal(val) );
            break;

        case UT_BIGNUM:
            str.setNum( bignum_l(val) );
            break;

        case UT_STRING:
        case UT_FILE:
        {
            USeriesIter si;
            int len;
            ur_seriesSlice( UT, &si, val );
            len = si.end - si.it;
            switch( si.buf->form )
            {
                case UR_ENC_LATIN1:
                    str = QString::fromLatin1( si.buf->ptr.c + si.it, len );
                    break;
                case UR_ENC_UTF8:
                    str = QString::fromUtf8( si.buf->ptr.c + si.it, len );
                    break;
                case UR_ENC_UCS2:
                    str = QString::fromUtf16( si.buf->ptr.u16 + si.it, len );
                    break;
            }
        }
            break;

        default:
        {
            UBuffer buf;
            ur_strInit( &buf, UR_ENC_LATIN1, 0 );
            ur_toStr( UT, val, &buf, 0 );
            str = QString::fromLatin1( buf.ptr.c, buf.used );
            ur_strFree( &buf );
        }
            break;
    }
}
示例#2
0
/*
    line-edit word!/string! <max-chars>
*/
static GWidget* ledit_make( UThread* ut, UBlockIter* bi,
                            const GWidgetClass* wclass )
{
    LineEdit* ep;
    const UCell* arg[2];
    int maxChars = 32;

    if( ! gui_parseArgs( ut, bi, wclass, ledit_args, arg ) )
        return 0;

    if( ur_isShared( arg[0]->series.buf ) )
    {
        ur_error( ut, UR_ERR_SCRIPT, "line-edit cannot modify shared string" );
        return 0;
    }

    if( arg[1] )
        maxChars = ur_int(arg[1]);

    ep = (LineEdit*) gui_allocWidget( sizeof(LineEdit), wclass );
    ep->wid.flags |= CHANGED;

    //ep->state = LEDIT_STATE_DISPLAY;
    ep->strN     = arg[0]->series.buf;
    ep->maxChars = maxChars;
    ep->vboN     = ledit_vbo( ut, maxChars );

    return (GWidget*) ep;
}
示例#3
0
文件: shader.c 项目: smorimura/boron
void setUniform( UThread* ut, UCell* path, UCell* val )
{
    if( ur_is(path, UT_SELECT) )
    {
        UCell* cval;
        Shader* sh;
        ShaderParam* pi;
        ShaderParam* pend;

        cval = ur_buffer( ctx->ctx.valBlk )->ptr.cell;
        if( cval && ur_is(cval, UT_SHADER) )
        {
            sh = (Shader*) ur_resPtr( cval->series.n )->ptr;
            pi   = sh->param;
            pend = sh->param + sh->paramCount;
            while( pi != pend )
            {
                if( pi->name == sel )
                {
                    switch( pi->type )
                    {
                    case GL_INT:
                    case GL_BOOL:
                        glUniform1i( pi->location, ur_int(val) );
                        break;
                    }
                    return;
                }
                ++pi;
            }
        }
    }
}
示例#4
0
static int _execSpawn( UThread* ut, char* cmd, UCell* res )
{
    STARTUPINFO si;
    PROCESS_INFORMATION pi;

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);

    ZeroMemory( &pi, sizeof(pi) );

    // Start the child process. 
    if( ! CreateProcess( NULL,   // No module name (use command line). 
        TEXT(cmd),        // Command line. 
        NULL,             // Process handle not inheritable. 
        NULL,             // Thread handle not inheritable. 
        FALSE,            // Set handle inheritance to FALSE. 
        0,                // No creation flags. 
        NULL,             // Use parent's environment block. 
        NULL,             // Use parent's starting directory. 
        &si,              // Pointer to STARTUPINFO structure.
        &pi )             // Pointer to PROCESS_INFORMATION structure.
    )
    {
        return ur_error( ut, UR_ERR_INTERNAL,
                         "CreateProcess failed (%d).\n", GetLastError() );
    }

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );

    ur_setId(res, UT_INT);
    ur_int(res) = pi.dwProcessId;
    return UR_OK;
}
示例#5
0
static void setWID( const UCell*& prev, int id )
{
    if( prev )
    {
        UCell* val = ur_wordCellM( UT, prev );
        assert( val );

        ur_setId(val, UT_INT);
        ur_int(val) = id;

        prev = 0;
    }
}
示例#6
0
int ur_readDir( UThread* ut, const char* filename, UCell* res )
{
    char filespec[ _MAX_PATH ];
    struct _finddata_t fileinfo;
    intptr_t handle;

    // Look for all files.  We ensure there is a slash before the wildcard.
    // It's OK if the path is already terminated with a slash - multiple
    // slashes are filtered by _findfirst.

    strcpy( filespec, filename );
    strcat( filespec, "\\*.*" );

    handle = _findfirst( filespec, &fileinfo );
    if( handle != -1 )
    {
        UCell* cell;
        UIndex blkN;
        UIndex hold;
        UIndex strN;
           
        blkN = ur_makeBlock( ut, 0 );
        hold = ur_hold( blkN );

        do
        {
            const char* cp = fileinfo.name;
            if( cp[0] == '.' && (cp[1] == '.' || cp[1] == '\0') )
                continue;

            strN = ur_makeStringUtf8( ut, (const uint8_t*) cp,
                                          (const uint8_t*) (cp + strlen(cp)) );
            cell = ur_blkAppendNew( ur_buffer(blkN), UT_FILE );
            ur_setSeries( cell, strN, 0 );
        }
        while( _findnext( handle, &fileinfo ) != -1 );

        _findclose( handle );

        ur_release( hold );

        ur_setId(res, UT_BLOCK);
        ur_setSeries(res, blkN, 0);
    }
    else
    {
        ur_setId(res, UT_LOGIC);
        ur_int(res) = 0;
    }
    return UR_OK;
}
示例#7
0
static int slider_select( GWidget* wp, UAtom atom, UCell* res )
{
    EX_PTR;
    if( atom == UR_ATOM_VALUE )
    {
        ur_setId(res, ep->dataType);
        if( ep->dataType == UT_INT )
            ur_int(res) = (int32_t) ep->data.val;
        else
            ur_decimal(res) = ep->data.val;
        return UR_OK;
    }
    return gui_areaSelect( wp, atom, res );
}
示例#8
0
static void slider_setValue( GSlider* ep, const UCell* cell )
{
    struct Value* da = &ep->data;
    float n;

    if( ur_is(cell, UT_INT) )
        n = (float) ur_int(cell);
    else if( ur_is(cell, UT_DECIMAL) )
        n = (float) ur_decimal(cell);
    else
        n = 0.0;

    if( n < da->min )
        n = da->min;
    else if( n > da->max )
        n = da->max;
    da->val = n;
}
示例#9
0
文件: shader.c 项目: smorimura/boron
void setUniform( UThread* ut, UAtom name, UCell* cell )
{
    GLint loc;

    loc = glGetUniformLocation( grState.shaderProg, ur_atomCStr(name, 0) );
    if( loc == -1 )
    {
        printf( "KR setUniform failed %d\n", grState.shaderProg );
        return;
    }

    switch( ur_type(cell) )
    {
        case UT_LOGIC:
        case UT_INT:
            glUniform1i( loc, ur_int(cell) );
            break;
    }
}
示例#10
0
/*
  Updates DrawContext attr & drawCount.

  Return UR_OK/UR_THROW.
*/
int itemview_parse( DrawContext* dc, UThread* ut, UBlockIter* bi, GWidget* wp )
{
    const UCell* arg[3];
    UAtom atom;
    int opcode;
    float x, y;

    while( bi->it != bi->end )
    {
        if( ur_is(bi->it, UT_WORD) )
        {
            atom = ur_atom( bi->it );
            opcode = ur_atomsSearch( glEnv.drawOpTable, DOP_COUNT, atom );
            switch( opcode )
            {
                case DOP_IMAGE:
                {
                    QuadDim qd;
                    int16_t rect[4];
                    const int16_t* coord;
                    FETCH_ARGS( iv_args_image );
                    //printf( "KR IV image\n" );
                    coord = arg[0]->coord.n;
                    rect[0] = coord[0] + dc->penX;
                    rect[1] = coord[1] + dc->penY;
                    rect[2] = coord[2];
                    rect[3] = coord[3];
                    quad_init( &qd, rect, arg[1]->coord.n, arg[2]->coord.n );
                    quad_emitVT( &qd, dc->attr, dc->attr + 3, AttrCount );
                    vbo_setVec3( dc->attr + 5, AttrCount, 6, dc->color );
                    dc->attr      += 6 * AttrCount;
                    dc->drawCount += 6;
                }
                    break;

                case DOP_COLOR:
                    FETCH_ARGS( iv_args_color );
                    dc->color[0] = (GLfloat) ur_int( arg[0] );
                    break;

                case DOP_FONT:
                    FETCH_ARGS( iv_args_font );
                    dc->fontN = ur_fontTF( arg[0] );
                    break;

                case DOP_TEXT:
                    FETCH_ARGS( iv_args_text );

                    x = dc->penX + (float) arg[0]->coord.n[0];
                    y = dc->penY + (float) arg[0]->coord.n[1];

                {
                    DrawTextState dts;
                    UBinaryIter si;
                    int glyphCount;

                    //printf( "KR IV text\n" );
                    dp_toString( ut, arg[1], &si );
                    vbo_drawTextInit( &dts,
                                      (TexFont*) ur_buffer( dc->fontN )->ptr.v,
                                      x, y );
                    dts.emitTris = 1;
                    glyphCount = vbo_drawText( &dts, dc->attr + 3, dc->attr,
                                               AttrCount, si.it, si.end );
                    glyphCount *= 6;
                    vbo_setVec3( dc->attr + 5, AttrCount, glyphCount,
                                 dc->color );
                    /*
                    while( si.it != si.end )
                        putchar( *si.it++ );
                    putchar( '\n' );
                    */
                    dc->attr      += glyphCount * AttrCount;
                    dc->drawCount += glyphCount;
                }
                    break;

                default:
                    goto invalid_op;
            }
        }
        else
        {
            goto invalid_op;
        }
    }
    return UR_OK;

invalid_op:

    return ur_error( ut, UR_ERR_SCRIPT, "Invalid item-view instruction" );
}
示例#11
0
文件: shader.c 项目: smorimura/boron
void setShaderUniforms( const Shader* sh, const UBuffer* blk )
{
    const ShaderParam* pi   = sh->param;
    const ShaderParam* pend = sh->param + sh->paramCount;
    const UCell* cval = blk->ptr.cell;
    int texUnit = 0;

#ifdef GL_ES_VERSION_2_0
    es_matrixUsed = 0;
#endif

    while( pi != pend )
    {
        // There is no cell type checking or conversion here for speed.
        // If the user loads bad types then we'll just get garbage.

        ++cval;
        switch( pi->type )
        {
            case GL_FLOAT:
                glUniform1f( pi->location, ur_decimal(cval) );
                break;

            case GL_FLOAT_VEC2:
                glUniform2fv( pi->location, 1, cval->vec3.xyz );
                break;

            case GL_FLOAT_VEC3:
                glUniform3fv( pi->location, 1, cval->vec3.xyz );
                break;

            //case GL_FLOAT_VEC4:

            case GL_INT:
            case GL_BOOL:
                glUniform1i( pi->location, ur_int(cval) );
                break;

            case GL_INT_VEC2:
                glUniform2i( pi->location,
                             cval->coord.n[0],
                             cval->coord.n[1] );
                break;

            case GL_INT_VEC3:
                glUniform3i( pi->location,
                             cval->coord.n[0],
                             cval->coord.n[1],
                             cval->coord.n[2] );
                break;

            //case GL_INT_VEC4:

#ifndef GL_ES_VERSION_2_0
            case GL_SAMPLER_1D:
                glActiveTexture( GL_TEXTURE0 + texUnit );
                glEnable( GL_TEXTURE_1D );
                glBindTexture( GL_TEXTURE_1D, ur_texId(cval) );
                glUniform1i( pi->location, texUnit );
                ++texUnit;
                break;
#endif

            case GL_SAMPLER_2D:
#ifndef GL_ES_VERSION_2_0
            case GL_SAMPLER_2D_SHADOW:
#endif
                glActiveTexture( GL_TEXTURE0 + texUnit );
                glEnable( GL_TEXTURE_2D );
                glBindTexture( GL_TEXTURE_2D, ur_texId(cval) );
                glUniform1i( pi->location, texUnit );
                ++texUnit;
                break;

            //case GL_SAMPLER_3D:

#ifdef GL_ES_VERSION_2_0
            case GL_FLOAT_MAT4:
                /*
                fprintf( stderr, "sha %f,%f,%f\n    %f,%f,%f\n    %f,%f,%f\n",
                         matrixTop[0], matrixTop[1], matrixTop[2],
                         matrixTop[4], matrixTop[5], matrixTop[6],
                         matrixTop[8], matrixTop[9], matrixTop[10] );
                */
                es_matrixLoc = pi->location;
                es_matrixUsed = 1;
                //glUniformMatrix4fv( pi->location, 1, GL_FALSE, matrixTop );
                break;
#endif
        }
        ++pi;
    }
}
示例#12
0
文件: shader.c 项目: smorimura/boron
/*
  Sets res to either a shader! or a context! whose first value is a shader!.
  Returns UR_OK/UR_THROW.
*/
int ur_makeShader( UThread* ut, const char* vert, const char* frag, UCell* res )
{
#define MAX_SHADER_PARAM    16      // LIMIT: User parameters per shader.
    Shader shad;
    Shader* sh;
    UIndex bufN;
    UBuffer* buf;
    int i;
    char name[ 128 ];
    ShaderParam param[ MAX_SHADER_PARAM ];
    ShaderParam* pi;
    GLsizei length;
    GLint size;
    GLenum type;
    GLint count = 0;

    if( ! createShader( ut, &shad, vert, frag ) )
        return UR_THROW;

    glGetProgramiv( shad.program, GL_ACTIVE_UNIFORMS, &count );

    // Collect non-gl parameters.

    pi = param;
    for( i = 0; i < count; ++i )
    {
        glGetActiveUniform( shad.program, i, 128, &length, &size, &type,
                            name );
        if( name[0] == 'g' && name[1] == 'l' && name[2] == '_' )
            continue;

        pi->type     = type;
        pi->location = glGetUniformLocation( shad.program, name );
        pi->name     = ur_internAtom( ut, name, name + length );
        if( pi->name == UR_INVALID_ATOM )
            return UR_THROW;

        ++pi;
    }
    count = pi - param;

    if( count )
    {
        ShaderParam* pend;
        UBuffer* ctx;
        UCell* cval;

        // We have parameters - make context to hold shader & params.

        ctx = ur_makeContextCell( ut, count + 1, res );
        cval = ur_ctxAddWord( ctx, UR_ATOM_SHADER );

        pi = param;
        pend = param + count;
        while( pi != pend )
        {
            cval = ur_ctxAddWord( ctx, pi->name );
#if 0
            printf( "KR Shader Param %d is type %d\n",
                    (int) (pi - param), pi->type );
#endif
            switch( pi->type )
            {
                case GL_FLOAT:
                    ur_setId( cval, UT_DECIMAL );
                    ur_decimal( cval ) = 0.0;
                    break;

                case GL_FLOAT_VEC2:
                case GL_FLOAT_VEC3:
                //case GL_FLOAT_VEC4:
                    ur_setId( cval, UT_VEC3 );
                    cval->vec3.xyz[0] =
                    cval->vec3.xyz[1] =
                    cval->vec3.xyz[2] = 0.0f;
                    break;

                case GL_INT:
                    ur_setId( cval, UT_INT );
                    ur_int( cval ) = 0;
                    break;

                case GL_INT_VEC2:
                case GL_INT_VEC3:
                //case GL_INT_VEC4:
                    ur_setId( cval, UT_COORD );
                    break;

                case GL_BOOL:
                    ur_setId( cval, UT_LOGIC );
                    ur_int( cval ) = 0;
                    break;

                case GL_SAMPLER_2D:
                case GL_SAMPLER_CUBE:
#ifndef GL_ES_VERSION_2_0
                case GL_SAMPLER_1D:
                case GL_SAMPLER_3D:
                case GL_SAMPLER_1D_SHADOW:
                case GL_SAMPLER_2D_SHADOW:
#endif
                    ur_setId( cval, UT_NONE );
                    ur_texId(cval) = 0;     // Expecting texture!.
                    break;

#ifdef GL_ES_VERSION_2_0
                case GL_FLOAT_MAT4:
                    ur_setId( cval, UT_NONE );
                    break;
#endif

                default:
                    ur_setId( cval, UT_NONE );
                    break;

                /*
                GL_BOOL_VEC2:
                GL_BOOL_VEC3:
                GL_BOOL_VEC4:
                GL_FLOAT_MAT2:
                GL_FLOAT_MAT3:
                GL_FLOAT_MAT4:
                GL_SAMPLER_2D_RECT:
                GL_SAMPLER_2D_RECT_SHADOW:
                */
            }

            ++pi;
        }
        ur_ctxSort( ctx );
    }

    ur_genBuffers( ut, 1, &bufN );
    buf = ur_buffer( bufN );
    buf->type = UT_SHADER;
    buf->ptr.v = memAlloc( sizeof(Shader) +
                           sizeof(ShaderParam) * (count - 1) );

    sh = (Shader*) buf->ptr.v;
    sh->program     = shad.program;
    sh->paramCount  = count;

    if( count )
    {
        memCpy( sh->param, param, sizeof(ShaderParam) * count );

        // First context value will be set to shader!.
        res = ur_buffer( res->series.buf )->ptr.cell;
    }

    ur_setId( res, UT_SHADER );
    ur_setSeries( res, bufN, 0 );
    return UR_OK;
}
示例#13
0
static int _execIO( UThread* ut, char* cmd, UCell* res,
                    const UBuffer* in, UBuffer* out, UBuffer* err )
{
    HANDLE childStdInR;
    HANDLE childStdInW;
    HANDLE childStdOutR;
    HANDLE childStdOutW;
    HANDLE childStdErrR;
    HANDLE childStdErrW;
    SECURITY_ATTRIBUTES sec;
    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    DWORD flags = 0;


    sec.nLength              = sizeof(SECURITY_ATTRIBUTES); 
    sec.lpSecurityDescriptor = NULL;
    sec.bInheritHandle       = TRUE; 

    childStdOutR = childStdErrR = INVALID_HANDLE_VALUE;

    if( in )
    {
        if( ! CreatePipe( &childStdInR, &childStdInW, &sec, 0 ) ) 
        {
fail0:
            return ur_error( ut, UR_ERR_INTERNAL, "CreatePipe failed\n" );
        }
        // Child does not inherit our end of pipe.
        SetHandleInformation( childStdInW, HANDLE_FLAG_INHERIT, 0 );
    }

    if( out )
    {
        if( ! CreatePipe( &childStdOutR, &childStdOutW, &sec, 0 ) ) 
        {
fail1:
            if( in )
                _closePipe( childStdInR, childStdInW );
            goto fail0;
        }
        // Child does not inherit our end of pipe.
        SetHandleInformation( childStdOutR, HANDLE_FLAG_INHERIT, 0 );
        flags = DETACHED_PROCESS;
    }

    if( err )
    {
        if( ! CreatePipe( &childStdErrR, &childStdErrW, &sec, 0 ) ) 
        {
            if( out )
                _closePipe( childStdOutR, childStdOutW );
            goto fail1;
        }
        // Child does not inherit our end of pipe.
        SetHandleInformation( childStdErrR, HANDLE_FLAG_INHERIT, 0 );
        flags = DETACHED_PROCESS;
    }

    ZeroMemory( &si, sizeof(si) );
    si.cb = sizeof(si);
    if( in || out || err )
    {
        si.hStdInput  = in  ? childStdInR  : NULL;
        si.hStdOutput = out ? childStdOutW : GetStdHandle( STD_OUTPUT_HANDLE );
        si.hStdError  = err ? childStdErrW : GetStdHandle( STD_ERROR_HANDLE );
        si.dwFlags    = STARTF_USESTDHANDLES;
    }

    ZeroMemory( &pi, sizeof(pi) );

    // Start the child process. 
    if( ! CreateProcess( NULL,   // No module name (use command line). 
        TEXT(cmd),        // Command line. 
        NULL,             // Process handle not inheritable. 
        NULL,             // Thread handle not inheritable. 
        TRUE,             // Handle inheritance. 
        flags,            // Creation flags.
        NULL,             // Use parent's environment block. 
        NULL,             // Use parent's starting directory. 
        &si,              // Pointer to STARTUPINFO structure.
        &pi )             // Pointer to PROCESS_INFORMATION structure.
    )
    {
        if( in )
            _closePipe( childStdInR, childStdInW );
        if( out )
            _closePipe( childStdOutR, childStdOutW );
        if( err )
            _closePipe( childStdErrR, childStdErrW );
        return ur_error( ut, UR_ERR_INTERNAL,
                         "CreateProcess failed (%d).\n", GetLastError() );
    }

    if( in )
    {
        DWORD nw;
        CloseHandle( childStdInR );
        WriteFile( childStdInW, in->ptr.v,
                   (in->type == UT_STRING) ? in->used * in->elemSize : in->used,
                   &nw, NULL );
        CloseHandle( childStdInW );
    }

    if( out || err )
    {
        if( out )
            CloseHandle( childStdOutW );
        if( err )
            CloseHandle( childStdErrW );
        _readPipes( childStdOutR, out, childStdErrR, err );
        if( out )
            CloseHandle( childStdOutR );
        if( err )
            CloseHandle( childStdErrR );
    }

    {
    DWORD code;

    // Wait until child process exits.
    WaitForSingleObject( pi.hProcess, INFINITE );

    if( GetExitCodeProcess( pi.hProcess, &code ) )
    {
        ur_setId(res, UT_INT);
        ur_int(res) = code;
    }
    else
    {
        ur_setId(res, UT_NONE);
    }
    }

    // Close process and thread handles. 
    CloseHandle( pi.hProcess );
    CloseHandle( pi.hThread );
    return UR_OK;
}
示例#14
0
/*
  Recursively evaluate math expression.

  \param cell   Cell to evaluate.
  \param res    Result.

  \return UR_OK or UR_THROW.
*/
int calc_eval( UThread* ut, UCell* cell, double* res )
{
    switch( ur_type(cell) )
    {
    case UT_WORD:
    {
        const UCell* val = ur_wordCell( ut, cell );
        if( ! val )
            return UR_THROW;
        if( ur_is(val, UT_DECIMAL) )
            *res = ur_decimal(val);
        else if( ur_is(val, UT_INT) || ur_is(val, UT_CHAR) )
            *res = (double) ur_int(val);
        else
        {
            return ur_error( ut, UR_ERR_SCRIPT, "Invalid word '%s",
                             ur_wordCStr( cell ) );
        }
    }
    break;

    case UT_DECIMAL:
        *res = ur_decimal(cell);
        break;

    case UT_INT:
    case UT_CHAR:
        *res = (double) ur_int(cell);
        break;

    case UT_BLOCK:
    case UT_PAREN:
    {
        UBlockIterM bi;
        double num = 0.0;
        double right;

#define RIGHT_VAL \
if( ++bi.it == bi.end ) \
    return ur_error( ut, UR_ERR_SCRIPT, "Expected operator r-value" ); \
if( ! calc_eval( ut, bi.it, &right ) ) \
    return UR_THROW;

        if( ! ur_blkSliceM( ut, &bi, cell ) )
            return UR_THROW;
        ur_foreach( bi )
        {
            if( ur_is(bi.it, UT_WORD) )
            {
                switch( ur_atom(bi.it) )
                {
                case UR_ATOM_PLUS:
                    RIGHT_VAL
                    num += right;
                    break;

                case UR_ATOM_MINUS:
                    RIGHT_VAL
                    num -= right;
                    break;

                case UR_ATOM_ASTERISK:
                    RIGHT_VAL
                    num *= right;
                    break;

                case UR_ATOM_SLASH:
                    RIGHT_VAL
                    num /= right;
                    break;

                default:
                    if( ! calc_eval( ut, bi.it, &num ) )
                        return UR_THROW;
                }
            }
            else if( ur_is(bi.it, UT_SETWORD) )
            {
                cell = ur_wordCellM( ut, bi.it );
                if( ! cell )
                    return UR_THROW;
                ur_setId( cell, UT_DECIMAL );
                ur_decimal(cell) = num;
            }
            else
            {
                if( ! calc_eval( ut, bi.it, &num ) )
                    return UR_THROW;
            }
        }
        *res = num;
    }
    break;

    default:
        *res = 0.0;
        break;
    }
    return UR_OK;
}
示例#15
0
/*
  Returns zero if matching rule not found or exception occured.
*/
static const UCell* _parseBin( UThread* ut, BinaryParser* pe,
                               const UCell* rit, const UCell* rend,
                               UIndex* spos )
{
    const UCell* set = 0;
    const UCell* tval;
    uint32_t bitCount;
    uint32_t field;
    UBuffer* ibin  = ur_buffer( pe->inputBufN );
    uint8_t* in    = ibin->ptr.b + *spos;
    uint8_t* inEnd = ibin->ptr.b + pe->inputEnd;


match:

    while( rit != rend )
    {
        switch( ur_type(rit) )
        {
            case UT_INT:
                bitCount = ur_int(rit);
                if( bitCount < 1 || bitCount > 32 )
                {
                    ur_error( PARSE_ERR, "bit-field size must be 1 to 32" );
                    goto parse_err;
                }
                if( bitCount > 24 )
                {
                    uint32_t high;
                    in = pullBits( pe, bitCount - 16, in, inEnd, &high );
                    if( ! in )
                        goto failed;
                    in = pullBits( pe, 16, in, inEnd, &field );
                    if( ! in )
                        goto failed;
                    field |= high << 16;
                }
                else
                {
                    in = pullBits( pe, bitCount, in, inEnd, &field );
                    if( ! in )
                        goto failed;
                }
                goto set_field;

            case UT_WORD:
                switch( ur_atom(rit) )
                {
                case UR_ATOM_U8:
                    if( in == inEnd )
                        goto failed;
                    field = *in++;
                    goto set_field;

                case UR_ATOM_U16:
                    if( (inEnd - in) < 2 )
                        goto failed;
                    if( pe->bigEndian )
                        field = (in[0] << 8) | in[1];
                    else
                        field = (in[1] << 8) | in[0];
                    in += 2;
                    goto set_field;

                case UR_ATOM_U32:
                    if( (inEnd - in) < 4 )
                        goto failed;
                    if( pe->bigEndian )
                        field = (in[0] << 24) | (in[1] << 16) |
                                (in[2] <<  8) |  in[3];
                    else
                        field = (in[3] << 24) | (in[2] << 16) |
                                (in[1] <<  8) |  in[0];
                    in += 4;
                    goto set_field;

                case UR_ATOM_SKIP:
                    ++rit;
                    ++in;
                    break;
#if 0
                case UR_ATOM_MARK:
                    break;

                case UR_ATOM_PLACE:
                    ++rit;
                    if( (rit != rend) && ur_is(rit, UT_WORD) )
                    {
                        tval = ur_wordCell( ut, rit++ );
                        CHECK_WORD(tval);
                        if( ur_is(tval, UT_BINARY) )
                        {
                            pos = tval->series.it;
                            break;
                        }
                    }
                    ur_error( PARSE_ERR, "place expected series word" );
                    goto parse_err;
#endif
                case UR_ATOM_COPY:      // copy  dest   size
                                        //       word!  int!/word!
                    ++rit;
                    if( (rit != rend) && ur_is(rit, UT_WORD) )
                    {
                        UCell* res = ur_wordCellM( ut, rit );
                        CHECK_WORD(res);
                        if( ++rit != rend )
                        {
                            tval = rit++;
                            if( ur_is(tval, UT_WORD) )
                            {
                                tval = ur_wordCell( ut, tval );
                                CHECK_WORD(tval);
                            }
                            if( ur_is(tval, UT_INT) )
                            {
                                UBuffer* cb;
                                int size = ur_int(tval);
                                cb = ur_makeBinaryCell( ut, size, res );
                                cb->used = size;
                                memCpy( cb->ptr.b, in, size );
                                in += size;
                                break;
                            }
                        }
                        ur_error( PARSE_ERR, "copy expected int! count" );
                        goto parse_err;
                    }
                    ur_error( PARSE_ERR, "copy expected word! destination" );
                    goto parse_err;

                case UR_ATOM_BIG_ENDIAN:
                    ++rit;
                    pe->bigEndian = 1;
                    break;

                case UR_ATOM_LITTLE_ENDIAN:
                    ++rit;
                    pe->bigEndian = 0;
                    break;

                default:
                    tval = ur_wordCell( ut, rit );
                    CHECK_WORD(tval);

                    if( ur_is(tval, UT_CHAR) )
                        goto match_char;
                    else if( ur_is(tval, UT_STRING) )
                        goto match_string;
                    else if( ur_is(tval, UT_BLOCK) )
                        goto match_block;
                    /*
                    else if( ur_is(tval, UT_BITSET) )
                        goto match_bitset;
                    */
                    else
                    {
                        ur_error( PARSE_ERR,
                                "parse expected char!/string!/block!" );
                        goto parse_err;
                    }
                    break;
                }
                break;

            case UT_SETWORD:
                set = rit++;
                while( (rit != rend) && ur_is(rit, UT_SETWORD) )
                    ++rit;
                break;
#if 0
            case UT_GETWORD:
                break;

            case UT_INT:
                repMin = ur_int(rit);

                ++rit;
                if( rit == rend )
                    return 0;

                if( ur_is(rit, UT_INT) )
                {
                    repMax = ur_int(rit);
                    ++rit;
                }
                else
                {
                    repMax = repMin;
                }
                goto repeat;
#endif
            case UT_CHAR:
match_char:
                if( *in != ur_int(rit) )
                    goto failed;
                ++in;
                ++rit;
                break;

            case UT_BLOCK:
                tval = rit;
match_block:
            {
                UBlockIter bi;
                UIndex pos = in - ibin->ptr.b;
                UIndex rblkN = tval->series.buf;
                ur_blkSlice( ut, &bi, tval );
                tval = _parseBin( ut, pe, bi.it, bi.end, &pos );
                ibin = ur_buffer( pe->inputBufN );
                if( ! tval )
                {
                    if( pe->exception == PARSE_EX_ERROR )
                    {
                        ur_appendTrace( ut, rblkN, 0 );
                        return 0;
                    }
                    if( pe->exception == PARSE_EX_BREAK )
                        pe->exception = PARSE_EX_NONE;
                    else
                        goto failed;
                }
                in    = ibin->ptr.b + pos;
                inEnd = ibin->ptr.b + pe->inputEnd;
                ++rit;
            }
                break;

            case UT_PAREN:
            {
                UIndex pos = in - ibin->ptr.b;

                if( UR_OK != pe->eval( ut, rit ) )
                    goto parse_err;

                /* Re-acquire pointer & check if input modified. */
                ibin = ur_buffer( pe->inputBufN );
                if( pe->sliced )
                {
                    // We have no way to track changes to the end of a slice,
                    // so just make sure we remain in valid memery.
                    if( ibin->used < pe->inputEnd )
                        pe->inputEnd = ibin->used;
                }
                else
                {
                    // Not sliced, track input end.
                    if( ibin->used != pe->inputEnd )
                        pe->inputEnd = ibin->used;
                }
                in    = ibin->ptr.b + pos;
                inEnd = ibin->ptr.b + pe->inputEnd;
                ++rit;
            }
                break;

            case UT_STRING:
                tval = rit;
match_string:
            {
                UBinaryIter bi;
                int size;

                ur_binSlice( ut, &bi, tval );
                if( ur_strIsUcs2(bi.buf) )
                    goto bad_enc;
                size = bi.end - bi.it;
                if( size > (inEnd - in) )
                    goto failed;
                if( match_pattern_8(in, inEnd, bi.it, bi.end) == bi.end )
                {
                    in += size;
                    ++rit;
                }
                else
                    goto failed;
            }
                break;
#if 0
            case UT_BITSET:
                tval = rit;
match_bitset:
            if( pos >= pe->inputEnd )
                goto failed;
            {
                const UBuffer* bin = ur_bufferSer( tval );
                int c = istr->ptr.c[ pos ];
                if( bitIsSet( bin->ptr.b, c ) )
                {
                    ++rit;
                    ++pos;
                }
                else
                    goto failed;
            }
                break;
#endif
            default:
                ur_error( PARSE_ERR, "invalid parse value" );
                             //orDatatypeName( ur_type(rit) ) );
                goto parse_err;
        }
    }

//complete:

    *spos = in - ibin->ptr.b;
    return rit;

set_field:

    if( set )
    {
        UCell* val;
        while( set != rit )
        {
            val = ur_wordCellM( ut, set++ );
            CHECK_WORD(val);
            ur_setId(val, UT_INT);
            ur_int(val) = field;
        }
        set = 0;
    }
    ++rit;
    goto match;

failed:

    *spos = in - ibin->ptr.b;
    return 0;

bad_enc:

    ur_error( ut, UR_ERR_INTERNAL,
              "parse binary does not handle UCS2 strings" );
    //goto parse_err;

parse_err:

    pe->exception = PARSE_EX_ERROR;
    return 0;
}
示例#16
0
/*
   Layout Language

   \return Layout pointer or zero if error generated.
*/
QLayout* ur_qtLayout( UThread* ut, LayoutInfo& parent, const UCell* blkC )
{
    CBParser cbp;
    UBlockIter bi;
    LayoutInfo lo;
    const UCell* val;
    const UCell* setWord = 0;
    QWidget* wid = 0;
    int match;


    ur_blkSlice( ut, &bi, blkC );

    cbp_beginParse( ut, &cbp, bi.it, bi.end, qEnv.layoutRules );
    while( (match = cbp_matchRule( &cbp )) > -1 )
    {
        switch( match )
        {
            case LD_HBOX:
            case LD_VBOX:
            {
                wid = 0;

                lo.grid = 0;
                lo.box  = new QBoxLayout( (match == LD_HBOX) ? 
                                          QBoxLayout::LeftToRight :
                                          QBoxLayout::TopToBottom );
                if( parent.layout() )
                    parent.addLayout( lo.box );

                val = cbp.values + 1;
                //TODO: Handle error.
                ur_qtLayout( ut, lo, val );
            }
                break;

            case LD_LABEL:
            {
                QString txt;
                if( ! getString( ut, cbp.values + 1, txt ) )
                    return 0;

                MAKE_WIDGET( SLabel )
                pw->setText( txt );
            }
                break;

            case LD_BUTTON:
            {
                MAKE_WIDGET( SButton )
                pw->setText( qstring( cbp.values + 1 ) );
                pw->setBlock( cbp.values + 2 );
            }
                break;

            case LD_CHECKBOX:
            {
                MAKE_WIDGET( SCheck )
                pw->setText( qstring( cbp.values + 1 ) );
            }
                break;

            case LD_SPIN_BOX:
            {
                MAKE_WIDGET( SSpinBox )
                pw->setRange( ur_int( cbp.values + 1 ),
                              ur_int( cbp.values + 2 ) );
            }
                break;

            case LD_COMBO:
            {
                MAKE_WIDGET( SCombo )

                val = cbp.values + 1;
                if( ur_is(val, UT_GETWORD) )
                {
                    if( ! (val = ur_wordCell( ut, val )) )
                        return 0;
                }

                if( ur_is(val, UT_BLOCK) )
                {
                    UBlockIter bi2;
                    ur_blkSlice( ut, &bi2, val ); 
                    ur_foreach( bi2 )
                    {
                        if( ur_is(bi2.it, UT_STRING) )
                            pw->addItem( qstring( bi2.it ) );
                    }
                }
                else
                {
                    pw->addItem( qstring( val ) );
                }
            }
                break;

            case LD_SPACER:
                if( ! parent.box )
                    goto no_layout;

                parent.box->addStretch( 1 );
                break;

            case LD_SPACE:
                if( ! parent.box )
                    goto no_layout;

                val = cbp.values + 1;
                parent.box->addSpacing( ur_int(val) );
                break;

            case LD_TAB:
            {
                MAKE_WIDGET( STabWidget )

                if( ! tabWidgetBlock( ut, pw, cbp.values + 1 ) )
                    return 0;
            }
                break;

            case LD_TIP:
                if( wid )
                    wid->setToolTip( qstring(cbp.values + 1) );
                break;

            case LD_TITLE:
                if( qEnv.curWidget )
                {
                    QString str;
                    if( ! getString( ut, cbp.values + 1, str ) )
                        return 0;
                    qEnv.curWidget->setWindowTitle( str );
                }
                break;

            case LD_RESIZE:
                if( qEnv.curWidget )
                {
                    val = cbp.values + 1;
                    qEnv.curWidget->resize( val->coord.n[0], val->coord.n[1] );
                }
                break;

            case LD_LINE_EDIT_STR:
            case LD_LINE_EDIT:
            {
                MAKE_WIDGET( SLineEdit )

                if( match == LD_LINE_EDIT_STR )
                    pw->setText( qstring( cbp.values + 1 ) );
            }
                break;

            case LD_LIST:
            {
                const UCell* hdr = cbp.values + 1;
                if( ur_is(hdr, UT_GETWORD) )
                {
                    if( ! (hdr = ur_wordCell( ut, hdr )) )
                        return 0;
                }

                val = cbp.values + 2;
                if( ur_is(val, UT_GETWORD) )
                {
                    if( ! (val = ur_wordCell( ut, val )) )
                        return 0;
                }

                MAKE_WIDGET( STreeView )
                pw->setRootIsDecorated( false );
                pw->setModel( new UTreeModel( pw, hdr, val ) );
            }
                break;

            case LD_TEXT_EDIT_STR:
            case LD_TEXT_EDIT:
            {
                MAKE_WIDGET( STextEdit )

                if( match == LD_TEXT_EDIT_STR )
                {
                    QString str;
                    if( ! getString( ut, cbp.values + 1, str ) )
                        return 0;
                    if( str[0] == '<' )
                        pw->setHtml( str );
                    else
                        pw->setPlainText( str );
                }
            }
                break;

            case LD_GROUP:
            case LD_GROUP_CHECKABLE:
            {
                MAKE_WIDGET( SGroup )

                val = cbp.values + 1;
                if( match == LD_GROUP_CHECKABLE )
                {
                    const UCell* enabled;
                    if( ! (enabled = ur_wordCell( ut, val )) )
                        return 0;

                    pw->setCheckable( true );
                    pw->setChecked( ur_isTrue( enabled ) );
                    ++val;
                }

                pw->setTitle( qstring( val ) );
                ++val;

                LayoutInfo lo2;
                QLayout* lr2 = ur_qtLayout(ut, lo2, val);
                if( ! lr2 )
                    return 0;
                pw->setLayout( lr2 );
            }
                break;

            case LD_READ_ONLY:
                if( wid )
                {
                    QTextEdit* tedit = qobject_cast<QTextEdit*>( wid );
                    if( tedit )
                        tedit->setReadOnly( true );
                }
                break;

            case LD_ON_EVENT:
                if( qEnv.curWidget )
                {
                    SWidget* sw = qobject_cast<SWidget*>( qEnv.curWidget );
                    if( sw )
                        sw->setEventBlock( cbp.values + 1 );
                }
                break;

            case LD_STRING:
                if( wid )
                {
                    SCombo* combo = qobject_cast<SCombo*>( wid );
                    if( combo )
                    {
                        combo->addItem( qstring( cbp.values ) );
                        break;
                    }

                    QTextEdit* texted = qobject_cast<QTextEdit*>( wid );
                    if( texted )
                    {
                        QString str;
                        cellToQString( cbp.values, str );
                        if( str[0] == '<' )
                            texted->setHtml( str );
                        else
                            texted->setPlainText( str );
                    }
                }
                break;

            case LD_BLOCK:
                if( wid )
                {
                    SCombo* combo = qobject_cast<SCombo*>( wid );
                    if( combo )
                    {
                        combo->setBlock( cbp.values );
                        break;
                    }
                    STreeView* tree = qobject_cast<STreeView*>( wid );
                    if( tree )
                    {
                        tree->setBlock( cbp.values );
                        break;
                    }
                }
                break;

            case LD_SET_WORD:
                setWord = cbp.values;
                break;

            case LD_GRID:
                val = cbp.values + 1;

                wid = 0;

                lo.box     = 0;
                lo.grid    = new QGridLayout;
                lo.columns = ur_int(val);
                lo.colN    = 0;
                lo.rowN    = 0;

                if( parent.layout() )
                    parent.addLayout( lo.grid );

                ++val;
                //TODO: Handle error.
                ur_qtLayout( ut, lo, val );
                break;

            case LD_PROGRESS:
            {
                MAKE_WIDGET( SProgress )
                pw->setRange( 0, ur_int(cbp.values+1) );
            }
                break;

            case LD_WEIGHT:
                if( parent.box && wid )
                {
                    parent.box->setStretchFactor(wid, ur_int(cbp.values+1));
                }
                break;
        }
    }
示例#17
0
/*
    Returns zero if matching rule not found or exception occured.
*/
static const UCell* _parseBlock( UThread* ut, BlockParser* pe,
                                 const UCell* rit, const UCell* rend,
                                 UIndex* spos )
{
    const UCell* tval;
    int32_t repMin;
    int32_t repMax;
    UAtom atom;
    const UBuffer* iblk = pe->blk;
    UIndex pos = *spos;


match:

    while( rit != rend )
    {
        switch( ur_type(rit) )
        {
            case UT_WORD:
                atom = ur_atom(rit);

                if( atom < UT_BI_COUNT )
                {
                    // Datatype
                    if( pos >= pe->inputEnd )
                        goto failed;
                    tval = iblk->ptr.cell + pos;
                    if( ur_type(tval) != atom )
                    {
                        /*
                        if( atom == UT_NUMBER )
                        {
                            if( ur_is(tval,UT_INT) || ur_is(tval,UT_DECIMAL) )
                                goto type_matched;
                        }
                        */
                        goto failed;
                    }
//type_matched:
                    ++rit;
                    ++pos;
                }
                else switch( atom )
                {
                    case UR_ATOM_OPT:
                        ++rit;
                        repMin = 0;
                        repMax = 1;
                        goto repeat;

                    case UR_ATOM_ANY:
                        ++rit;
                        repMin = 0;
                        repMax = 0x7fffffff;
                        goto repeat;

                    case UR_ATOM_SOME:
                        ++rit;
                        repMin = 1;
                        repMax = 0x7fffffff;
                        goto repeat;

                    case UR_ATOM_BREAK:
                        pe->exception = PARSE_EX_BREAK;
                        *spos = pos;
                        return 0;

                    case UR_ATOM_BAR:
                        goto complete;

                    case UR_ATOM_TO:
                    case UR_ATOM_THRU:
                    {
                        const UCell* ci;
                        const UCell* ce;
                        UAtom ratom = ur_atom(rit);

                        ++rit;
                        if( rit == rend )
                            return 0;

                        ci = iblk->ptr.cell + pos;
                        ce = iblk->ptr.cell + pe->inputEnd;

                        if( ur_is(rit, UT_WORD) )
                        {
                            if( ur_atom(rit) < UT_BI_COUNT )
                            {
                                atom = ur_atom(rit);
                                while( ci != ce )
                                {
                                    if( ur_type(ci) == atom )
                                        break;
                                    ++ci;
                                }
                                if( ci == ce )
                                    goto failed;
                                pos = ci - iblk->ptr.cell;
                                if( ratom == UR_ATOM_THRU )
                                    ++pos;
                                ++rit;
                                break;
                            }
                            else
                            {
                                tval = ur_wordCell( ut, rit );
                                CHECK_WORD( tval )
                            }
                        }
                        else
                        {
                            tval = rit;
                        }


                        if( ur_is(tval, UT_BLOCK) )
                        {
                            // TODO: If block then all values must match.
                            BLK_RULE_ERROR( "to/thru block! not implemented" );
                        }
                        else
                        {
                            while( ci != ce )
                            {
                                if( ur_equal(ut, ci, tval) )
                                    break;
                                ++ci;
                            }
                            if( ci == ce )
                                goto failed;
                            pos = ci - iblk->ptr.cell;
                            if( ratom == UR_ATOM_THRU )
                                ++pos;
                        }
                        ++rit;
                    }
                        break;

                    case UR_ATOM_INTO:
                        ++rit;
                        if( rit == rend || ! ur_is(rit, UT_BLOCK) )
                        {
                            BLK_RULE_ERROR( "parse into expected block" );
                        }
                        tval = iblk->ptr.cell + pos;
                        if( ! ur_is(tval, UT_BLOCK) )
                            goto failed;
                        if( ur_isShared( tval->series.buf ) )
                            goto failed;
                    {
                        BlockParser ip;
                        UBlockIter bi;
                        UIndex parsePos = 0;

                        ip.eval = pe->eval;
                        ip.blk  = ur_bufferSer( tval );
                        ip.inputBuf  = tval->series.buf;
                        ip.inputEnd  = ip.blk->used;
                        ip.sliced    = 0;
                        ip.exception = PARSE_EX_NONE;

                        ur_blkSlice( ut, &bi, rit );

                        tval = _parseBlock( ut, &ip, bi.it, bi.end, &parsePos );
                        iblk = _acquireInput( ut, pe );
                        if( ! tval )
                        {
                            if( ip.exception == PARSE_EX_ERROR )
                            {
                                pe->exception = PARSE_EX_ERROR;
                                ur_appendTrace( ut, rit->series.buf, 0 );
                                return 0;
                            }
                            if( ip.exception != PARSE_EX_BREAK )
                                goto failed;
                        }
                    }
                        ++rit;
                        ++pos;
                        break;

                    case UR_ATOM_SKIP:
                        repMin = 1;
skip:
                        if( (pos + repMin) > pe->inputEnd )
                            goto failed;
                        pos += repMin;
                        ++rit;
                        break;

                    case UR_ATOM_SET:
                        ++rit;
                        if( rit == rend )
                            goto unexpected_end;
                        if( ! ur_is(rit, UT_WORD) )
                        {
                            BLK_RULE_ERROR( "parse set expected word" );
                        }
                        {
                        UCell* cell = ur_wordCellM( ut, rit );
                        CHECK_WORD( cell )
                        *cell = iblk->ptr.cell[ pos ];
                        }
                        ++rit;
                        break;

                    case UR_ATOM_PLACE:
                        ++rit;
                        if( (rit != rend) && ur_is(rit, UT_WORD) )
                        {
                            tval = ur_wordCell( ut, rit++ );
                            CHECK_WORD( tval )
                            if( ur_is(tval, UT_BLOCK) )
                            {
                                pos = tval->series.it;
                                break;
                            }
                        }
                        BLK_RULE_ERROR( "place expected series word" );

                    //case UR_ATOM_COPY:

                    default:
                    {
                        tval = ur_wordCell( ut, rit );
                        CHECK_WORD( tval )

                        if( ur_is(tval, UT_BLOCK) )
                        {
                            goto match_block;
                        }
                        else
                        {
                            BLK_RULE_ERROR( "parse expected block" );
                        }
                    }
                        break;
                }
                break;

            case UT_SETWORD:
            {
                UCell* cell = ur_wordCellM( ut, rit );
                CHECK_WORD( cell )
                ++rit;

                ur_setId( cell, UT_BLOCK );
                ur_setSlice( cell, pe->inputBuf, pos, pe->inputEnd );
            }
                break;

            case UT_GETWORD:
            {
                UCell* cell = ur_wordCellM( ut, rit );
                CHECK_WORD( cell )
                ++rit;

                if( ur_is(cell, UT_BLOCK) &&
                    (cell->series.buf == pe->inputBuf) )
                    cell->series.end = pos;
            }
                break;

            case UT_LITWORD:
                if( pos >= pe->inputEnd )
                    goto failed;
                tval = iblk->ptr.cell + pos;
                if( (ur_is(tval, UT_WORD) || ur_is(tval, UT_LITWORD))
                    && (ur_atom(tval) == ur_atom(rit)) )
                {
                    ++rit;
                    ++pos;
                }
                else
                    goto failed;
                break;

            case UT_INT:
                repMin = ur_int(rit);

                ++rit;
                if( rit == rend )
                    return 0;

                if( ur_is(rit, UT_INT) )
                {
                    repMax = ur_int(rit);
                    ++rit;
                }
                else if( ur_is(rit, UT_WORD) && ur_atom(rit) == UR_ATOM_SKIP )
                {
                    goto skip;
                }
                else
                {
                    repMax = repMin;
                }
                goto repeat;

            case UT_DATATYPE:
                if( pos >= pe->inputEnd )
                    goto failed;
                if( ! ur_isDatatype( iblk->ptr.cell + pos, rit ) )
                    goto failed;
                ++rit;
                ++pos;
                break;

            case UT_CHAR:
            case UT_BINARY:
            case UT_STRING:
            case UT_FILE:
                if( pos >= pe->inputEnd )
                    goto failed;
                if( ! ur_equal( ut, iblk->ptr.cell + pos, rit ) )
                    goto failed;
                ++rit;
                ++pos;
                break;

            case UT_BLOCK:
                tval = rit;
match_block:
                {
                UBlockIter bi;
                UIndex rblkN = tval->series.buf;
                ur_blkSlice( ut, &bi, tval );
                tval = _parseBlock( ut, pe, bi.it, bi.end, &pos );
                iblk = pe->blk;
                if( ! tval )
                {
                    if( pe->exception == PARSE_EX_ERROR )
                    {
                        ur_appendTrace( ut, rblkN, 0 );
                        return 0;
                    }
                    if( pe->exception == PARSE_EX_BREAK )
                        pe->exception = PARSE_EX_NONE;
                    else
                        goto failed;
                }
                }
                ++rit;
                break;

            case UT_PAREN:
                if( UR_OK != pe->eval( ut, rit ) )
                    goto parse_err;
                iblk = _acquireInput( ut, pe );
                ++rit;
                break;

            default:
                BLK_RULE_ERROR( "invalid parse value" );
        }