Ejemplo n.º 1
0
// ------------------------------------------------------------------------------------------------
SQInteger Routine::Create(HSQUIRRELVM vm)
{
    // Locate the identifier of a free slot
    const SQInteger slot = FindUnused();
    // See if we have where to store this routine
    if (slot < 0)
    {
        return sq_throwerror(vm, "Reached the maximum number of active routines");
    }
    // Grab the top of the stack
    const SQInteger top = sq_gettop(vm);
    // See if too many arguments were specified
    if (top >= 20) /* 5 base + 14 parameters = 19 */
    {
        return sq_throwerror(vm, "Too many parameters specified");
    }
    // Was there was an environment specified?
    else if (top <= 1)
    {
        return sq_throwerror(vm, "Missing routine environment");
    }
    // Was there was a callback specified?
    else if (top <= 2)
    {
        return sq_throwerror(vm, "Missing routine callback");
    }
    // Validate the callback type
    else if (sq_gettype(vm, 3) != OT_CLOSURE && sq_gettype(vm, 3) != OT_NATIVECLOSURE)
    {
        return sq_throwerror(vm, "Invalid callback type");
    }

    SQRESULT res = SQ_OK;
    // Prepare an object for the environment
    HSQOBJECT env;
    // Is the specified environment a null value?
    if (sq_gettype(vm, 2) == OT_NULL)
    {
        // Preserve the stack state
        const StackGuard sg(vm);
        // Push the root table on the stack
        sq_pushroottable(vm);
        // Attempt to retrieve the table object
        res = sq_getstackobj(vm, -1, &env);
    }
    else
    {
        sq_getstackobj(vm, 2, &env); // Just retrieve the specified environment
    }
    // Validate the result
    if (SQ_FAILED(res))
    {
        return res; // Propagate the error
    }

    // Prepare an object for the function
    HSQOBJECT func;
    // Fetch the specified callback object
    res = sq_getstackobj(vm, 3, &func);
    // Validate the result
    if (SQ_FAILED(res))
    {
        return res; // Propagate the error
    }

    // The number of iterations and interval to execute the routine
    SQInteger intrv = 0, itr = 0;
    // Was there an interval specified?
    if (top > 3)
    {
        // Grab the interval from the stack
        res = sq_getinteger(vm, 4, &intrv);
        // Validate the result
        if (SQ_FAILED(res))
        {
            return res; // Propagate the error
        }
    }
    // Was there a number of iterations specified?
    if (top > 4)
    {
        // Grab the iterations from the stack
        res = sq_getinteger(vm, 5, &itr);
        // Validate the result
        if (SQ_FAILED(res))
        {
            return res; // Propagate the error
        }
    }

    // Attempt to create a routine instance
    try
    {
        ClassType< Routine >::PushInstance(vm, new Routine());
    }
    catch (const Sqrat::Exception & e)
    {
        return sq_throwerror(vm, "Unable to create the routine instance");
    }
    // Prepare an object for the routine
    HSQOBJECT obj;
    // Fetch the created routine object
    res = sq_getstackobj(vm, -1, &obj);
    // Validate the result
    if (SQ_FAILED(res))
    {
        return res; // Propagate the error
    }

    // At this point we can grab a reference to our slot
    Instance & inst = s_Instances[slot];
    // Were there any arguments specified?
    if (top > 5)
    {
        // Grab a pointer to the arguments array
        Argument * args = inst.mArgv;
        // Reset the argument counter
        inst.mArgc = 0;
        // Grab the specified arguments from the stack
        for (SQInteger i = 6; i <= top; ++i)
        {
            res = sq_getstackobj(vm, i, &(args[inst.mArgc].mObj));
            // Validate the result
            if (SQ_FAILED(res))
            {
                // Clear previous arguments
                inst.Clear();
                // Propagate the error
                return res;
            }
            // Keep a strong reference to the argument
            sq_addref(vm, &(args[inst.mArgc].mObj));
            // Increase the argument counter
            ++inst.mArgc;
        }
    }

    // Attempt to retrieve the routine from the stack and associate it with the slot
    try
    {
        Var< Routine * >(vm, -1).value->m_Slot = ConvTo< Uint32 >::From(slot);
    }
    catch (const Sqrat::Exception & e)
    {
        // Clear extracted arguments
        inst.Clear();
        // Now it's safe to throw the error
        return sq_throwerror(vm, "Unable to create the routine instance");
    }

    // Alright, at this point we can initialize the slot
    inst.Init(env, func, obj, intrv, itr);
    // Now initialize the timer
    s_Intervals[slot] = intrv;
    // We have the created routine on the stack, so let's return it
    return 1;
}
Ejemplo n.º 2
0
int main( int argc, char **argv )
{
    int     i;
    FILE    *skeleton, *temp, *tokout, *actout;
    int     ch;
    char    tempfname[10];
    char    *fileprefix = "y";
    size_t  size;

    param_requested = 0;
    for( i = 1; i < argc; ++i ) {
        ch = argv[i][0];
        switch( param_requested ) {
        case 'b':
            if( ch != '-' ) {
                if( ch != '\0' )
                    fileprefix = argv[i];
                ++i;
            }
            break;
        case 'p':
            if( ch != '-' ) {
                if( ch != '\0' )
                    symprefix = argv[i];
                ++i;
            }
            break;
        default:
            break;
        }
        param_requested = 0;
        if( argv[i][0] != '-' )
            break;
        setoptions( &argv[i][1] );
    }
    if( i != argc - 1 && i != argc - 2 ) {
        puts( "usage: yacc [-dlv] [-d[bcdfhpstuw]] [-b <file_prefix>] [-p <sym_prefix>]" );
        puts( "                  <grammar> [<driver>]" );
        puts( "options:" );
        puts( "    -b <file_prefix> file prefix used in place of default 'y' prefix" );
        puts( "    -d    output header file" );
        puts( "    -db   output bigger (less optimal) tables" );
        puts( "    -dc   output compact tables (slower to execute)" );
        puts( "    -dd   use dense tokens (no '+' style tokens allowed)" );
        puts( "    -de   dump all symbols to header file as enum items, no macros" );
        puts( "    -df   output fast tables (larger size)" );
        puts( "    -dh   use 'default shift' optimization" );
        puts( "    -dp   dump all productions" );
        puts( "    -ds   dump full state tables" );
        puts( "    -dt   translate 'keyword' to Y_KEYWORD, '++' to Y_PLUS_PLUS, etc." );
        puts( "    -du   eliminate useless unit production reduction" );
        puts( "    -dw   disable default action type checking" );
        puts( "    -l    output #line directives" );
        puts( "    -p <sym_prefix> symbol prefix used in place of default 'yy' prefix" );
        puts( "    -v    write description and report into file" );
        exit( 1 );
    }
    skeleton = NULL;
    if( i == argc - 2 ) {
        skeleton = openr( argv[argc - 1] );
        if( skeleton == NULL ) {
            msg( "could not open driver source code '%s'\n", argv[argc - 1] );
        }
    }
    loadpath = argv[0];
    *getname( loadpath ) = '\0';
    srcname = argv[i];
    if( !strrchr( srcname, '.' ) ) {
        srcname = alloca( strlen( argv[i] )+3 );
        srcname = strcat( strcpy( srcname, argv[i] ), ".y" );
    }
    yaccin = openr( srcname );

    size = strlen( fileprefix);
    codefilename   = MALLOC( size + 6, char );
    strcat( strcpy( codefilename, fileprefix), "tab.c" );
    headerfilename = MALLOC( size + 6, char );
    strcat( strcpy( headerfilename, fileprefix), "tab.h" );
    descfilename   = MALLOC( size + 5, char );
    strcat( strcpy( descfilename, fileprefix), ".out" );
    actout = openw( codefilename );
    defs( actout );
    tokout = openw( headerfilename );
    dump_header( tokout );
    temp = NULL;
    for( i = 0; i < 1000 && temp == NULL; ++i ) {
        sprintf( tempfname, "ytab.%3d", i );
        temp = fopen( tempfname, "w+" );
    }
    if( temp == NULL ) {
        msg( "Cannot create temporary file\n" );
    }
    rules( temp );
    buildpro();
    CalcMinSentence();
    if( proflag || showflag ) {
        showpro();
    }
    lr0();
    lalr1();
    SetupStateTable();
    /* apply state filters */
    FindUnused();
    if( eliminateunitflag ) {
        EliminateUnitReductions();
    }
    if( default_shiftflag ) {
        if( keyword_id_low == 0 ) {
            msg( "No %%keyword_id <low> <high> specified." );
        } else {
            MarkDefaultShifts();
        }
    }
    MarkNoUnitRuleOptimizationStates();
    RemoveDeadStates();
    MarkDefaultReductions();
    if( showflag ) {
        showstates();
    }
    if( warnings ) {
        if( warnings == 1 ) {
            printf( "%s: 1 warning\n", srcname );
        } else {
            printf( "%s: %d warnings\n", srcname, warnings );
        }
        exit( 1 );
    }
    parsestats();
    dumpstatistic( "parser states", nstate );
    dumpstatistic( "# states (1 reduce only)", nstate_1_reduce );
    dumpstatistic( "reduce/reduce conflicts", RR_conflicts );
    dumpstatistic( "shift/reduce conflicts", SR_conflicts );
    show_unused();
    if( skeleton == NULL ) {
        skeleton = fpopen( loadpath, "yydriver.c" );
        if( skeleton == NULL ) {
            warn( "Can't find yacc skeleton yydriver.c\n" );
        }
    }
    /* copy first part of skeleton */
    if( skeleton != NULL )
        copy_part( skeleton, actout );
    rewind( tokout );
    /* copy tokens */
    copy_rest( tokout, actout );
    close_header( tokout );
    genobj( actout );
    /* copy middle part of skeleton */
    if( skeleton != NULL )
        copy_part( skeleton, actout );
    rewind( temp );
    copy_rest( temp, actout );
    fclose( temp );
    remove( tempfname );
    /* copy last part of skeleton */
    if( skeleton != NULL ) {
        copy_rest( skeleton, actout );
        fclose( skeleton );
    }
    tail( actout );
    fclose( actout );
    FREE( codefilename );
    FREE( headerfilename );
    FREE( descfilename );
    return( 0 );
}