Пример #1
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;
}
Пример #2
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;
}
Пример #3
0
static int ledit_select( GWidget* wp, UAtom atom, UCell* res )
{
    if( atom == UR_ATOM_TEXT )
    {
        EX_PTR;
        ur_setId(res, UT_STRING);
        ur_setSeries(res, ep->strN, 0);
        return UR_OK;
    }
    else if( atom == UR_ATOM_ACTION )
    {
        EX_PTR;
        ur_setId(res, UT_BLOCK);
        ur_setSeries(res, ep->codeN, 0);
        return UR_OK;
    }
    return gui_areaSelect( wp, atom, res );
}
Пример #4
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;
    }
}
Пример #5
0
/**
  Generate a single binary and set cell to reference it.

  If you need multiple buffers then ur_genBuffers() should be used.

  \param size   Number of bytes to reserve.
  \param cell   Cell to initialize.

  \return  Pointer to binary buffer.
*/
UBuffer* ur_makeBinaryCell( UThread* ut, int size, UCell* cell )
{
    UBuffer* buf;
    UIndex bufN;

    ur_genBuffers( ut, 1, &bufN );
    buf = ur_buffer( bufN );
    ur_binInit( buf, size );

    ur_setId( cell, UT_BINARY );
    ur_setSeries( cell, bufN, 0 );

    return buf;
}
Пример #6
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 );
}
Пример #7
0
/*
  Define the words 'pi and 'e.
*/
void defineWords( UThread* ut )
{
    static double constants[2] = { 3.14159265358979, 2.71828182845904 };
    UAtom atoms[2];
    UBuffer* ctx;
    UCell* cell;
    int i;

    ur_internAtoms( ut, "pi e", atoms );

    ctx = ur_threadContext( ut );
    for( i = 0; i < 2; ++i )
    {
        cell = ur_ctxAddWord( ctx, atoms[i] );
        ur_setId( cell, UT_DECIMAL );
        ur_decimal(cell) = constants[i];
    }
    ur_ctxSort( ctx );
}
Пример #8
0
static int itemview_select( GWidget* wp, UAtom atom, UCell* res )
{
    if( atom == UR_ATOM_VALUE /*selection*/ )
    {
        EX_PTR;

        if( ep->selRow > -1 )
        {
            UThread* ut = glEnv.guiUT;
            const UBuffer* items = ur_buffer( ep->dataBlkN );
            *res = items->ptr.cell[ ep->selRow ];
        }
        else
        {
            ur_setId( res, UT_NONE );
        }
        return UR_OK;
    }
    return gui_areaSelect( wp, atom, res );
}
Пример #9
0
static int ssl_read( UThread* ut, UBuffer* port, UCell* dest, int len )
{
    SSLExt* ext = ur_ptr(SSLExt, port);
    UBuffer* buf = ur_buffer( dest->series.buf );
    int n;

    if( port->FD > -1 && len )
    {
retry:
        n = mbedtls_ssl_read( &ext->sc, buf->ptr.b + buf->used, len );
        //printf( "KR ssl_read %d\n", n );
        if( n > 0 )
        {
            buf->used += n;
        }
        else if( n < 0 )
        {
            if( n == MBEDTLS_ERR_SSL_WANT_READ ||
                    n == MBEDTLS_ERR_SSL_WANT_WRITE )
            {
                ssl_wait();
                goto retry;
            }

            // An error occured; the ssl context must not be used again.
            ssl_free( ext );
            port->FD = -1;

            return ur_error( ut, UR_ERR_ACCESS, "ssl_read %d", n );
        }
        else
        {
            ur_setId(dest, UT_NONE);
        }
    }
    return UR_OK;
}
Пример #10
0
/*
  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;
}
Пример #11
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" );
        }
Пример #12
0
static void ledit_layout( GWidget* wp )
{
    UCell* style = glEnv.guiStyle;
    UThread* ut  = glEnv.guiUT;
    UCell* rc;
    EX_PTR;


    // Set draw list variables.

    rc = style + CI_STYLE_LABEL;
    ur_setId( rc, UT_STRING );
    ur_setSeries( rc, ep->strN, 0 );

    rc = style + CI_STYLE_AREA;
    gui_initRectCoord( rc, wp, UR_ATOM_RECT );


    // Compile draw lists.

    if( ! gDPC )
        return;

    // Make sure the tgeo vertex buffers are bound before the switch.
    // Otherwise only the first case would emit the code to do it. 
    // NOTE: This assumes the button draw programs actually use tgeo.
    dp_tgeoInit( gDPC );

    ep->dpSwitch = dp_beginSwitch( gDPC, 2 );

    rc = style + CI_STYLE_EDITOR;
    if( ur_is(rc, UT_BLOCK) )
        ur_compileDP( ut, rc, 1 );
    dp_endCase( gDPC, ep->dpSwitch );

    rc = style + CI_STYLE_EDITOR_ACTIVE;
    if( ur_is(rc, UT_BLOCK) )
        ur_compileDP( ut, rc, 1 );
    dp_endCase( gDPC, ep->dpSwitch );

    dp_endSwitch( gDPC, ep->dpSwitch, ep->state );

    setFlag( CHANGED );

#if 0
    rc = style + CI_STYLE_EDITOR_CURSOR;
    if( ur_is(rc, UT_BLOCK) )
    {
        DPCompiler dc;
        DPCompiler* save;

        save = gx_beginDP( &dc );
        if( save )
            dc.shaderProg = save->shaderProg;
        ur_compileDP( ut, rc, 1 );
        gx_endDP( ur_buffer( ep->textResN ), save );

        //dp_compile( &dc, ut, rc->series.n );
    }
#endif
}
Пример #13
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;
}
Пример #14
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;
}
Пример #15
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;
}