예제 #1
0
int main (int argc, char** argv)
{
	int i;
	LIMdlBuilder* builder;
	LIMdlModel* model;

	if (!argc || !strcmp (argv[1], "--help") || !strcmp (argv[1], "-h"))
	{
		printf ("Usage: %s [lmdl...]\n", argv[0]);
		return 0;
	}

	for (i = 1 ; i < argc ; i++)
	{
		/* Load the model. */
		model = limdl_model_new_from_file (argv[i], 1);
		if (model == NULL)
		{
			lisys_error_report ();
			continue;
		}

		/* Check for existing LOD. */
		if (!model->lod.array[0].indices.count)
		{
			printf ("      Unneeded %s\n", argv[i]);
			continue;
		}
		if (model->lod.count > 1)
		{
			printf ("%3d%%: Existing %s\n", 100 - 100 *
				model->lod.array[model->lod.count - 1].indices.count /
				model->lod.array[0].indices.count, argv[i]);
			limdl_model_free (model);
			continue;
		}

		/* Build the detail levels. */
		builder = limdl_builder_new (model);
		if (builder == NULL)
		{
			lisys_error_report ();
			limdl_model_free (model);
			continue;
		}
		limdl_builder_calculate_lod (builder, 5, 0.05f);
		limdl_builder_finish (builder);
		limdl_builder_free (builder);

		/* Save the modified model. */
		printf ("%3d%%: Built    %s\n", 100 - 100 *
			model->lod.array[model->lod.count - 1].indices.count /
			model->lod.array[0].indices.count, argv[i]);
		limdl_model_write_file (model, argv[i]);
		limdl_model_free (model);
	}

	return 0;
}
예제 #2
0
static void Heightmap_new (LIScrArgs* args)
{
	int i;
	int size;
	float spacing;
	float scaling;
	LIExtHeightmap* heightmap;
	LIExtHeightmapModule* module;
	LIImgImage* image;
	LIMatVector position;
	LIScrData* data;

	/* Get arguments. */
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_HEIGHTMAP);
	if (!liscr_args_geti_vector (args, 0, &position))
		position = limat_vector_init (0.0f, 0.0f, 0.0f);
	if (!liscr_args_geti_int (args, 1, &size))
		size = 33;
	else if (size < 0)
		size = 0;
	if (!liscr_args_geti_float (args, 2, &spacing))
		spacing = 1.0f;
	else if (spacing <= 0.0f)
		spacing = 1.0f;
	if (!liscr_args_geti_float (args, 3, &scaling))
		scaling = 1.0f;
	else if (scaling <= 0.0f)
		scaling = 1.0f;
	if (liscr_args_geti_data (args, 4, LIEXT_SCRIPT_IMAGE, &data))
		image = liscr_data_get_data (data);
	else
		image = NULL;

	/* Ensure that the size is valid. */
	for (i = 32 ; i < 65536 ; i *= 2)
	{
		if (size == i + 1)
			break;
	}
	if (size != i + 1)
	{
		lisys_error_set (EINVAL, "invalid heightmap size");
		lisys_error_report ();
		return;
	}

	/* Allocate the heightmap. */
	heightmap = liext_heightmap_new (module, image, &position, size, spacing, scaling);
	if (heightmap == NULL)
		return;

	/* Allocate the userdata. */
	data = liscr_data_new (args->script, args->lua, heightmap, LIEXT_SCRIPT_HEIGHTMAP, liext_heightmap_free);
	if (data == NULL)
	{
		liext_heightmap_free (heightmap);
		return;
	}
	liscr_args_seti_stack (args);
}
예제 #3
0
static void Heightmap_add_texture_layer (LIScrArgs* args)
{
	float size;
	const char* name;
	const char* diffuse;
	const char* specular;
	const char* normal;
	const char* height;
	const char* blend;

	/* Get arguments. */
	if (!liscr_args_geti_float (args, 0, &size))
		size = 1.0f;
	if (!liscr_args_geti_string (args, 1, &name) ||
	    !liscr_args_geti_string (args, 2, &diffuse) ||
	    !liscr_args_geti_string (args, 3, &specular) ||
	    !liscr_args_geti_string (args, 4, &normal) ||
	    !liscr_args_geti_string (args, 5, &height))
		return;
	if (!liscr_args_geti_string (args, 6, &blend))
		blend = NULL;

	/* Create the layer. */
	if (!liext_heightmap_add_texture_layer (args->self, size, name, diffuse, specular, normal, height, blend))
		lisys_error_report ();
}
예제 #4
0
static void private_thread_main (
	LISysThread* thread,
	void*        data)
{
	LIExtThread* self = data;

	if (self->code != NULL)
	{
		if (!limai_program_execute_string (self->program, self->code))
			lisys_error_report ();
	}
	else
	{
		if (!limai_program_execute_script (self->program, self->file))
			lisys_error_report ();
	}
}
예제 #5
0
static void private_worker_thread (
	LISysAsyncCall* call,
	void*           data)
{
	LISndSample* self = data;

	if (lisys_path_check_ext (self->file, "flac"))
	{
		if (!private_load_flac (self, self->file))
			lisys_error_report ();
	}
	else if (lisys_path_check_ext (self->file, "ogg"))
	{
		if (!private_load_vorbis (self, self->file))
			lisys_error_report ();
	}
	self->loaded = 1;
}
예제 #6
0
/**
 * \brief Initializes the global video card information.
 * \return Nonzero on success.
 */
int livid_video_init ()
{
	int ver[3];
	GLenum error;
	const GLubyte* tmp;

	/* Initialize GLEW. */
	error = glewInit ();
	if (error != GLEW_OK)
	{
		lisys_error_set (LISYS_ERROR_UNKNOWN, "%s", glewGetErrorString (error));
		return 0;
	}

	/* Check for OpenGL 3.2 capabilities. */
	/* GLEW versions up to 1.5.3 had a bug that completely broke OpenGL 3.2
	   support. We try to detect it and warn the user of the problem. */
	if (GLEW_VERSION_3_2)
		return 1;
	tmp = glewGetString (GLEW_VERSION);
	if (sscanf ((const char*) tmp, "%d.%d.%d", ver, ver + 1, ver + 2) == 3 &&
	   (ver[0] < 1 || ver[1] < 5 || ver[2] <= 3))
	{
		lisys_error_set (EINVAL, "OpenGL 3.2 isn't supported because it requires GLEW 1.5.4 or newer while you have %s", tmp);
		lisys_error_report ();
	}
	else
	{
		lisys_error_set (EINVAL, "OpenGL 3.2 isn't supported by your graphics card or drivers");
		lisys_error_report ();
	}

	/* Check for OpenGL 2.1 capabilities. */
	if (GLEW_VERSION_2_1)
		return 1;
	lisys_error_set (EINVAL, "OpenGL 2.1 isn't supported by your graphics card or drivers");

	return 0;
}
예제 #7
0
static void Model_merge (LIScrArgs* args)
{
	LIScrData* data;
	LIEngModel* model1;
	LIEngModel* model2;

	if (liscr_args_geti_data (args, 0, LISCR_SCRIPT_MODEL, &data) ||
	    liscr_args_gets_data (args, "model", LISCR_SCRIPT_MODEL, &data))
	{
		model1 = args->self;
		model2 = liscr_data_get_data (data);
		if (!limdl_model_merge (model1->model, model2->model))
			lisys_error_report ();
	}
}
예제 #8
0
static void Lobby_upload_server_info (LIScrArgs* args)
{
#ifdef HAVE_CURL
	int port = 0;
	int players = 0;
	char* url;
	char* decoded;
	const char* desc = NULL;
	const char* master = NULL;
	const char* name = NULL;
	char error_buffer[CURL_ERROR_SIZE];
	CURL* curl;

	/* Get arguments. */
	if (!liscr_args_gets_string (args, "desc", &desc) ||
	    !liscr_args_gets_string (args, "master", &master) ||
	    !liscr_args_gets_string (args, "name", &name) ||
	    !liscr_args_gets_int (args, "players", &players) ||
	    !liscr_args_gets_int (args, "port", &port))
		return;
	players = LIMAT_CLAMP (players, 0, 256);
	port = LIMAT_CLAMP (port, 1, 65535);

	/* Format the script URL. */
	url = lisys_string_concat (master, "/lossrvapi.php");
	if (url == NULL)
		return;

	/* POST to the master server. */
	curl = curl_easy_init();
	if (curl != NULL)
	{
		decoded = lisys_string_format ("u=%d|%d|%s|%s", port, players, name, desc);
		curl_easy_setopt (curl, CURLOPT_URL, url);
		curl_easy_setopt (curl, CURLOPT_POSTFIELDS, decoded);
		curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, error_buffer);
		if (curl_easy_perform (curl))
		{
			lisys_error_set (EINVAL, "lobby: %s", error_buffer);
			lisys_error_report ();
		}
		curl_easy_cleanup (curl);
		lisys_free (decoded);
	}
	lisys_free (url);
#endif
}
예제 #9
0
static void Animation_load (LIScrArgs* args)
{
	char* file;
	const char* path;
	const char* name;
	LIMdlAnimation* self;
	LIExtAnimationModule* module;
	LIScrData* data;

	/* Get arguments. */
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_ANIMATION);
	if (!liscr_args_geti_string (args, 0, &name))
		return;

	/* Create the path. */
	file = lisys_string_concat (name, ".lani");
	if (file == NULL)
		return;
	path = lipth_paths_find_file (module->program->paths, file);
	lisys_free (file);
	if (path == NULL)
		return;

	/* Allocate the animation. */
	self = limdl_animation_new_from_file (path);
	if (self == NULL)
	{
		lisys_error_report ();
		return;
	}

	/* Allocate the userdata. */
	data = liscr_data_new (args->script, args->lua, self, LIEXT_SCRIPT_ANIMATION, limdl_animation_free);
	if (data == NULL)
	{
		limdl_animation_free (self);
		return;
	}
	liscr_args_seti_stack (args);
}
/**
 * \brief Creates a rendering framebuffer.
 * \param render Renderer.
 * \param width Framebuffer width.
 * \param height Framebuffer height.
 * \param samples Number of multisamples.
 * \param hdr Nonzero to use floating point framebuffer to enable HDR.
 * \return New deferred framebuffer or NULL.
 */
LIRenFramebuffer32* liren_framebuffer32_new (
    LIRenRender32* render,
    int            width,
    int            height,
    int            samples,
    int            hdr)
{
    LIRenFramebuffer32* self;

    /* Allocate self. */
    self = lisys_calloc (1, sizeof (LIRenFramebuffer32));
    if (self == NULL)
        return NULL;
    self->render = render;
    self->width = width;
    self->height = height;

    /* Create frame buffer object. */
    for ( ; samples > 0 ; samples--)
    {
        if (!liren_framebuffer32_resize (self, width, height, samples, hdr))
            lisys_error_report ();
        else
            break;
    }
    if (samples == 0)
    {
        liren_framebuffer32_free (self);
        return NULL;
    }

    /* Add to dictionary. */
    if (!lialg_ptrdic_insert (render->framebuffers, self, self))
    {
        liren_framebuffer32_free (self);
        return NULL;
    }

    return self;
}
예제 #11
0
static void Widgets_add_font_style (LIScrArgs* args)
{
	int size = 16;
	const char* file;
	const char* name;
	LIExtModule* module;

	/* Arguments. */
	if (!liscr_args_geti_string (args, 0, &name) &&
	    !liscr_args_gets_string (args, "name", &name))
		return;
	if (!liscr_args_geti_string (args, 1, &file) &&
	    !liscr_args_gets_string (args, "file", &file))
		return;
	if (!liscr_args_geti_int (args, 2, &size))
	    liscr_args_gets_int (args, "size", &size);

	/* Load the font. */
	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_WIDGETS);
	if (!liwdg_styles_load_font (module->widgets->styles, name, file, size))
		lisys_error_report ();
}
예제 #12
0
/**
 * \brief Prints the traceback to the terminal.
 *
 * This function is intended to be used for debugging. It helps with locating
 * crashes and other problems that involve Lua calling the C functions.
 *
 * \param lua Lua state.
 */
void liscr_traceback (
	lua_State* lua)
{
	/* Get debug table. */
	lua_getfield (lua, LUA_GLOBALSINDEX, "debug");
	if (lua_type (lua, -1) != LUA_TTABLE)
	{
		lisys_error_set (EINVAL, "invalid debug table");
		lua_pop (lua, 1);
		return;
	}

	/* Get traceback function. */
	lua_getfield (lua, -1, "traceback");
	lua_remove (lua, -2);
	if (lua_type (lua, -1) != LUA_TFUNCTION)
	{
		lisys_error_set (EINVAL, "invalid traceback function");
		lua_pop (lua, 1);
		return;
	}

	/* Call traceback excluding itself from the trace. */
	lua_pushstring (lua, "");
	lua_pushinteger (lua, 1);
	if (lua_pcall (lua, 2, 1, 0) != 0)
	{
		lisys_error_set (EINVAL, lua_tostring (lua, -1));
		lisys_error_report ();
		lua_pop (lua, 1);
		return;
	}

	/* Print the traceback to the terminal. */
	printf ("\nLua traceback:\n%s\n\n", lua_tostring (lua, -1));
	lua_pop (lua, 1);
}
예제 #13
0
int main (int argc, char** argv)
{
	char* path;
	char* launch_name;
	char* launch_args;
	LIMaiProgram* program;

	/* Resolve game directory. */
	path = lipth_paths_get_root ();
	if (path == NULL)
	{
		lisys_error_report ();
		return 1;
	}

	/* Parse command line arguments. */
	launch_name = "default";
	launch_args = NULL;
	if (!private_parse_arguments (argc, argv, &launch_name, &launch_args))
	{
		lisys_error_report ();
		lisys_free (path);
		return 1;
	}

	/* Start the program. */
	program = limai_program_new (path, launch_name, launch_args);
	lisys_free (launch_args);
	if (program == NULL)
	{
		lisys_error_report ();
		lisys_free (path);
		return 1;
	}

	/* Execute mods until one exits without starting a new one. */
	while (program != NULL)
	{
		/* Execute the module until the script exits. */
		if (!limai_program_execute_script (program, "main.lua"))
		{
			lisys_error_report ();
			break;
		}

		/* Check if the module started another one. */
		launch_name = program->launch_name;
		launch_args = program->launch_args;
		if (launch_name == NULL)
			break;
		program->launch_name = NULL;
		program->launch_args = NULL;
		limai_program_free (program);

		/* Unload the old module and load a new one. */
		program = limai_program_new (path, launch_name, launch_args);
		lisys_free (launch_name);
		lisys_free (launch_args);
		if (program == NULL)
		{
			lisys_error_report ();
			break;
		}
	}

	/* Free all resources. */
	limai_program_free (program);
	lisys_free (path);
	SDL_Quit ();

	return 0;
}
예제 #14
0
static void Lobby_download_server_list (LIScrArgs* args)
{
#ifdef HAVE_CURL
	int ret;
	int port = 0;
	int players = 0;
	char* url;
	char* desc;
	char* ip;
	char* name;
	const char* master;
	char error_buffer[CURL_ERROR_SIZE];
	LIArcReader* reader;
	LIArcWriter* writer;
	CURL* curl;

	/* Get arguments. */
	if (!liscr_args_gets_string (args, "master", &master))
		return;
	liscr_args_set_output (args, LISCR_ARGS_OUTPUT_TABLE_FORCE);

	/* Format the script URL. */
	url = lisys_string_concat (master, "/lossrvapi.php");
	if (url == NULL)
		return;

	/* GET from the master server. */
	curl = curl_easy_init();
	if (curl != NULL)
	{
		writer = liarc_writer_new ();
		curl_easy_setopt (curl, CURLOPT_URL, url);
		curl_easy_setopt (curl, CURLOPT_WRITEDATA, writer);
		curl_easy_setopt (curl, CURLOPT_WRITEFUNCTION, private_write);
		curl_easy_setopt (curl, CURLOPT_ERRORBUFFER, error_buffer);
		if (curl_easy_perform (curl))
		{
			lisys_error_set (EINVAL, "lobby: %s", error_buffer);
			lisys_error_report ();
			curl_easy_cleanup (curl);
			liarc_writer_free (writer);
			lisys_free (url);
			return;
		}
		curl_easy_cleanup (curl);
		liarc_writer_append_nul (writer);
		reader = liarc_reader_new (
			liarc_writer_get_buffer (writer),
			liarc_writer_get_length (writer));
		while (!liarc_reader_check_end (reader))
		{
			ip = NULL;
			name = NULL;
			desc = NULL;
			ret = liarc_reader_get_text (reader, "\t", &ip) &&
				liarc_reader_get_text_int (reader, &port) &&
				liarc_reader_skip_bytes (reader, 1) &&
				liarc_reader_get_text_int (reader, &players) &&
				liarc_reader_skip_bytes (reader, 1) &&
				liarc_reader_get_text (reader, "\t", &name) &&
				liarc_reader_get_text (reader, "\n", &desc);
			if (ret)
			{
				lua_newtable (args->lua);
				lua_pushstring (args->lua, ip);
				lua_setfield (args->lua, -2, "ip");
				lua_pushnumber (args->lua, port);
				lua_setfield (args->lua, -2, "port");
				lua_pushnumber (args->lua, players);
				lua_setfield (args->lua, -2, "players");
				lua_pushstring (args->lua, name);
				lua_setfield (args->lua, -2, "name");
				lua_pushstring (args->lua, desc);
				lua_setfield (args->lua, -2, "desc");
				liscr_args_seti_stack (args);
			}
			lisys_free (ip);
			lisys_free (name);
			lisys_free (desc);
			if (!ret)
				break;
		}
		liarc_reader_free (reader);
		liarc_writer_free (writer);
	}
	lisys_free (url);
#endif
}
예제 #15
0
static void Database_new (LIScrArgs* args)
{
	int ok;
	char* path;
	char* path1;
	const char* ptr;
	const char* name;
	sqlite3* sql;
	LIExtModule* module;
	LIScrData* data;

	module = liscr_script_get_userdata (args->script, LIEXT_SCRIPT_DATABASE);

	/* Get and validate the filename. */
	if (!liscr_args_geti_string (args, 0, &name) &&
	    !liscr_args_gets_string (args, "name", &name))
		return;
	for (ptr = name ; *ptr != '\0' ; ptr++)
	{
		if (*ptr >= 'a' && *ptr <= 'z') ok = 1;
		else if (*ptr >= 'A' && *ptr <= 'Z') ok = 1;
		else if (*ptr >= '0' && *ptr <= '9') ok = 1;
		else if (*ptr == '-') ok = 1;
		else if (*ptr == '_') ok = 1;
		else if (*ptr == '.') ok = 1;
		else ok = 0;
		if (!ok)
		{
			lisys_error_set (EINVAL, "invalid database name `%s'", name);
			lisys_error_report ();
			return;
		}
	}

	/* Format the path. */
	ptr = lipth_paths_create_file (module->program->paths, name, 0);
	if (ptr == NULL)
	{
		lisys_error_report ();
		return;
	}
	path = lisys_string_dup (ptr);
	if (path == NULL)
		return;

	/* Convert the path to UTF-8. */
	/* Unlike other file functions we use, SQLite requires the filename to
	   be in UTF-8 instead of the system locale. */
	path1 = lisys_string_convert_sys_to_utf8 (path);
	if (path1 != NULL)
	{
		lisys_free (path);
		path = path1;
	}

	/* Open database. */
	if (sqlite3_open_v2 (path, &sql, SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, NULL) != SQLITE_OK)
	{
		lisys_error_set (EINVAL, "sqlite: %s", sqlite3_errmsg (sql));
		lisys_error_report ();
		lisys_free (path);
		lisys_free (sql);
		return;
	}
	lisys_free (path);

	/* Allocate userdata. */
	data = liscr_data_new (args->script, args->lua, sql, LIEXT_SCRIPT_DATABASE, private_free_database);
	if (data == NULL)
	{
		sqlite3_close (sql);
		return;
	}
	liscr_args_seti_stack (args);
}
예제 #16
0
static void Database_query (LIScrArgs* args)
{
	int i;
	int col;
	int row;
	int ret;
	int size;
	const char* query;
	const char* str;
	sqlite3* self;
	LIArcPacket* packet;
	LIScrData* data;
	sqlite3_stmt* statement;

	self = args->self;
	if (!liscr_args_geti_string (args, 0, &query) &&
	    !liscr_args_gets_string (args, "query", &query))
		return;

	/* Create a statement. */
	if (sqlite3_prepare_v2 (self, query, -1, &statement, NULL) != SQLITE_OK)
	{
		lisys_error_set (EINVAL, "SQL prepare: %s", sqlite3_errmsg (self));
		lisys_error_report ();
		return;
	}

	/* Bind variables. */
	if (liscr_args_geti_table (args, 1) || liscr_args_gets_table (args, "bind"))
	{
		for (i = 1 ; i < sqlite3_bind_parameter_count (statement) + 1 ; i++)
		{
			/* We got a table that has the bound variables in fields matching
			   the indices of the bound variables. We can simply loop through
			   the table and use the binding index as the key. */
			lua_pushnumber (args->lua, i);
			lua_gettable (args->lua, -2);
			switch (lua_type (args->lua, -1))
			{
				/* Bind numbers as doubles. */
				case LUA_TNUMBER:
					if (sqlite3_bind_double (statement, i, lua_tonumber (args->lua, -1)) != SQLITE_OK)
					{
						lisys_error_set (EINVAL, "SQL bind: %s", sqlite3_errmsg (self));
						lisys_error_report ();
						sqlite3_finalize (statement);
						return;
					}
					break;

				/* Bind strings as text. */
				case LUA_TSTRING:
					if (sqlite3_bind_text (statement, i, lua_tostring (args->lua, -1), -1, SQLITE_TRANSIENT) != SQLITE_OK)
					{
						lisys_error_set (EINVAL, "SQL bind: %s", sqlite3_errmsg (self));
						lisys_error_report ();
						sqlite3_finalize (statement);
						return;
					}
					break;

				/* Bind packets as blobs. */
				case LUA_TUSERDATA:
					data = liscr_isdata (args->lua, -1, LISCR_SCRIPT_PACKET);
					if (data == NULL)
						break;
					packet = liscr_data_get_data (data);
					if (packet->writer != NULL)
					{
						if (sqlite3_bind_blob (statement, i, packet->writer->memory.buffer,
							packet->writer->memory.length, SQLITE_TRANSIENT) != SQLITE_OK)
						{
							lisys_error_set (EINVAL, "SQL bind: %s", sqlite3_errmsg (self));
							lisys_error_report ();
							sqlite3_finalize (statement);
							return;
						}
					}
					else
					{
						if (sqlite3_bind_blob (statement, i, packet->reader->buffer,
							packet->reader->length, SQLITE_TRANSIENT) != SQLITE_OK)
						{
							lisys_error_set (EINVAL, "SQL bind: %s", sqlite3_errmsg (self));
							lisys_error_report ();
							sqlite3_finalize (statement);
							return;
						}
					}
					break;

				/* Bind any other values as NULL. */
				default:
					if (sqlite3_bind_null (statement, i) != SQLITE_OK)
					{
						lisys_error_set (EINVAL, "SQL bind: %s", sqlite3_errmsg (self));
						lisys_error_report ();
						sqlite3_finalize (statement);
						return;
					}
					break;
			}
			lua_pop (args->lua, 1);
		}
		lua_pop (args->lua, 1);
	}

	/* Execute the statement and process results. */
	for (row = 0, ret = sqlite3_step (statement) ; ret != SQLITE_DONE ; ret = sqlite3_step (statement), row++)
	{
		/* Check for errors. */
		if (ret != SQLITE_ROW)
		{
			lisys_error_set (EINVAL, "SQL step: %s", sqlite3_errmsg (self));
			lisys_error_report ();
			sqlite3_finalize (statement);
			return;
		}
		if (!row)
			liscr_args_set_output (args, LISCR_ARGS_OUTPUT_TABLE_FORCE);

		/* Create a row table. */
		lua_newtable (args->lua);

		/* Push the columns to the table. */
		for (col = 0 ; col < sqlite3_column_count (statement) ; col++)
		{
			switch (sqlite3_column_type (statement, col))
			{
				case SQLITE_INTEGER:
					lua_pushnumber (args->lua, col + 1);
					lua_pushnumber (args->lua, sqlite3_column_int (statement, col));
					lua_settable (args->lua, -3);
					break;
				case SQLITE_FLOAT:
					lua_pushnumber (args->lua, col + 1);
					lua_pushnumber (args->lua, sqlite3_column_double (statement, col));
					lua_settable (args->lua, -3);
					break;
				case SQLITE_TEXT:
					str = (const char*) sqlite3_column_text (statement, col);
					size = sqlite3_column_bytes (statement, col);
					lua_pushnumber (args->lua, col + 1);
					if (size > 0 && str != NULL)
						lua_pushstring (args->lua, str);
					else
						lua_pushstring (args->lua, str);
					lua_settable (args->lua, -3);
					break;
				case SQLITE_BLOB:
					str = sqlite3_column_blob (statement, col);
					size = sqlite3_column_bytes (statement, col);
					packet = liarc_packet_new_readable (str, size);
					if (packet != NULL)
					{
						lua_pushnumber (args->lua, col + 1);
						data = liscr_data_new (args->script, args->lua, packet, LISCR_SCRIPT_PACKET, liarc_packet_free);
						if (data != NULL)
							lua_settable (args->lua, -3);
						else
						{
							lua_pop (args->lua, 1);
							liarc_packet_free (packet);
						}
					}
					break;
				case SQLITE_NULL:
					break;
				default:
					lisys_assert (0 && "invalid column type");
					break;
			}
		}

		/* Add the row to the return values. */
		liscr_args_seti_stack (args);
	}
	if (!row)
		liscr_args_set_output (args, LISCR_ARGS_OUTPUT_TABLE_FORCE);
	sqlite3_finalize (statement);
}