예제 #1
0
void Opcode803AHandler::_run()
{
    Logger::debug("SCRIPT") << "[803A] [*] op_sub(a, b) -" << std::endl;
    auto bValue = _vm->dataStack()->pop();
    auto aValue = _vm->dataStack()->pop();
    if (!bValue.isNumber() || !aValue.isNumber())
    {
        _error(std::string("op_sub(a, b): Incompatible types: ") + aValue.typeName() + " - " + bValue.typeName());
    }
    if (aValue.type() == VMStackValue::Type::INTEGER)
    {
        if (bValue.type() == VMStackValue::Type::INTEGER)
        {
            _vm->dataStack()->push(aValue.integerValue() - bValue.integerValue());
        }
        else
        {
            _vm->dataStack()->push((float)aValue.integerValue() - bValue.floatValue());
        }
    }
    else
    {
        if (bValue.type() == VMStackValue::Type::INTEGER)
        {
            _vm->dataStack()->push(aValue.floatValue() - (float)bValue.integerValue());
        }
        else
        {
            _vm->dataStack()->push(aValue.floatValue() - bValue.floatValue());
        }
    }
}
예제 #2
0
            void Opcode80E1::_run()
            {
                // @TODO: add implementation
                Logger::debug("SCRIPT") << "[80E1] [*] int metarule3(int meta, int p1, int p2, int p3)" << std::endl;
                auto dataStack = _script->dataStack();

                auto arg3 = dataStack->pop();
                auto arg2 = dataStack->pop();
                auto arg1 = dataStack->pop();
                auto meta = dataStack->popInteger();
                int result = 0;
                switch(meta)
                {
                    case 100: // rm_fixed_timer_event(object, fixed_param, 0)
                    {
                        auto state = Game::Game::getInstance()->locationState();
                        if (state)
                        {
                            state->removeTimerEvent(arg1.objectValue(), arg2.integerValue());
                        }
                        break;
                    }
                    case 101: // mark subtile visited on worldmap - mark_world_subtile_visited(x, y, radius)
                        break;
                    case 102: // METARULE3_SET_WM_MUSIC - (map index, ACM file name)
                        break;
                    case 103: // player_kill_count(critterType)
                        break;
                    case 104: // int mark_map_entrance_state(int map_idx, int state, int elev); elev -1 means for all elevations
                        break;
                    case 105: // int wm_get_subtile_state(int xPos, int yPos)  (0 - unknown, 1 - known, 2 - visited)
                        break;
                    case 106: // ObjectPtr tile_get_next_critter(int tile_num, int elev, ObjectPtr last_critter)
                        break;
                    case 107: // int art_change_fid_num(ObjectPtr who, int fid) - change base FID num for object
                        break;
                    case 108: // void tile_set_center(int tileNum) - center camera on given tile
                    {
                        auto state = Game::Game::getInstance()->locationState();
                        if (state)
                        {
                            state->centerCameraAtHexagon(arg1.integerValue());
                        }
                        break;
                    }
                    default:
                        _error("metarule3 - unknown meta: " + std::to_string(meta));
                        break;
                }
                dataStack->push(result);
            }
예제 #3
0
void Opcode8014Handler::_run()
{
    auto& debug = Logger::debug("SCRIPT");
    debug << "[8014] [+] value = op_fetch_external(name)" << std::endl;
    auto game = Game::getInstance();
    auto EVARS = game->locationState()->EVARS();
    std::string name;
    auto nameValue = _vm->dataStack()->pop();
    switch (nameValue.type())
    {
        case VMStackValue::Type::INTEGER:
            name = _vm->script()->identifiers()->at((unsigned int)nameValue.integerValue());
            break;
        case VMStackValue::Type::STRING:
        {
            name = nameValue.stringValue();
            break;
        }
        default:
            _error(std::string("op_fetch_external - invalid argument type: ") + nameValue.typeName());
    }
    debug << " name = " << name;
    if (EVARS->find(name) == EVARS->end())
    {
        _error(std::string() + "op_fetch_external: exported variable \"" + name + "\" not found.");
    }
    auto value = EVARS->at(name);
    debug << ", type = " << value.typeName() << ", value = " << value.toString() << std::endl;
    _vm->dataStack()->push(value);
}
예제 #4
0
// INTEGER LITERAL VALUE
rapidjson::Value SuperastCPP::createIntegerValue(const int64_t value) {
  rapidjson::Value integerValue(rapidjson::kObjectType);
  integerValue.AddMember("type", "int", allocator);
  integerValue.AddMember("value", value, allocator);

  return integerValue;
}
예제 #5
0
파일: Constant.hpp 프로젝트: scrossuk/locic
			size_t hash() const {
				Hasher hasher;
				hasher.add(kind());
				
				switch (kind()) {
					case NULLVAL:
						break;
					case BOOLEAN:
						hasher.add(boolValue());
						break;
					case INTEGER:
						hasher.add(integerValue());
						break;
					case FLOATINGPOINT:
						hasher.add(floatValue());
						break;
					case CHARACTER:
						hasher.add(characterValue());
						break;
					case STRING:
						hasher.add(stringValue());
						break;
				}
				
				return hasher.get();
			}
예제 #6
0
 void Opcode8046::_run()
 {
     Logger::debug("SCRIPT") << "[8046] [*] op_negate" << std::endl;
     auto value = _script->dataStack()->pop();
     if (value.type() == StackValue::Type::INTEGER)
     {
         _script->dataStack()->push(- value.integerValue());
     }
     else if (value.type() == StackValue::Type::FLOAT)
     {
         _script->dataStack()->push(- value.floatValue());
     }
     else
     {
         _error(std::string("Invalid argument type: ") + value.typeName());
     }
 }
예제 #7
0
void Opcode8044Handler::_run()
{
    Logger::debug("SCRIPT") << "[8044] [*] op_floor" << std::endl;
    auto value = _vm->dataStack()->pop();
    int result = 0;
    if (value.type() == VMStackValue::Type::FLOAT)
    {
        result = (int)value.floatValue(); // this is how "floor" originally worked..
    }
    else if (value.type() == VMStackValue::Type::INTEGER)
    {
        result = value.integerValue();
    }
    else
    {
        _error(std::string("op_floor: invalid argument type: ") + value.typeName());
    }
    _vm->dataStack()->push(result);
}
예제 #8
0
파일: Constant.hpp 프로젝트: scrossuk/locic
			std::string toString() const {
				switch (kind_) {
					case NULLVAL:
						return "NullConstant";
					case BOOLEAN:
						return makeString("BoolConstant(%s)", bool_ ? "true" : "false");
					case INTEGER:
						return makeString("IntegerConstant(%s)", integerValue().toString().c_str());
					case FLOATINGPOINT:
						return makeString("FloatConstant(%Lf)", floatValue());
					case CHARACTER:
						return makeString("CharacterConstant(%llu)",
						                  static_cast<unsigned long long>(characterValue()));
					case STRING:
						return makeString("StringConstant(\"%s\")", escapeString(stringValue().asStdString()).c_str());
				}
				
				return "[UNKNOWN CONSTANT]";
			}
예제 #9
0
파일: Constant.hpp 프로젝트: scrossuk/locic
			bool operator==(const Constant& other) const {
				if (kind() != other.kind()) {
					return false;
				}
				
				switch (kind()) {
					case NULLVAL:
						return true;
					case BOOLEAN:
						return boolValue() == other.boolValue();
					case INTEGER:
						return integerValue() == other.integerValue();
					case FLOATINGPOINT:
						return floatValue() == other.floatValue();
					case CHARACTER:
						return characterValue() == other.characterValue();
					case STRING:
						return stringValue() == other.stringValue();
				}
				
				return false;
			}
예제 #10
0
파일: oop.cpp 프로젝트: bhatti/RoarVM
void Oop::print(Printer* p) {
  if (is_int())
    p->printf("%d", integerValue());
  else
    as_object()->print(p);
}
예제 #11
0
static void setIntegerField(JNIEnv* env, jobject obj, const char* fieldName, int value) {
    ScopedLocalRef<jobject> integerValue(env, integerValueOf(env, value));
    jfieldID fid = env->GetFieldID(JniConstants::localeDataClass, fieldName, "Ljava/lang/Integer;");
    env->SetObjectField(obj, fid, integerValue.get());
}
예제 #12
0
void OpcodeComparisonHandler::_run()
{
    Logger::debug("SCRIPT") << "[8033-8038] [*] " << _cmpOpcodeName() << std::endl;
    auto bValue = _vm->dataStack()->pop();
    auto aValue = _vm->dataStack()->pop();
    int result = 0;
    switch (aValue.type())
    {
        case VMStackValue::Type::INTEGER:
        {
            int arg1 = aValue.integerValue();
            switch (bValue.type())
            {
                case VMStackValue::Type::INTEGER:
                {
                    result = _compare(arg1, bValue.integerValue()); // INTEGER op INTEGER
                    break;
                }
                case VMStackValue::Type::FLOAT:
                {
                    result = _compare(arg1, bValue.floatValue()); // INTEGER op FLOAT
                    break;
                }
                case VMStackValue::Type::STRING:
                {
                    result = _compare(arg1, bValue.toInteger()); // INTEGER op STRING (parsed as int)
                    break;
                }
                default:
                {
                    _error(std::string() + _cmpOpcodeName() + ": invalid right argument type: " + bValue.typeName());
                }
            }
            break;
        }
        case VMStackValue::Type::FLOAT:
        {
            float arg1 = aValue.floatValue();
            switch (bValue.type())
            {
                case VMStackValue::Type::INTEGER:
                {
                    result = _compare(arg1, bValue.integerValue()); // FLOAT op INTEGER
                    break;
                }
                case VMStackValue::Type::FLOAT:
                {
                    result = _compare(arg1, bValue.floatValue()); // FLOAT op FLOAT
                    break;
                }
                case VMStackValue::Type::STRING:
                {
                    float arg2 = 0.0;
                    try 
                    {
                        arg2 = std::stof(bValue.stringValue());
                    }
                    catch (std::invalid_argument ex) { }
                    catch (std::out_of_range ex) { }
                    result = _compare(arg1, arg2); // FLOAT op STRING (parsed as float)
                    break;
                }
                default:
                {
                    _error(std::string() + _cmpOpcodeName() + ": invalid right argument type: " + bValue.typeName());
                }
            }
            break;
        }
        case VMStackValue::Type::STRING:
        {
            switch (bValue.type())
            {
                case VMStackValue::Type::INTEGER:
                {
                    result = _compare(aValue.toInteger(), bValue.integerValue()); // STRING (as integer) op INTEGER
                    break;
                }
                case VMStackValue::Type::FLOAT:
                {
                    float arg1 = 0.0;
                    try 
                    {
                        arg1 = std::stof(aValue.stringValue());
                    }
                    catch (std::invalid_argument ex) { }
                    catch (std::out_of_range ex) { }
                    result = _compare(arg1, bValue.floatValue()); // STRING (as float) op FLOAT
                    break;
                }
                case VMStackValue::Type::STRING:
                {
                    result = _compare(aValue.stringValue(), bValue.stringValue()); // STRING op STRING
                    break;
                }
                default:
                {
                    _error(std::string() + _cmpOpcodeName() + ": invalid right argument type: " + bValue.typeName());
                }
            }
            break;
        }
        case VMStackValue::Type::OBJECT:
        {
            switch (bValue.type())
            {
                case VMStackValue::Type::INTEGER:
                {
                    result = _compare((int)aValue.toBoolean(), bValue.integerValue()); // OBJECT op INTEGER
                    break;
                }
                case VMStackValue::Type::FLOAT:
                {
                    result = _compare((float)aValue.toBoolean(), bValue.floatValue()); // OBJECT op FLOAT
                    break;
                }
                case VMStackValue::Type::STRING:
                {
                    result = _compare(aValue.toString(), bValue.stringValue()); // OBJECT op STRING - compare object name
                    break;
                }
                default:
                {
                    _error(std::string() + _cmpOpcodeName() + ": invalid right argument type: " + bValue.typeName());
                }
            }
            break;
        }
        default:
        {
            _error(std::string() + _cmpOpcodeName() + ": invalid left argument type: " + aValue.typeName());
        }
    }
    _vm->dataStack()->push(result);
}
예제 #13
0
 void Opcode8039::_run()
 {
     auto& debug = Logger::debug("SCRIPT");
     debug << "[8039] [*] op_add(aValue, bValue)" << std::endl;
     auto bValue = _script->dataStack()->pop();
     auto aValue = _script->dataStack()->pop();
     debug << "    types: " << aValue.typeName() << " + " << bValue.typeName() << std::endl;
     switch (bValue.type())
     {
         case StackValue::Type::INTEGER: // INTEGER
         {
             int arg2 = bValue.integerValue();
             switch (aValue.type())
             {
                 case StackValue::Type::INTEGER: // INTEGER + INTEGER
                 {
                     _script->dataStack()->push(aValue.integerValue() + arg2);
                     break;
                 }
                 case StackValue::Type::FLOAT: // FLOAT + INTEGER
                 {
                     _script->dataStack()->push(aValue.floatValue() + (float)arg2);
                     break;
                 }
                 case StackValue::Type::STRING: // STRING + INTEGER
                 {
                     std::string arg1 = aValue.stringValue();
                     _script->dataStack()->push(arg1 + bValue.toString());
                     break;
                 }
                 default:
                 {
                     _error(std::string("op_add - invalid left argument type: ") + aValue.typeName());
                 }
             }
             break;
         }
         case StackValue::Type::STRING:
         {
             auto arg2 = bValue.stringValue();
             switch (aValue.type())
             {
                 case StackValue::Type::STRING: // STRING + STRING
                 {
                     _script->dataStack()->push(aValue.stringValue() + arg2);
                     break;
                 }
                 case StackValue::Type::FLOAT: // FLOAT + STRING
                 {
                     _error("op_add - FLOAT+STRING not allowed");
                 }
                 case StackValue::Type::INTEGER: // INTEGER + STRING
                 {
                     _error("op_add - INTEGER+STRING not allowed");
                 }
                 default:
                 {
                     _error(std::string("op_add - invalid left argument type: ") + aValue.typeName());
                 }
             }
             break;
         }
         case StackValue::Type::FLOAT: // FLOAT
         {
             auto arg2 = bValue.floatValue();
             switch (aValue.type())
             {
                 case StackValue::Type::INTEGER: // INTEGER + FLOAT
                 {
                     _script->dataStack()->push((float)aValue.integerValue() + arg2);
                     break;
                 }
                 case StackValue::Type::FLOAT: // FLOAT + FLOAT
                 {
                     _script->dataStack()->push(aValue.floatValue() + arg2);
                     break;
                 }
                 case StackValue::Type::STRING: // STRING + FLOAT
                 {
                     auto arg1 = aValue.stringValue();
                     _script->dataStack()->push(arg1 + bValue.toString());
                     break;
                 }
                 default:
                 {
                     _error(std::string("op_add - invalid left argument type: ") + aValue.typeName());
                 }
             }
             break;
         }
         default:
         {
             _error(std::string("op_add - invalid right argument type: ") + bValue.typeName());
         }
     }
 }
예제 #14
0
int main(int argc, char **argv){
  sqlite3_int64 iBegin;        /* Start time of this program */
  int quietFlag = 0;           /* True if --quiet or -q */
  int verboseFlag = 0;         /* True if --verbose or -v */
  char *zInsSql = 0;           /* SQL statement for --load-db or --load-sql */
  int iFirstInsArg = 0;        /* First argv[] to use for --load-db or --load-sql */
  sqlite3 *db = 0;             /* The open database connection */
  sqlite3_stmt *pStmt;         /* A prepared statement */
  int rc;                      /* Result code from SQLite interface calls */
  Blob *pSql;                  /* For looping over SQL scripts */
  Blob *pDb;                   /* For looping over template databases */
  int i;                       /* Loop index for the argv[] loop */
  int onlySqlid = -1;          /* --sqlid */
  int onlyDbid = -1;           /* --dbid */
  int nativeFlag = 0;          /* --native-vfs */
  int rebuildFlag = 0;         /* --rebuild */
  int vdbeLimitFlag = 0;       /* --limit-vdbe */
  int timeoutTest = 0;         /* undocumented --timeout-test flag */
  int runFlags = 0;            /* Flags sent to runSql() */
  char *zMsg = 0;              /* Add this message */
  int nSrcDb = 0;              /* Number of source databases */
  char **azSrcDb = 0;          /* Array of source database names */
  int iSrcDb;                  /* Loop over all source databases */
  int nTest = 0;               /* Total number of tests performed */
  char *zDbName = "";          /* Appreviated name of a source database */
  const char *zFailCode = 0;   /* Value of the TEST_FAILURE environment variable */
  int cellSzCkFlag = 0;        /* --cell-size-check */
  int sqlFuzz = 0;             /* True for SQL fuzz testing. False for DB fuzz */
  int iTimeout = 120;          /* Default 120-second timeout */
  int nMem = 0;                /* Memory limit */
  char *zExpDb = 0;            /* Write Databases to files in this directory */
  char *zExpSql = 0;           /* Write SQL to files in this directory */

  iBegin = timeOfDay();
#ifdef __unix__
  signal(SIGALRM, timeoutHandler);
#endif
  g.zArgv0 = argv[0];
  zFailCode = getenv("TEST_FAILURE");
  for(i=1; i<argc; i++){
    const char *z = argv[i];
    if( z[0]=='-' ){
      z++;
      if( z[0]=='-' ) z++;
      if( strcmp(z,"cell-size-check")==0 ){
        cellSzCkFlag = 1;
      }else
      if( strcmp(z,"dbid")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        onlyDbid = integerValue(argv[++i]);
      }else
      if( strcmp(z,"export-db")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        zExpDb = argv[++i];
      }else
      if( strcmp(z,"export-sql")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        zExpSql = argv[++i];
      }else
      if( strcmp(z,"help")==0 ){
        showHelp();
        return 0;
      }else
      if( strcmp(z,"limit-mem")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        nMem = integerValue(argv[++i]);
      }else
      if( strcmp(z,"limit-vdbe")==0 ){
        vdbeLimitFlag = 1;
      }else
      if( strcmp(z,"load-sql")==0 ){
        zInsSql = "INSERT INTO xsql(sqltext) VALUES(CAST(readfile(?1) AS text))";
        iFirstInsArg = i+1;
        break;
      }else
      if( strcmp(z,"load-db")==0 ){
        zInsSql = "INSERT INTO db(dbcontent) VALUES(readfile(?1))";
        iFirstInsArg = i+1;
        break;
      }else
      if( strcmp(z,"m")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        zMsg = argv[++i];
      }else
      if( strcmp(z,"native-vfs")==0 ){
        nativeFlag = 1;
      }else
      if( strcmp(z,"quiet")==0 || strcmp(z,"q")==0 ){
        quietFlag = 1;
        verboseFlag = 0;
      }else
      if( strcmp(z,"rebuild")==0 ){
        rebuildFlag = 1;
      }else
      if( strcmp(z,"result-trace")==0 ){
        runFlags |= SQL_OUTPUT;
      }else
      if( strcmp(z,"sqlid")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        onlySqlid = integerValue(argv[++i]);
      }else
      if( strcmp(z,"timeout")==0 ){
        if( i>=argc-1 ) fatalError("missing arguments on %s", argv[i]);
        iTimeout = integerValue(argv[++i]);
      }else
      if( strcmp(z,"timeout-test")==0 ){
        timeoutTest = 1;
#ifndef __unix__
        fatalError("timeout is not available on non-unix systems");
#endif
      }else
      if( strcmp(z,"verbose")==0 || strcmp(z,"v")==0 ){
        quietFlag = 0;
        verboseFlag = 1;
        runFlags |= SQL_TRACE;
      }else
      {
        fatalError("unknown option: %s", argv[i]);
      }
    }else{
      nSrcDb++;
      azSrcDb = safe_realloc(azSrcDb, nSrcDb*sizeof(azSrcDb[0]));
      azSrcDb[nSrcDb-1] = argv[i];
    }
  }
  if( nSrcDb==0 ) fatalError("no source database specified");
  if( nSrcDb>1 ){
    if( zMsg ){
      fatalError("cannot change the description of more than one database");
    }
    if( zInsSql ){
      fatalError("cannot import into more than one database");
    }
  }

  /* Process each source database separately */
  for(iSrcDb=0; iSrcDb<nSrcDb; iSrcDb++){
    rc = sqlite3_open(azSrcDb[iSrcDb], &db);
    if( rc ){
      fatalError("cannot open source database %s - %s",
      azSrcDb[iSrcDb], sqlite3_errmsg(db));
    }
    rc = sqlite3_exec(db,
       "CREATE TABLE IF NOT EXISTS db(\n"
       "  dbid INTEGER PRIMARY KEY, -- database id\n"
       "  dbcontent BLOB            -- database disk file image\n"
       ");\n"
       "CREATE TABLE IF NOT EXISTS xsql(\n"
       "  sqlid INTEGER PRIMARY KEY,   -- SQL script id\n"
       "  sqltext TEXT                 -- Text of SQL statements to run\n"
       ");"
       "CREATE TABLE IF NOT EXISTS readme(\n"
       "  msg TEXT -- Human-readable description of this file\n"
       ");", 0, 0, 0);
    if( rc ) fatalError("cannot create schema: %s", sqlite3_errmsg(db));
    if( zMsg ){
      char *zSql;
      zSql = sqlite3_mprintf(
               "DELETE FROM readme; INSERT INTO readme(msg) VALUES(%Q)", zMsg);
      rc = sqlite3_exec(db, zSql, 0, 0, 0);
      sqlite3_free(zSql);
      if( rc ) fatalError("cannot change description: %s", sqlite3_errmsg(db));
    }
    if( zInsSql ){
      sqlite3_create_function(db, "readfile", 1, SQLITE_UTF8, 0,
                              readfileFunc, 0, 0);
      rc = sqlite3_prepare_v2(db, zInsSql, -1, &pStmt, 0);
      if( rc ) fatalError("cannot prepare statement [%s]: %s",
                          zInsSql, sqlite3_errmsg(db));
      rc = sqlite3_exec(db, "BEGIN", 0, 0, 0);
      if( rc ) fatalError("cannot start a transaction");
      for(i=iFirstInsArg; i<argc; i++){
        sqlite3_bind_text(pStmt, 1, argv[i], -1, SQLITE_STATIC);
        sqlite3_step(pStmt);
        rc = sqlite3_reset(pStmt);
        if( rc ) fatalError("insert failed for %s", argv[i]);
      }
      sqlite3_finalize(pStmt);
      rc = sqlite3_exec(db, "COMMIT", 0, 0, 0);
      if( rc ) fatalError("cannot commit the transaction: %s", sqlite3_errmsg(db));
      rebuild_database(db);
      sqlite3_close(db);
      return 0;
    }
    if( zExpDb!=0 || zExpSql!=0 ){
      sqlite3_create_function(db, "writefile", 2, SQLITE_UTF8, 0,
                              writefileFunc, 0, 0);
      if( zExpDb!=0 ){
        const char *zExDb = 
          "SELECT writefile(printf('%s/db%06d.db',?1,dbid),dbcontent),"
          "       dbid, printf('%s/db%06d.db',?1,dbid), length(dbcontent)"
          "  FROM db WHERE ?2<0 OR dbid=?2;";
        rc = sqlite3_prepare_v2(db, zExDb, -1, &pStmt, 0);
        if( rc ) fatalError("cannot prepare statement [%s]: %s",
                            zExDb, sqlite3_errmsg(db));
        sqlite3_bind_text64(pStmt, 1, zExpDb, strlen(zExpDb),
                            SQLITE_STATIC, SQLITE_UTF8);
        sqlite3_bind_int(pStmt, 2, onlyDbid);
        while( sqlite3_step(pStmt)==SQLITE_ROW ){
          printf("write db-%d (%d bytes) into %s\n",
             sqlite3_column_int(pStmt,1),
             sqlite3_column_int(pStmt,3),
             sqlite3_column_text(pStmt,2));
        }
        sqlite3_finalize(pStmt);
      }
      if( zExpSql!=0 ){
        const char *zExSql = 
          "SELECT writefile(printf('%s/sql%06d.txt',?1,sqlid),sqltext),"
          "       sqlid, printf('%s/sql%06d.txt',?1,sqlid), length(sqltext)"
          "  FROM xsql WHERE ?2<0 OR sqlid=?2;";
        rc = sqlite3_prepare_v2(db, zExSql, -1, &pStmt, 0);
        if( rc ) fatalError("cannot prepare statement [%s]: %s",
                            zExSql, sqlite3_errmsg(db));
        sqlite3_bind_text64(pStmt, 1, zExpSql, strlen(zExpSql),
                            SQLITE_STATIC, SQLITE_UTF8);
        sqlite3_bind_int(pStmt, 2, onlySqlid);
        while( sqlite3_step(pStmt)==SQLITE_ROW ){
          printf("write sql-%d (%d bytes) into %s\n",
             sqlite3_column_int(pStmt,1),
             sqlite3_column_int(pStmt,3),
             sqlite3_column_text(pStmt,2));
        }
        sqlite3_finalize(pStmt);
      }
      sqlite3_close(db);
      return 0;
    }
  
    /* Load all SQL script content and all initial database images from the
    ** source db
    */
    blobListLoadFromDb(db, "SELECT sqlid, sqltext FROM xsql", onlySqlid,
                           &g.nSql, &g.pFirstSql);
    if( g.nSql==0 ) fatalError("need at least one SQL script");
    blobListLoadFromDb(db, "SELECT dbid, dbcontent FROM db", onlyDbid,
                       &g.nDb, &g.pFirstDb);
    if( g.nDb==0 ){
      g.pFirstDb = safe_realloc(0, sizeof(Blob));
      memset(g.pFirstDb, 0, sizeof(Blob));
      g.pFirstDb->id = 1;
      g.pFirstDb->seq = 0;
      g.nDb = 1;
      sqlFuzz = 1;
    }
  
    /* Print the description, if there is one */
    if( !quietFlag ){
      int i;
      zDbName = azSrcDb[iSrcDb];
      i = strlen(zDbName) - 1;
      while( i>0 && zDbName[i-1]!='/' && zDbName[i-1]!='\\' ){ i--; }
      zDbName += i;
      sqlite3_prepare_v2(db, "SELECT msg FROM readme", -1, &pStmt, 0);
      if( pStmt && sqlite3_step(pStmt)==SQLITE_ROW ){
        printf("%s: %s\n", zDbName, sqlite3_column_text(pStmt,0));
      }
      sqlite3_finalize(pStmt);
    }

    /* Rebuild the database, if requested */
    if( rebuildFlag ){
      if( !quietFlag ){
        printf("%s: rebuilding... ", zDbName);
        fflush(stdout);
      }
      rebuild_database(db);
      if( !quietFlag ) printf("done\n");
    }
  
    /* Close the source database.  Verify that no SQLite memory allocations are
    ** outstanding.
    */
    sqlite3_close(db);
    if( sqlite3_memory_used()>0 ){
      fatalError("SQLite has memory in use before the start of testing");
    }

    /* Limit available memory, if requested */
    if( nMem>0 ){
      void *pHeap;
      sqlite3_shutdown();
      pHeap = malloc(nMem);
      if( pHeap==0 ){
        fatalError("failed to allocate %d bytes of heap memory", nMem);
      }
      sqlite3_config(SQLITE_CONFIG_HEAP, pHeap, nMem, 128);
    }
  
    /* Register the in-memory virtual filesystem
    */
    formatVfs();
    inmemVfsRegister();
    
    /* Run a test using each SQL script against each database.
    */
    if( !verboseFlag && !quietFlag ) printf("%s:", zDbName);
    for(pSql=g.pFirstSql; pSql; pSql=pSql->pNext){
      for(pDb=g.pFirstDb; pDb; pDb=pDb->pNext){
        int openFlags;
        const char *zVfs = "inmem";
        sqlite3_snprintf(sizeof(g.zTestName), g.zTestName, "sqlid=%d,dbid=%d",
                         pSql->id, pDb->id);
        if( verboseFlag ){
          printf("%s\n", g.zTestName);
          fflush(stdout);
        }else if( !quietFlag ){
          static int prevAmt = -1;
          int idx = pSql->seq*g.nDb + pDb->id - 1;
          int amt = idx*10/(g.nDb*g.nSql);
          if( amt!=prevAmt ){
            printf(" %d%%", amt*10);
            fflush(stdout);
            prevAmt = amt;
          }
        }
        createVFile("main.db", pDb->sz, pDb->a);
        openFlags = SQLITE_OPEN_CREATE | SQLITE_OPEN_READWRITE;
        if( nativeFlag && pDb->sz==0 ){
          openFlags |= SQLITE_OPEN_MEMORY;
          zVfs = 0;
        }
        rc = sqlite3_open_v2("main.db", &db, openFlags, zVfs);
        if( rc ) fatalError("cannot open inmem database");
#ifdef SQLITE_ENABLE_JSON1
        {
          extern int sqlite3_json_init(sqlite3*);
          sqlite3_json_init(db);
        }
#endif
        if( cellSzCkFlag ) runSql(db, "PRAGMA cell_size_check=ON", runFlags);
        setAlarm(iTimeout);
#ifndef SQLITE_OMIT_PROGRESS_CALLBACK
        if( sqlFuzz || vdbeLimitFlag ){
          sqlite3_progress_handler(db, 100000, progressHandler, &vdbeLimitFlag);
        }
#endif
        do{
          runSql(db, (char*)pSql->a, runFlags);
        }while( timeoutTest );
        setAlarm(0);
        sqlite3_close(db);
        if( sqlite3_memory_used()>0 ) fatalError("memory leak");
        reformatVfs();
        nTest++;
        g.zTestName[0] = 0;

        /* Simulate an error if the TEST_FAILURE environment variable is "5".
        ** This is used to verify that automated test script really do spot
        ** errors that occur in this test program.
        */
        if( zFailCode ){
          if( zFailCode[0]=='5' && zFailCode[1]==0 ){
            fatalError("simulated failure");
          }else if( zFailCode[0]!=0 ){
            /* If TEST_FAILURE is something other than 5, just exit the test
            ** early */
            printf("\nExit early due to TEST_FAILURE being set\n");
            iSrcDb = nSrcDb-1;
            goto sourcedb_cleanup;
          }
        }
      }
    }
    if( !quietFlag && !verboseFlag ){
      printf(" 100%% - %d tests\n", g.nDb*g.nSql);
    }
  
    /* Clean up at the end of processing a single source database
    */
  sourcedb_cleanup:
    blobListFree(g.pFirstSql);
    blobListFree(g.pFirstDb);
    reformatVfs();
 
  } /* End loop over all source databases */

  if( !quietFlag ){
    sqlite3_int64 iElapse = timeOfDay() - iBegin;
    printf("fuzzcheck: 0 errors out of %d tests in %d.%03d seconds\n"
           "SQLite %s %s\n",
           nTest, (int)(iElapse/1000), (int)(iElapse%1000),
           sqlite3_libversion(), sqlite3_sourceid());
  }
  free(azSrcDb);
  return 0;
}