// ------------------------------------------------------------------------------------------------ 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; }
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 ); }