diff --git a/.gitignore b/.gitignore
index 3c4efe2..67d76f0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -258,4 +258,7 @@ paket-files/
# Python Tools for Visual Studio (PTVS)
__pycache__/
-*.pyc
\ No newline at end of file
+*.pyc
+
+# cmake folders
+cmake-build-debug
\ No newline at end of file
diff --git a/01_DCS/Mods/services/Perun/dll/ReadMe.txt b/01_DCS/Mods/services/Perun/dll/ReadMe.txt
new file mode 100644
index 0000000..4e26f29
--- /dev/null
+++ b/01_DCS/Mods/services/Perun/dll/ReadMe.txt
@@ -0,0 +1 @@
+Download and put the dll from https://github.com/szporwolik/perun/releases .
\ No newline at end of file
diff --git a/01_DCS/Mods/services/Perun/lua/perun_config.lua b/01_DCS/Mods/services/Perun/lua/perun_config.lua
new file mode 100644
index 0000000..af632f1
--- /dev/null
+++ b/01_DCS/Mods/services/Perun/lua/perun_config.lua
@@ -0,0 +1,26 @@
+-- Perun for DCS World https://github.com/szporwolik/perun -> DCS Hook config component
+local PerunConfig = {}
+
+-- ###################### SETTINGS - DO NOT MODIFY OUTSIDE THIS SECTION #############################
+-- Connection
+PerunConfig.TCPPerunHost = "localhost" -- (string) [default: "localhost"] IP adress of the Perun instance or "localhost"
+PerunConfig.TCPTargetPort = 48621 -- (int) [default: 48621] TCP port to send data to
+PerunConfig.Instance = 1 -- (int) [default: 1] Id number of instance (if multiple DCS instances are to run at the same PC)
+PerunConfig.RefreshStatus = 60 -- (int) [default: 60] Base refresh rate in seconds to send status update
+
+-- Mission Configuration
+PerunConfig.MissionStartNoDeathWindow = 300 -- (int) [default: 300] Number of secounds after mission start when death of the pilot will not go to statistics, shall avoid death penalty during spawning DCS bugs
+
+-- Localisation
+PerunConfig.MOTD_L1 = "[Perun] Welcome to our server !" -- (string) Message send to players connecting the server - Line 1
+PerunConfig.MOTD_L2 = "[Perun] Stats and event data integrated with Perun for DCS World" -- (string) Message send to players connecting the server - Line 2
+PerunConfig.ConnectionError_L1 = "[Perun] ERROR: Connection broken - contact server admin!" -- (string) Information to send to players when Perun connection is broken
+
+-- Misc
+PerunConfig.BroadcastPerunErrors = 1 -- (int) [0 (default),1] Value greater than 0 will broadcast chat message about missing connection to Perun
+
+-- Debug
+PerunConfig.DebugMode = 1 -- (int) [0 (default),1,2] Value greater than 0 will display Perun information in DCS log file, values: 1 - minimal verbose, 2 - all log information will be logged
+
+-- ###################### END OF SETTINGS - DO NOT MODIFY OUTSIDE THIS SECTION ######################
+return PerunConfig
diff --git a/01_DCS/Hooks/Perun.lua b/01_DCS/Scripts/Hooks/Perun-hook.lua
similarity index 100%
rename from 01_DCS/Hooks/Perun.lua
rename to 01_DCS/Scripts/Hooks/Perun-hook.lua
diff --git a/02_Windows_App/Perun_v1/00_Config/App.config b/02_Windows_App/Perun_v1/00_Config/App.config
index 7aeb785..cf4058e 100644
--- a/02_Windows_App/Perun_v1/00_Config/App.config
+++ b/02_Windows_App/Perun_v1/00_Config/App.config
@@ -35,35 +35,15 @@
False
-
+
+ 1
+
+
+ 1
+
+ 3306
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- False
-
-
- False
-
-
\ No newline at end of file
diff --git a/02_Windows_App/Perun_v1/01_Classes/DatabaseController.cs b/02_Windows_App/Perun_v1/01_Classes/DatabaseController.cs
index c2640a1..b82b003 100644
--- a/02_Windows_App/Perun_v1/01_Classes/DatabaseController.cs
+++ b/02_Windows_App/Perun_v1/01_Classes/DatabaseController.cs
@@ -5,125 +5,28 @@ using System;
public class DatabaseController
{
- public string DatabaseConnectionString; // MySQL connection string
- public MySqlConnection DatabaseConnection;
- public bool DatabaseStatus;
+ public string DatabaseConnectionString; // MySQL connection string
+ public MySqlConnection DatabaseConnection; // MySQL connection
+ public bool DatabaseStatus; // MySQL connections status
public int SendToMySql(string RawTCPFrame, bool CheckConnection = false)
{
// Main function to send data to mysql
+ string SQLQueryTxt = ""; // MySQL Query string
+ int ReturnValue = 1; // Default return value [1 for success]
+
+ // Below is used to check if we still have database connection
if (CheckConnection)
{
RawTCPFrame = "{\"type\": \"-1\"}";
}
- dynamic TCPFrame = JsonConvert.DeserializeObject(RawTCPFrame); // Deserialize raw data
- string TCPFrameType = TCPFrame.type;
- string TCPFrameTimestamp = TCPFrame.timestamp;
- string TCPFrameInstance = TCPFrame.instance;
- string TCPFramePayload;
- string SQLQueryTxt;
- int ReturnValue = 1;
-
- // Some frames may come without timestamp, use database currrent timestampe then
- if (TCPFrameTimestamp != null)
- {
- TCPFrameTimestamp = "'" + TCPFrameTimestamp + "'";
- }
- else
- {
- TCPFrameTimestamp = "CURRENT_TIMESTAMP()";
- }
-
- // Modify specific types
- if (TCPFrameType == "1")
- {
- TCPFrame.payload["v_win"] = "v" + Globals.VersionPerun; // Inject app version information
-
- // Pull DCS hook version
- Globals.VersionDCSHook = TCPFrame.payload.v_dcs_hook;
- }
-
- // Specific SQL per each frame type
- if (TCPFrameType == "50")
- {
- // Add entry to chat log
- SQLQueryTxt = "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_ucid`) SELECT '" + TCPFrame.payload.ucid + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataPlayers` where `pe_DataPlayers_ucid` = '" + TCPFrame.payload.ucid + "' );";
- SQLQueryTxt += "UPDATE `pe_DataPlayers` SET `pe_DataPlayers_updated` = " + TCPFrameTimestamp + ",`pe_DataPlayers_lastname`=@PAR_payload_player WHERE `pe_DataPlayers_ucid`='" + TCPFrame.payload.ucid + "' ;";
- SQLQueryTxt += "INSERT INTO `pe_DataMissionHashes` (`pe_DataMissionHashes_hash`,`pe_DataMissionHashes_instance`) SELECT '" + TCPFrame.payload.missionhash + "','" + TCPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataMissionHashes` where `pe_DataMissionHashes_hash` ='" + TCPFrame.payload.missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + ");";
- SQLQueryTxt += "UPDATE `pe_DataMissionHashes` SET `pe_DataMissionHashes_datetime` = " + TCPFrameTimestamp + " WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + " ;";
- SQLQueryTxt += "INSERT INTO `pe_LogChat` (`pe_LogChat_id`,`pe_LogChat_datetime`, `pe_LogChat_playerid`, `pe_LogChat_msg`, `pe_LogChat_all`,`pe_LogChat_missionhash_id`) VALUES (NULL,'" + TCPFrame.payload.datetime + "', (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + TCPFrame.payload.ucid + "'), @PAR_payload_msg, '" + TCPFrame.payload.all + "',(SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.missionhash + "'));";
- }
- else if (TCPFrameType == "51")
- {
- // Add entry to event log
- SQLQueryTxt = "INSERT INTO `pe_DataMissionHashes` (`pe_DataMissionHashes_hash`,`pe_DataMissionHashes_instance`) SELECT '" + TCPFrame.payload.log_missionhash + "','" + TCPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataMissionHashes` where `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.log_missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + ");";
- SQLQueryTxt += "UPDATE `pe_DataMissionHashes` SET `pe_DataMissionHashes_datetime` = " + TCPFrameTimestamp + " WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.log_missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + ";";
- SQLQueryTxt += "INSERT INTO `pe_LogEvent` (`pe_LogEvent_arg1`,`pe_LogEvent_arg2`,`pe_LogEvent_id`, `pe_LogEvent_datetime`, `pe_LogEvent_type`, `pe_LogEvent_content`,`pe_LogEvent_missionhash_id`) VALUES ('" + TCPFrame.payload.log_arg_1 + "','" + TCPFrame.payload.log_arg_2 + "', NULL, '" + TCPFrame.payload.log_datetime + "', '" + TCPFrame.payload.log_type + "', @PAR_log_content, (SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.log_missionhash + "'));";
- }
- else if (TCPFrameType == "52")
- {
- // Update user stats
- SQLQueryTxt = "INSERT INTO `pe_DataMissionHashes` (`pe_DataMissionHashes_hash`,`pe_DataMissionHashes_instance`) SELECT '" + TCPFrame.payload.stat_missionhash + "','" + TCPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataMissionHashes` where `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + ");";
- SQLQueryTxt += "UPDATE `pe_DataMissionHashes` SET `pe_DataMissionHashes_datetime` = " + TCPFrameTimestamp + " WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + " ;";
- SQLQueryTxt += "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_ucid`) SELECT '" + TCPFrame.payload.stat_ucid + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataPlayers` where `pe_DataPlayers_ucid` = '" + TCPFrame.payload.stat_ucid + "');";
- SQLQueryTxt += "UPDATE `pe_DataPlayers` SET `pe_DataPlayers_updated`=" + TCPFrameTimestamp + " WHERE `pe_DataPlayers_ucid`='" + TCPFrame.payload.stat_ucid + "';";
- SQLQueryTxt += "INSERT INTO `pe_DataTypes` (`pe_DataTypes_name`) SELECT '" + TCPFrame.payload.stat_data_type + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + TCPFrame.payload.stat_data_type + "');";
- SQLQueryTxt += "INSERT INTO `pe_LogStats` (`pe_LogStats_playerid`,`pe_LogStats_missionhash_id`,`pe_LogStats_typeid`) SELECT (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + TCPFrame.payload.stat_ucid + "'), (SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "'), (SELECT pe_DataTypes_id FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + TCPFrame.payload.stat_data_type + "') FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_LogStats` WHERE `pe_LogStats_missionhash_id`=(SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "') AND `pe_LogStats_playerid` = (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + TCPFrame.payload.stat_ucid + "') AND `pe_LogStats_typeid`= (SELECT pe_DataTypes_id FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + TCPFrame.payload.stat_data_type + "'));";
- SQLQueryTxt += "UPDATE `pe_LogStats` SET `ps_time`=" + TCPFrame.payload.stat_data_perun.ps_time + ",`pe_LogStats_seat`=" + TCPFrame.payload.stat_data_subslot + ",`pe_LogStats_masterslot`=" + TCPFrame.payload.stat_data_masterslot + ",`ps_kills_fortification`=" + TCPFrame.payload.stat_data_perun.ps_kills_fortification +",`ps_kills_artillery`=" + TCPFrame.payload.stat_data_perun.ps_kills_artillery + ",`ps_other_landings`=" + TCPFrame.payload.stat_data_perun.ps_other_landings + ",`ps_other_takeoffs`=" + TCPFrame.payload.stat_data_perun.ps_other_takeoffs + ",`ps_pvp`=" + TCPFrame.payload.stat_data_perun.ps_pvp + ",`ps_deaths`=" + TCPFrame.payload.stat_data_perun.ps_deaths + ",`ps_ejections`=" + TCPFrame.payload.stat_data_perun.ps_ejections + ",`ps_crashes`=" + TCPFrame.payload.stat_data_perun.ps_crashes + ",`ps_teamkills`=" + TCPFrame.payload.stat_data_perun.ps_teamkills + ",`ps_kills_planes`=" + TCPFrame.payload.stat_data_perun.ps_kills_planes + ",`ps_kills_helicopters`=" + TCPFrame.payload.stat_data_perun.ps_kills_helicopters + ",`ps_kills_air_defense`=" + TCPFrame.payload.stat_data_perun.ps_kills_air_defense + ",`ps_kills_armor`=" + TCPFrame.payload.stat_data_perun.ps_kills_armor + ",`ps_kills_unarmed`=" + TCPFrame.payload.stat_data_perun.ps_kills_unarmed + ",`ps_kills_infantry`=" + TCPFrame.payload.stat_data_perun.ps_kills_infantry + ",`ps_kills_ships`=" + TCPFrame.payload.stat_data_perun.ps_kills_ships + ",`ps_kills_other`=" + TCPFrame.payload.stat_data_perun.ps_kills_other + ",`ps_airfield_takeoffs`=" + TCPFrame.payload.stat_data_perun.ps_airfield_takeoffs + ",`ps_airfield_landings`=" + TCPFrame.payload.stat_data_perun.ps_airfield_landings + ",`ps_ship_takeoffs`=" + TCPFrame.payload.stat_data_perun.ps_ship_takeoffs + ",`ps_ship_landings`=" + TCPFrame.payload.stat_data_perun.ps_ship_landings + ",`ps_farp_takeoffs`=" + TCPFrame.payload.stat_data_perun.ps_farp_takeoffs + ",`ps_farp_landings`=" + TCPFrame.payload.stat_data_perun.ps_farp_landings + ", `pe_LogStats_datetime`='" + TCPFrame.payload.stat_datetime + "',`pe_LogStats_playerid` = (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + TCPFrame.payload.stat_ucid + "'),`pe_LogStats_missionhash_id`=(SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "') WHERE `pe_LogStats_missionhash_id`=(SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "') AND `pe_LogStats_playerid` = (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + TCPFrame.payload.stat_ucid + "') AND `pe_LogStats_typeid`=(SELECT pe_DataTypes_id FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + TCPFrame.payload.stat_data_type + "');";
- }
- else if (TCPFrameType == "53")
- {
- // User logged in to DCS server
-
- SQLQueryTxt = "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_ucid`) SELECT '" + TCPFrame.payload.login_ucid + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataPlayers` where pe_DataPlayers_ucid='" + TCPFrame.payload.login_ucid + "');";
- SQLQueryTxt += "UPDATE `pe_DataPlayers` SET pe_DataPlayers_lastip='" + TCPFrame.payload.login_ipaddr + "', pe_DataPlayers_lastname=@PAR_login_name,pe_DataPlayers_updated='" + TCPFrame.payload.login_datetime + "' WHERE `pe_DataPlayers_ucid`= '" + TCPFrame.payload.login_ucid + "';";
- SQLQueryTxt += "INSERT INTO `pe_LogLogins` (`pe_LogLogins_datetime`, `pe_LogLogins_playerid`, `pe_LogLogins_name`, `pe_LogLogins_ip`,`pe_LogLogins_instance`) VALUES ('" + TCPFrame.payload.login_datetime + "', (SELECT pe_DataPlayers_id from pe_DataPlayers WHERE pe_DataPlayers_ucid = '" + TCPFrame.payload.login_ucid + "'), @PAR_login_name, '" + TCPFrame.payload.login_ipaddr + "','" + TCPFrameInstance + "');";
- }
- else if (TCPFrameType == "-1")
- {
- // Keep alive message
- SQLQueryTxt = "SELECT `pe_Config_payload` FROM `pe_Config` WHERE `pe_Config_id` = 1;";
- }
- else
- {
- // General definition used for 1-10 type packets
-
-
- SQLQueryTxt = "INSERT INTO `pe_DataRaw` (`pe_dataraw_type`,`pe_dataraw_instance`) SELECT '" + TCPFrameType + "','" + TCPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataRaw` WHERE `pe_dataraw_type` = '" + TCPFrameType + "' AND `pe_dataraw_instance` = " + TCPFrameInstance + ");";
- SQLQueryTxt += "UPDATE `pe_DataRaw` SET `pe_dataraw_payload` = @PAR_TCPFramePayload, `pe_dataraw_updated`=" + TCPFrameTimestamp + " WHERE `pe_dataraw_type`=" + TCPFrameType + " AND `pe_dataraw_instance` = " + TCPFrameInstance + ";";
- }
-
- // Handling of special data (like parsing JSONs to DB)
- switch (Int32.Parse(TCPFrameType))
- {
- case 1:
- // General status information
- SQLQueryTxt += "INSERT INTO `pe_OnlineStatus` (`pe_OnlineStatus_instance`) SELECT '" + Int32.Parse(TCPFrameInstance) + "' FROM DUAL WHERE NOT EXISTS(SELECT * FROM `pe_OnlineStatus` WHERE `pe_OnlineStatus_instance` = '" + Int32.Parse(TCPFrameInstance) + "');";
- SQLQueryTxt += "UPDATE `pe_OnlineStatus` SET `pe_OnlineStatus_perunversion_winapp` = '" + TCPFrame.payload.v_win + "', `pe_OnlineStatus_perunversion_dcshook` ='" + TCPFrame.payload.v_dcs_hook + "' WHERE `pe_OnlineStatus_instance` = '" + Int32.Parse(TCPFrameInstance) + "' ;";
-
- break;
-
- case 2:
- // SRS Data
- SQLQueryTxt += "DELETE FROM pe_OnlinePlayers WHERE pe_OnlinePlayers_instance = " + Int32.Parse(TCPFrameInstance) +";";
-
- int player_count = 0;
- foreach (var record_player in TCPFrame.payload.players)
- {
- SQLQueryTxt += "INSERT INTO `pe_OnlinePlayers` (`pe_OnlinePlayers_id`, `pe_OnlinePlayers_instance`, `pe_OnlinePlayers_ping`, `pe_OnlinePlayers_side`, `pe_OnlinePlayers_slot`, `pe_OnlinePlayers_ucid`) VALUES ("+ record_player.id + ", '"+ Int32.Parse(TCPFrameInstance) + "', '" + record_player.ping + "', '" + record_player.side + "', '" + record_player.slot + "', '" + record_player.ucid + "');";
- player_count++;
- }
-
- //SQLQueryTxt += "DELETE FROM pe_OnlineStatus WHERE pe_OnlineStatus_instance = " + Int32.Parse(TCPFrameInstance) + ";";
- SQLQueryTxt += "INSERT INTO `pe_OnlineStatus` (`pe_OnlineStatus_instance`) SELECT '" + Int32.Parse(TCPFrameInstance) + "' FROM DUAL WHERE NOT EXISTS(SELECT * FROM `pe_OnlineStatus` WHERE `pe_OnlineStatus_instance` = '" + Int32.Parse(TCPFrameInstance) + "');";
- SQLQueryTxt += "UPDATE `pe_OnlineStatus` SET `pe_OnlineStatus_theatre` = '" + TCPFrame.payload.mission.theatre + "', `pe_OnlineStatus_name` = '" + TCPFrame.payload.mission.name + "' , `pe_OnlineStatus_pause` = '" + TCPFrame.payload.mission.pause + "', `pe_OnlineStatus_multiplayer` = '" + TCPFrame.payload.mission.multiplayer + "', `pe_OnlineStatus_realtime` = '" + TCPFrame.payload.mission.realtime + "', `pe_OnlineStatus_modeltime` = '" + TCPFrame.payload.mission.modeltime + "', `pe_OnlineStatus_players` = " + player_count + " WHERE `pe_OnlineStatus_instance` = '" + Int32.Parse(TCPFrameInstance) + "';";
-
- break;
-
- default:
- break;
- }
+ // Parse frame
+ dynamic TCPFrame = JsonConvert.DeserializeObject(RawTCPFrame); // Deserialize raw data
+ string TCPFrameType = TCPFrame.type; // Frame type
+ string TCPFrameTimestamp = (TCPFrame.timestamp != null) ? $"'{TCPFrame.timestamp}'" : "CURRENT_TIMESTAMP()"; // Frame timestamp (Some frames may come without timestamp, use database timestamp then)
+ string TCPFrameInstance = TCPFrame.instance; // Frame instance
+ string TCPFramePayload; // Frame payload (we will deserialise only for specific frame types)
// Connect to mysql and execute sql
try
@@ -135,90 +38,204 @@ public class DatabaseController
Console.WriteLine("Sending data to MySQL - Begin");
DatabaseConnection.Open();
DatabaseStatus = true;
- MySqlCommand DatabaseCommand = new MySqlCommand(SQLQueryTxt, DatabaseConnection);
+
+
+ string LogInfo = "";
+ int LogDirection = 1;
+ MySqlCommand DatabaseCommand = null;
- // Add parameters - prevent SQL injection
- if (TCPFrameType == "50")
+ // For frames 1 to 10 we will put those into data raw tables
+ if (Int32.Parse(TCPFrameType) >= 1 && Int32.Parse(TCPFrameType) <= 10)
{
- DatabaseCommand.Parameters.AddWithValue("@PAR_payload_player", TCPFrame.payload.player);
- DatabaseCommand.Parameters.AddWithValue("@PAR_payload_msg", TCPFrame.payload.msg);
- }
- else if (TCPFrameType == "51")
- {
- DatabaseCommand.Parameters.AddWithValue("@PAR_log_content", TCPFrame.payload.log_content);
- }
- else if (TCPFrameType == "53")
- {
- DatabaseCommand.Parameters.AddWithValue("@PAR_login_name", TCPFrame.payload.login_name);
- }
+ SQLQueryTxt = "INSERT INTO `pe_DataRaw` (`pe_dataraw_type`,`pe_dataraw_instance`) SELECT '" + TCPFrameType + "','" + TCPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataRaw` WHERE `pe_dataraw_type` = '" + TCPFrameType + "' AND `pe_dataraw_instance` = " + TCPFrameInstance + ");";
+ SQLQueryTxt += "UPDATE `pe_DataRaw` SET `pe_dataraw_payload` = @PAR_TCPFramePayload, `pe_dataraw_updated`=" + TCPFrameTimestamp + " WHERE `pe_dataraw_type`=" + TCPFrameType + " AND `pe_dataraw_instance` = " + TCPFrameInstance + ";";
+ }
else
{
- TCPFramePayload = JsonConvert.SerializeObject(TCPFrame.payload); // Deserialize payload
- DatabaseCommand.Parameters.AddWithValue("@PAR_TCPFramePayload", TCPFramePayload);
+ SQLQueryTxt = "";
}
+
+ switch (Int32.Parse(TCPFrameType))
+ {
+ case -1:
+ // Keep alive message
+ LogInfo = $"Reading MySQL config";
+ LogDirection = 3;
+
+ SQLQueryTxt = "SELECT `pe_Config_payload` FROM `pe_Config` WHERE `pe_Config_id` = 1;";
+
+ DatabaseCommand = new MySqlCommand(SQLQueryTxt, DatabaseConnection);
+ break;
+
+ case 1:
+ // General status information (diagnostic information)
+ LogInfo = $"Status data updated";
+
+ TCPFrame.payload.server["v_win"] = "v" + Globals.VersionPerun; // Inject app version information (for database)
+ Globals.VersionDCSHook = TCPFrame.payload.v_dcs_hook; // Pull DCS hook version (for app)
+
+ SQLQueryTxt += "INSERT INTO `pe_OnlineStatus` (`pe_OnlineStatus_instance`) SELECT @PAR_TCPFrameInstance FROM DUAL WHERE NOT EXISTS(SELECT * FROM `pe_OnlineStatus` WHERE `pe_OnlineStatus_instance` = @PAR_TCPFrameInstance);";
+ SQLQueryTxt += "UPDATE `pe_OnlineStatus` SET `pe_OnlineStatus_perunversion_winapp` = '" + TCPFrame.payload.server.v_win + "', `pe_OnlineStatus_perunversion_dcshook` ='" + TCPFrame.payload.server.v_dcs_hook + "' WHERE `pe_OnlineStatus_instance` = @PAR_TCPFrameInstance ;";
+ SQLQueryTxt += "DELETE FROM pe_OnlinePlayers WHERE pe_OnlinePlayers_instance = @PAR_TCPFrameInstance;";
+
+ int player_count = 0;
+ foreach (var record_player in TCPFrame.payload.clients)
+ {
+ SQLQueryTxt += "INSERT INTO `pe_OnlinePlayers` (`pe_OnlinePlayers_id`, `pe_OnlinePlayers_instance`, `pe_OnlinePlayers_ping`, `pe_OnlinePlayers_side`, `pe_OnlinePlayers_slot`, `pe_OnlinePlayers_ucid`, `pe_OnlinePlayers_name`) VALUES (" + record_player.id + ", @PAR_TCPFrameInstance, '" + record_player.ping + "', '" + record_player.side + "', '" + record_player.slot + "', '" + record_player.ucid + $"',@PAR_UserName_{player_count});";
+ player_count++;
+ Globals.CurrentMission.PlayerCount = player_count; // Save information for GUI - player count
+ }
+ SQLQueryTxt += "INSERT INTO `pe_OnlineStatus` (`pe_OnlineStatus_instance`) SELECT @PAR_TCPFrameInstance FROM DUAL WHERE NOT EXISTS(SELECT * FROM `pe_OnlineStatus` WHERE `pe_OnlineStatus_instance` = @PAR_TCPFrameInstance);";
+ SQLQueryTxt += "UPDATE `pe_OnlineStatus` SET `pe_OnlineStatus_mission_theatre` = @PAR_MissionTheathre, `pe_OnlineStatus_mission_name` = @PAR_MissionName , `pe_OnlineStatus_server_pause` = @PAR_MissionPause, `pe_OnlineStatus_mission_multiplayer` = '" + TCPFrame.payload.mission.multiplayer + "', `pe_OnlineStatus_server_realtime` = '" + TCPFrame.payload.mission.realtime + "', `pe_OnlineStatus_mission_modeltime` = '" + TCPFrame.payload.mission.modeltime + "', `pe_OnlineStatus_server_players` = " + player_count + " WHERE `pe_OnlineStatus_instance` = @PAR_TCPFrameInstance;";
+
+ DatabaseCommand = new MySqlCommand(SQLQueryTxt, DatabaseConnection);
+ TCPFramePayload = JsonConvert.SerializeObject(TCPFrame.payload); // Deserialize payload TUTAJ DODAC CATCH TBD
+ DatabaseCommand.Parameters.AddWithValue("@PAR_TCPFramePayload", TCPFramePayload);
+ DatabaseCommand.Parameters.AddWithValue("@PAR_TCPFrameInstance", TCPFrameInstance);
+ DatabaseCommand.Parameters.AddWithValue("@PAR_MissionName", TCPFrame.payload.mission.name);
+ DatabaseCommand.Parameters.AddWithValue("@PAR_MissionTheathre", TCPFrame.payload.mission.theatre);
+ DatabaseCommand.Parameters.AddWithValue("@PAR_MissionPause", TCPFrame.payload.mission.pause);
+
+ player_count = 0;
+ foreach (var record_player in TCPFrame.payload.clients)
+ {
+ DatabaseCommand.Parameters.AddWithValue($"@PAR_UserName_{player_count}", TCPFrame.payload.clients[player_count].name);
+ player_count++;
+ }
+
+ // Save for GUI
+ Globals.CurrentMission.Theatre = TCPFrame.payload.mission.theatre; // Mission theatre
+ Globals.CurrentMission.Mission = TCPFrame.payload.mission.name; // Mission name
+ Globals.CurrentMission.Pause = TCPFrame.payload.mission.pause; // Mission pause
+
+ Globals.CurrentMission.ModelTime = TCPFrame.payload.mission.modeltime; // Mission time
+ Globals.CurrentMission.RealTime = TCPFrame.payload.mission.realtime; // Since start of server
+ break;
+
+ case 2:
+ // Slots Data (basic mission etc)
+ LogInfo = $"Slots data updated";
+
+ DatabaseCommand = new MySqlCommand(SQLQueryTxt, DatabaseConnection);
+ TCPFramePayload = JsonConvert.SerializeObject(TCPFrame.payload); // Deserialize payload
+ DatabaseCommand.Parameters.AddWithValue("@PAR_TCPFramePayload", TCPFramePayload);
+
+ break;
+ case 50:
+ // Chat entry
+ LogInfo = $"Player \"{TCPFrame.payload.player}\" -> chat message saved";
+
+ SQLQueryTxt = "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_ucid`) SELECT '" + TCPFrame.payload.ucid + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataPlayers` where `pe_DataPlayers_ucid` = '" + TCPFrame.payload.ucid + "' );";
+ SQLQueryTxt += "UPDATE `pe_DataPlayers` SET `pe_DataPlayers_updated` = " + TCPFrameTimestamp + ",`pe_DataPlayers_lastname`=@PAR_payload_player WHERE `pe_DataPlayers_ucid`='" + TCPFrame.payload.ucid + "' ;";
+ SQLQueryTxt += "INSERT INTO `pe_DataMissionHashes` (`pe_DataMissionHashes_hash`,`pe_DataMissionHashes_instance`) SELECT '" + TCPFrame.payload.missionhash + "','" + TCPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataMissionHashes` where `pe_DataMissionHashes_hash` ='" + TCPFrame.payload.missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + ");";
+ SQLQueryTxt += "UPDATE `pe_DataMissionHashes` SET `pe_DataMissionHashes_datetime` = " + TCPFrameTimestamp + " WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + " ;";
+ SQLQueryTxt += "INSERT INTO `pe_LogChat` (`pe_LogChat_id`,`pe_LogChat_datetime`, `pe_LogChat_playerid`, `pe_LogChat_msg`, `pe_LogChat_all`,`pe_LogChat_missionhash_id`) VALUES (NULL,'" + TCPFrame.payload.datetime + "', (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + TCPFrame.payload.ucid + "'), @PAR_payload_msg, '" + TCPFrame.payload.all + "',(SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.missionhash + "'));";
+
+ DatabaseCommand = new MySqlCommand(SQLQueryTxt, DatabaseConnection);
+
+ DatabaseCommand.Parameters.AddWithValue("@PAR_payload_player", TCPFrame.payload.player);
+ DatabaseCommand.Parameters.AddWithValue("@PAR_payload_msg", TCPFrame.payload.msg);
+
+ break;
+
+ case 51:
+ // Add entry to event log
+ LogInfo = $"Game event \"{TCPFrame.payload.log_content}\" -> saved";
+
+ SQLQueryTxt = "INSERT INTO `pe_DataMissionHashes` (`pe_DataMissionHashes_hash`,`pe_DataMissionHashes_instance`) SELECT '" + TCPFrame.payload.log_missionhash + "','" + TCPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataMissionHashes` where `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.log_missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + ");";
+ SQLQueryTxt += "UPDATE `pe_DataMissionHashes` SET `pe_DataMissionHashes_datetime` = " + TCPFrameTimestamp + " WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.log_missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + ";";
+ SQLQueryTxt += "INSERT INTO `pe_LogEvent` (`pe_LogEvent_arg1`,`pe_LogEvent_arg2`,`pe_LogEvent_id`, `pe_LogEvent_datetime`, `pe_LogEvent_type`, `pe_LogEvent_content`,`pe_LogEvent_missionhash_id`) VALUES ('" + TCPFrame.payload.log_arg_1 + "','" + TCPFrame.payload.log_arg_2 + "', NULL, '" + TCPFrame.payload.log_datetime + "', '" + TCPFrame.payload.log_type + "', @PAR_log_content, (SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.log_missionhash + "'));";
+
+ DatabaseCommand = new MySqlCommand(SQLQueryTxt, DatabaseConnection);
+
+ DatabaseCommand.Parameters.AddWithValue("@PAR_log_content", TCPFrame.payload.log_content);
+
+ break;
+
+ case 52:
+ // Update user stats
+ LogInfo = $"Player \"{TCPFrame.payload.stat_name}\" -> stats updated";
+
+ SQLQueryTxt = "INSERT INTO `pe_DataMissionHashes` (`pe_DataMissionHashes_hash`,`pe_DataMissionHashes_instance`) SELECT '" + TCPFrame.payload.stat_missionhash + "','" + TCPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataMissionHashes` where `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + ");";
+ SQLQueryTxt += "UPDATE `pe_DataMissionHashes` SET `pe_DataMissionHashes_datetime` = " + TCPFrameTimestamp + " WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "' AND `pe_DataMissionHashes_instance`=" + TCPFrameInstance + " ;";
+ SQLQueryTxt += "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_ucid`) SELECT '" + TCPFrame.payload.stat_ucid + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataPlayers` where `pe_DataPlayers_ucid` = '" + TCPFrame.payload.stat_ucid + "');";
+ SQLQueryTxt += "UPDATE `pe_DataPlayers` SET `pe_DataPlayers_updated`=" + TCPFrameTimestamp + " WHERE `pe_DataPlayers_ucid`='" + TCPFrame.payload.stat_ucid + "';";
+ SQLQueryTxt += "INSERT INTO `pe_DataTypes` (`pe_DataTypes_name`) SELECT '" + TCPFrame.payload.stat_data_type + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + TCPFrame.payload.stat_data_type + "');";
+ SQLQueryTxt += "INSERT INTO `pe_LogStats` (`pe_LogStats_playerid`,`pe_LogStats_missionhash_id`,`pe_LogStats_typeid`) SELECT (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + TCPFrame.payload.stat_ucid + "'), (SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "'), (SELECT pe_DataTypes_id FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + TCPFrame.payload.stat_data_type + "') FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_LogStats` WHERE `pe_LogStats_missionhash_id`=(SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "') AND `pe_LogStats_playerid` = (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + TCPFrame.payload.stat_ucid + "') AND `pe_LogStats_typeid`= (SELECT pe_DataTypes_id FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + TCPFrame.payload.stat_data_type + "'));";
+ SQLQueryTxt += "UPDATE `pe_LogStats` SET `ps_time`=" + TCPFrame.payload.stat_data_perun.ps_time + ",`pe_LogStats_seat`=" + TCPFrame.payload.stat_data_subslot + ",`pe_LogStats_masterslot`=" + TCPFrame.payload.stat_data_masterslot + ",`ps_kills_fortification`=" + TCPFrame.payload.stat_data_perun.ps_kills_fortification + ",`ps_kills_artillery`=" + TCPFrame.payload.stat_data_perun.ps_kills_artillery + ",`ps_other_landings`=" + TCPFrame.payload.stat_data_perun.ps_other_landings + ",`ps_other_takeoffs`=" + TCPFrame.payload.stat_data_perun.ps_other_takeoffs + ",`ps_pvp`=" + TCPFrame.payload.stat_data_perun.ps_pvp + ",`ps_deaths`=" + TCPFrame.payload.stat_data_perun.ps_deaths + ",`ps_ejections`=" + TCPFrame.payload.stat_data_perun.ps_ejections + ",`ps_crashes`=" + TCPFrame.payload.stat_data_perun.ps_crashes + ",`ps_teamkills`=" + TCPFrame.payload.stat_data_perun.ps_teamkills + ",`ps_kills_planes`=" + TCPFrame.payload.stat_data_perun.ps_kills_planes + ",`ps_kills_helicopters`=" + TCPFrame.payload.stat_data_perun.ps_kills_helicopters + ",`ps_kills_air_defense`=" + TCPFrame.payload.stat_data_perun.ps_kills_air_defense + ",`ps_kills_armor`=" + TCPFrame.payload.stat_data_perun.ps_kills_armor + ",`ps_kills_unarmed`=" + TCPFrame.payload.stat_data_perun.ps_kills_unarmed + ",`ps_kills_infantry`=" + TCPFrame.payload.stat_data_perun.ps_kills_infantry + ",`ps_kills_ships`=" + TCPFrame.payload.stat_data_perun.ps_kills_ships + ",`ps_kills_other`=" + TCPFrame.payload.stat_data_perun.ps_kills_other + ",`ps_airfield_takeoffs`=" + TCPFrame.payload.stat_data_perun.ps_airfield_takeoffs + ",`ps_airfield_landings`=" + TCPFrame.payload.stat_data_perun.ps_airfield_landings + ",`ps_ship_takeoffs`=" + TCPFrame.payload.stat_data_perun.ps_ship_takeoffs + ",`ps_ship_landings`=" + TCPFrame.payload.stat_data_perun.ps_ship_landings + ",`ps_farp_takeoffs`=" + TCPFrame.payload.stat_data_perun.ps_farp_takeoffs + ",`ps_farp_landings`=" + TCPFrame.payload.stat_data_perun.ps_farp_landings + ", `pe_LogStats_datetime`='" + TCPFrame.payload.stat_datetime + "',`pe_LogStats_playerid` = (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + TCPFrame.payload.stat_ucid + "'),`pe_LogStats_missionhash_id`=(SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "') WHERE `pe_LogStats_missionhash_id`=(SELECT `pe_DataMissionHashes_id` FROM `pe_DataMissionHashes` WHERE `pe_DataMissionHashes_hash` = '" + TCPFrame.payload.stat_missionhash + "') AND `pe_LogStats_playerid` = (SELECT `pe_DataPlayers_id` from `pe_DataPlayers` WHERE `pe_DataPlayers_ucid` = '" + TCPFrame.payload.stat_ucid + "') AND `pe_LogStats_typeid`=(SELECT pe_DataTypes_id FROM `pe_DataTypes` where `pe_DataTypes_name` = '" + TCPFrame.payload.stat_data_type + "');";
+
+ DatabaseCommand = new MySqlCommand(SQLQueryTxt, DatabaseConnection);
+
+ break;
+
+ case 53:
+ // User logged in to DCS server
+ LogInfo = $"Player \"{TCPFrame.payload.login_name}\" -> logged in";
+
+ SQLQueryTxt = "INSERT INTO `pe_DataPlayers` (`pe_DataPlayers_ucid`) SELECT '" + TCPFrame.payload.login_ucid + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataPlayers` where pe_DataPlayers_ucid='" + TCPFrame.payload.login_ucid + "');";
+ SQLQueryTxt += "UPDATE `pe_DataPlayers` SET pe_DataPlayers_lastip='" + TCPFrame.payload.login_ipaddr + "', pe_DataPlayers_lastname=@PAR_login_name,pe_DataPlayers_updated='" + TCPFrame.payload.login_datetime + "' WHERE `pe_DataPlayers_ucid`= '" + TCPFrame.payload.login_ucid + "';";
+ SQLQueryTxt += "INSERT INTO `pe_LogLogins` (`pe_LogLogins_datetime`, `pe_LogLogins_playerid`, `pe_LogLogins_name`, `pe_LogLogins_ip`,`pe_LogLogins_instance`) VALUES ('" + TCPFrame.payload.login_datetime + "', (SELECT pe_DataPlayers_id from pe_DataPlayers WHERE pe_DataPlayers_ucid = '" + TCPFrame.payload.login_ucid + "'), @PAR_login_name, '" + TCPFrame.payload.login_ipaddr + "','" + TCPFrameInstance + "');";
+
+ DatabaseCommand = new MySqlCommand(SQLQueryTxt, DatabaseConnection);
+
+ DatabaseCommand.Parameters.AddWithValue("@PAR_login_name", TCPFrame.payload.login_name);
+
+ break;
+
+ default:
+ // General definition used for other packets
+
+ // Switch to insert correct log information
+ switch (Int32.Parse(TCPFrameType))
+ {
+ case 3:
+ LogInfo = "Mission data updated";
+ break;
+ case 100:
+ LogInfo = "DCS SRS data updated";
+ break;
+ case 101:
+ LogInfo = "LotATC data updated";
+ break;
+ default:
+ LogInfo = "Unknown data updated";
+ break;
+ }
+
+ SQLQueryTxt = "INSERT INTO `pe_DataRaw` (`pe_dataraw_type`,`pe_dataraw_instance`) SELECT '" + TCPFrameType + "','" + TCPFrameInstance + "' FROM DUAL WHERE NOT EXISTS (SELECT * FROM `pe_DataRaw` WHERE `pe_dataraw_type` = '" + TCPFrameType + "' AND `pe_dataraw_instance` = " + TCPFrameInstance + ");";
+ SQLQueryTxt += "UPDATE `pe_DataRaw` SET `pe_dataraw_payload` = @PAR_TCPFramePayload, `pe_dataraw_updated`=" + TCPFrameTimestamp + " WHERE `pe_dataraw_type`=" + TCPFrameType + " AND `pe_dataraw_instance` = " + TCPFrameInstance + ";";
+
+ DatabaseCommand = new MySqlCommand(SQLQueryTxt, DatabaseConnection);
+
+ TCPFramePayload = JsonConvert.SerializeObject(TCPFrame.payload); // Deserialize payload
+ DatabaseCommand.Parameters.AddWithValue("@PAR_TCPFramePayload", TCPFramePayload);
+
+ break;
+ }
+
// End of add parameters
+ MySqlDataReader DatabaseReader = DatabaseCommand.ExecuteReader();
+ PerunHelper.LogDebug(ref Globals.AppLogHistory, LogInfo, LogDirection, 0, TCPFrameType);
- MySqlDataReader DatabaseReader = DatabaseCommand.ExecuteReader();
-
+ // Handle reading from database
if (DatabaseReader.HasRows)
{
while (DatabaseReader.Read())
{
+ PerunHelper.LogDebug(ref Globals.AppLogHistory, $"Received MySQL response, fields: {DatabaseReader.FieldCount}", 2, 0, TCPFrameType);
if (TCPFrameType == "-1")
{
- Globals.VersionDatabase= DatabaseReader.GetString(0);
+ Globals.VersionDatabase = DatabaseReader.GetString(0);
}
}
}
- else
- {
- // Do nothing
- }
-
DatabaseReader.Close();
-
- switch (Int32.Parse(TCPFrameType))
- {
- case 1:
- PerunHelper.AddLog(ref Globals.AppLogHistory, "Connected players: " + TCPFrame.payload["c_players"], 1,0,"1");
- break;
- case 2:
- PerunHelper.AddLog(ref Globals.AppLogHistory, "Mission: \"" + TCPFrame.payload["mission"]["name"]+"\""+ ", time:" + TCPFrame.payload["mission"]["modeltime"], 1, 0, "2");
- break;
- case 3:
- PerunHelper.AddLog(ref Globals.AppLogHistory, "Slots data updated", 1, 0, "3");
- break;
- case 50:
- PerunHelper.AddLog(ref Globals.AppLogHistory, "Player's \""+ TCPFrame.payload.player + "\" chat message saved", 1, 0, "50");
- break;
- case 51:
- PerunHelper.AddLog(ref Globals.AppLogHistory, "Game event: \""+ TCPFrame.payload.log_content +"\"", 1, 0, "51");
- break;
- case 52:
- PerunHelper.AddLog(ref Globals.AppLogHistory, "Player's \""+ TCPFrame.payload.stat_name + "\" stats saved", 1, 0, "52");
- break;
- case 53:
- PerunHelper.AddLog(ref Globals.AppLogHistory, "Player \""+ TCPFrame.payload.login_name + "\" logged in", 1, 0, "53");
- break;
- case 100:
- PerunHelper.AddLog(ref Globals.AppLogHistory, "SRS data send", 1,0,"100");
- break;
- case 101:
- PerunHelper.AddLog(ref Globals.AppLogHistory, "LotATC data send", 1,0,"101");
- break;
- case -1:
- break;
- default:
- PerunHelper.AddLog(ref Globals.AppLogHistory, "Data send", 1,0, TCPFrameType);
- break;
- }
-
}
catch (ArgumentException a_ex)
{
// General exception found
Console.WriteLine(a_ex.ToString());
- PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - error: " + a_ex.Message,1,1, TCPFrameType);
+ PerunHelper.LogError(ref Globals.AppLogHistory, $"ERROR MySQL - error: {a_ex.Message}", 1, 1, TCPFrameType);
Globals.ErrorsGame++;
DatabaseStatus = false;
ReturnValue = 0;
@@ -228,39 +245,49 @@ public class DatabaseController
// MySQL exception found
switch (m_ex.Number)
{
- case 1042: // Unable to connect to any of the specified MySQL hosts (Check Server,Port)
- PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - unable to connect, error: " + m_ex.Message,1,1, TCPFrameType);
+ case 0: // Access denied (Check DB name,username,password)
+ PerunHelper.LogError(ref Globals.AppLogHistory, $"ERROR MySQL - access denied, error: {m_ex.Message}", 1, 1, TCPFrameType);
DatabaseStatus = false;
ReturnValue = 0;
break;
- case 0: // Access denied (Check DB name,username,password)
- PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - access denied, error: " + m_ex.Message,1,1, TCPFrameType);
+ case 1042: // Unable to connect to any of the specified MySQL hosts (Check Server,Port)
+ PerunHelper.LogError(ref Globals.AppLogHistory, $"ERROR MySQL - unable to connect, error: {m_ex.Message}", 1, 1, TCPFrameType);
DatabaseStatus = false;
ReturnValue = 0;
break;
case 1064: // Incorrect query
- PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - query: " + SQLQueryTxt, 1, 1, TCPFrameType);
- PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - error: " + m_ex.Message, 1, 1, TCPFrameType);
+ PerunHelper.LogError(ref Globals.AppLogHistory, $"ERROR MySQL - query: {SQLQueryTxt}", 1, 1, TCPFrameType);
+ PerunHelper.LogError(ref Globals.AppLogHistory, $"ERROR MySQL - error: {m_ex.Message}", 1, 1, TCPFrameType);
DatabaseStatus = true; // True as connection is not broken
ReturnValue = 1; // Return a value to remove this query from quae
break;
- default:
- PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - error id: " + m_ex.Number,1,1, TCPFrameType);
- PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - query: " + SQLQueryTxt, 1, 1, TCPFrameType);
- PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - error: " + m_ex.Message,1,1, TCPFrameType);
+ default: // Default error handler
+ PerunHelper.LogError(ref Globals.AppLogHistory, $"ERROR MySQL - error id: {m_ex.Number}", 1, 1, TCPFrameType);
+ PerunHelper.LogError(ref Globals.AppLogHistory, $"ERROR MySQL - query: {SQLQueryTxt}", 1, 1, TCPFrameType);
+ PerunHelper.LogError(ref Globals.AppLogHistory, $"ERROR MySQL - error: {m_ex.Message}", 1, 1, TCPFrameType);
DatabaseStatus = false;
ReturnValue = 0;
break;
}
Globals.ErrorsGame++;
-
+
+ }
+ catch (Exception e)
+ {
+ // General exception found
+ Console.WriteLine(e.ToString());
+ PerunHelper.LogError(ref Globals.AppLogHistory, $"ERROR General - error: {e.Message}", 1, 1, TCPFrameType);
+ Globals.ErrorsGame++;
+ DatabaseStatus = false;
+ ReturnValue = 0;
}
DatabaseConnection.Close();
Console.WriteLine("Sending data to MySQL - Done");
}
catch (ArgumentException x_ex)
{
- PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR MySQL - unable to connect, error: " + x_ex.Message,1,1, TCPFrameType);
+ // MySQL connection error
+ PerunHelper.LogError(ref Globals.AppLogHistory, $"ERROR MySQL - unable to connect, error: {x_ex.Message}",1,1, TCPFrameType);
ReturnValue = 0;
Globals.ErrorsGame++;
}
diff --git a/02_Windows_App/Perun_v1/01_Classes/Globals.cs b/02_Windows_App/Perun_v1/01_Classes/Globals.cs
index 1dcab73..d04a588 100644
--- a/02_Windows_App/Perun_v1/01_Classes/Globals.cs
+++ b/02_Windows_App/Perun_v1/01_Classes/Globals.cs
@@ -1,4 +1,56 @@
-// This class gathers all global variable
+using System;
+using System.Diagnostics;
+using System.Management;
+
+// Class to hold all global information
+
+class HardwareMonitorClass
+{
+ // Class for HW monitoring
+ protected PerformanceCounter PerformanceCounterCPU;
+ protected PerformanceCounter PerformanceCounterRAM;
+
+ public string LastCurrentCpuUsage = "-1"; // Last measured CPU usage
+ public string LastCurrentRamUsage = "-1"; // Last measured RAM usage
+ public HardwareMonitorClass()
+ {
+ // Prepare CPU counter
+ PerformanceCounterCPU = new PerformanceCounter();
+ PerformanceCounterCPU.CategoryName = "Processor";
+ PerformanceCounterCPU.CounterName = "% Processor Time";
+ PerformanceCounterCPU.InstanceName = "_Total";
+
+ // Prepare RAM counter
+ PerformanceCounterRAM = new PerformanceCounter();
+ PerformanceCounterRAM.CategoryName = "Memory";
+ PerformanceCounterRAM.CounterName = "% Committed Bytes In Use";
+ }
+ // Get CPU usage
+ public string getCurrentCpuUsage()
+ {
+ LastCurrentCpuUsage = PerformanceCounterCPU.NextValue().ToString("0.00");
+ return LastCurrentCpuUsage;
+ }
+
+ // Get available RAM memory
+ public string getCurrentRamUsage()
+ {
+ LastCurrentRamUsage = PerformanceCounterRAM.NextValue().ToString("0.00");
+ return LastCurrentRamUsage;
+ }
+}
+class CurrentMissionClass
+{
+ // Class holding current mission/DCS server status
+ public string Theatre = ""; // Mission theathre
+ public string Mission = ""; // Mission name
+
+ public string Pause = ""; // Mission pause
+ public int PlayerCount = 0; // Actual player time
+
+ public float ModelTime = 0; // Mission time
+ public float RealTime = 0; // Server time
+}
internal class Globals
{
@@ -8,11 +60,14 @@ internal class Globals
public static int AppInstanceID = 0; // Kepp the instance ID
public static bool AppForceIconReload = true; // Force main window icons reload
+ public static string[] DatabaseSendBuffer = new string[500]; // MySQL send buffer
+
public static bool StatusDatabase = false; // Historic db connection status
public static bool StatusSRS = false; // Historic srs connection status
public static bool StatusLotATC = false; // Historic lotatc connection status
- public static bool StatusHistoryConnection = false; // Historic tcp connection status
+ public static bool StatusHistoryConnection = false; // Historic tcp connection status
public static bool StatusConnection = false; // Flag if is TCP connectionstill alive
+
public static int ErrorsDatabase = 0; // MySQL - Error counter
public static int ErrorsGame = 0; // TCP connection - Error counter
public static int ErrorsHistoryGame = 0; // TCP connection - historic value of Error counter
@@ -22,5 +77,21 @@ internal class Globals
public static string VersionDCSHook = ""; // Version - DCS hook
public static string VersionDatabase = ""; // Version - Database
public static string VersionPerun = "DEBUG"; // Version - Perun
+
+ public static string LastLogLocation = ""; // Last used log location
+ public static bool RotateLogs = false; // Rotate logs true/false
+
+ public static float LastFrameTime = 0f; // Last recorded frame time
+ public static float LastFrameDelay = 0f; // Last recorded frame time
+
+ public static string[] arrGUILogHistory; // Log history for GUI
+ public static string[] arrMySQLSendBuffer; // MySQL send buffer TBD zwiekszyc
+
+ public static CurrentMissionClass CurrentMission = new CurrentMissionClass(); // Actual mission information single ton
+
+ public static HardwareMonitorClass HardwareMonitor = new HardwareMonitorClass(); // Hardware monitor singleton
+
+ public static DatabaseController DatabaseConnection = new DatabaseController(); // Main MySQL controller
+ public static TCPController TCPServer = new TCPController(); // Main TCP controller
}
diff --git a/02_Windows_App/Perun_v1/01_Classes/LogController.cs b/02_Windows_App/Perun_v1/01_Classes/LogController.cs
index 98b2a5a..9dad7c1 100644
--- a/02_Windows_App/Perun_v1/01_Classes/LogController.cs
+++ b/02_Windows_App/Perun_v1/01_Classes/LogController.cs
@@ -3,16 +3,31 @@ using System.IO;
class LogController
{
- // TBD - done via https://stackoverflow.com/questions/20185015/how-to-write-log-file-in-c
- public static void WriteLog(string strLog)
+ // Singleton class - log controller
+ private static LogController _instance = new LogController(); // Singleton instance
+ public int level; // Level of logging
+
+ public static LogController instance
{
+ get
+ {
+ return _instance; // Return current instance
+ }
+ }
+
+ public void WriteLog(int logLevel, string strLog)
+ {
+ // Write log entry to file
+ if (logLevel > this.level) return; // Check if we shall log it with the current log level, if not - exit
+
+ // Declare variables
StreamWriter LogStreamWriter;
FileStream LogFileStream = null;
DirectoryInfo LogDirectoryInfo = null;
FileInfo LogFileInfo;
- string LogFilePath = Path.Combine(Environment.ExpandEnvironmentVariables("%userprofile%"), "Documents") + "\\Perun\\";
- LogFilePath = LogFilePath + "Perun_Log_" + System.DateTime.Today.ToString("yyyyddMM") + "." + "txt";
+ string LogFileDir = Path.Combine(Environment.ExpandEnvironmentVariables("%userprofile%"), "Documents") + "\\Perun\\";
+ string LogFilePath = LogFileDir + "Perun_Log_" + Globals.AppInstanceID + "_" + System.DateTime.Today.ToString("yyyyMMdd") + "." + "log";
LogFileInfo = new FileInfo(LogFilePath);
LogDirectoryInfo = new DirectoryInfo(LogFileInfo.DirectoryName);
if (!LogDirectoryInfo.Exists) LogDirectoryInfo.Create();
@@ -28,7 +43,7 @@ class LogController
}
catch
{
- // Do nothing
+ // Do nothing - TBD error handling
}
}
try
@@ -36,10 +51,26 @@ class LogController
LogStreamWriter = new StreamWriter(LogFileStream);
LogStreamWriter.WriteLine(strLog);
LogStreamWriter.Close();
+ Globals.LastLogLocation = LogFilePath;
}
catch
{
- // Do nothing
+ // Do nothing - TBD error handling
+ }
+
+ // Delete old files - log rotation
+ if (Globals.RotateLogs)
+ {
+ DirectoryInfo di = new DirectoryInfo(LogFileDir);
+ FileInfo[] files = di.GetFiles("*.log");
+
+ foreach (FileInfo fi in files)
+ {
+ if (fi.LastAccessTime < DateTime.Now.AddDays(-7))
+ {
+ fi.Delete();
+ }
+ }
}
}
}
diff --git a/02_Windows_App/Perun_v1/01_Classes/PerunHelper.cs b/02_Windows_App/Perun_v1/01_Classes/PerunHelper.cs
index 1f96346..f129ed6 100644
--- a/02_Windows_App/Perun_v1/01_Classes/PerunHelper.cs
+++ b/02_Windows_App/Perun_v1/01_Classes/PerunHelper.cs
@@ -5,11 +5,51 @@ using System.Text.RegularExpressions;
internal class PerunHelper
{
- public static void AddLog(ref string[] arrLogHistory, string strEntryToAdd, int intDirection = 0, int intMarker = 0, string strType = " ", bool bSkipGui = false)
+ public static string SecondsToString(float Seconds)
+ {
+ int Hours = (int) Seconds / 3600;
+ int Minutes = ((int)Seconds % 3600)/60 ;
+ string ToReturn = $"{Hours.ToString("00")}h {Minutes.ToString("00")}m";
+ return ToReturn;
+ }
+
+ public static void SetFrameRates(float frame_rate, float last_delay)
+ {
+ Globals.LastFrameTime = frame_rate;
+ Globals.LastFrameDelay = last_delay;
+ }
+
+ // Add error infomation
+ public static void LogError(ref string[] arrLogHistory, string strEntryToAdd, int intDirection = 0, int intMarker = 0, string strType = " ", bool bSkipGui = false)
+ {
+ AddLog(0, ref arrLogHistory, strEntryToAdd, intDirection, intMarker, strType, bSkipGui);
+ }
+
+ // Add warning information
+ public static void LogWarning(ref string[] arrLogHistory, string strEntryToAdd, int intDirection = 0, int intMarker = 0, string strType = " ", bool bSkipGui = false)
+ {
+ AddLog(1, ref arrLogHistory, strEntryToAdd, intDirection, intMarker, strType, bSkipGui);
+ }
+
+ // Add info information
+ public static void LogInfo(ref string[] arrLogHistory, string strEntryToAdd, int intDirection = 0, int intMarker = 0, string strType = " ", bool bSkipGui = false)
+ {
+ AddLog(2, ref arrLogHistory, strEntryToAdd, intDirection, intMarker, strType, bSkipGui);
+ }
+
+ // Add debug information
+ public static void LogDebug(ref string[] arrLogHistory, string strEntryToAdd, int intDirection = 0, int intMarker = 0, string strType = " ", bool bSkipGui = false)
+ {
+ AddLog(3, ref arrLogHistory, strEntryToAdd, intDirection, intMarker, strType, bSkipGui);
+ }
+
+ // Add log
+ private static void AddLog(int logLevel, ref string[] arrLogHistory, string strEntryToAdd, int intDirection = 0, int intMarker = 0, string strType = " ", bool bSkipGui = false)
{
// Declare values
string LogDirection;
string LogMarker;
+
// Set direction marker
switch (intDirection)
{
@@ -23,17 +63,35 @@ internal class PerunHelper
LogDirection = "^";
break;
default:
- LogDirection = " ";
+ LogDirection = "-";
+ break;
+ }
+
+ // Insert information about which log type we are curently handling
+ string LogType;
+ switch (logLevel)
+ {
+ case 0:
+ LogType = "E";
+ break;
+ case 1:
+ LogType = "W";
+ break;
+ case 2:
+ LogType = "I";
+ break;
+ default:
+ LogType = "D";
break;
}
// Set marker for user flags (markers)
- LogMarker = (intMarker>0) ? "X" : " ";
+ LogMarker = (intMarker > 0) ? "X" : " ";
// Set frame type
- strType=strType.PadLeft(3, ' ');
+ strType = strType.PadLeft(3, ' ');
- if (!bSkipGui)
+ if (!bSkipGui) // Shall we skip GUI?
{
// Rotate log history
for (int i = 0; i < arrLogHistory.Length - 1; i++)
@@ -42,24 +100,28 @@ internal class PerunHelper
}
// Add new entry
- arrLogHistory[arrLogHistory.Length - 1] = DateTime.Now.ToString("HH:mm:ss") + " " + LogDirection + " " + strEntryToAdd; // Add entry at the last position
+ arrLogHistory[arrLogHistory.Length - 1] = $"{DateTime.Now.ToString("HH:mm:ss")} {LogType} {Globals.LastFrameDelay.ToString("0.")}u {strEntryToAdd}"; // Add entry at the last position
// Update control at my window
Globals.AppUpdateGUI = true;
}
// Add the entry to log file
- LogController.WriteLog(DateTime.Now.ToString("yyyy-MM-dd ") + " " + DateTime.Now.ToString("HH:mm:ss") + " | Instance: "+ Globals.AppInstanceID + " | " + LogMarker + " | "+ LogDirection + " | "+ strType + " | " + strEntryToAdd);
+ LogController.instance.WriteLog(logLevel, $"{DateTime.Now.ToString("yyyy-MM-dd ")} {DateTime.Now.ToString("HH:mm:ss.fff")} | {Globals.HardwareMonitor.LastCurrentCpuUsage} | {Globals.HardwareMonitor.LastCurrentRamUsage} | {Globals.LastFrameTime.ToString("000000.")} | {Globals.LastFrameDelay.ToString("000000.")} | {Globals.AppInstanceID} | {LogMarker} | {LogDirection} | {strType} | {strEntryToAdd}");
}
- public static string GetAppVersion(string strBeginning)
+ // Gets build version
+ public static string GetAppVersion(string strBeginning, string strEnding = "")
{
- // Gets build version
Globals.VersionPerun = Assembly.GetExecutingAssembly().GetName().Version.ToString();
- return strBeginning + "v" + Globals.VersionPerun;
+#if DEBUG
+ Globals.VersionPerun = $"{Globals.VersionPerun} (DEV)";
+#endif
+ return $"{strBeginning}v{Globals.VersionPerun}{strEnding}";
}
public static int CheckVersions()
{
+ // Checks if all versions (mysql, winapp, lua) are the same - ommit if run as debug build
#if !DEBUG
// Checks the versions of APP, DCS Hook and MySQL database
Match match = Regex.Match(Globals.VersionPerun, @"^\d+.\d+.\d+", RegexOptions.Compiled | RegexOptions.IgnoreCase);
@@ -72,7 +134,7 @@ internal class PerunHelper
if(VersionApp != Globals.VersionDatabase)
{
// Incorrect database version
- PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR Incorrect database revision : "+ Globals.VersionDatabase, 1, 1, "?");
+ PerunHelper.LogError(ref Globals.AppLogHistory, $"ERROR Incorrect database revision : {Globals.VersionDatabase}", 1, 1, "?");
Globals.ErrorsDatabase++;
ReturnValue = 0;
}
@@ -84,7 +146,7 @@ internal class PerunHelper
if (VersionApp != Globals.VersionDCSHook)
{
// Incorrect dcs script version
- PerunHelper.AddLog(ref Globals.AppLogHistory, "ERROR Incorrect DCS hook revision : " + Globals.VersionDCSHook, 2, 1, "?");
+ PerunHelper.LogError(ref Globals.AppLogHistory, $"ERROR Incorrect DCS hook revision: {Globals.VersionDCSHook}", 2, 1, "?");
Globals.ErrorsGame++;
ReturnValue = 0;
}
diff --git a/02_Windows_App/Perun_v1/01_Classes/TCPController.cs b/02_Windows_App/Perun_v1/01_Classes/TCPController.cs
index a92dfb6..502f271 100644
--- a/02_Windows_App/Perun_v1/01_Classes/TCPController.cs
+++ b/02_Windows_App/Perun_v1/01_Classes/TCPController.cs
@@ -12,16 +12,15 @@ public class TCPController
// Main class for TCP listener
public int intListenPort; // Port to connect to
public bool bCloseConnection; // Helper to exit main loop without killing thread
- public string[] arrGUILogHistory; // Log history for GUI
- public string[] arrMySQLSendBuffer; // MySQL send buffer
+
public Thread thrTCPListener; // Seperate thread for TCP
public void Create(int par_intListenPort, ref string[] par_arrLogHistory, ref string[] par_arrSendBuffer)
{
// Create class and map creation arguments to class
intListenPort = par_intListenPort;
- arrGUILogHistory = par_arrLogHistory;
- arrMySQLSendBuffer = par_arrSendBuffer;
+ Globals.arrGUILogHistory = par_arrLogHistory;
+ Globals.arrMySQLSendBuffer = par_arrSendBuffer;
bCloseConnection = false;
}
@@ -31,9 +30,9 @@ public class TCPController
bCloseConnection = true;
// Clear send buffer
- for (int i = 0; i < arrMySQLSendBuffer.Length - 1; i++)
+ for (int i = 0; i < Globals.arrMySQLSendBuffer.Length - 1; i++)
{
- arrMySQLSendBuffer[i] = null;
+ Globals.arrMySQLSendBuffer[i] = null; // Empty send buffer
}
}
@@ -72,11 +71,11 @@ public class TCPController
Console.WriteLine("TCP: Connected");
bTCPConnectionOnline = true;
tcpClient = tcpServer.AcceptTcpClient(); //if a connection exists, the server will accept it
+
nsReadStream = tcpClient.GetStream(); //networkstream is used to send/receive messages
nsReadStream.ReadTimeout = 10000;
tcpClient.ReceiveTimeout = 10000;
-
while (tcpClient.Connected && !bCloseConnection && bTCPConnectionOnline) //while the client is connected, we look for incoming messages
{
StringBuilder CompleteMessage = new StringBuilder();
@@ -94,7 +93,7 @@ public class TCPController
{
Console.WriteLine("TCP: Read");
numberOfBytesRead = nsReadStream.Read(ReadBuffer, 0, ReadBuffer.Length);
- CompleteMessage.AppendFormat("{0}", Encoding.ASCII.GetString(ReadBuffer, 0, numberOfBytesRead));
+ CompleteMessage.AppendFormat("{0}", Encoding.UTF8.GetString(ReadBuffer, 0, numberOfBytesRead));
if (numberOfBytesRead == 0)
{
break;
@@ -126,25 +125,30 @@ public class TCPController
if (Int32.Parse(strRawTCPFrameType) != 0)
{
// Add to mySQL send buffer (find first empty slot)
- PerunHelper.AddLog(ref arrGUILogHistory, "Packet received" , 2,0, strRawTCPFrameType,true);
+ PerunHelper.LogDebug(ref Globals.arrGUILogHistory, "Packet received" , 2,0, strRawTCPFrameType);
bool AddedDataToBuffer = false;
- for (int i = 0; i < arrMySQLSendBuffer.Length - 1; i++)
+ for (int i = 0; i < Globals.arrMySQLSendBuffer.Length - 1; i++)
{
- if (arrMySQLSendBuffer[i] == null)
+ if (Globals.arrMySQLSendBuffer[i] == null)
{
- arrMySQLSendBuffer[i] = strReceivedData;
+ Globals.arrMySQLSendBuffer[i] = strReceivedData;
AddedDataToBuffer = true;
break;
}
}
if (!AddedDataToBuffer)
{
- PerunHelper.AddLog(ref arrGUILogHistory, "ERROR package was dropped", 1, 1, strRawTCPFrameType);
+ PerunHelper.LogError(ref Globals.arrGUILogHistory, "ERROR TCP package was dropped", 1, 1, strRawTCPFrameType);
}
} else
{
// Keep alive
- PerunHelper.AddLog(ref arrGUILogHistory, "Keep-alive received", 2,0,"0",true);
+ PerunHelper.LogDebug(ref Globals.arrGUILogHistory, "Keep-alive received", 2,0,"0");
+ }
+
+ if (dynamicRawTCPFrame.dcs_frame_time != null && dynamicRawTCPFrame.dcs_current_frame_delay != null)
+ {
+ PerunHelper.SetFrameRates((float)dynamicRawTCPFrame.dcs_frame_time, (float)dynamicRawTCPFrame.dcs_current_frame_delay);
}
}
else
@@ -156,7 +160,7 @@ public class TCPController
{
Globals.ErrorsGame++;
Console.WriteLine(e.ToString());
- PerunHelper.AddLog(ref arrGUILogHistory, "ERROR while message parsing , error: " + e.Message,2,1,"?");
+ PerunHelper.LogError(ref Globals.arrGUILogHistory, $"ERROR TCP while message parsing , error: {e.Message}",2,1,"?");
bTCPConnectionOnline = false;
}
@@ -168,7 +172,7 @@ public class TCPController
catch (SocketException e)
{
Console.WriteLine(e.ToString());
- PerunHelper.AddLog(ref arrGUILogHistory, "TCP ERROR cannot check connection, error: " + e.Message,2,1,"?");
+ PerunHelper.LogError(ref Globals.arrGUILogHistory, $"ERROR TCP cannot check connection, error: {e.Message}",2,1,"?");
}
}
@@ -182,8 +186,13 @@ public class TCPController
{
Globals.ErrorsGame++;
Console.WriteLine(e.ToString());
- PerunHelper.AddLog(ref arrGUILogHistory, "TCP error - connection closed or port in use, error: " + e.Message,1,1,"?");
- bTCPConnectionOnline = false;
+ PerunHelper.LogError(ref Globals.arrGUILogHistory, $"ERROR TCP - connection closed or port in use, error: {e.Message}",1,1,"?");
+
+ // Reset last frame times on broken connection
+ Globals.LastFrameTime = 0f;
+ Globals.LastFrameDelay = 0f;
+
+ bTCPConnectionOnline = false;
}
// Clean up and prepare for next connection
diff --git a/02_Windows_App/Perun_v1/02_Forms/form_Main.Designer.cs b/02_Windows_App/Perun_v1/02_Forms/form_Main.Designer.cs
index eb8535b..c48c2d1 100644
--- a/02_Windows_App/Perun_v1/02_Forms/form_Main.Designer.cs
+++ b/02_Windows_App/Perun_v1/02_Forms/form_Main.Designer.cs
@@ -34,6 +34,10 @@
this.con_Button_Listen_ON = new System.Windows.Forms.Button();
this.con_Button_Listen_OFF = new System.Windows.Forms.Button();
this.con_GroupBox_1 = new System.Windows.Forms.GroupBox();
+ this.con_Button_See_log = new System.Windows.Forms.Button();
+ this.label15 = new System.Windows.Forms.Label();
+ this.con_com_loglevel = new System.Windows.Forms.ComboBox();
+ this.con_Button_Add_Marker = new System.Windows.Forms.Button();
this.tim_GUI = new System.Windows.Forms.Timer(this.components);
this.con_GroupBox_2 = new System.Windows.Forms.GroupBox();
this.label6 = new System.Windows.Forms.Label();
@@ -64,29 +68,57 @@
this.con_txt_dcs_instance = new System.Windows.Forms.MaskedTextBox();
this.label7 = new System.Windows.Forms.Label();
this.con_txt_dcs_server_port = new System.Windows.Forms.MaskedTextBox();
- this.label9 = new System.Windows.Forms.Label();
- this.label10 = new System.Windows.Forms.Label();
- this.label11 = new System.Windows.Forms.Label();
- this.label12 = new System.Windows.Forms.Label();
- this.con_Button_Reset_Flags = new System.Windows.Forms.Button();
this.label13 = new System.Windows.Forms.Label();
this.label14 = new System.Windows.Forms.Label();
this.con_img_logo = new System.Windows.Forms.PictureBox();
+ this.TIM_Autostart = new System.Windows.Forms.Timer(this.components);
+ this.con_check_minimize_to_tray = new System.Windows.Forms.CheckBox();
+ this.con_GroupBox_4 = new System.Windows.Forms.GroupBox();
+ this.con_Button_Reset_Flags = new System.Windows.Forms.Button();
+ this.label12 = new System.Windows.Forms.Label();
+ this.label11 = new System.Windows.Forms.Label();
+ this.label10 = new System.Windows.Forms.Label();
+ this.label9 = new System.Windows.Forms.Label();
this.con_img_lotATC = new System.Windows.Forms.PictureBox();
this.con_img_srs = new System.Windows.Forms.PictureBox();
this.con_img_dcs = new System.Windows.Forms.PictureBox();
this.con_img_db = new System.Windows.Forms.PictureBox();
- this.con_Button_Add_Marker = new System.Windows.Forms.Button();
- this.TIM_Autostart = new System.Windows.Forms.Timer(this.components);
+ this.con_GroupBox_5 = new System.Windows.Forms.GroupBox();
+ this.con_check_delete_logs = new System.Windows.Forms.CheckBox();
+ this.con_GroupBox_6 = new System.Windows.Forms.GroupBox();
+ this.label26 = new System.Windows.Forms.Label();
+ this.label25 = new System.Windows.Forms.Label();
+ this.label24 = new System.Windows.Forms.Label();
+ this.label23 = new System.Windows.Forms.Label();
+ this.label22 = new System.Windows.Forms.Label();
+ this.label21 = new System.Windows.Forms.Label();
+ this.label16 = new System.Windows.Forms.Label();
+ this.label19 = new System.Windows.Forms.Label();
+ this.label18 = new System.Windows.Forms.Label();
+ this.label17 = new System.Windows.Forms.Label();
+ this.con_GroupBox_7 = new System.Windows.Forms.GroupBox();
+ this.label33 = new System.Windows.Forms.Label();
+ this.label32 = new System.Windows.Forms.Label();
+ this.label31 = new System.Windows.Forms.Label();
+ this.label30 = new System.Windows.Forms.Label();
+ this.label29 = new System.Windows.Forms.Label();
+ this.label28 = new System.Windows.Forms.Label();
+ this.label27 = new System.Windows.Forms.Label();
+ this.label20 = new System.Windows.Forms.Label();
+ this.tim_HW_status = new System.Windows.Forms.Timer(this.components);
this.con_GroupBox_1.SuspendLayout();
this.con_GroupBox_2.SuspendLayout();
this.con_GroupBox_3.SuspendLayout();
this.groupBox1.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.con_img_logo)).BeginInit();
+ this.con_GroupBox_4.SuspendLayout();
((System.ComponentModel.ISupportInitialize)(this.con_img_lotATC)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_srs)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_dcs)).BeginInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_db)).BeginInit();
+ this.con_GroupBox_5.SuspendLayout();
+ this.con_GroupBox_6.SuspendLayout();
+ this.con_GroupBox_7.SuspendLayout();
this.SuspendLayout();
//
// con_List_Received
@@ -95,14 +127,14 @@
this.con_List_Received.FormattingEnabled = true;
this.con_List_Received.Items.AddRange(new object[] {
"Not connected"});
- this.con_List_Received.Location = new System.Drawing.Point(11, 19);
+ this.con_List_Received.Location = new System.Drawing.Point(8, 44);
this.con_List_Received.Name = "con_List_Received";
this.con_List_Received.Size = new System.Drawing.Size(307, 134);
this.con_List_Received.TabIndex = 0;
//
// con_Button_Listen_ON
//
- this.con_Button_Listen_ON.Location = new System.Drawing.Point(12, 602);
+ this.con_Button_Listen_ON.Location = new System.Drawing.Point(342, 441);
this.con_Button_Listen_ON.Name = "con_Button_Listen_ON";
this.con_Button_Listen_ON.Size = new System.Drawing.Size(86, 39);
this.con_Button_Listen_ON.TabIndex = 2;
@@ -113,7 +145,7 @@
// con_Button_Listen_OFF
//
this.con_Button_Listen_OFF.Enabled = false;
- this.con_Button_Listen_OFF.Location = new System.Drawing.Point(104, 602);
+ this.con_Button_Listen_OFF.Location = new System.Drawing.Point(434, 441);
this.con_Button_Listen_OFF.Name = "con_Button_Listen_OFF";
this.con_Button_Listen_OFF.Size = new System.Drawing.Size(86, 39);
this.con_Button_Listen_OFF.TabIndex = 3;
@@ -123,14 +155,69 @@
//
// con_GroupBox_1
//
+ this.con_GroupBox_1.Controls.Add(this.con_Button_See_log);
+ this.con_GroupBox_1.Controls.Add(this.label15);
+ this.con_GroupBox_1.Controls.Add(this.con_com_loglevel);
this.con_GroupBox_1.Controls.Add(this.con_List_Received);
- this.con_GroupBox_1.Location = new System.Drawing.Point(12, 434);
+ this.con_GroupBox_1.Controls.Add(this.con_Button_Add_Marker);
+ this.con_GroupBox_1.Location = new System.Drawing.Point(342, 248);
this.con_GroupBox_1.Name = "con_GroupBox_1";
- this.con_GroupBox_1.Size = new System.Drawing.Size(324, 162);
+ this.con_GroupBox_1.Size = new System.Drawing.Size(324, 187);
this.con_GroupBox_1.TabIndex = 4;
this.con_GroupBox_1.TabStop = false;
this.con_GroupBox_1.Text = "Data log";
//
+ // con_Button_See_log
+ //
+ this.con_Button_See_log.Enabled = false;
+ this.con_Button_See_log.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.con_Button_See_log.Location = new System.Drawing.Point(170, 12);
+ this.con_Button_See_log.Name = "con_Button_See_log";
+ this.con_Button_See_log.Size = new System.Drawing.Size(56, 20);
+ this.con_Button_See_log.TabIndex = 24;
+ this.con_Button_See_log.Text = "See log";
+ this.con_Button_See_log.UseVisualStyleBackColor = true;
+ this.con_Button_See_log.Click += new System.EventHandler(this.con_Button_See_log_Click);
+ //
+ // label15
+ //
+ this.label15.AutoSize = true;
+ this.label15.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.label15.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label15.Location = new System.Drawing.Point(6, 18);
+ this.label15.Name = "label15";
+ this.label15.Size = new System.Drawing.Size(50, 13);
+ this.label15.TabIndex = 22;
+ this.label15.Text = "Log level";
+ //
+ // con_com_loglevel
+ //
+ this.con_com_loglevel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList;
+ this.con_com_loglevel.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F);
+ this.con_com_loglevel.FormattingEnabled = true;
+ this.con_com_loglevel.Items.AddRange(new object[] {
+ "Error",
+ "Warning",
+ "Info",
+ "Debug"});
+ this.con_com_loglevel.Location = new System.Drawing.Point(62, 12);
+ this.con_com_loglevel.Name = "con_com_loglevel";
+ this.con_com_loglevel.Size = new System.Drawing.Size(102, 20);
+ this.con_com_loglevel.TabIndex = 23;
+ this.con_com_loglevel.SelectedIndexChanged += new System.EventHandler(this.con_com_loglevell_SelectedIndexChanged);
+ //
+ // con_Button_Add_Marker
+ //
+ this.con_Button_Add_Marker.Enabled = false;
+ this.con_Button_Add_Marker.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.con_Button_Add_Marker.Location = new System.Drawing.Point(232, 12);
+ this.con_Button_Add_Marker.Name = "con_Button_Add_Marker";
+ this.con_Button_Add_Marker.Size = new System.Drawing.Size(86, 20);
+ this.con_Button_Add_Marker.TabIndex = 21;
+ this.con_Button_Add_Marker.Text = "Add log marker";
+ this.con_Button_Add_Marker.UseVisualStyleBackColor = true;
+ this.con_Button_Add_Marker.Click += new System.EventHandler(this.con_Button_Add_Marker_Click);
+ //
// tim_GUI
//
this.tim_GUI.Interval = 200;
@@ -148,12 +235,12 @@
this.con_GroupBox_2.Controls.Add(this.con_txt_mysql_database);
this.con_GroupBox_2.Controls.Add(this.con_txt_mysql_server);
this.con_GroupBox_2.Controls.Add(this.con_txt_mysql_password);
- this.con_GroupBox_2.Location = new System.Drawing.Point(14, 54);
+ this.con_GroupBox_2.Location = new System.Drawing.Point(12, 12);
this.con_GroupBox_2.Name = "con_GroupBox_2";
this.con_GroupBox_2.Size = new System.Drawing.Size(324, 154);
this.con_GroupBox_2.TabIndex = 5;
this.con_GroupBox_2.TabStop = false;
- this.con_GroupBox_2.Text = "MySQL";
+ this.con_GroupBox_2.Text = "Database settings";
//
// label6
//
@@ -242,33 +329,33 @@
this.con_GroupBox_3.Controls.Add(this.con_txt_3rd_srs);
this.con_GroupBox_3.Controls.Add(this.con_check_3rd_lotatc);
this.con_GroupBox_3.Controls.Add(this.con_check_3rd_srs);
- this.con_GroupBox_3.Location = new System.Drawing.Point(14, 288);
+ this.con_GroupBox_3.Location = new System.Drawing.Point(12, 246);
this.con_GroupBox_3.Name = "con_GroupBox_3";
- this.con_GroupBox_3.Size = new System.Drawing.Size(324, 68);
+ this.con_GroupBox_3.Size = new System.Drawing.Size(324, 118);
this.con_GroupBox_3.TabIndex = 6;
this.con_GroupBox_3.TabStop = false;
- this.con_GroupBox_3.Text = "3rd party";
+ this.con_GroupBox_3.Text = "Integration settings";
//
// con_txt_3rd_lotatc
//
- this.con_txt_3rd_lotatc.Location = new System.Drawing.Point(123, 39);
+ this.con_txt_3rd_lotatc.Location = new System.Drawing.Point(6, 91);
this.con_txt_3rd_lotatc.Name = "con_txt_3rd_lotatc";
- this.con_txt_3rd_lotatc.Size = new System.Drawing.Size(190, 20);
+ this.con_txt_3rd_lotatc.Size = new System.Drawing.Size(307, 20);
this.con_txt_3rd_lotatc.TabIndex = 4;
this.con_txt_3rd_lotatc.MouseClick += new System.Windows.Forms.MouseEventHandler(this.con_txt_3rd_lotatc_Click);
//
// con_txt_3rd_srs
//
- this.con_txt_3rd_srs.Location = new System.Drawing.Point(123, 16);
+ this.con_txt_3rd_srs.Location = new System.Drawing.Point(6, 42);
this.con_txt_3rd_srs.Name = "con_txt_3rd_srs";
- this.con_txt_3rd_srs.Size = new System.Drawing.Size(190, 20);
+ this.con_txt_3rd_srs.Size = new System.Drawing.Size(307, 20);
this.con_txt_3rd_srs.TabIndex = 3;
this.con_txt_3rd_srs.MouseClick += new System.Windows.Forms.MouseEventHandler(this.con_txt_3rd_srs_Click);
//
// con_check_3rd_lotatc
//
this.con_check_3rd_lotatc.AutoSize = true;
- this.con_check_3rd_lotatc.Location = new System.Drawing.Point(6, 42);
+ this.con_check_3rd_lotatc.Location = new System.Drawing.Point(6, 72);
this.con_check_3rd_lotatc.Name = "con_check_3rd_lotatc";
this.con_check_3rd_lotatc.Size = new System.Drawing.Size(100, 17);
this.con_check_3rd_lotatc.TabIndex = 1;
@@ -287,7 +374,7 @@
//
// con_Button_Quit
//
- this.con_Button_Quit.Location = new System.Drawing.Point(251, 602);
+ this.con_Button_Quit.Location = new System.Drawing.Point(580, 441);
this.con_Button_Quit.Name = "con_Button_Quit";
this.con_Button_Quit.Size = new System.Drawing.Size(86, 39);
this.con_Button_Quit.TabIndex = 7;
@@ -299,7 +386,7 @@
//
this.con_lab_github.AutoSize = true;
this.con_lab_github.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.con_lab_github.Location = new System.Drawing.Point(183, 39);
+ this.con_lab_github.Location = new System.Drawing.Point(172, 456);
this.con_lab_github.Name = "con_lab_github";
this.con_lab_github.Size = new System.Drawing.Size(155, 12);
this.con_lab_github.TabIndex = 8;
@@ -311,7 +398,7 @@
//
this.label5.AutoSize = true;
this.label5.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label5.Location = new System.Drawing.Point(183, 27);
+ this.label5.Location = new System.Drawing.Point(223, 444);
this.label5.Name = "label5";
this.label5.Size = new System.Drawing.Size(102, 12);
this.label5.TabIndex = 9;
@@ -350,12 +437,12 @@
this.groupBox1.Controls.Add(this.con_txt_dcs_instance);
this.groupBox1.Controls.Add(this.label7);
this.groupBox1.Controls.Add(this.con_txt_dcs_server_port);
- this.groupBox1.Location = new System.Drawing.Point(14, 214);
+ this.groupBox1.Location = new System.Drawing.Point(12, 172);
this.groupBox1.Name = "groupBox1";
this.groupBox1.Size = new System.Drawing.Size(324, 68);
this.groupBox1.TabIndex = 7;
this.groupBox1.TabStop = false;
- this.groupBox1.Text = "DCS Connection";
+ this.groupBox1.Text = "DCS World settings";
//
// label8
//
@@ -389,67 +476,11 @@
this.con_txt_dcs_server_port.Size = new System.Drawing.Size(207, 20);
this.con_txt_dcs_server_port.TabIndex = 3;
//
- // label9
- //
- this.label9.AutoSize = true;
- this.label9.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
- this.label9.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label9.Location = new System.Drawing.Point(21, 396);
- this.label9.Name = "label9";
- this.label9.Size = new System.Drawing.Size(61, 13);
- this.label9.TabIndex = 1;
- this.label9.Text = "Database";
- //
- // label10
- //
- this.label10.AutoSize = true;
- this.label10.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
- this.label10.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label10.Location = new System.Drawing.Point(117, 396);
- this.label10.Name = "label10";
- this.label10.Size = new System.Drawing.Size(39, 13);
- this.label10.TabIndex = 14;
- this.label10.Text = "Game";
- //
- // label11
- //
- this.label11.AutoSize = true;
- this.label11.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
- this.label11.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label11.Location = new System.Drawing.Point(205, 396);
- this.label11.Name = "label11";
- this.label11.Size = new System.Drawing.Size(32, 13);
- this.label11.TabIndex = 15;
- this.label11.Text = "SRS";
- //
- // label12
- //
- this.label12.AutoSize = true;
- this.label12.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
- this.label12.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label12.Location = new System.Drawing.Point(282, 396);
- this.label12.Name = "label12";
- this.label12.Size = new System.Drawing.Size(49, 13);
- this.label12.TabIndex = 16;
- this.label12.Text = "LotATC";
- //
- // con_Button_Reset_Flags
- //
- this.con_Button_Reset_Flags.Enabled = false;
- this.con_Button_Reset_Flags.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.con_Button_Reset_Flags.Location = new System.Drawing.Point(224, 414);
- this.con_Button_Reset_Flags.Name = "con_Button_Reset_Flags";
- this.con_Button_Reset_Flags.Size = new System.Drawing.Size(114, 20);
- this.con_Button_Reset_Flags.TabIndex = 17;
- this.con_Button_Reset_Flags.Text = "Reset error flags";
- this.con_Button_Reset_Flags.UseVisualStyleBackColor = true;
- this.con_Button_Reset_Flags.Click += new System.EventHandler(this.con_Button_Reset_Flags_Click);
- //
// label13
//
this.label13.AutoSize = true;
this.label13.Font = new System.Drawing.Font("Microsoft Sans Serif", 15.75F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label13.Location = new System.Drawing.Point(63, 7);
+ this.label13.Location = new System.Drawing.Point(64, 427);
this.label13.Name = "label13";
this.label13.Size = new System.Drawing.Size(74, 25);
this.label13.TabIndex = 19;
@@ -459,7 +490,7 @@
//
this.label14.AutoSize = true;
this.label14.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.label14.Location = new System.Drawing.Point(65, 32);
+ this.label14.Location = new System.Drawing.Point(66, 452);
this.label14.Name = "label14";
this.label14.Size = new System.Drawing.Size(88, 13);
this.label14.TabIndex = 20;
@@ -469,84 +500,397 @@
//
this.con_img_logo.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
this.con_img_logo.Image = global::Perun_v1.Properties.Resources.perun_logo;
- this.con_img_logo.Location = new System.Drawing.Point(12, 7);
+ this.con_img_logo.Location = new System.Drawing.Point(13, 427);
this.con_img_logo.Name = "con_img_logo";
this.con_img_logo.Size = new System.Drawing.Size(45, 41);
this.con_img_logo.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
this.con_img_logo.TabIndex = 18;
this.con_img_logo.TabStop = false;
//
+ // TIM_Autostart
+ //
+ this.TIM_Autostart.Interval = 500;
+ this.TIM_Autostart.Tick += new System.EventHandler(this.TIM_Autostart_Tick);
+ //
+ // con_check_minimize_to_tray
+ //
+ this.con_check_minimize_to_tray.AutoSize = true;
+ this.con_check_minimize_to_tray.Checked = true;
+ this.con_check_minimize_to_tray.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.con_check_minimize_to_tray.Location = new System.Drawing.Point(6, 19);
+ this.con_check_minimize_to_tray.Name = "con_check_minimize_to_tray";
+ this.con_check_minimize_to_tray.Size = new System.Drawing.Size(98, 17);
+ this.con_check_minimize_to_tray.TabIndex = 24;
+ this.con_check_minimize_to_tray.Text = "Minimize to tray";
+ this.con_check_minimize_to_tray.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText;
+ this.con_check_minimize_to_tray.UseVisualStyleBackColor = true;
+ this.con_check_minimize_to_tray.Validated += new System.EventHandler(this.con_check_minimize_to_tray_Validated);
+ //
+ // con_GroupBox_4
+ //
+ this.con_GroupBox_4.Controls.Add(this.con_Button_Reset_Flags);
+ this.con_GroupBox_4.Controls.Add(this.label12);
+ this.con_GroupBox_4.Controls.Add(this.label11);
+ this.con_GroupBox_4.Controls.Add(this.label10);
+ this.con_GroupBox_4.Controls.Add(this.label9);
+ this.con_GroupBox_4.Controls.Add(this.con_img_lotATC);
+ this.con_GroupBox_4.Controls.Add(this.con_img_srs);
+ this.con_GroupBox_4.Controls.Add(this.con_img_dcs);
+ this.con_GroupBox_4.Controls.Add(this.con_img_db);
+ this.con_GroupBox_4.Location = new System.Drawing.Point(342, 12);
+ this.con_GroupBox_4.Name = "con_GroupBox_4";
+ this.con_GroupBox_4.Size = new System.Drawing.Size(324, 87);
+ this.con_GroupBox_4.TabIndex = 25;
+ this.con_GroupBox_4.TabStop = false;
+ this.con_GroupBox_4.Text = "Perun status";
+ //
+ // con_Button_Reset_Flags
+ //
+ this.con_Button_Reset_Flags.Enabled = false;
+ this.con_Button_Reset_Flags.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.con_Button_Reset_Flags.Location = new System.Drawing.Point(254, 25);
+ this.con_Button_Reset_Flags.Name = "con_Button_Reset_Flags";
+ this.con_Button_Reset_Flags.Size = new System.Drawing.Size(61, 40);
+ this.con_Button_Reset_Flags.TabIndex = 26;
+ this.con_Button_Reset_Flags.Text = "Reset error flags";
+ this.con_Button_Reset_Flags.UseVisualStyleBackColor = true;
+ this.con_Button_Reset_Flags.Click += new System.EventHandler(this.con_Button_Reset_Flags_Click);
+ //
+ // label12
+ //
+ this.label12.AutoSize = true;
+ this.label12.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.label12.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label12.Location = new System.Drawing.Point(187, 59);
+ this.label12.Name = "label12";
+ this.label12.Size = new System.Drawing.Size(49, 13);
+ this.label12.TabIndex = 25;
+ this.label12.Text = "LotATC";
+ //
+ // label11
+ //
+ this.label11.AutoSize = true;
+ this.label11.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.label11.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label11.Location = new System.Drawing.Point(138, 59);
+ this.label11.Name = "label11";
+ this.label11.Size = new System.Drawing.Size(32, 13);
+ this.label11.TabIndex = 24;
+ this.label11.Text = "SRS";
+ //
+ // label10
+ //
+ this.label10.AutoSize = true;
+ this.label10.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.label10.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label10.Location = new System.Drawing.Point(77, 59);
+ this.label10.Name = "label10";
+ this.label10.Size = new System.Drawing.Size(39, 13);
+ this.label10.TabIndex = 23;
+ this.label10.Text = "Game";
+ //
+ // label9
+ //
+ this.label9.AutoSize = true;
+ this.label9.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
+ this.label9.Font = new System.Drawing.Font("Microsoft Sans Serif", 8.25F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
+ this.label9.Location = new System.Drawing.Point(9, 59);
+ this.label9.Name = "label9";
+ this.label9.Size = new System.Drawing.Size(61, 13);
+ this.label9.TabIndex = 18;
+ this.label9.Text = "Database";
+ //
// con_img_lotATC
//
- this.con_img_lotATC.Location = new System.Drawing.Point(292, 362);
+ this.con_img_lotATC.Location = new System.Drawing.Point(196, 28);
this.con_img_lotATC.Name = "con_img_lotATC";
this.con_img_lotATC.Size = new System.Drawing.Size(29, 28);
this.con_img_lotATC.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
- this.con_img_lotATC.TabIndex = 13;
+ this.con_img_lotATC.TabIndex = 22;
this.con_img_lotATC.TabStop = false;
//
// con_img_srs
//
- this.con_img_srs.Location = new System.Drawing.Point(207, 362);
+ this.con_img_srs.Location = new System.Drawing.Point(139, 28);
this.con_img_srs.Name = "con_img_srs";
this.con_img_srs.Size = new System.Drawing.Size(29, 28);
this.con_img_srs.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
- this.con_img_srs.TabIndex = 12;
+ this.con_img_srs.TabIndex = 21;
this.con_img_srs.TabStop = false;
//
// con_img_dcs
//
- this.con_img_dcs.Location = new System.Drawing.Point(122, 362);
+ this.con_img_dcs.Location = new System.Drawing.Point(82, 28);
this.con_img_dcs.Name = "con_img_dcs";
this.con_img_dcs.Size = new System.Drawing.Size(29, 28);
this.con_img_dcs.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
- this.con_img_dcs.TabIndex = 11;
+ this.con_img_dcs.TabIndex = 20;
this.con_img_dcs.TabStop = false;
//
// con_img_db
//
this.con_img_db.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None;
- this.con_img_db.Location = new System.Drawing.Point(37, 362);
+ this.con_img_db.Location = new System.Drawing.Point(25, 28);
this.con_img_db.Name = "con_img_db";
this.con_img_db.Size = new System.Drawing.Size(29, 28);
this.con_img_db.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage;
- this.con_img_db.TabIndex = 10;
+ this.con_img_db.TabIndex = 19;
this.con_img_db.TabStop = false;
//
- // con_Button_Add_Marker
+ // con_GroupBox_5
//
- this.con_Button_Add_Marker.Enabled = false;
- this.con_Button_Add_Marker.Font = new System.Drawing.Font("Microsoft Sans Serif", 6.75F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
- this.con_Button_Add_Marker.Location = new System.Drawing.Point(12, 414);
- this.con_Button_Add_Marker.Name = "con_Button_Add_Marker";
- this.con_Button_Add_Marker.Size = new System.Drawing.Size(114, 20);
- this.con_Button_Add_Marker.TabIndex = 21;
- this.con_Button_Add_Marker.Text = "Add log marker";
- this.con_Button_Add_Marker.UseVisualStyleBackColor = true;
- this.con_Button_Add_Marker.Click += new System.EventHandler(this.con_Button_Add_Marker_Click);
+ this.con_GroupBox_5.Controls.Add(this.con_check_delete_logs);
+ this.con_GroupBox_5.Controls.Add(this.con_check_minimize_to_tray);
+ this.con_GroupBox_5.Location = new System.Drawing.Point(13, 370);
+ this.con_GroupBox_5.Name = "con_GroupBox_5";
+ this.con_GroupBox_5.Size = new System.Drawing.Size(323, 46);
+ this.con_GroupBox_5.TabIndex = 26;
+ this.con_GroupBox_5.TabStop = false;
+ this.con_GroupBox_5.Text = "Other settings";
//
- // TIM_Autostart
+ // con_check_delete_logs
//
- this.TIM_Autostart.Interval = 500;
+ this.con_check_delete_logs.AutoSize = true;
+ this.con_check_delete_logs.Checked = true;
+ this.con_check_delete_logs.CheckState = System.Windows.Forms.CheckState.Checked;
+ this.con_check_delete_logs.Location = new System.Drawing.Point(105, 19);
+ this.con_check_delete_logs.Name = "con_check_delete_logs";
+ this.con_check_delete_logs.Size = new System.Drawing.Size(138, 17);
+ this.con_check_delete_logs.TabIndex = 25;
+ this.con_check_delete_logs.Text = "Rotate logs after 7 days";
+ this.con_check_delete_logs.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageAboveText;
+ this.con_check_delete_logs.UseVisualStyleBackColor = true;
+ this.con_check_delete_logs.Validated += new System.EventHandler(this.con_check_delete_logs_Validated);
+ //
+ // con_GroupBox_6
+ //
+ this.con_GroupBox_6.Controls.Add(this.label26);
+ this.con_GroupBox_6.Controls.Add(this.label25);
+ this.con_GroupBox_6.Controls.Add(this.label24);
+ this.con_GroupBox_6.Controls.Add(this.label23);
+ this.con_GroupBox_6.Controls.Add(this.label22);
+ this.con_GroupBox_6.Controls.Add(this.label21);
+ this.con_GroupBox_6.Controls.Add(this.label16);
+ this.con_GroupBox_6.Controls.Add(this.label19);
+ this.con_GroupBox_6.Controls.Add(this.label18);
+ this.con_GroupBox_6.Controls.Add(this.label17);
+ this.con_GroupBox_6.Location = new System.Drawing.Point(343, 105);
+ this.con_GroupBox_6.Name = "con_GroupBox_6";
+ this.con_GroupBox_6.Size = new System.Drawing.Size(323, 76);
+ this.con_GroupBox_6.TabIndex = 28;
+ this.con_GroupBox_6.TabStop = false;
+ this.con_GroupBox_6.Text = "DCS World status";
+ //
+ // label26
+ //
+ this.label26.AutoSize = true;
+ this.label26.Location = new System.Drawing.Point(240, 53);
+ this.label26.Name = "label26";
+ this.label26.Size = new System.Drawing.Size(77, 13);
+ this.label26.TabIndex = 33;
+ this.label26.Text = "player(s) online";
+ this.label26.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // label25
+ //
+ this.label25.AutoSize = true;
+ this.label25.Location = new System.Drawing.Point(6, 55);
+ this.label25.Name = "label25";
+ this.label25.Size = new System.Drawing.Size(79, 13);
+ this.label25.TabIndex = 32;
+ this.label25.Text = "Mission uptime:";
+ this.label25.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // label24
+ //
+ this.label24.AutoSize = true;
+ this.label24.Location = new System.Drawing.Point(10, 42);
+ this.label24.Name = "label24";
+ this.label24.Size = new System.Drawing.Size(75, 13);
+ this.label24.TabIndex = 31;
+ this.label24.Text = "Server uptime:";
+ this.label24.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // label23
+ //
+ this.label23.AutoSize = true;
+ this.label23.Location = new System.Drawing.Point(54, 30);
+ this.label23.Name = "label23";
+ this.label23.Size = new System.Drawing.Size(31, 13);
+ this.label23.TabIndex = 30;
+ this.label23.Text = "Map:";
+ this.label23.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // label22
+ //
+ this.label22.AutoSize = true;
+ this.label22.Location = new System.Drawing.Point(40, 17);
+ this.label22.Name = "label22";
+ this.label22.Size = new System.Drawing.Size(45, 13);
+ this.label22.TabIndex = 29;
+ this.label22.Text = "Mission:";
+ this.label22.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // label21
+ //
+ this.label21.AutoSize = true;
+ this.label21.Location = new System.Drawing.Point(82, 55);
+ this.label21.Name = "label21";
+ this.label21.Size = new System.Drawing.Size(69, 13);
+ this.label21.TabIndex = 28;
+ this.label21.Text = "[mission time]";
+ //
+ // label16
+ //
+ this.label16.AutoSize = true;
+ this.label16.Location = new System.Drawing.Point(82, 42);
+ this.label16.Name = "label16";
+ this.label16.Size = new System.Drawing.Size(64, 13);
+ this.label16.TabIndex = 27;
+ this.label16.Text = "[server time]";
+ this.label16.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // label19
+ //
+ this.label19.AutoSize = true;
+ this.label19.Font = new System.Drawing.Font("Microsoft Sans Serif", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(238)));
+ this.label19.Location = new System.Drawing.Point(267, 31);
+ this.label19.Name = "label19";
+ this.label19.RightToLeft = System.Windows.Forms.RightToLeft.Yes;
+ this.label19.Size = new System.Drawing.Size(50, 24);
+ this.label19.TabIndex = 2;
+ this.label19.Text = "[000]";
+ this.label19.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
+ //
+ // label18
+ //
+ this.label18.AutoSize = true;
+ this.label18.Location = new System.Drawing.Point(82, 29);
+ this.label18.Name = "label18";
+ this.label18.Size = new System.Drawing.Size(70, 13);
+ this.label18.TabIndex = 1;
+ this.label18.Text = "[mission map]";
+ //
+ // label17
+ //
+ this.label17.AutoSize = true;
+ this.label17.Location = new System.Drawing.Point(82, 16);
+ this.label17.Name = "label17";
+ this.label17.Size = new System.Drawing.Size(76, 13);
+ this.label17.TabIndex = 0;
+ this.label17.Text = "[mission name]";
+ //
+ // con_GroupBox_7
+ //
+ this.con_GroupBox_7.Controls.Add(this.label33);
+ this.con_GroupBox_7.Controls.Add(this.label32);
+ this.con_GroupBox_7.Controls.Add(this.label31);
+ this.con_GroupBox_7.Controls.Add(this.label30);
+ this.con_GroupBox_7.Controls.Add(this.label29);
+ this.con_GroupBox_7.Controls.Add(this.label28);
+ this.con_GroupBox_7.Controls.Add(this.label27);
+ this.con_GroupBox_7.Controls.Add(this.label20);
+ this.con_GroupBox_7.Location = new System.Drawing.Point(343, 187);
+ this.con_GroupBox_7.Name = "con_GroupBox_7";
+ this.con_GroupBox_7.Size = new System.Drawing.Size(323, 55);
+ this.con_GroupBox_7.TabIndex = 29;
+ this.con_GroupBox_7.TabStop = false;
+ this.con_GroupBox_7.Text = "System status";
+ //
+ // label33
+ //
+ this.label33.AutoSize = true;
+ this.label33.Location = new System.Drawing.Point(174, 34);
+ this.label33.Name = "label33";
+ this.label33.Size = new System.Drawing.Size(67, 13);
+ this.label33.TabIndex = 36;
+ this.label33.Text = "[frame delay]";
+ //
+ // label32
+ //
+ this.label32.AutoSize = true;
+ this.label32.Location = new System.Drawing.Point(86, 34);
+ this.label32.Name = "label32";
+ this.label32.Size = new System.Drawing.Size(87, 13);
+ this.label32.TabIndex = 35;
+ this.label32.Text = "Last frame delay:";
+ this.label32.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // label31
+ //
+ this.label31.AutoSize = true;
+ this.label31.Location = new System.Drawing.Point(174, 16);
+ this.label31.Name = "label31";
+ this.label31.Size = new System.Drawing.Size(61, 13);
+ this.label31.TabIndex = 34;
+ this.label31.Text = "[frame time]";
+ //
+ // label30
+ //
+ this.label30.AutoSize = true;
+ this.label30.Location = new System.Drawing.Point(92, 16);
+ this.label30.Name = "label30";
+ this.label30.Size = new System.Drawing.Size(81, 13);
+ this.label30.TabIndex = 34;
+ this.label30.Text = "Last frame time:";
+ this.label30.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // label29
+ //
+ this.label29.AutoSize = true;
+ this.label29.Location = new System.Drawing.Point(40, 34);
+ this.label29.Name = "label29";
+ this.label29.Size = new System.Drawing.Size(37, 13);
+ this.label29.TabIndex = 34;
+ this.label29.Text = "[RAM]";
+ //
+ // label28
+ //
+ this.label28.AutoSize = true;
+ this.label28.Location = new System.Drawing.Point(40, 16);
+ this.label28.Name = "label28";
+ this.label28.Size = new System.Drawing.Size(35, 13);
+ this.label28.TabIndex = 34;
+ this.label28.Text = "[CPU]";
+ //
+ // label27
+ //
+ this.label27.AutoSize = true;
+ this.label27.Location = new System.Drawing.Point(10, 34);
+ this.label27.Name = "label27";
+ this.label27.Size = new System.Drawing.Size(34, 13);
+ this.label27.TabIndex = 34;
+ this.label27.Text = "RAM:";
+ this.label27.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // label20
+ //
+ this.label20.AutoSize = true;
+ this.label20.Location = new System.Drawing.Point(10, 16);
+ this.label20.Name = "label20";
+ this.label20.Size = new System.Drawing.Size(32, 13);
+ this.label20.TabIndex = 34;
+ this.label20.Text = "CPU:";
+ this.label20.TextAlign = System.Drawing.ContentAlignment.MiddleRight;
+ //
+ // tim_HW_status
+ //
+ this.tim_HW_status.Enabled = true;
+ this.tim_HW_status.Interval = 1000;
+ this.tim_HW_status.Tick += new System.EventHandler(this.tim_HW_status_Tick);
//
// form_Main
//
this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
- this.ClientSize = new System.Drawing.Size(349, 653);
- this.Controls.Add(this.con_Button_Add_Marker);
+ this.ClientSize = new System.Drawing.Size(675, 485);
+ this.Controls.Add(this.con_GroupBox_7);
+ this.Controls.Add(this.con_GroupBox_6);
+ this.Controls.Add(this.con_GroupBox_5);
+ this.Controls.Add(this.con_GroupBox_4);
this.Controls.Add(this.label14);
this.Controls.Add(this.label13);
this.Controls.Add(this.con_img_logo);
- this.Controls.Add(this.con_Button_Reset_Flags);
- this.Controls.Add(this.label12);
- this.Controls.Add(this.label11);
- this.Controls.Add(this.label10);
- this.Controls.Add(this.label9);
- this.Controls.Add(this.con_img_lotATC);
- this.Controls.Add(this.con_img_srs);
- this.Controls.Add(this.con_img_dcs);
- this.Controls.Add(this.con_img_db);
this.Controls.Add(this.groupBox1);
this.Controls.Add(this.con_GroupBox_3);
this.Controls.Add(this.label5);
@@ -561,10 +905,12 @@
this.MaximizeBox = false;
this.Name = "form_Main";
this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen;
- this.Text = "Perun for DCS";
+ this.Text = "Perun for DCS World";
this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.form_Main_FormClosing);
this.Load += new System.EventHandler(this.form_Main_Load);
+ this.Resize += new System.EventHandler(this.form_Main_Resize);
this.con_GroupBox_1.ResumeLayout(false);
+ this.con_GroupBox_1.PerformLayout();
this.con_GroupBox_2.ResumeLayout(false);
this.con_GroupBox_2.PerformLayout();
this.con_GroupBox_3.ResumeLayout(false);
@@ -572,16 +918,21 @@
this.groupBox1.ResumeLayout(false);
this.groupBox1.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.con_img_logo)).EndInit();
+ this.con_GroupBox_4.ResumeLayout(false);
+ this.con_GroupBox_4.PerformLayout();
((System.ComponentModel.ISupportInitialize)(this.con_img_lotATC)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_srs)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_dcs)).EndInit();
((System.ComponentModel.ISupportInitialize)(this.con_img_db)).EndInit();
+ this.con_GroupBox_5.ResumeLayout(false);
+ this.con_GroupBox_5.PerformLayout();
+ this.con_GroupBox_6.ResumeLayout(false);
+ this.con_GroupBox_6.PerformLayout();
+ this.con_GroupBox_7.ResumeLayout(false);
+ this.con_GroupBox_7.PerformLayout();
this.ResumeLayout(false);
this.PerformLayout();
- // TIM_Autostart
- //
- this.TIM_Autostart.Tick += new System.EventHandler(this.TIM_Autostart_Tick);
- //
+
}
#endregion
@@ -620,20 +971,48 @@
private System.Windows.Forms.Label label7;
private System.Windows.Forms.Label label8;
private System.Windows.Forms.MaskedTextBox con_txt_dcs_instance;
- private System.Windows.Forms.PictureBox con_img_db;
- private System.Windows.Forms.PictureBox con_img_dcs;
- private System.Windows.Forms.PictureBox con_img_srs;
- private System.Windows.Forms.PictureBox con_img_lotATC;
- private System.Windows.Forms.Label label9;
- private System.Windows.Forms.Label label10;
- private System.Windows.Forms.Label label11;
- private System.Windows.Forms.Label label12;
- private System.Windows.Forms.Button con_Button_Reset_Flags;
private System.Windows.Forms.PictureBox con_img_logo;
private System.Windows.Forms.Label label13;
private System.Windows.Forms.Label label14;
private System.Windows.Forms.Button con_Button_Add_Marker;
private System.Windows.Forms.Timer TIM_Autostart;
+ private System.Windows.Forms.Label label15;
+ private System.Windows.Forms.ComboBox con_com_loglevel;
+ private System.Windows.Forms.CheckBox con_check_minimize_to_tray;
+ private System.Windows.Forms.GroupBox con_GroupBox_4;
+ private System.Windows.Forms.Button con_Button_Reset_Flags;
+ private System.Windows.Forms.Label label12;
+ private System.Windows.Forms.Label label11;
+ private System.Windows.Forms.Label label10;
+ private System.Windows.Forms.Label label9;
+ private System.Windows.Forms.PictureBox con_img_lotATC;
+ private System.Windows.Forms.PictureBox con_img_srs;
+ private System.Windows.Forms.PictureBox con_img_dcs;
+ private System.Windows.Forms.PictureBox con_img_db;
+ private System.Windows.Forms.GroupBox con_GroupBox_5;
+ private System.Windows.Forms.GroupBox con_GroupBox_6;
+ private System.Windows.Forms.Label label26;
+ private System.Windows.Forms.Label label25;
+ private System.Windows.Forms.Label label24;
+ private System.Windows.Forms.Label label23;
+ private System.Windows.Forms.Label label22;
+ private System.Windows.Forms.Label label21;
+ private System.Windows.Forms.Label label16;
+ private System.Windows.Forms.Label label19;
+ private System.Windows.Forms.Label label18;
+ private System.Windows.Forms.Label label17;
+ private System.Windows.Forms.GroupBox con_GroupBox_7;
+ private System.Windows.Forms.Label label29;
+ private System.Windows.Forms.Label label28;
+ private System.Windows.Forms.Label label27;
+ private System.Windows.Forms.Label label20;
+ private System.Windows.Forms.Timer tim_HW_status;
+ private System.Windows.Forms.Button con_Button_See_log;
+ private System.Windows.Forms.CheckBox con_check_delete_logs;
+ private System.Windows.Forms.Label label31;
+ private System.Windows.Forms.Label label30;
+ private System.Windows.Forms.Label label33;
+ private System.Windows.Forms.Label label32;
}
}
diff --git a/02_Windows_App/Perun_v1/02_Forms/form_Main.cs b/02_Windows_App/Perun_v1/02_Forms/form_Main.cs
index b0a4fed..d15a09e 100644
--- a/02_Windows_App/Perun_v1/02_Forms/form_Main.cs
+++ b/02_Windows_App/Perun_v1/02_Forms/form_Main.cs
@@ -2,6 +2,7 @@
using System;
using System.Diagnostics;
using System.Drawing;
+using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
@@ -10,22 +11,20 @@ namespace Perun_v1
public partial class form_Main : Form
{
// Variable definitions
- public string[] DatabaseSendBuffer = new string[50]; // MySQL send buffer
+
public bool AppCanClose = false; // Helper to handle system tray - true needed to quit the app
-
- public DatabaseController DatabaseConnection = new DatabaseController(); // Main MySQL controller
- public TCPController TCPServer = new TCPController(); // Main TCP controller
-
public bool ExtSRSStatus; // True if to use empty/default SRS status
public bool ExtLotATCStatus; // True if to use empty/default LotATC status
// ################################ Main ################################
private void form_Main_Load(object sender, EventArgs e)
{
- // Form loaded
- Globals.AppLogHistory[0] = DateTime.Now.ToString("HH:mm:ss") + " > " + "Perun started"; // Add information to the log control
- form_Main_LoadSettings(); // Load settings from registry
+ // Load settings from registry
+ form_Main_LoadSettings();
+ // Form loaded
+ PerunHelper.LogInfo(ref Globals.AppLogHistory, PerunHelper.GetAppVersion("Perun started - "));
+
// Display build version in title bar
Globals.AppTitle = PerunHelper.GetAppVersion(this.Text + " - ");
this.Text = Globals.AppTitle;
@@ -54,7 +53,7 @@ namespace Perun_v1
}
}
}
-
+
if (args.Length > 3)
{
// Get argument DCS SRS file path
@@ -90,7 +89,7 @@ namespace Perun_v1
if (args[5] != "-1")
{
TIM_Autostart.Enabled = true;
- PerunHelper.AddLog(ref Globals.AppLogHistory, "Autostart parameter provided", 0, 1);
+ PerunHelper.LogInfo(ref Globals.AppLogHistory, "Autostart parameter provided", 0, 1);
}
}
}
@@ -101,6 +100,8 @@ namespace Perun_v1
con_img_dcs.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected");
con_img_lotATC.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected");
con_img_srs.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected");
+
+ this.form_Main_SetBlankMissionInfo();
}
public form_Main()
@@ -124,6 +125,9 @@ namespace Perun_v1
con_check_3rd_srs.Checked = Properties.Settings.Default.OTHER_SRS_USE;
con_txt_dcs_server_port.Text = Properties.Settings.Default.DCS_Server_Port.ToString();
con_txt_dcs_instance.Text = Properties.Settings.Default.DCS_Instance.ToString();
+ con_com_loglevel.SelectedIndex = Properties.Settings.Default.OTHER_Log_Level;
+ con_check_minimize_to_tray.Checked = Properties.Settings.Default.OTHER_Minimize_to_Tray;
+ con_check_delete_logs.Checked = Properties.Settings.Default.OTHER_Log_Rotate;
}
private void form_Main_SaveSettings()
@@ -142,6 +146,9 @@ namespace Perun_v1
Properties.Settings.Default.OTHER_SRS_USE = con_check_3rd_srs.Checked;
Properties.Settings.Default.DCS_Server_Port = Int32.Parse(con_txt_dcs_server_port.Text);
Properties.Settings.Default.DCS_Instance = Int32.Parse(con_txt_dcs_instance.Text);
+ Properties.Settings.Default.OTHER_Log_Level = con_com_loglevel.SelectedIndex;
+ Properties.Settings.Default.OTHER_Minimize_to_Tray = con_check_minimize_to_tray.Checked;
+ Properties.Settings.Default.OTHER_Log_Rotate = con_check_delete_logs.Checked;
Properties.Settings.Default.Save();
}
@@ -165,6 +172,7 @@ namespace Perun_v1
con_check_3rd_srs.Enabled = false;
con_txt_dcs_server_port.Enabled = false;
con_txt_dcs_instance.Enabled = false;
+ con_com_loglevel.Enabled = true;
}
private void form_Main_SetControlsToDisconnected()
@@ -186,7 +194,21 @@ namespace Perun_v1
con_check_3rd_srs.Enabled = true;
con_txt_dcs_server_port.Enabled = true;
con_txt_dcs_instance.Enabled = true;
+ con_com_loglevel.Enabled = true;
+ this.form_Main_SetBlankMissionInfo();
+ }
+
+ private void form_Main_SetBlankMissionInfo()
+ {
+ // Init values for the controls
+
+ // Mission information
+ label16.Text = "[unknown]";
+ label17.Text = "[unknown]";
+ label18.Text = "[unknown]";
+ label19.Text = "?";
+ label21.Text = "[unknown]";
}
// ################################ User input ################################
@@ -196,27 +218,27 @@ namespace Perun_v1
// Set globals
Globals.AppInstanceID = Int32.Parse(con_txt_dcs_instance.Text);
Globals.AppForceIconReload = true;
- Globals.ErrorsDatabase = 0; // Reset error counter
+ Globals.ErrorsDatabase = 0; // Reset error counter
Globals.ErrorsGame = 0; // Reset error counter
Globals.ErrorsSRS = 0; // Reset error counter
Globals.ErrorsLotATC = 0; // Reset error counter
- Globals.StatusConnection = false; // Reset connection status
+ Globals.StatusConnection = false; // Reset connection status
// Prepare GUI
form_Main_SetControlsToConnected();
form_Main_SaveSettings();
- this.Text = "[#" + con_txt_dcs_instance.Text + "] " + Globals.AppTitle; // Set title bar
+ this.Text = $"[#{con_txt_dcs_instance.Text}] {Globals.AppTitle}"; // Set title bar
trayIconMain.Text = this.Text; // Set notification icon text
// Prepare MySQL connection string
- DatabaseConnection.DatabaseConnectionString = "server=" + con_txt_mysql_server.Text + ";user=" + con_txt_mysql_username.Text + ";database=" + con_txt_mysql_database.Text + ";port=" + con_txt_mysql_port.Text + ";password=" + con_txt_mysql_password.Text;
+ Globals.DatabaseConnection.DatabaseConnectionString = $"server={con_txt_mysql_server.Text};user={con_txt_mysql_username.Text};database={con_txt_mysql_database.Text};port={con_txt_mysql_port.Text};password={con_txt_mysql_password.Text}";
// Start listening
- PerunHelper.AddLog(ref Globals.AppLogHistory, "Opening connections", 0, 1);
- TCPServer.Create(Int32.Parse(con_txt_dcs_server_port.Text), ref Globals.AppLogHistory, ref DatabaseSendBuffer);
- TCPServer.thrTCPListener = new Thread(TCPServer.StartListen);
- TCPServer.thrTCPListener.Start();
- TCPServer.thrTCPListener.Name = "TCPThread";
+ PerunHelper.LogInfo(ref Globals.AppLogHistory, "Opening connections", 0, 1);
+ Globals.TCPServer.Create(Int32.Parse(con_txt_dcs_server_port.Text), ref Globals.AppLogHistory, ref Globals.DatabaseSendBuffer);
+ Globals.TCPServer.thrTCPListener = new Thread(Globals.TCPServer.StartListen);
+ Globals.TCPServer.thrTCPListener.Start();
+ Globals.TCPServer.thrTCPListener.Name = "TCPThread";
// Start timmers
tim_MySQL.Enabled = true;
@@ -233,7 +255,7 @@ namespace Perun_v1
{
// Stop listening
// Prepare GUI
- PerunHelper.AddLog(ref Globals.AppLogHistory, "Closing connections", 0, 1);
+ PerunHelper.LogInfo(ref Globals.AppLogHistory, "Closing connections", 0, 1);
con_Button_Listen_OFF.Enabled = false;
Tim_GUI_Tick(null, null);
this.Refresh();
@@ -247,15 +269,15 @@ namespace Perun_v1
try
{
// Stop the server
- TCPServer.StopListen();
+ Globals.TCPServer.StopListen();
}
catch (Exception ex)
{
- PerunHelper.AddLog(ref Globals.AppLogHistory, "TCP ERROR, error: " + ex.Message, 2, 1, "?");
+ PerunHelper.LogError(ref Globals.AppLogHistory, $"ERROR TCP, error: {ex.Message}", 2, 1, "?");
Console.WriteLine(ex.ToString());
}
- while (TCPServer.thrTCPListener.IsAlive)
+ while (Globals.TCPServer.thrTCPListener.IsAlive)
{
// Wait untill TCP server closed connection
Thread.Sleep(200); //ms
@@ -269,7 +291,7 @@ namespace Perun_v1
con_img_srs.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected");
// Display information about closed connections
- PerunHelper.AddLog(ref Globals.AppLogHistory, "Connections closed", 0, 1);
+ PerunHelper.LogInfo(ref Globals.AppLogHistory, "Connections closed", 0, 1);
Tim_GUI_Tick(null, null);
// Set title bar
@@ -323,21 +345,76 @@ namespace Perun_v1
}
}
+ private void con_com_loglevell_SelectedIndexChanged(object sender, EventArgs e)
+ {
+ // Changed log level state
+ LogController.instance.level = con_com_loglevel.SelectedIndex;
+ }
+
+ private void con_check_minimize_to_tray_Validated(object sender, EventArgs e)
+ {
+ // Changed close to try state
+ Properties.Settings.Default.OTHER_Minimize_to_Tray = con_check_minimize_to_tray.Checked;
+ }
+
+ private void con_check_delete_logs_Validated(object sender, EventArgs e)
+ {
+ // Changed rotate logs state
+ Properties.Settings.Default.OTHER_Log_Rotate = con_check_delete_logs.Checked;
+ }
+
+ private void con_Button_Reset_Flags_Click(object sender, EventArgs e)
+ {
+ // Reset error flags
+ DialogResult dialogResult = MessageBox.Show("Are you sure to reset error flags?", "Question", MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
+ if (dialogResult == DialogResult.Yes)
+ {
+ // Reset errors counter
+ Globals.ErrorsDatabase = 0; // MySQL - Error counter
+ Globals.ErrorsGame = 0; // TCP connection - Error counter
+ Globals.ErrorsHistoryGame = 0; // TCP connection - historic value of Error counter
+ Globals.ErrorsSRS = 0; // DCS SRS - error counter
+ Globals.ErrorsLotATC = 0; // LotATC - error counter
+
+ // Force icons reload
+ Globals.AppForceIconReload = true;
+
+ // Add information
+ PerunHelper.LogInfo(ref Globals.AppLogHistory, "Resetted error counter", 0, 1);
+ }
+ else if (dialogResult == DialogResult.No)
+ {
+ // Do nothing
+ }
+
+ }
+
+ private void con_Button_Add_Marker_Click(object sender, EventArgs e)
+ {
+ // Added user marker
+ PerunHelper.LogError(ref Globals.AppLogHistory, "User Marker", 0, 1);
+ }
+
// ################################ Form state ################################
private void con_Button_Quit_Click(object sender, EventArgs e)
{
// Try to close app
- DialogResult dialogResult = MessageBox.Show("Are you sure to exit Perun?", "Question", MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
- if (dialogResult == DialogResult.Yes)
+ if (tim_MySQL.Enabled == false)
{
- form_Main_SaveSettings();
+ DialogResult dialogResult = MessageBox.Show("Are you sure to exit Perun?", "Question", MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
+ if (dialogResult == DialogResult.Yes)
+ {
+ form_Main_SaveSettings();
- AppCanClose = true; // Save settings on exit
- this.Close(); // Allow to exit application
- }
- else if (dialogResult == DialogResult.No)
- {
- //do nothing
+ AppCanClose = true; // Save settings on exit
+ this.Close(); // Allow to exit application
+ }
+ else if (dialogResult == DialogResult.No)
+ {
+ //do nothing
+ }
+ } else {
+ MessageBox.Show("You cannot exit Perun while the connections are open. Stop the server and try again.");
}
}
@@ -345,8 +422,32 @@ namespace Perun_v1
{
// Sends app to system tray
trayIconMain.Visible = true;
+
+ // For instances 1-5 we have prepared special icons
+ switch (Globals.AppInstanceID)
+ {
+ case 1:
+ trayIconMain.Icon = Perun_v1.Properties.Resources.perun_logo_1;
+ break;
+ case 2:
+ trayIconMain.Icon = Perun_v1.Properties.Resources.perun_logo_2;
+ break;
+ case 3:
+ trayIconMain.Icon = Perun_v1.Properties.Resources.perun_logo_3;
+ break;
+ case 4:
+ trayIconMain.Icon = Perun_v1.Properties.Resources.perun_logo_4;
+ break;
+ case 5:
+ trayIconMain.Icon = Perun_v1.Properties.Resources.perun_logo_5;
+ break;
+ default:
+ break;
+ }
+
+
this.WindowState = FormWindowState.Minimized;
- this.ShowInTaskbar = false;
+ this.ShowInTaskbar = false;
}
private void form_Main_BringFromTray()
@@ -360,12 +461,10 @@ namespace Perun_v1
{
WindowState = FormWindowState.Normal;
}
- // get our current "TopMost" value (ours will always be false though)
- bool top = TopMost;
- // make our form jump to the top of everything
- TopMost = true;
- // set it back to whatever it was
- TopMost = top;
+
+ bool top = TopMost; // Get our current "TopMost" value (ours will always be false though)
+ TopMost = true; // Make our form jump to the top of everything
+ TopMost = top; // Set it back to whatever it was
}
private void form_Main_FormClosing(object sender, FormClosingEventArgs e)
@@ -374,7 +473,7 @@ namespace Perun_v1
if (e.CloseReason == CloseReason.UserClosing && !AppCanClose)
{
e.Cancel = true;
- form_Main_SendToTray(); // Send app to system tray
+ con_Button_Quit_Click(sender, e);
}
}
@@ -384,6 +483,17 @@ namespace Perun_v1
form_Main_BringFromTray(); // Bring app from system tray
}
+ private void form_Main_Resize(object sender, EventArgs e)
+ {
+ // Form was minimised to try
+ if (WindowState == FormWindowState.Minimized)
+ {
+ if (con_check_minimize_to_tray.Checked) // Check if user wants to minimize to tray icon
+ {
+ form_Main_SendToTray();
+ }
+ }
+ }
// ################################ Timers ################################
private void Tim_GUI_Tick(object sender, EventArgs e)
{
@@ -407,10 +517,37 @@ namespace Perun_v1
// Do nothing , control does not require update
}
- // Update status icons at main form - MySQL
- if ((DatabaseConnection.DatabaseStatus != Globals.StatusDatabase) || Globals.AppForceIconReload)
+ // Enable see log button
+ if(Globals.LastLogLocation != "")
{
- if (DatabaseConnection.DatabaseStatus)
+ con_Button_See_log.Enabled = true;
+ }
+
+ // Update mission status
+ if (Globals.CurrentMission.Mission != "")
+ {
+
+ label17.Text = Globals.CurrentMission.Mission;
+ label18.Text = Globals.CurrentMission.Theatre;
+ label19.Text = Globals.CurrentMission.PlayerCount.ToString();
+
+ label21.Text = PerunHelper.SecondsToString(Globals.CurrentMission.ModelTime);
+ label16.Text = PerunHelper.SecondsToString(Globals.CurrentMission.RealTime);
+
+ if (Globals.CurrentMission.Pause == "True")
+ {
+ label21.Text = $"{label21.Text} (paused)";
+ }
+ }
+ else
+ {
+ this.form_Main_SetBlankMissionInfo();
+ }
+
+ // Update status icons at main form - MySQL
+ if ((Globals.DatabaseConnection.DatabaseStatus != Globals.StatusDatabase) || Globals.AppForceIconReload)
+ {
+ if (Globals.DatabaseConnection.DatabaseStatus)
{
if (Globals.ErrorsDatabase == 0)
{
@@ -425,7 +562,7 @@ namespace Perun_v1
{
con_img_db.Image = (Image)Properties.Resources.ResourceManager.GetObject("status_disconnected_error");
}
- Globals.StatusDatabase = DatabaseConnection.DatabaseStatus;
+ Globals.StatusDatabase = Globals.DatabaseConnection.DatabaseStatus;
}
// Update status icons at main form - DCS
if ((Globals.StatusConnection != Globals.StatusHistoryConnection) || Globals.AppForceIconReload || Globals.ErrorsGame != Globals.ErrorsHistoryGame)
@@ -448,6 +585,14 @@ namespace Perun_v1
Globals.StatusHistoryConnection = Globals.StatusConnection;
Globals.ErrorsHistoryGame = Globals.ErrorsGame;
}
+
+ // Frame times
+ label31.Text = $"{Globals.LastFrameTime.ToString("0.")}u";
+ label33.Text = $"{Globals.LastFrameDelay.ToString("0.")}u";
+
+ // Check if we shall rate logs
+ Globals.RotateLogs = con_check_minimize_to_tray.Checked;
+
// Update status icons at main form - SRS
if ((ExtSRSStatus != Globals.StatusSRS) || Globals.AppForceIconReload)
{
@@ -494,13 +639,13 @@ namespace Perun_v1
private void Tim_MySQL_Tick(object sender, EventArgs e)
{
// Send buffer to MySQL
- for (int i = 0; i < DatabaseSendBuffer.Length - 1; i++)
+ for (int i = 0; i < Globals.DatabaseSendBuffer.Length - 1; i++)
{
- if (DatabaseSendBuffer[i] != null)
+ if (Globals.DatabaseSendBuffer[i] != null)
{
- if (DatabaseConnection.SendToMySql(DatabaseSendBuffer[i]) > 0)
+ if (Globals.DatabaseConnection.SendToMySql(Globals.DatabaseSendBuffer[i]) > 0)
{
- DatabaseSendBuffer[i] = null; // If packet was send then delete it from send buffer
+ Globals.DatabaseSendBuffer[i] = null; // If packet was send then delete it from send buffer
}
}
}
@@ -511,7 +656,7 @@ namespace Perun_v1
// Main timer to check MySQL connection and send JSON files to MySQL
// Send ping to check for possible connection issues
- DatabaseConnection.SendToMySql("", true);
+ Globals.DatabaseConnection.SendToMySql("", true);
if (PerunHelper.CheckVersions() == 0)
{
@@ -522,6 +667,7 @@ namespace Perun_v1
// Take care of 3rd party stuff
string ExtSRSJson = "";
string ExtLotATCJson = "";
+ string ClientName = "";
bool ExtSRSUseDefault = true;
bool ExtLotATCUseDefault = true;
@@ -534,36 +680,45 @@ namespace Perun_v1
try
{
ExtSRSJson = System.IO.File.ReadAllText(con_txt_3rd_srs.Text);
- dynamic raw_lotatc = JsonConvert.DeserializeObject(ExtSRSJson);
+ dynamic raw_dcssrs = JsonConvert.DeserializeObject(ExtSRSJson);
- for (int i = 0; i < raw_lotatc.Clients.Count; i++)
+ for (int i = 0; i < raw_dcssrs.Clients.Count; i++)
{
- if (raw_lotatc.Clients[i].RadioInfo != null)
+ if (raw_dcssrs.Clients[i].RadioInfo != null)
{
- int temp = raw_lotatc.Clients[i].RadioInfo.radios.Count - 1;
+ int temp = raw_dcssrs.Clients[i].RadioInfo.radios.Count - 1;
for (int j = temp; j >= 0; j--)
{
-
- if (raw_lotatc.Clients[i].RadioInfo.radios[j].name == "No Radio")
+ if (raw_dcssrs.Clients[i].RadioInfo.radios[j].name == "No Radio")
{
- raw_lotatc.Clients[i].RadioInfo.radios[j].Remove();
+ raw_dcssrs.Clients[i].RadioInfo.radios[j].Remove();
}
}
}
+ if (raw_dcssrs.Clients[i].Name != null)
+ {
+ // Clean the user names from non alphanumeric characters
+ ClientName = raw_dcssrs.Clients[i].Name;
+ Regex rgx = new Regex("[^a-zA-Z0-9 -]");
+ ClientName = rgx.Replace(ClientName, "");
+
+ raw_dcssrs.Clients[i].Name = ClientName;
+ }
}
- ExtSRSJson = JsonConvert.SerializeObject(raw_lotatc);
- ExtSRSJson = "{'type':'100','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':'" + ExtSRSJson + "'}";
+ ExtSRSJson = JsonConvert.SerializeObject(raw_dcssrs);
+
+ ExtSRSJson = $"{{'type':'100','instance':'{Int32.Parse(con_txt_dcs_instance.Text)}','payload':{ExtSRSJson}}}";
ExtSRSUseDefault = false;
- PerunHelper.AddLog(ref Globals.AppLogHistory, "SRS data loaded", 3, 0, "100", true);
+ PerunHelper.LogInfo(ref Globals.AppLogHistory, "SRS data loaded", 3, 0, "100", true);
ExtSRSStatus = true;
}
catch (Exception exc_srs)
{
- PerunHelper.AddLog(ref Globals.AppLogHistory, "SRS data ERROR , error: " + exc_srs.Message, 3, 1, "100");
+ PerunHelper.LogError(ref Globals.AppLogHistory, $"ERROR SRS Data, error: {exc_srs.Message}", 3, 1, "100");
ExtSRSStatus = false;
Globals.ErrorsSRS++;
}
@@ -572,11 +727,11 @@ namespace Perun_v1
}
if (ExtSRSUseDefault)
{
- ExtSRSJson = "{'type':'100','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':{'ignore':'true'}}";
+ ExtSRSJson = $"{{'type':'100','instance':'{Int32.Parse(con_txt_dcs_instance.Text)}','payload':{{'ignore':'true'}}";
}
if (ExtSRSStatus)
{
- DatabaseConnection.SendToMySql(ExtSRSJson);
+ Globals.DatabaseConnection.SendToMySql(ExtSRSJson);
}
}
@@ -588,16 +743,15 @@ namespace Perun_v1
try
{
ExtLotATCJson = System.IO.File.ReadAllText(con_txt_3rd_lotatc.Text);
- dynamic raw_srs = JsonConvert.DeserializeObject(ExtLotATCJson);
- ExtLotATCJson = "{'type':'101','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':'" + ExtLotATCJson + "'}";
+ ExtLotATCJson = $"{{'type':'101','instance':'{Int32.Parse(con_txt_dcs_instance.Text)}','payload':{ExtLotATCJson}}}";
ExtLotATCUseDefault = false;
- PerunHelper.AddLog(ref Globals.AppLogHistory, "LotATC data loaded", 3, 0, "101", true);
+ PerunHelper.LogInfo(ref Globals.AppLogHistory, "LotATC data loaded", 3, 0, "101", true);
ExtLotATCStatus = true;
}
catch (Exception exc_lotatc)
{
- PerunHelper.AddLog(ref Globals.AppLogHistory, "LotATC data ERROR, error: " + exc_lotatc.Message, 3, 1, "101");
+ PerunHelper.LogError(ref Globals.AppLogHistory, $"ERROR LotATC Data, error: {exc_lotatc.Message}", 3, 1, "101");
ExtLotATCStatus = false;
Globals.ErrorsLotATC++;
}
@@ -606,11 +760,11 @@ namespace Perun_v1
}
if (ExtLotATCUseDefault)
{
- ExtLotATCJson = "{'type':'101','instance':'" + Int32.Parse(con_txt_dcs_instance.Text) + "','payload':{'ignore':'true'}}"; // No LotATC controller connected
+ ExtLotATCJson = $"{{'type':'101','instance':'{Int32.Parse(con_txt_dcs_instance.Text)}','payload':{{'ignore':'true'}}}}"; // No LotATC controller connected
}
if (ExtLotATCStatus)
{
- DatabaseConnection.SendToMySql(ExtLotATCJson);
+ Globals.DatabaseConnection.SendToMySql(ExtLotATCJson);
}
}
@@ -622,43 +776,27 @@ namespace Perun_v1
}
- private void con_Button_Reset_Flags_Click(object sender, EventArgs e)
+ private void tim_HW_status_Tick(object sender, EventArgs e)
{
- // Reset error flags
- DialogResult dialogResult = MessageBox.Show("Are you sure to reset error flags?", "Question", MessageBoxButtons.YesNo, System.Windows.Forms.MessageBoxIcon.Question);
- if (dialogResult == DialogResult.Yes)
- {
- // Reset errors counter
- Globals.ErrorsDatabase = 0; // MySQL - Error counter
- Globals.ErrorsGame = 0; // TCP connection - Error counter
- Globals.ErrorsHistoryGame = 0; // TCP connection - historic value of Error counter
- Globals.ErrorsSRS = 0; // DCS SRS - error counter
- Globals.ErrorsLotATC = 0; // LotATC - error counter
-
- // Force icons reload
- Globals.AppForceIconReload = true;
-
- // Add information
- PerunHelper.AddLog(ref Globals.AppLogHistory, "Resetted error counter", 0, 1);
- }
- else if (dialogResult == DialogResult.No)
- {
- // Do nothing
- }
-
+ //Handle getting of system status
+ label28.Text = $"{Globals.HardwareMonitor.getCurrentCpuUsage()}%";
+ label29.Text = $"{Globals.HardwareMonitor.getCurrentRamUsage()}%";
}
-
- private void con_Button_Add_Marker_Click(object sender, EventArgs e)
- {
- // Added user marker
- PerunHelper.AddLog(ref Globals.AppLogHistory, "User Marker", 0, 1);
- }
-
+
private void TIM_Autostart_Tick(object sender, EventArgs e)
{
// Handle autostart parameter from command line
TIM_Autostart.Enabled = false; // Disable timer
- con_Button_Listen_ON_Click(sender,e); // Simulate button click
+ con_Button_Listen_ON_Click(sender, e); // Simulate button click
}
+
+ private void con_Button_See_log_Click(object sender, EventArgs e)
+ {
+ if (Globals.LastLogLocation != "")
+ {
+ Process.Start(Globals.LastLogLocation);
+ }
+ }
+
}
}
diff --git a/02_Windows_App/Perun_v1/02_Forms/form_Main.resx b/02_Windows_App/Perun_v1/02_Forms/form_Main.resx
index 11d5fd4..62757df 100644
--- a/02_Windows_App/Perun_v1/02_Forms/form_Main.resx
+++ b/02_Windows_App/Perun_v1/02_Forms/form_Main.resx
@@ -420,10 +420,13 @@
687, 19
- 800, 4
+ 681, 56
+
+
+ 552, 55
- 26
+ 181
diff --git a/02_Windows_App/Perun_v1/03_Resources/perun_logo_1.ico b/02_Windows_App/Perun_v1/03_Resources/perun_logo_1.ico
new file mode 100644
index 0000000..0889dbd
Binary files /dev/null and b/02_Windows_App/Perun_v1/03_Resources/perun_logo_1.ico differ
diff --git a/02_Windows_App/Perun_v1/03_Resources/perun_logo_2.ico b/02_Windows_App/Perun_v1/03_Resources/perun_logo_2.ico
new file mode 100644
index 0000000..696a1a5
Binary files /dev/null and b/02_Windows_App/Perun_v1/03_Resources/perun_logo_2.ico differ
diff --git a/02_Windows_App/Perun_v1/03_Resources/perun_logo_3.ico b/02_Windows_App/Perun_v1/03_Resources/perun_logo_3.ico
new file mode 100644
index 0000000..8bbc22f
Binary files /dev/null and b/02_Windows_App/Perun_v1/03_Resources/perun_logo_3.ico differ
diff --git a/02_Windows_App/Perun_v1/03_Resources/perun_logo_4.ico b/02_Windows_App/Perun_v1/03_Resources/perun_logo_4.ico
new file mode 100644
index 0000000..7199449
Binary files /dev/null and b/02_Windows_App/Perun_v1/03_Resources/perun_logo_4.ico differ
diff --git a/02_Windows_App/Perun_v1/03_Resources/perun_logo_5.ico b/02_Windows_App/Perun_v1/03_Resources/perun_logo_5.ico
new file mode 100644
index 0000000..ca02f44
Binary files /dev/null and b/02_Windows_App/Perun_v1/03_Resources/perun_logo_5.ico differ
diff --git a/02_Windows_App/Perun_v1/Perun_v1.csproj b/02_Windows_App/Perun_v1/Perun_v1.csproj
index b0fe9fd..7083635 100644
--- a/02_Windows_App/Perun_v1/Perun_v1.csproj
+++ b/02_Windows_App/Perun_v1/Perun_v1.csproj
@@ -14,7 +14,7 @@
truefalse
- C:\Users\DCS\Desktop\Perun\
+ C:\Users\Gildias1s2\Desktop\Perun\trueDiskfalse
@@ -31,8 +31,8 @@
szporwolikPerunPerun.htm
- 1
- 0.11.1.%2a
+ 0
+ 0.12.0.%2afalsetruetrue
@@ -62,7 +62,8 @@
- 03_Resources\perun_logo.ico
+
+ 2ACE4C8C2C325A04CA5986B1CD76744B4B03755D
@@ -170,10 +171,10 @@
Resources.Designer.cs
-
+ SettingsSingleFileGeneratorSettings.Designer.cs
@@ -195,7 +196,7 @@
False
- Microsoft .NET Framework 4.6.1 %28x86 and x64%29
+ Microsoft .NET Framework 4.6.1 %28x86 i x64%29true
@@ -205,14 +206,27 @@
-
+
+
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/02_Windows_App/Perun_v1/Properties/AssemblyInfo.cs b/02_Windows_App/Perun_v1/Properties/AssemblyInfo.cs
index f6a876c..2c68d47 100644
--- a/02_Windows_App/Perun_v1/Properties/AssemblyInfo.cs
+++ b/02_Windows_App/Perun_v1/Properties/AssemblyInfo.cs
@@ -33,7 +33,7 @@ using System.Runtime.InteropServices;
// Możesz określić wszystkie wartości lub użyć domyślnych numerów kompilacji i poprawki
// przy użyciu symbolu „*”, tak jak pokazano poniżej:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("0.11.1.0")]
-[assembly: AssemblyFileVersion("0.11.1.0")]
+[assembly: AssemblyVersion("0.12.0.0")]
+[assembly: AssemblyFileVersion("0.12.0.0")]
[assembly: NeutralResourcesLanguage("en")]
diff --git a/02_Windows_App/Perun_v1/Properties/DataSources/Globals.datasource b/02_Windows_App/Perun_v1/Properties/DataSources/Globals.datasource
new file mode 100644
index 0000000..9e2a905
--- /dev/null
+++ b/02_Windows_App/Perun_v1/Properties/DataSources/Globals.datasource
@@ -0,0 +1,10 @@
+
+
+
+ Globals, Perun, Version=0.12.0.0, Culture=neutral, PublicKeyToken=null
+
\ No newline at end of file
diff --git a/02_Windows_App/Perun_v1/Properties/Resources.Designer.cs b/02_Windows_App/Perun_v1/Properties/Resources.Designer.cs
index f3d5c91..73ef024 100644
--- a/02_Windows_App/Perun_v1/Properties/Resources.Designer.cs
+++ b/02_Windows_App/Perun_v1/Properties/Resources.Designer.cs
@@ -1,10 +1,10 @@
//------------------------------------------------------------------------------
//
-// This code was generated by a tool.
-// Runtime Version:4.0.30319.42000
+// Ten kod został wygenerowany przez narzędzie.
+// Wersja wykonawcza:4.0.30319.42000
//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
+// Zmiany w tym pliku mogą spowodować nieprawidłowe zachowanie i zostaną utracone, jeśli
+// kod zostanie ponownie wygenerowany.
//
//------------------------------------------------------------------------------
@@ -13,12 +13,12 @@ namespace Perun_v1.Properties {
///
- /// A strongly-typed resource class, for looking up localized strings, etc.
+ /// Klasa zasobu wymagająca zdefiniowania typu do wyszukiwania zlokalizowanych ciągów itd.
///
- // This class was auto-generated by the StronglyTypedResourceBuilder
- // class via a tool like ResGen or Visual Studio.
- // To add or remove a member, edit your .ResX file then rerun ResGen
- // with the /str option, or rebuild your VS project.
+ // Ta klasa została automatycznie wygenerowana za pomocą klasy StronglyTypedResourceBuilder
+ // przez narzędzie, takie jak ResGen lub Visual Studio.
+ // Aby dodać lub usunąć składową, edytuj plik ResX, a następnie ponownie uruchom narzędzie ResGen
+ // z opcją /str lub ponownie utwórz projekt VS.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
@@ -33,7 +33,7 @@ namespace Perun_v1.Properties {
}
///
- /// Returns the cached ResourceManager instance used by this class.
+ /// Zwraca buforowane wystąpienie ResourceManager używane przez tę klasę.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
@@ -47,8 +47,8 @@ namespace Perun_v1.Properties {
}
///
- /// Overrides the current thread's CurrentUICulture property for all
- /// resource lookups using this strongly typed resource class.
+ /// Przesłania właściwość CurrentUICulture bieżącego wątku dla wszystkich
+ /// przypadków przeszukiwania zasobów za pomocą tej klasy zasobów wymagającej zdefiniowania typu.
///
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
@@ -61,7 +61,7 @@ namespace Perun_v1.Properties {
}
///
- /// Looks up a localized resource of type System.Drawing.Bitmap.
+ /// Wyszukuje zlokalizowany zasób typu System.Drawing.Bitmap.
///
internal static System.Drawing.Bitmap perun_logo {
get {
@@ -71,7 +71,67 @@ namespace Perun_v1.Properties {
}
///
- /// Looks up a localized resource of type System.Drawing.Bitmap.
+ /// Wyszukuje zlokalizowany zasób typu System.Drawing.Icon podobny do zasobu (Ikona).
+ ///
+ internal static System.Drawing.Icon perun_logo_1 {
+ get {
+ object obj = ResourceManager.GetObject("perun_logo_1", resourceCulture);
+ return ((System.Drawing.Icon)(obj));
+ }
+ }
+
+ ///
+ /// Wyszukuje zlokalizowany zasób typu System.Drawing.Icon podobny do zasobu (Ikona).
+ ///
+ internal static System.Drawing.Icon perun_logo_2 {
+ get {
+ object obj = ResourceManager.GetObject("perun_logo_2", resourceCulture);
+ return ((System.Drawing.Icon)(obj));
+ }
+ }
+
+ ///
+ /// Wyszukuje zlokalizowany zasób typu System.Drawing.Icon podobny do zasobu (Ikona).
+ ///
+ internal static System.Drawing.Icon perun_logo_3 {
+ get {
+ object obj = ResourceManager.GetObject("perun_logo_3", resourceCulture);
+ return ((System.Drawing.Icon)(obj));
+ }
+ }
+
+ ///
+ /// Wyszukuje zlokalizowany zasób typu System.Drawing.Icon podobny do zasobu (Ikona).
+ ///
+ internal static System.Drawing.Icon perun_logo_4 {
+ get {
+ object obj = ResourceManager.GetObject("perun_logo_4", resourceCulture);
+ return ((System.Drawing.Icon)(obj));
+ }
+ }
+
+ ///
+ /// Wyszukuje zlokalizowany zasób typu System.Drawing.Icon podobny do zasobu (Ikona).
+ ///
+ internal static System.Drawing.Icon perun_logo_5 {
+ get {
+ object obj = ResourceManager.GetObject("perun_logo_5", resourceCulture);
+ return ((System.Drawing.Icon)(obj));
+ }
+ }
+
+ ///
+ /// Wyszukuje zlokalizowany zasób typu System.Drawing.Icon podobny do zasobu (Ikona).
+ ///
+ internal static System.Drawing.Icon perun_logo_def {
+ get {
+ object obj = ResourceManager.GetObject("perun_logo_def", resourceCulture);
+ return ((System.Drawing.Icon)(obj));
+ }
+ }
+
+ ///
+ /// Wyszukuje zlokalizowany zasób typu System.Drawing.Bitmap.
///
internal static System.Drawing.Bitmap status_connected {
get {
@@ -81,7 +141,7 @@ namespace Perun_v1.Properties {
}
///
- /// Looks up a localized resource of type System.Drawing.Bitmap.
+ /// Wyszukuje zlokalizowany zasób typu System.Drawing.Bitmap.
///
internal static System.Drawing.Bitmap status_connected_error {
get {
@@ -91,7 +151,7 @@ namespace Perun_v1.Properties {
}
///
- /// Looks up a localized resource of type System.Drawing.Bitmap.
+ /// Wyszukuje zlokalizowany zasób typu System.Drawing.Bitmap.
///
internal static System.Drawing.Bitmap status_disconnected {
get {
@@ -101,7 +161,7 @@ namespace Perun_v1.Properties {
}
///
- /// Looks up a localized resource of type System.Drawing.Bitmap.
+ /// Wyszukuje zlokalizowany zasób typu System.Drawing.Bitmap.
///
internal static System.Drawing.Bitmap status_disconnected_error {
get {
diff --git a/02_Windows_App/Perun_v1/Properties/Resources.resx b/02_Windows_App/Perun_v1/Properties/Resources.resx
index 6d2bfc3..ebd156d 100644
--- a/02_Windows_App/Perun_v1/Properties/Resources.resx
+++ b/02_Windows_App/Perun_v1/Properties/Resources.resx
@@ -121,6 +121,24 @@
..\03_Resources\perun_logo.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+ ..\03_Resources\perun_logo_1.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\03_Resources\perun_logo_2.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\03_Resources\perun_logo_3.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\03_Resources\perun_logo_4.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\03_Resources\perun_logo_5.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
+
+ ..\03_Resources\perun_logo.ico;System.Drawing.Icon, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
+
..\03_Resources\status-connected.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
diff --git a/02_Windows_App/Perun_v1/Properties/Settings.Designer.cs b/02_Windows_App/Perun_v1/Properties/Settings.Designer.cs
index 778c811..2f448a8 100644
--- a/02_Windows_App/Perun_v1/Properties/Settings.Designer.cs
+++ b/02_Windows_App/Perun_v1/Properties/Settings.Designer.cs
@@ -1,10 +1,10 @@
//------------------------------------------------------------------------------
//
-// This code was generated by a tool.
-// Runtime Version:4.0.30319.42000
+// Ten kod został wygenerowany przez narzędzie.
+// Wersja wykonawcza:4.0.30319.42000
//
-// Changes to this file may cause incorrect behavior and will be lost if
-// the code is regenerated.
+// Zmiany w tym pliku mogą spowodować nieprawidłowe zachowanie i zostaną utracone, jeśli
+// kod zostanie ponownie wygenerowany.
//
//------------------------------------------------------------------------------
@@ -12,7 +12,7 @@ namespace Perun_v1.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
- [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.2.0.0")]
+ [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "16.8.1.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
@@ -154,5 +154,41 @@ namespace Perun_v1.Properties {
this["DCS_Instance"] = value;
}
}
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("1")]
+ public int OTHER_Log_Level {
+ get {
+ return ((int)(this["OTHER_Log_Level"]));
+ }
+ set {
+ this["OTHER_Log_Level"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("True")]
+ public bool OTHER_Minimize_to_Tray {
+ get {
+ return ((bool)(this["OTHER_Minimize_to_Tray"]));
+ }
+ set {
+ this["OTHER_Minimize_to_Tray"] = value;
+ }
+ }
+
+ [global::System.Configuration.UserScopedSettingAttribute()]
+ [global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
+ [global::System.Configuration.DefaultSettingValueAttribute("True")]
+ public bool OTHER_Log_Rotate {
+ get {
+ return ((bool)(this["OTHER_Log_Rotate"]));
+ }
+ set {
+ this["OTHER_Log_Rotate"] = value;
+ }
+ }
}
}
diff --git a/02_Windows_App/Perun_v1/Properties/Settings.settings b/02_Windows_App/Perun_v1/Properties/Settings.settings
index 37e5157..99680ba 100644
--- a/02_Windows_App/Perun_v1/Properties/Settings.settings
+++ b/02_Windows_App/Perun_v1/Properties/Settings.settings
@@ -35,5 +35,14 @@
1
+
+ 1
+
+
+ True
+
+
+ True
+
\ No newline at end of file
diff --git a/02_Windows_App/Perun_v1/Properties/app.manifest b/02_Windows_App/Perun_v1/Properties/app.manifest
index 70833e8..2fcad2d 100644
--- a/02_Windows_App/Perun_v1/Properties/app.manifest
+++ b/02_Windows_App/Perun_v1/Properties/app.manifest
@@ -20,7 +20,7 @@
-
+
diff --git a/02_Windows_App/Perun_v1/Resources/perun_logo.png b/02_Windows_App/Perun_v1/Resources/perun_logo.png
deleted file mode 100644
index 3e9d6ed..0000000
Binary files a/02_Windows_App/Perun_v1/Resources/perun_logo.png and /dev/null differ
diff --git a/02_Windows_App/Perun_v1/app.config b/02_Windows_App/Perun_v1/app.config
index 02494be..db0c0f9 100644
--- a/02_Windows_App/Perun_v1/app.config
+++ b/02_Windows_App/Perun_v1/app.config
@@ -40,6 +40,15 @@
1
+
+ 1
+
+
+ True
+
+
+ True
+
diff --git a/03_Perun_Lua_Wrapper/.gitignore b/03_Perun_Lua_Wrapper/.gitignore
new file mode 100644
index 0000000..c481f8e
--- /dev/null
+++ b/03_Perun_Lua_Wrapper/.gitignore
@@ -0,0 +1,3 @@
+out
+.vs
+.idea
\ No newline at end of file
diff --git a/03_Perun_Lua_Wrapper/CMakeLists.txt b/03_Perun_Lua_Wrapper/CMakeLists.txt
new file mode 100644
index 0000000..1ef4ac9
--- /dev/null
+++ b/03_Perun_Lua_Wrapper/CMakeLists.txt
@@ -0,0 +1,12 @@
+# CMakeList.txt : CMake project for perun_dll, include source and define
+# project specific logic here.
+#
+cmake_minimum_required (VERSION 3.8)
+
+project ("parent")
+
+set(CMAKE_CXX_STANDARD 20)
+set_property(GLOBAL PROPERTY USE_FOLDERS ON)
+
+add_subdirectory(lua-5.1.5)
+add_subdirectory(perun)
\ No newline at end of file
diff --git a/03_Perun_Lua_Wrapper/CMakeSettings.json b/03_Perun_Lua_Wrapper/CMakeSettings.json
new file mode 100644
index 0000000..d18bcd9
--- /dev/null
+++ b/03_Perun_Lua_Wrapper/CMakeSettings.json
@@ -0,0 +1,28 @@
+{
+ "configurations": [
+ {
+ "name": "x64-Debug (default)",
+ "generator": "Ninja",
+ "configurationType": "Debug",
+ "inheritEnvironments": [ "msvc_x64_x64" ],
+ "buildRoot": "${projectDir}\\out\\build\\${name}",
+ "installRoot": "${projectDir}\\out\\install\\${name}",
+ "cmakeCommandArgs": "",
+ "buildCommandArgs": "",
+ "ctestCommandArgs": "",
+ "variables": []
+ },
+ {
+ "name": "x64-Release",
+ "generator": "Ninja",
+ "configurationType": "RelWithDebInfo",
+ "buildRoot": "${projectDir}\\out\\build\\${name}",
+ "installRoot": "${projectDir}\\out\\install\\${name}",
+ "cmakeCommandArgs": "",
+ "buildCommandArgs": "",
+ "ctestCommandArgs": "",
+ "inheritEnvironments": [ "msvc_x64_x64" ],
+ "variables": []
+ }
+ ]
+}
\ No newline at end of file
diff --git a/03_Perun_Lua_Wrapper/lua-5.1.5/COPYRIGHT b/03_Perun_Lua_Wrapper/lua-5.1.5/COPYRIGHT
new file mode 100644
index 0000000..a860268
--- /dev/null
+++ b/03_Perun_Lua_Wrapper/lua-5.1.5/COPYRIGHT
@@ -0,0 +1,34 @@
+Lua License
+-----------
+
+Lua is licensed under the terms of the MIT license reproduced below.
+This means that Lua is free software and can be used for both academic
+and commercial purposes at absolutely no cost.
+
+For details and rationale, see http://www.lua.org/license.html .
+
+===============================================================================
+
+Copyright (C) 1994-2012 Lua.org, PUC-Rio.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
+===============================================================================
+
+(end of COPYRIGHT)
diff --git a/03_Perun_Lua_Wrapper/lua-5.1.5/CmakeLists.txt b/03_Perun_Lua_Wrapper/lua-5.1.5/CmakeLists.txt
new file mode 100644
index 0000000..a227577
--- /dev/null
+++ b/03_Perun_Lua_Wrapper/lua-5.1.5/CmakeLists.txt
@@ -0,0 +1,37 @@
+cmake_minimum_required(VERSION 3.17)
+
+project(lua-5.1.5)
+
+set(CMAKE_C_STANDARD 99)
+
+set (LUA_RUNTIME_SOURCES
+ "src/lapi.c"
+ "src/lapi.h"
+ "src/lauxlib.h" "src/lauxlib.c"
+ "src/lcode.h" "src/lcode.c"
+ "src/ldebug.h" "src/ldebug.c"
+ "src/ldo.c" "src/ldo.h"
+ "src/ldump.c"
+ "src/lgc.c" "src/lgc.h"
+ "src/lfunc.c" "src/lfunc.h"
+ "src/llex.c" "src/llex.h"
+ "src/lobject.c" "src/lobject.h"
+ "src/lopcodes.c" "src/lopcodes.h"
+ "src/lparser.c" "src/lparser.h"
+ "src/lstate.c" "src/lstate.h"
+ "src/lstring.c" "src/lstring.h"
+ "src/ltable.c" "src/ltable.h"
+ "src/ltm.c" "src/ltm.h"
+ "src/lmem.h" "src/lmem.c"
+ "src/lundump.c" "src/lundump.h"
+ "src/lvm.h" "src/lvm.c"
+ "src/lua.h"
+ "src/lualib.h"
+ "src/lzio.c" "src/lzio.h"
+)
+
+
+add_library( lua-5.1.5 ${LUA_RUNTIME_SOURCES} )
+SET_TARGET_PROPERTIES(lua-5.1.5 PROPERTIES LINKER_LANGUAGE C)
+
+target_include_directories ( lua-5.1.5 PUBLIC "${PROJECT_SOURCE_DIR}/src")
\ No newline at end of file
diff --git a/03_Perun_Lua_Wrapper/lua-5.1.5/HISTORY b/03_Perun_Lua_Wrapper/lua-5.1.5/HISTORY
new file mode 100644
index 0000000..ce0c95b
--- /dev/null
+++ b/03_Perun_Lua_Wrapper/lua-5.1.5/HISTORY
@@ -0,0 +1,183 @@
+HISTORY for Lua 5.1
+
+* Changes from version 5.0 to 5.1
+ -------------------------------
+ Language:
+ + new module system.
+ + new semantics for control variables of fors.
+ + new semantics for setn/getn.
+ + new syntax/semantics for varargs.
+ + new long strings and comments.
+ + new `mod' operator (`%')
+ + new length operator #t
+ + metatables for all types
+ API:
+ + new functions: lua_createtable, lua_get(set)field, lua_push(to)integer.
+ + user supplies memory allocator (lua_open becomes lua_newstate).
+ + luaopen_* functions must be called through Lua.
+ Implementation:
+ + new configuration scheme via luaconf.h.
+ + incremental garbage collection.
+ + better handling of end-of-line in the lexer.
+ + fully reentrant parser (new Lua function `load')
+ + better support for 64-bit machines.
+ + native loadlib support for Mac OS X.
+ + standard distribution in only one library (lualib.a merged into lua.a)
+
+* Changes from version 4.0 to 5.0
+ -------------------------------
+ Language:
+ + lexical scoping.
+ + Lua coroutines.
+ + standard libraries now packaged in tables.
+ + tags replaced by metatables and tag methods replaced by metamethods,
+ stored in metatables.
+ + proper tail calls.
+ + each function can have its own global table, which can be shared.
+ + new __newindex metamethod, called when we insert a new key into a table.
+ + new block comments: --[[ ... ]].
+ + new generic for.
+ + new weak tables.
+ + new boolean type.
+ + new syntax "local function".
+ + (f()) returns the first value returned by f.
+ + {f()} fills a table with all values returned by f.
+ + \n ignored in [[\n .
+ + fixed and-or priorities.
+ + more general syntax for function definition (e.g. function a.x.y:f()...end).
+ + more general syntax for function calls (e.g. (print or write)(9)).
+ + new functions (time/date, tmpfile, unpack, require, load*, etc.).
+ API:
+ + chunks are loaded by using lua_load; new luaL_loadfile and luaL_loadbuffer.
+ + introduced lightweight userdata, a simple "void*" without a metatable.
+ + new error handling protocol: the core no longer prints error messages;
+ all errors are reported to the caller on the stack.
+ + new lua_atpanic for host cleanup.
+ + new, signal-safe, hook scheme.
+ Implementation:
+ + new license: MIT.
+ + new, faster, register-based virtual machine.
+ + support for external multithreading and coroutines.
+ + new and consistent error message format.
+ + the core no longer needs "stdio.h" for anything (except for a single
+ use of sprintf to convert numbers to strings).
+ + lua.c now runs the environment variable LUA_INIT, if present. It can
+ be "@filename", to run a file, or the chunk itself.
+ + support for user extensions in lua.c.
+ sample implementation given for command line editing.
+ + new dynamic loading library, active by default on several platforms.
+ + safe garbage-collector metamethods.
+ + precompiled bytecodes checked for integrity (secure binary dostring).
+ + strings are fully aligned.
+ + position capture in string.find.
+ + read('*l') can read lines with embedded zeros.
+
+* Changes from version 3.2 to 4.0
+ -------------------------------
+ Language:
+ + new "break" and "for" statements (both numerical and for tables).
+ + uniform treatment of globals: globals are now stored in a Lua table.
+ + improved error messages.
+ + no more '$debug': full speed *and* full debug information.
+ + new read form: read(N) for next N bytes.
+ + general read patterns now deprecated.
+ (still available with -DCOMPAT_READPATTERNS.)
+ + all return values are passed as arguments for the last function
+ (old semantics still available with -DLUA_COMPAT_ARGRET)
+ + garbage collection tag methods for tables now deprecated.
+ + there is now only one tag method for order.
+ API:
+ + New API: fully re-entrant, simpler, and more efficient.
+ + New debug API.
+ Implementation:
+ + faster than ever: cleaner virtual machine and new hashing algorithm.
+ + non-recursive garbage-collector algorithm.
+ + reduced memory usage for programs with many strings.
+ + improved treatment for memory allocation errors.
+ + improved support for 16-bit machines (we hope).
+ + code now compiles unmodified as both ANSI C and C++.
+ + numbers in bases other than 10 are converted using strtoul.
+ + new -f option in Lua to support #! scripts.
+ + luac can now combine text and binaries.
+
+* Changes from version 3.1 to 3.2
+ -------------------------------
+ + redirected all output in Lua's core to _ERRORMESSAGE and _ALERT.
+ + increased limit on the number of constants and globals per function
+ (from 2^16 to 2^24).
+ + debugging info (lua_debug and hooks) moved into lua_state and new API
+ functions provided to get and set this info.
+ + new debug lib gives full debugging access within Lua.
+ + new table functions "foreachi", "sort", "tinsert", "tremove", "getn".
+ + new io functions "flush", "seek".
+
+* Changes from version 3.0 to 3.1
+ -------------------------------
+ + NEW FEATURE: anonymous functions with closures (via "upvalues").
+ + new syntax:
+ - local variables in chunks.
+ - better scope control with DO block END.
+ - constructors can now be also written: { record-part; list-part }.
+ - more general syntax for function calls and lvalues, e.g.:
+ f(x).y=1
+ o:f(x,y):g(z)
+ f"string" is sugar for f("string")
+ + strings may now contain arbitrary binary data (e.g., embedded zeros).
+ + major code re-organization and clean-up; reduced module interdependecies.
+ + no arbitrary limits on the total number of constants and globals.
+ + support for multiple global contexts.
+ + better syntax error messages.
+ + new traversal functions "foreach" and "foreachvar".
+ + the default for numbers is now double.
+ changing it to use floats or longs is easy.
+ + complete debug information stored in pre-compiled chunks.
+ + sample interpreter now prompts user when run interactively, and also
+ handles control-C interruptions gracefully.
+
+* Changes from version 2.5 to 3.0
+ -------------------------------
+ + NEW CONCEPT: "tag methods".
+ Tag methods replace fallbacks as the meta-mechanism for extending the
+ semantics of Lua. Whereas fallbacks had a global nature, tag methods
+ work on objects having the same tag (e.g., groups of tables).
+ Existing code that uses fallbacks should work without change.
+ + new, general syntax for constructors {[exp] = exp, ... }.
+ + support for handling variable number of arguments in functions (varargs).
+ + support for conditional compilation ($if ... $else ... $end).
+ + cleaner semantics in API simplifies host code.
+ + better support for writing libraries (auxlib.h).
+ + better type checking and error messages in the standard library.
+ + luac can now also undump.
+
+* Changes from version 2.4 to 2.5
+ -------------------------------
+ + io and string libraries are now based on pattern matching;
+ the old libraries are still available for compatibility
+ + dofile and dostring can now return values (via return statement)
+ + better support for 16- and 64-bit machines
+ + expanded documentation, with more examples
+
+* Changes from version 2.2 to 2.4
+ -------------------------------
+ + external compiler creates portable binary files that can be loaded faster
+ + interface for debugging and profiling
+ + new "getglobal" fallback
+ + new functions for handling references to Lua objects
+ + new functions in standard lib
+ + only one copy of each string is stored
+ + expanded documentation, with more examples
+
+* Changes from version 2.1 to 2.2
+ -------------------------------
+ + functions now may be declared with any "lvalue" as a name
+ + garbage collection of functions
+ + support for pipes
+
+* Changes from version 1.1 to 2.1
+ -------------------------------
+ + object-oriented support
+ + fallbacks
+ + simplified syntax for tables
+ + many internal improvements
+
+(end of HISTORY)
diff --git a/03_Perun_Lua_Wrapper/lua-5.1.5/INSTALL b/03_Perun_Lua_Wrapper/lua-5.1.5/INSTALL
new file mode 100644
index 0000000..17eb8ae
--- /dev/null
+++ b/03_Perun_Lua_Wrapper/lua-5.1.5/INSTALL
@@ -0,0 +1,99 @@
+INSTALL for Lua 5.1
+
+* Building Lua
+ ------------
+ Lua is built in the src directory, but the build process can be
+ controlled from the top-level Makefile.
+
+ Building Lua on Unix systems should be very easy. First do "make" and
+ see if your platform is listed. If so, just do "make xxx", where xxx
+ is your platform name. The platforms currently supported are:
+ aix ansi bsd freebsd generic linux macosx mingw posix solaris
+
+ If your platform is not listed, try the closest one or posix, generic,
+ ansi, in this order.
+
+ See below for customization instructions and for instructions on how
+ to build with other Windows compilers.
+
+ If you want to check that Lua has been built correctly, do "make test"
+ after building Lua. Also, have a look at the example programs in test.
+
+* Installing Lua
+ --------------
+ Once you have built Lua, you may want to install it in an official
+ place in your system. In this case, do "make install". The official
+ place and the way to install files are defined in Makefile. You must
+ have the right permissions to install files.
+
+ If you want to build and install Lua in one step, do "make xxx install",
+ where xxx is your platform name.
+
+ If you want to install Lua locally, then do "make local". This will
+ create directories bin, include, lib, man, and install Lua there as
+ follows:
+
+ bin: lua luac
+ include: lua.h luaconf.h lualib.h lauxlib.h lua.hpp
+ lib: liblua.a
+ man/man1: lua.1 luac.1
+
+ These are the only directories you need for development.
+
+ There are man pages for lua and luac, in both nroff and html, and a
+ reference manual in html in doc, some sample code in test, and some
+ useful stuff in etc. You don't need these directories for development.
+
+ If you want to install Lua locally, but in some other directory, do
+ "make install INSTALL_TOP=xxx", where xxx is your chosen directory.
+
+ See below for instructions for Windows and other systems.
+
+* Customization
+ -------------
+ Three things can be customized by editing a file:
+ - Where and how to install Lua -- edit Makefile.
+ - How to build Lua -- edit src/Makefile.
+ - Lua features -- edit src/luaconf.h.
+
+ You don't actually need to edit the Makefiles because you may set the
+ relevant variables when invoking make.
+
+ On the other hand, if you need to select some Lua features, you'll need
+ to edit src/luaconf.h. The edited file will be the one installed, and
+ it will be used by any Lua clients that you build, to ensure consistency.
+
+ We strongly recommend that you enable dynamic loading. This is done
+ automatically for all platforms listed above that have this feature
+ (and also Windows). See src/luaconf.h and also src/Makefile.
+
+* Building Lua on Windows and other systems
+ -----------------------------------------
+ If you're not using the usual Unix tools, then the instructions for
+ building Lua depend on the compiler you use. You'll need to create
+ projects (or whatever your compiler uses) for building the library,
+ the interpreter, and the compiler, as follows:
+
+ library: lapi.c lcode.c ldebug.c ldo.c ldump.c lfunc.c lgc.c llex.c
+ lmem.c lobject.c lopcodes.c lparser.c lstate.c lstring.c
+ ltable.c ltm.c lundump.c lvm.c lzio.c
+ lauxlib.c lbaselib.c ldblib.c liolib.c lmathlib.c loslib.c
+ ltablib.c lstrlib.c loadlib.c linit.c
+
+ interpreter: library, lua.c
+
+ compiler: library, luac.c print.c
+
+ If you use Visual Studio .NET, you can use etc/luavs.bat in its
+ "Command Prompt".
+
+ If all you want is to build the Lua interpreter, you may put all .c files
+ in a single project, except for luac.c and print.c. Or just use etc/all.c.
+
+ To use Lua as a library in your own programs, you'll need to know how to
+ create and use libraries with your compiler.
+
+ As mentioned above, you may edit luaconf.h to select some features before
+ building Lua.
+
+(end of INSTALL)
diff --git a/03_Perun_Lua_Wrapper/lua-5.1.5/Makefile b/03_Perun_Lua_Wrapper/lua-5.1.5/Makefile
new file mode 100644
index 0000000..209a132
--- /dev/null
+++ b/03_Perun_Lua_Wrapper/lua-5.1.5/Makefile
@@ -0,0 +1,128 @@
+# makefile for installing Lua
+# see INSTALL for installation instructions
+# see src/Makefile and src/luaconf.h for further customization
+
+# == CHANGE THE SETTINGS BELOW TO SUIT YOUR ENVIRONMENT =======================
+
+# Your platform. See PLATS for possible values.
+PLAT= none
+
+# Where to install. The installation starts in the src and doc directories,
+# so take care if INSTALL_TOP is not an absolute path.
+INSTALL_TOP= /usr/local
+INSTALL_BIN= $(INSTALL_TOP)/bin
+INSTALL_INC= $(INSTALL_TOP)/include
+INSTALL_LIB= $(INSTALL_TOP)/lib
+INSTALL_MAN= $(INSTALL_TOP)/man/man1
+#
+# You probably want to make INSTALL_LMOD and INSTALL_CMOD consistent with
+# LUA_ROOT, LUA_LDIR, and LUA_CDIR in luaconf.h (and also with etc/lua.pc).
+INSTALL_LMOD= $(INSTALL_TOP)/share/lua/$V
+INSTALL_CMOD= $(INSTALL_TOP)/lib/lua/$V
+
+# How to install. If your install program does not support "-p", then you
+# may have to run ranlib on the installed liblua.a (do "make ranlib").
+INSTALL= install -p
+INSTALL_EXEC= $(INSTALL) -m 0755
+INSTALL_DATA= $(INSTALL) -m 0644
+#
+# If you don't have install you can use cp instead.
+# INSTALL= cp -p
+# INSTALL_EXEC= $(INSTALL)
+# INSTALL_DATA= $(INSTALL)
+
+# Utilities.
+MKDIR= mkdir -p
+RANLIB= ranlib
+
+# == END OF USER SETTINGS. NO NEED TO CHANGE ANYTHING BELOW THIS LINE =========
+
+# Convenience platforms targets.
+PLATS= aix ansi bsd freebsd generic linux macosx mingw posix solaris
+
+# What to install.
+TO_BIN= lua luac
+TO_INC= lua.h luaconf.h lualib.h lauxlib.h ../etc/lua.hpp
+TO_LIB= liblua.a
+TO_MAN= lua.1 luac.1
+
+# Lua version and release.
+V= 5.1
+R= 5.1.5
+
+all: $(PLAT)
+
+$(PLATS) clean:
+ cd src && $(MAKE) $@
+
+test: dummy
+ src/lua test/hello.lua
+
+install: dummy
+ cd src && $(MKDIR) $(INSTALL_BIN) $(INSTALL_INC) $(INSTALL_LIB) $(INSTALL_MAN) $(INSTALL_LMOD) $(INSTALL_CMOD)
+ cd src && $(INSTALL_EXEC) $(TO_BIN) $(INSTALL_BIN)
+ cd src && $(INSTALL_DATA) $(TO_INC) $(INSTALL_INC)
+ cd src && $(INSTALL_DATA) $(TO_LIB) $(INSTALL_LIB)
+ cd doc && $(INSTALL_DATA) $(TO_MAN) $(INSTALL_MAN)
+
+ranlib:
+ cd src && cd $(INSTALL_LIB) && $(RANLIB) $(TO_LIB)
+
+local:
+ $(MAKE) install INSTALL_TOP=..
+
+none:
+ @echo "Please do"
+ @echo " make PLATFORM"
+ @echo "where PLATFORM is one of these:"
+ @echo " $(PLATS)"
+ @echo "See INSTALL for complete instructions."
+
+# make may get confused with test/ and INSTALL in a case-insensitive OS
+dummy:
+
+# echo config parameters
+echo:
+ @echo ""
+ @echo "These are the parameters currently set in src/Makefile to build Lua $R:"
+ @echo ""
+ @cd src && $(MAKE) -s echo
+ @echo ""
+ @echo "These are the parameters currently set in Makefile to install Lua $R:"
+ @echo ""
+ @echo "PLAT = $(PLAT)"
+ @echo "INSTALL_TOP = $(INSTALL_TOP)"
+ @echo "INSTALL_BIN = $(INSTALL_BIN)"
+ @echo "INSTALL_INC = $(INSTALL_INC)"
+ @echo "INSTALL_LIB = $(INSTALL_LIB)"
+ @echo "INSTALL_MAN = $(INSTALL_MAN)"
+ @echo "INSTALL_LMOD = $(INSTALL_LMOD)"
+ @echo "INSTALL_CMOD = $(INSTALL_CMOD)"
+ @echo "INSTALL_EXEC = $(INSTALL_EXEC)"
+ @echo "INSTALL_DATA = $(INSTALL_DATA)"
+ @echo ""
+ @echo "See also src/luaconf.h ."
+ @echo ""
+
+# echo private config parameters
+pecho:
+ @echo "V = $(V)"
+ @echo "R = $(R)"
+ @echo "TO_BIN = $(TO_BIN)"
+ @echo "TO_INC = $(TO_INC)"
+ @echo "TO_LIB = $(TO_LIB)"
+ @echo "TO_MAN = $(TO_MAN)"
+
+# echo config parameters as Lua code
+# uncomment the last sed expression if you want nil instead of empty strings
+lecho:
+ @echo "-- installation parameters for Lua $R"
+ @echo "VERSION = '$V'"
+ @echo "RELEASE = '$R'"
+ @$(MAKE) echo | grep = | sed -e 's/= /= "/' -e 's/$$/"/' #-e 's/""/nil/'
+ @echo "-- EOF"
+
+# list targets that do not create files (but not all makes understand .PHONY)
+.PHONY: all $(PLATS) clean test install local none dummy echo pecho lecho
+
+# (end of Makefile)
diff --git a/03_Perun_Lua_Wrapper/lua-5.1.5/README b/03_Perun_Lua_Wrapper/lua-5.1.5/README
new file mode 100644
index 0000000..11b4dff
--- /dev/null
+++ b/03_Perun_Lua_Wrapper/lua-5.1.5/README
@@ -0,0 +1,37 @@
+README for Lua 5.1
+
+See INSTALL for installation instructions.
+See HISTORY for a summary of changes since the last released version.
+
+* What is Lua?
+ ------------
+ Lua is a powerful, light-weight programming language designed for extending
+ applications. Lua is also frequently used as a general-purpose, stand-alone
+ language. Lua is free software.
+
+ For complete information, visit Lua's web site at http://www.lua.org/ .
+ For an executive summary, see http://www.lua.org/about.html .
+
+ Lua has been used in many different projects around the world.
+ For a short list, see http://www.lua.org/uses.html .
+
+* Availability
+ ------------
+ Lua is freely available for both academic and commercial purposes.
+ See COPYRIGHT and http://www.lua.org/license.html for details.
+ Lua can be downloaded at http://www.lua.org/download.html .
+
+* Installation
+ ------------
+ Lua is implemented in pure ANSI C, and compiles unmodified in all known
+ platforms that have an ANSI C compiler. In most Unix-like platforms, simply
+ do "make" with a suitable target. See INSTALL for detailed instructions.
+
+* Origin
+ ------
+ Lua is developed at Lua.org, a laboratory of the Department of Computer
+ Science of PUC-Rio (the Pontifical Catholic University of Rio de Janeiro
+ in Brazil).
+ For more information about the authors, see http://www.lua.org/authors.html .
+
+(end of README)
diff --git a/03_Perun_Lua_Wrapper/lua-5.1.5/doc/contents.html b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/contents.html
new file mode 100644
index 0000000..3d83da9
--- /dev/null
+++ b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/contents.html
@@ -0,0 +1,497 @@
+
+
+
+Lua 5.1 Reference Manual - contents
+
+
+
+
+
+
+
+
+
+
+Lua 5.1 Reference Manual
+
+
+
+The reference manual is the official definition of the Lua language.
+For a complete introduction to Lua programming, see the book
+Programming in Lua.
+
+
+This manual is also available as a book:
+
+
+
+
+Lua 5.1 Reference Manual
+ by R. Ierusalimschy, L. H. de Figueiredo, W. Celes
+ Lua.org, August 2006
+ ISBN 85-903798-3-3
+
+
+
+Last update:
+Mon Feb 13 18:53:32 BRST 2012
+
+
+
+
+
diff --git a/03_Perun_Lua_Wrapper/lua-5.1.5/doc/cover.png b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/cover.png
new file mode 100644
index 0000000..2dbb198
Binary files /dev/null and b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/cover.png differ
diff --git a/03_Perun_Lua_Wrapper/lua-5.1.5/doc/logo.gif b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/logo.gif
new file mode 100644
index 0000000..2f5e4ac
Binary files /dev/null and b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/logo.gif differ
diff --git a/03_Perun_Lua_Wrapper/lua-5.1.5/doc/lua.1 b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/lua.1
new file mode 100644
index 0000000..24809cc
--- /dev/null
+++ b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/lua.1
@@ -0,0 +1,163 @@
+.\" $Id: lua.man,v 1.11 2006/01/06 16:03:34 lhf Exp $
+.TH LUA 1 "$Date: 2006/01/06 16:03:34 $"
+.SH NAME
+lua \- Lua interpreter
+.SH SYNOPSIS
+.B lua
+[
+.I options
+]
+[
+.I script
+[
+.I args
+]
+]
+.SH DESCRIPTION
+.B lua
+is the stand-alone Lua interpreter.
+It loads and executes Lua programs,
+either in textual source form or
+in precompiled binary form.
+(Precompiled binaries are output by
+.BR luac ,
+the Lua compiler.)
+.B lua
+can be used as a batch interpreter and also interactively.
+.LP
+The given
+.I options
+(see below)
+are executed and then
+the Lua program in file
+.I script
+is loaded and executed.
+The given
+.I args
+are available to
+.I script
+as strings in a global table named
+.BR arg .
+If these arguments contain spaces or other characters special to the shell,
+then they should be quoted
+(but note that the quotes will be removed by the shell).
+The arguments in
+.B arg
+start at 0,
+which contains the string
+.RI ' script '.
+The index of the last argument is stored in
+.BR arg.n .
+The arguments given in the command line before
+.IR script ,
+including the name of the interpreter,
+are available in negative indices in
+.BR arg .
+.LP
+At the very start,
+before even handling the command line,
+.B lua
+executes the contents of the environment variable
+.BR LUA_INIT ,
+if it is defined.
+If the value of
+.B LUA_INIT
+is of the form
+.RI '@ filename ',
+then
+.I filename
+is executed.
+Otherwise, the string is assumed to be a Lua statement and is executed.
+.LP
+Options start with
+.B '\-'
+and are described below.
+You can use
+.B "'\--'"
+to signal the end of options.
+.LP
+If no arguments are given,
+then
+.B "\-v \-i"
+is assumed when the standard input is a terminal;
+otherwise,
+.B "\-"
+is assumed.
+.LP
+In interactive mode,
+.B lua
+prompts the user,
+reads lines from the standard input,
+and executes them as they are read.
+If a line does not contain a complete statement,
+then a secondary prompt is displayed and
+lines are read until a complete statement is formed or
+a syntax error is found.
+So, one way to interrupt the reading of an incomplete statement is
+to force a syntax error:
+adding a
+.B ';'
+in the middle of a statement is a sure way of forcing a syntax error
+(except inside multiline strings and comments; these must be closed explicitly).
+If a line starts with
+.BR '=' ,
+then
+.B lua
+displays the values of all the expressions in the remainder of the
+line. The expressions must be separated by commas.
+The primary prompt is the value of the global variable
+.BR _PROMPT ,
+if this value is a string;
+otherwise, the default prompt is used.
+Similarly, the secondary prompt is the value of the global variable
+.BR _PROMPT2 .
+So,
+to change the prompts,
+set the corresponding variable to a string of your choice.
+You can do that after calling the interpreter
+or on the command line
+(but in this case you have to be careful with quotes
+if the prompt string contains a space; otherwise you may confuse the shell.)
+The default prompts are "> " and ">> ".
+.SH OPTIONS
+.TP
+.B \-
+load and execute the standard input as a file,
+that is,
+not interactively,
+even when the standard input is a terminal.
+.TP
+.BI \-e " stat"
+execute statement
+.IR stat .
+You need to quote
+.I stat
+if it contains spaces, quotes,
+or other characters special to the shell.
+.TP
+.B \-i
+enter interactive mode after
+.I script
+is executed.
+.TP
+.BI \-l " name"
+call
+.BI require(' name ')
+before executing
+.IR script .
+Typically used to load libraries.
+.TP
+.B \-v
+show version information.
+.SH "SEE ALSO"
+.BR luac (1)
+.br
+http://www.lua.org/
+.SH DIAGNOSTICS
+Error messages should be self explanatory.
+.SH AUTHORS
+R. Ierusalimschy,
+L. H. de Figueiredo,
+and
+W. Celes
+.\" EOF
diff --git a/03_Perun_Lua_Wrapper/lua-5.1.5/doc/lua.css b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/lua.css
new file mode 100644
index 0000000..7fafbb1
--- /dev/null
+++ b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/lua.css
@@ -0,0 +1,83 @@
+body {
+ color: #000000 ;
+ background-color: #FFFFFF ;
+ font-family: Helvetica, Arial, sans-serif ;
+ text-align: justify ;
+ margin-right: 30px ;
+ margin-left: 30px ;
+}
+
+h1, h2, h3, h4 {
+ font-family: Verdana, Geneva, sans-serif ;
+ font-weight: normal ;
+ font-style: italic ;
+}
+
+h2 {
+ padding-top: 0.4em ;
+ padding-bottom: 0.4em ;
+ padding-left: 30px ;
+ padding-right: 30px ;
+ margin-left: -30px ;
+ background-color: #E0E0FF ;
+}
+
+h3 {
+ padding-left: 0.5em ;
+ border-left: solid #E0E0FF 1em ;
+}
+
+table h3 {
+ padding-left: 0px ;
+ border-left: none ;
+}
+
+a:link {
+ color: #000080 ;
+ background-color: inherit ;
+ text-decoration: none ;
+}
+
+a:visited {
+ background-color: inherit ;
+ text-decoration: none ;
+}
+
+a:link:hover, a:visited:hover {
+ color: #000080 ;
+ background-color: #E0E0FF ;
+}
+
+a:link:active, a:visited:active {
+ color: #FF0000 ;
+}
+
+hr {
+ border: 0 ;
+ height: 1px ;
+ color: #a0a0a0 ;
+ background-color: #a0a0a0 ;
+}
+
+:target {
+ background-color: #F8F8F8 ;
+ padding: 8px ;
+ border: solid #a0a0a0 2px ;
+}
+
+.footer {
+ color: gray ;
+ font-size: small ;
+}
+
+input[type=text] {
+ border: solid #a0a0a0 2px ;
+ border-radius: 2em ;
+ -moz-border-radius: 2em ;
+ background-image: url('images/search.png') ;
+ background-repeat: no-repeat;
+ background-position: 4px center ;
+ padding-left: 20px ;
+ height: 2em ;
+}
+
diff --git a/03_Perun_Lua_Wrapper/lua-5.1.5/doc/lua.html b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/lua.html
new file mode 100644
index 0000000..1d435ab
--- /dev/null
+++ b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/lua.html
@@ -0,0 +1,172 @@
+
+
+
+LUA man page
+
+
+
+
+
+
NAME
+lua - Lua interpreter
+
SYNOPSIS
+lua
+[
+options
+]
+[
+script
+[
+args
+]
+]
+
DESCRIPTION
+lua
+is the stand-alone Lua interpreter.
+It loads and executes Lua programs,
+either in textual source form or
+in precompiled binary form.
+(Precompiled binaries are output by
+luac,
+the Lua compiler.)
+lua
+can be used as a batch interpreter and also interactively.
+
+The given
+options
+(see below)
+are executed and then
+the Lua program in file
+script
+is loaded and executed.
+The given
+args
+are available to
+script
+as strings in a global table named
+arg.
+If these arguments contain spaces or other characters special to the shell,
+then they should be quoted
+(but note that the quotes will be removed by the shell).
+The arguments in
+arg
+start at 0,
+which contains the string
+'script'.
+The index of the last argument is stored in
+arg.n.
+The arguments given in the command line before
+script,
+including the name of the interpreter,
+are available in negative indices in
+arg.
+
+At the very start,
+before even handling the command line,
+lua
+executes the contents of the environment variable
+LUA_INIT,
+if it is defined.
+If the value of
+LUA_INIT
+is of the form
+'@filename',
+then
+filename
+is executed.
+Otherwise, the string is assumed to be a Lua statement and is executed.
+
+Options start with
+'-'
+and are described below.
+You can use
+'--'
+to signal the end of options.
+
+If no arguments are given,
+then
+"-v -i"
+is assumed when the standard input is a terminal;
+otherwise,
+"-"
+is assumed.
+
+In interactive mode,
+lua
+prompts the user,
+reads lines from the standard input,
+and executes them as they are read.
+If a line does not contain a complete statement,
+then a secondary prompt is displayed and
+lines are read until a complete statement is formed or
+a syntax error is found.
+So, one way to interrupt the reading of an incomplete statement is
+to force a syntax error:
+adding a
+';'
+in the middle of a statement is a sure way of forcing a syntax error
+(except inside multiline strings and comments; these must be closed explicitly).
+If a line starts with
+'=',
+then
+lua
+displays the values of all the expressions in the remainder of the
+line. The expressions must be separated by commas.
+The primary prompt is the value of the global variable
+_PROMPT,
+if this value is a string;
+otherwise, the default prompt is used.
+Similarly, the secondary prompt is the value of the global variable
+_PROMPT2.
+So,
+to change the prompts,
+set the corresponding variable to a string of your choice.
+You can do that after calling the interpreter
+or on the command line
+(but in this case you have to be careful with quotes
+if the prompt string contains a space; otherwise you may confuse the shell.)
+The default prompts are "> " and ">> ".
+
OPTIONS
+
+-
+load and execute the standard input as a file,
+that is,
+not interactively,
+even when the standard input is a terminal.
+
+-e stat
+execute statement
+stat.
+You need to quote
+stat
+if it contains spaces, quotes,
+or other characters special to the shell.
+
+-i
+enter interactive mode after
+script
+is executed.
+
+-l name
+call
+require('name')
+before executing
+script.
+Typically used to load libraries.
+
+R. Ierusalimschy,
+L. H. de Figueiredo,
+and
+W. Celes
+
+
+
diff --git a/03_Perun_Lua_Wrapper/lua-5.1.5/doc/luac.1 b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/luac.1
new file mode 100644
index 0000000..d814678
--- /dev/null
+++ b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/luac.1
@@ -0,0 +1,136 @@
+.\" $Id: luac.man,v 1.28 2006/01/06 16:03:34 lhf Exp $
+.TH LUAC 1 "$Date: 2006/01/06 16:03:34 $"
+.SH NAME
+luac \- Lua compiler
+.SH SYNOPSIS
+.B luac
+[
+.I options
+] [
+.I filenames
+]
+.SH DESCRIPTION
+.B luac
+is the Lua compiler.
+It translates programs written in the Lua programming language
+into binary files that can be later loaded and executed.
+.LP
+The main advantages of precompiling chunks are:
+faster loading,
+protecting source code from accidental user changes,
+and
+off-line syntax checking.
+.LP
+Pre-compiling does not imply faster execution
+because in Lua chunks are always compiled into bytecodes before being executed.
+.B luac
+simply allows those bytecodes to be saved in a file for later execution.
+.LP
+Pre-compiled chunks are not necessarily smaller than the corresponding source.
+The main goal in pre-compiling is faster loading.
+.LP
+The binary files created by
+.B luac
+are portable only among architectures with the same word size and byte order.
+.LP
+.B luac
+produces a single output file containing the bytecodes
+for all source files given.
+By default,
+the output file is named
+.BR luac.out ,
+but you can change this with the
+.B \-o
+option.
+.LP
+In the command line,
+you can mix
+text files containing Lua source and
+binary files containing precompiled chunks.
+This is useful to combine several precompiled chunks,
+even from different (but compatible) platforms,
+into a single precompiled chunk.
+.LP
+You can use
+.B "'\-'"
+to indicate the standard input as a source file
+and
+.B "'\--'"
+to signal the end of options
+(that is,
+all remaining arguments will be treated as files even if they start with
+.BR "'\-'" ).
+.LP
+The internal format of the binary files produced by
+.B luac
+is likely to change when a new version of Lua is released.
+So,
+save the source files of all Lua programs that you precompile.
+.LP
+.SH OPTIONS
+Options must be separate.
+.TP
+.B \-l
+produce a listing of the compiled bytecode for Lua's virtual machine.
+Listing bytecodes is useful to learn about Lua's virtual machine.
+If no files are given, then
+.B luac
+loads
+.B luac.out
+and lists its contents.
+.TP
+.BI \-o " file"
+output to
+.IR file ,
+instead of the default
+.BR luac.out .
+(You can use
+.B "'\-'"
+for standard output,
+but not on platforms that open standard output in text mode.)
+The output file may be a source file because
+all files are loaded before the output file is written.
+Be careful not to overwrite precious files.
+.TP
+.B \-p
+load files but do not generate any output file.
+Used mainly for syntax checking and for testing precompiled chunks:
+corrupted files will probably generate errors when loaded.
+Lua always performs a thorough integrity test on precompiled chunks.
+Bytecode that passes this test is completely safe,
+in the sense that it will not break the interpreter.
+However,
+there is no guarantee that such code does anything sensible.
+(None can be given, because the halting problem is unsolvable.)
+If no files are given, then
+.B luac
+loads
+.B luac.out
+and tests its contents.
+No messages are displayed if the file passes the integrity test.
+.TP
+.B \-s
+strip debug information before writing the output file.
+This saves some space in very large chunks,
+but if errors occur when running a stripped chunk,
+then the error messages may not contain the full information they usually do.
+For instance,
+line numbers and names of local variables are lost.
+.TP
+.B \-v
+show version information.
+.SH FILES
+.TP 15
+.B luac.out
+default output file
+.SH "SEE ALSO"
+.BR lua (1)
+.br
+http://www.lua.org/
+.SH DIAGNOSTICS
+Error messages should be self explanatory.
+.SH AUTHORS
+L. H. de Figueiredo,
+R. Ierusalimschy and
+W. Celes
+.\" EOF
diff --git a/03_Perun_Lua_Wrapper/lua-5.1.5/doc/luac.html b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/luac.html
new file mode 100644
index 0000000..179ffe8
--- /dev/null
+++ b/03_Perun_Lua_Wrapper/lua-5.1.5/doc/luac.html
@@ -0,0 +1,145 @@
+
+
+
+LUAC man page
+
+
+
+
+
+
NAME
+luac - Lua compiler
+
SYNOPSIS
+luac
+[
+options
+] [
+filenames
+]
+
DESCRIPTION
+luac
+is the Lua compiler.
+It translates programs written in the Lua programming language
+into binary files that can be later loaded and executed.
+
+The main advantages of precompiling chunks are:
+faster loading,
+protecting source code from accidental user changes,
+and
+off-line syntax checking.
+
+Precompiling does not imply faster execution
+because in Lua chunks are always compiled into bytecodes before being executed.
+luac
+simply allows those bytecodes to be saved in a file for later execution.
+
+Precompiled chunks are not necessarily smaller than the corresponding source.
+The main goal in precompiling is faster loading.
+
+The binary files created by
+luac
+are portable only among architectures with the same word size and byte order.
+
+luac
+produces a single output file containing the bytecodes
+for all source files given.
+By default,
+the output file is named
+luac.out,
+but you can change this with the
+-o
+option.
+
+In the command line,
+you can mix
+text files containing Lua source and
+binary files containing precompiled chunks.
+This is useful because several precompiled chunks,
+even from different (but compatible) platforms,
+can be combined into a single precompiled chunk.
+
+You can use
+'-'
+to indicate the standard input as a source file
+and
+'--'
+to signal the end of options
+(that is,
+all remaining arguments will be treated as files even if they start with
+'-').
+
+The internal format of the binary files produced by
+luac
+is likely to change when a new version of Lua is released.
+So,
+save the source files of all Lua programs that you precompile.
+
+
OPTIONS
+Options must be separate.
+
+-l
+produce a listing of the compiled bytecode for Lua's virtual machine.
+Listing bytecodes is useful to learn about Lua's virtual machine.
+If no files are given, then
+luac
+loads
+luac.out
+and lists its contents.
+
+-o file
+output to
+file,
+instead of the default
+luac.out.
+(You can use
+'-'
+for standard output,
+but not on platforms that open standard output in text mode.)
+The output file may be a source file because
+all files are loaded before the output file is written.
+Be careful not to overwrite precious files.
+
+-p
+load files but do not generate any output file.
+Used mainly for syntax checking and for testing precompiled chunks:
+corrupted files will probably generate errors when loaded.
+Lua always performs a thorough integrity test on precompiled chunks.
+Bytecode that passes this test is completely safe,
+in the sense that it will not break the interpreter.
+However,
+there is no guarantee that such code does anything sensible.
+(None can be given, because the halting problem is unsolvable.)
+If no files are given, then
+luac
+loads
+luac.out
+and tests its contents.
+No messages are displayed if the file passes the integrity test.
+
+-s
+strip debug information before writing the output file.
+This saves some space in very large chunks,
+but if errors occur when running a stripped chunk,
+then the error messages may not contain the full information they usually do.
+For instance,
+line numbers and names of local variables are lost.
+
+Lua is an extension programming language designed to support
+general procedural programming with data description
+facilities.
+It also offers good support for object-oriented programming,
+functional programming, and data-driven programming.
+Lua is intended to be used as a powerful, light-weight
+scripting language for any program that needs one.
+Lua is implemented as a library, written in clean C
+(that is, in the common subset of ANSI C and C++).
+
+
+
+Being an extension language, Lua has no notion of a "main" program:
+it only works embedded in a host client,
+called the embedding program or simply the host.
+This host program can invoke functions to execute a piece of Lua code,
+can write and read Lua variables,
+and can register C functions to be called by Lua code.
+Through the use of C functions, Lua can be augmented to cope with
+a wide range of different domains,
+thus creating customized programming languages sharing a syntactical framework.
+The Lua distribution includes a sample host program called lua,
+which uses the Lua library to offer a complete, stand-alone Lua interpreter.
+
+
+
+Lua is free software,
+and is provided as usual with no guarantees,
+as stated in its license.
+The implementation described in this manual is available
+at Lua's official web site, www.lua.org.
+
+
+
+Like any other reference manual,
+this document is dry in places.
+For a discussion of the decisions behind the design of Lua,
+see the technical papers available at Lua's web site.
+For a detailed introduction to programming in Lua,
+see Roberto's book, Programming in Lua (Second Edition).
+
+
+
+
+This section describes the lexis, the syntax, and the semantics of Lua.
+In other words,
+this section describes
+which tokens are valid,
+how they can be combined,
+and what their combinations mean.
+
+
+
+The language constructs will be explained using the usual extended BNF notation,
+in which
+{a} means 0 or more a's, and
+[a] means an optional a.
+Non-terminals are shown like non-terminal,
+keywords are shown like kword,
+and other terminal symbols are shown like `=´.
+The complete syntax of Lua can be found in §8
+at the end of this manual.
+
+
+
+
+Names
+(also called identifiers)
+in Lua can be any string of letters,
+digits, and underscores,
+not beginning with a digit.
+This coincides with the definition of names in most languages.
+(The definition of letter depends on the current locale:
+any character considered alphabetic by the current locale
+can be used in an identifier.)
+Identifiers are used to name variables and table fields.
+
+
+
+The following keywords are reserved
+and cannot be used as names:
+
+
+
+ and break do else elseif
+ end false for function if
+ in local nil not or
+ repeat return then true until while
+
+
+
+Lua is a case-sensitive language:
+and is a reserved word, but And and AND
+are two different, valid names.
+As a convention, names starting with an underscore followed by
+uppercase letters (such as _VERSION)
+are reserved for internal global variables used by Lua.
+
+
+
+Literal strings
+can be delimited by matching single or double quotes,
+and can contain the following C-like escape sequences:
+'\a' (bell),
+'\b' (backspace),
+'\f' (form feed),
+'\n' (newline),
+'\r' (carriage return),
+'\t' (horizontal tab),
+'\v' (vertical tab),
+'\\' (backslash),
+'\"' (quotation mark [double quote]),
+and '\'' (apostrophe [single quote]).
+Moreover, a backslash followed by a real newline
+results in a newline in the string.
+A character in a string can also be specified by its numerical value
+using the escape sequence \ddd,
+where ddd is a sequence of up to three decimal digits.
+(Note that if a numerical escape is to be followed by a digit,
+it must be expressed using exactly three digits.)
+Strings in Lua can contain any 8-bit value, including embedded zeros,
+which can be specified as '\0'.
+
+
+
+Literal strings can also be defined using a long format
+enclosed by long brackets.
+We define an opening long bracket of level n as an opening
+square bracket followed by n equal signs followed by another
+opening square bracket.
+So, an opening long bracket of level 0 is written as [[,
+an opening long bracket of level 1 is written as [=[,
+and so on.
+A closing long bracket is defined similarly;
+for instance, a closing long bracket of level 4 is written as ]====].
+A long string starts with an opening long bracket of any level and
+ends at the first closing long bracket of the same level.
+Literals in this bracketed form can run for several lines,
+do not interpret any escape sequences,
+and ignore long brackets of any other level.
+They can contain anything except a closing bracket of the proper level.
+
+
+
+For convenience,
+when the opening long bracket is immediately followed by a newline,
+the newline is not included in the string.
+As an example, in a system using ASCII
+(in which 'a' is coded as 97,
+newline is coded as 10, and '1' is coded as 49),
+the five literal strings below denote the same string:
+
+
+ a = 'alo\n123"'
+ a = "alo\n123\""
+ a = '\97lo\10\04923"'
+ a = [[alo
+ 123"]]
+ a = [==[
+ alo
+ 123"]==]
+
+
+
+A numerical constant can be written with an optional decimal part
+and an optional decimal exponent.
+Lua also accepts integer hexadecimal constants,
+by prefixing them with 0x.
+Examples of valid numerical constants are
+
+
+ 3 3.0 3.1416 314.16e-2 0.31416E1 0xff 0x56
+
+
+
+A comment starts with a double hyphen (--)
+anywhere outside a string.
+If the text immediately after -- is not an opening long bracket,
+the comment is a short comment,
+which runs until the end of the line.
+Otherwise, it is a long comment,
+which runs until the corresponding closing long bracket.
+Long comments are frequently used to disable code temporarily.
+
+
+
+
+
+
+Lua is a dynamically typed language.
+This means that
+variables do not have types; only values do.
+There are no type definitions in the language.
+All values carry their own type.
+
+
+
+All values in Lua are first-class values.
+This means that all values can be stored in variables,
+passed as arguments to other functions, and returned as results.
+
+
+
+There are eight basic types in Lua:
+nil, boolean, number,
+string, function, userdata,
+thread, and table.
+Nil is the type of the value nil,
+whose main property is to be different from any other value;
+it usually represents the absence of a useful value.
+Boolean is the type of the values false and true.
+Both nil and false make a condition false;
+any other value makes it true.
+Number represents real (double-precision floating-point) numbers.
+(It is easy to build Lua interpreters that use other
+internal representations for numbers,
+such as single-precision float or long integers;
+see file luaconf.h.)
+String represents arrays of characters.
+
+Lua is 8-bit clean:
+strings can contain any 8-bit character,
+including embedded zeros ('\0') (see §2.1).
+
+
+
+Lua can call (and manipulate) functions written in Lua and
+functions written in C
+(see §2.5.8).
+
+
+
+The type userdata is provided to allow arbitrary C data to
+be stored in Lua variables.
+This type corresponds to a block of raw memory
+and has no pre-defined operations in Lua,
+except assignment and identity test.
+However, by using metatables,
+the programmer can define operations for userdata values
+(see §2.8).
+Userdata values cannot be created or modified in Lua,
+only through the C API.
+This guarantees the integrity of data owned by the host program.
+
+
+
+The type thread represents independent threads of execution
+and it is used to implement coroutines (see §2.11).
+Do not confuse Lua threads with operating-system threads.
+Lua supports coroutines on all systems,
+even those that do not support threads.
+
+
+
+The type table implements associative arrays,
+that is, arrays that can be indexed not only with numbers,
+but with any value (except nil).
+Tables can be heterogeneous;
+that is, they can contain values of all types (except nil).
+Tables are the sole data structuring mechanism in Lua;
+they can be used to represent ordinary arrays,
+symbol tables, sets, records, graphs, trees, etc.
+To represent records, Lua uses the field name as an index.
+The language supports this representation by
+providing a.name as syntactic sugar for a["name"].
+There are several convenient ways to create tables in Lua
+(see §2.5.7).
+
+
+
+Like indices,
+the value of a table field can be of any type (except nil).
+In particular,
+because functions are first-class values,
+table fields can contain functions.
+Thus tables can also carry methods (see §2.5.9).
+
+
+
+Tables, functions, threads, and (full) userdata values are objects:
+variables do not actually contain these values,
+only references to them.
+Assignment, parameter passing, and function returns
+always manipulate references to such values;
+these operations do not imply any kind of copy.
+
+
+
+The library function type returns a string describing the type
+of a given value.
+
+
+
+
+Lua provides automatic conversion between
+string and number values at run time.
+Any arithmetic operation applied to a string tries to convert
+this string to a number, following the usual conversion rules.
+Conversely, whenever a number is used where a string is expected,
+the number is converted to a string, in a reasonable format.
+For complete control over how numbers are converted to strings,
+use the format function from the string library
+(see string.format).
+
+
+
+
+
+
+
+
+Variables are places that store values.
+
+There are three kinds of variables in Lua:
+global variables, local variables, and table fields.
+
+
+
+A single name can denote a global variable or a local variable
+(or a function's formal parameter,
+which is a particular kind of local variable):
+
+
+ var ::= Name
+
+Name denotes identifiers, as defined in §2.1.
+
+
+
+Any variable is assumed to be global unless explicitly declared
+as a local (see §2.4.7).
+Local variables are lexically scoped:
+local variables can be freely accessed by functions
+defined inside their scope (see §2.6).
+
+
+
+Before the first assignment to a variable, its value is nil.
+
+
+
+Square brackets are used to index a table:
+
+
+ var ::= prefixexp `[´ exp `]´
+
+The meaning of accesses to global variables
+and table fields can be changed via metatables.
+An access to an indexed variable t[i] is equivalent to
+a call gettable_event(t,i).
+(See §2.8 for a complete description of the
+gettable_event function.
+This function is not defined or callable in Lua.
+We use it here only for explanatory purposes.)
+
+
+
+The syntax var.Name is just syntactic sugar for
+var["Name"]:
+
+
+ var ::= prefixexp `.´ Name
+
+
+
+All global variables live as fields in ordinary Lua tables,
+called environment tables or simply
+environments (see §2.9).
+Each function has its own reference to an environment,
+so that all global variables in this function
+will refer to this environment table.
+When a function is created,
+it inherits the environment from the function that created it.
+To get the environment table of a Lua function,
+you call getfenv.
+To replace it,
+you call setfenv.
+(You can only manipulate the environment of C functions
+through the debug library; (see §5.9).)
+
+
+
+An access to a global variable x
+is equivalent to _env.x,
+which in turn is equivalent to
+
+
+ gettable_event(_env, "x")
+
+where _env is the environment of the running function.
+(See §2.8 for a complete description of the
+gettable_event function.
+This function is not defined or callable in Lua.
+Similarly, the _env variable is not defined in Lua.
+We use them here only for explanatory purposes.)
+
+
+
+
+
+
+Lua supports an almost conventional set of statements,
+similar to those in Pascal or C.
+This set includes
+assignments, control structures, function calls,
+and variable declarations.
+
+
+
+
+The unit of execution of Lua is called a chunk.
+A chunk is simply a sequence of statements,
+which are executed sequentially.
+Each statement can be optionally followed by a semicolon:
+
+
+ chunk ::= {stat [`;´]}
+
+There are no empty statements and thus ';;' is not legal.
+
+
+
+Lua handles a chunk as the body of an anonymous function
+with a variable number of arguments
+(see §2.5.9).
+As such, chunks can define local variables,
+receive arguments, and return values.
+
+
+
+A chunk can be stored in a file or in a string inside the host program.
+To execute a chunk,
+Lua first pre-compiles the chunk into instructions for a virtual machine,
+and then it executes the compiled code
+with an interpreter for the virtual machine.
+
+
+
+Chunks can also be pre-compiled into binary form;
+see program luac for details.
+Programs in source and compiled forms are interchangeable;
+Lua automatically detects the file type and acts accordingly.
+
+
+
+
+
+
+
+A block is a list of statements;
+syntactically, a block is the same as a chunk:
+
+
+ block ::= chunk
+
+
+
+A block can be explicitly delimited to produce a single statement:
+
+
+ stat ::= do block end
+
+Explicit blocks are useful
+to control the scope of variable declarations.
+Explicit blocks are also sometimes used to
+add a return or break statement in the middle
+of another block (see §2.4.4).
+
+
+
+
+
+
+Lua allows multiple assignments.
+Therefore, the syntax for assignment
+defines a list of variables on the left side
+and a list of expressions on the right side.
+The elements in both lists are separated by commas:
+
+
+ stat ::= varlist `=´ explist
+ varlist ::= var {`,´ var}
+ explist ::= exp {`,´ exp}
+
+Before the assignment,
+the list of values is adjusted to the length of
+the list of variables.
+If there are more values than needed,
+the excess values are thrown away.
+If there are fewer values than needed,
+the list is extended with as many nil's as needed.
+If the list of expressions ends with a function call,
+then all values returned by that call enter the list of values,
+before the adjustment
+(except when the call is enclosed in parentheses; see §2.5).
+
+
+
+The assignment statement first evaluates all its expressions
+and only then are the assignments performed.
+Thus the code
+
+
+ i = 3
+ i, a[i] = i+1, 20
+
+sets a[3] to 20, without affecting a[4]
+because the i in a[i] is evaluated (to 3)
+before it is assigned 4.
+Similarly, the line
+
+
+ x, y = y, x
+
+exchanges the values of x and y,
+and
+
+
+ x, y, z = y, z, x
+
+cyclically permutes the values of x, y, and z.
+
+
+
+The meaning of assignments to global variables
+and table fields can be changed via metatables.
+An assignment to an indexed variable t[i] = val is equivalent to
+settable_event(t,i,val).
+(See §2.8 for a complete description of the
+settable_event function.
+This function is not defined or callable in Lua.
+We use it here only for explanatory purposes.)
+
+
+
+An assignment to a global variable x = val
+is equivalent to the assignment
+_env.x = val,
+which in turn is equivalent to
+
+
+ settable_event(_env, "x", val)
+
+where _env is the environment of the running function.
+(The _env variable is not defined in Lua.
+We use it here only for explanatory purposes.)
+
+
+
+
+
+
+The control structures
+if, while, and repeat have the usual meaning and
+familiar syntax:
+
+
+
+
+
+ stat ::= while exp do block end
+ stat ::= repeat block until exp
+ stat ::= if exp then block {elseif exp then block} [else block] end
+
+Lua also has a for statement, in two flavors (see §2.4.5).
+
+
+
+The condition expression of a
+control structure can return any value.
+Both false and nil are considered false.
+All values different from nil and false are considered true
+(in particular, the number 0 and the empty string are also true).
+
+
+
+In the repeat–until loop,
+the inner block does not end at the until keyword,
+but only after the condition.
+So, the condition can refer to local variables
+declared inside the loop block.
+
+
+
+The return statement is used to return values
+from a function or a chunk (which is just a function).
+
+Functions and chunks can return more than one value,
+and so the syntax for the return statement is
+
+
+ stat ::= return [explist]
+
+
+
+The break statement is used to terminate the execution of a
+while, repeat, or for loop,
+skipping to the next statement after the loop:
+
+
+
+ stat ::= break
+
+A break ends the innermost enclosing loop.
+
+
+
+The return and break
+statements can only be written as the last statement of a block.
+If it is really necessary to return or break in the
+middle of a block,
+then an explicit inner block can be used,
+as in the idioms
+do return end and do break end,
+because now return and break are the last statements in
+their (inner) blocks.
+
+
+
+
+
+
+
+The for statement has two forms:
+one numeric and one generic.
+
+
+
+The numeric for loop repeats a block of code while a
+control variable runs through an arithmetic progression.
+It has the following syntax:
+
+
+ stat ::= for Name `=´ exp `,´ exp [`,´ exp] do block end
+
+The block is repeated for name starting at the value of
+the first exp, until it passes the second exp by steps of the
+third exp.
+More precisely, a for statement like
+
+
+ for v = e1, e2, e3 do block end
+
+is equivalent to the code:
+
+
+ do
+ local var, limit, step = tonumber(e1), tonumber(e2), tonumber(e3)
+ if not (var and limit and step) then error() end
+ while (step > 0 and var <= limit) or (step <= 0 and var >= limit) do
+ local v = var
+ block
+ var = var + step
+ end
+ end
+
+Note the following:
+
+
+
+
+All three control expressions are evaluated only once,
+before the loop starts.
+They must all result in numbers.
+
+
+
+var, limit, and step are invisible variables.
+The names shown here are for explanatory purposes only.
+
+
+
+If the third expression (the step) is absent,
+then a step of 1 is used.
+
+
+
+You can use break to exit a for loop.
+
+
+
+The loop variable v is local to the loop;
+you cannot use its value after the for ends or is broken.
+If you need this value,
+assign it to another variable before breaking or exiting the loop.
+
+
+
+
+
+The generic for statement works over functions,
+called iterators.
+On each iteration, the iterator function is called to produce a new value,
+stopping when this new value is nil.
+The generic for loop has the following syntax:
+
+
+ stat ::= for namelist in explist do block end
+ namelist ::= Name {`,´ Name}
+
+A for statement like
+
+
+ for var_1, ···, var_n in explist do block end
+
+is equivalent to the code:
+
+
+ do
+ local f, s, var = explist
+ while true do
+ local var_1, ···, var_n = f(s, var)
+ var = var_1
+ if var == nil then break end
+ block
+ end
+ end
+
+Note the following:
+
+
+
+
+explist is evaluated only once.
+Its results are an iterator function,
+a state,
+and an initial value for the first iterator variable.
+
+
+
+f, s, and var are invisible variables.
+The names are here for explanatory purposes only.
+
+
+
+You can use break to exit a for loop.
+
+
+
+The loop variables var_i are local to the loop;
+you cannot use their values after the for ends.
+If you need these values,
+then assign them to other variables before breaking or exiting the loop.
+
+Local variables can be declared anywhere inside a block.
+The declaration can include an initial assignment:
+
+
+ stat ::= local namelist [`=´ explist]
+
+If present, an initial assignment has the same semantics
+of a multiple assignment (see §2.4.3).
+Otherwise, all variables are initialized with nil.
+
+
+
+A chunk is also a block (see §2.4.1),
+and so local variables can be declared in a chunk outside any explicit block.
+The scope of such local variables extends until the end of the chunk.
+
+
+
+The visibility rules for local variables are explained in §2.6.
+
+
+
+
+
+
+
+
+Numbers and literal strings are explained in §2.1;
+variables are explained in §2.3;
+function definitions are explained in §2.5.9;
+function calls are explained in §2.5.8;
+table constructors are explained in §2.5.7.
+Vararg expressions,
+denoted by three dots ('...'), can only be used when
+directly inside a vararg function;
+they are explained in §2.5.9.
+
+
+
+Binary operators comprise arithmetic operators (see §2.5.1),
+relational operators (see §2.5.2), logical operators (see §2.5.3),
+and the concatenation operator (see §2.5.4).
+Unary operators comprise the unary minus (see §2.5.1),
+the unary not (see §2.5.3),
+and the unary length operator (see §2.5.5).
+
+
+
+Both function calls and vararg expressions can result in multiple values.
+If an expression is used as a statement
+(only possible for function calls (see §2.4.6)),
+then its return list is adjusted to zero elements,
+thus discarding all returned values.
+If an expression is used as the last (or the only) element
+of a list of expressions,
+then no adjustment is made
+(unless the call is enclosed in parentheses).
+In all other contexts,
+Lua adjusts the result list to one element,
+discarding all values except the first one.
+
+
+
+Here are some examples:
+
+
+ f() -- adjusted to 0 results
+ g(f(), x) -- f() is adjusted to 1 result
+ g(x, f()) -- g gets x plus all results from f()
+ a,b,c = f(), x -- f() is adjusted to 1 result (c gets nil)
+ a,b = ... -- a gets the first vararg parameter, b gets
+ -- the second (both a and b can get nil if there
+ -- is no corresponding vararg parameter)
+
+ a,b,c = x, f() -- f() is adjusted to 2 results
+ a,b,c = f() -- f() is adjusted to 3 results
+ return f() -- returns all results from f()
+ return ... -- returns all received vararg parameters
+ return x,y,f() -- returns x, y, and all results from f()
+ {f()} -- creates a list with all results from f()
+ {...} -- creates a list with all vararg parameters
+ {f(), nil} -- f() is adjusted to 1 result
+
+
+
+Any expression enclosed in parentheses always results in only one value.
+Thus,
+(f(x,y,z)) is always a single value,
+even if f returns several values.
+(The value of (f(x,y,z)) is the first value returned by f
+or nil if f does not return any values.)
+
+
+
+
+Lua supports the usual arithmetic operators:
+the binary + (addition),
+- (subtraction), * (multiplication),
+/ (division), % (modulo), and ^ (exponentiation);
+and unary - (negation).
+If the operands are numbers, or strings that can be converted to
+numbers (see §2.2.1),
+then all operations have the usual meaning.
+Exponentiation works for any exponent.
+For instance, x^(-0.5) computes the inverse of the square root of x.
+Modulo is defined as
+
+
+ a % b == a - math.floor(a/b)*b
+
+That is, it is the remainder of a division that rounds
+the quotient towards minus infinity.
+
+
+
+
+
+
+These operators always result in false or true.
+
+
+
+Equality (==) first compares the type of its operands.
+If the types are different, then the result is false.
+Otherwise, the values of the operands are compared.
+Numbers and strings are compared in the usual way.
+Objects (tables, userdata, threads, and functions)
+are compared by reference:
+two objects are considered equal only if they are the same object.
+Every time you create a new object
+(a table, userdata, thread, or function),
+this new object is different from any previously existing object.
+
+
+
+You can change the way that Lua compares tables and userdata
+by using the "eq" metamethod (see §2.8).
+
+
+
+The conversion rules of §2.2.1
+do not apply to equality comparisons.
+Thus, "0"==0 evaluates to false,
+and t[0] and t["0"] denote different
+entries in a table.
+
+
+
+The operator ~= is exactly the negation of equality (==).
+
+
+
+The order operators work as follows.
+If both arguments are numbers, then they are compared as such.
+Otherwise, if both arguments are strings,
+then their values are compared according to the current locale.
+Otherwise, Lua tries to call the "lt" or the "le"
+metamethod (see §2.8).
+A comparison a > b is translated to b < a
+and a >= b is translated to b <= a.
+
+
+
+
+
+
+The logical operators in Lua are
+and, or, and not.
+Like the control structures (see §2.4.4),
+all logical operators consider both false and nil as false
+and anything else as true.
+
+
+
+The negation operator not always returns false or true.
+The conjunction operator and returns its first argument
+if this value is false or nil;
+otherwise, and returns its second argument.
+The disjunction operator or returns its first argument
+if this value is different from nil and false;
+otherwise, or returns its second argument.
+Both and and or use short-cut evaluation;
+that is,
+the second operand is evaluated only if necessary.
+Here are some examples:
+
+
+ 10 or 20 --> 10
+ 10 or error() --> 10
+ nil or "a" --> "a"
+ nil and 10 --> nil
+ false and error() --> false
+ false and nil --> false
+ false or nil --> nil
+ 10 and 20 --> 20
+
+(In this manual,
+--> indicates the result of the preceding expression.)
+
+
+
+
+
+
+The string concatenation operator in Lua is
+denoted by two dots ('..').
+If both operands are strings or numbers, then they are converted to
+strings according to the rules mentioned in §2.2.1.
+Otherwise, the "concat" metamethod is called (see §2.8).
+
+
+
+
+
+
+The length operator is denoted by the unary operator #.
+The length of a string is its number of bytes
+(that is, the usual meaning of string length when each
+character is one byte).
+
+
+
+The length of a table t is defined to be any
+integer index n
+such that t[n] is not nil and t[n+1] is nil;
+moreover, if t[1] is nil, n can be zero.
+For a regular array, with non-nil values from 1 to a given n,
+its length is exactly that n,
+the index of its last value.
+If the array has "holes"
+(that is, nil values between other non-nil values),
+then #t can be any of the indices that
+directly precedes a nil value
+(that is, it may consider any such nil value as the end of
+the array).
+
+
+
+
+
+
+Operator precedence in Lua follows the table below,
+from lower to higher priority:
+
+
+ or
+ and
+ < > <= >= ~= ==
+ ..
+ + -
+ * / %
+ not # - (unary)
+ ^
+
+As usual,
+you can use parentheses to change the precedences of an expression.
+The concatenation ('..') and exponentiation ('^')
+operators are right associative.
+All other binary operators are left associative.
+
+
+
+
+
+
+Table constructors are expressions that create tables.
+Every time a constructor is evaluated, a new table is created.
+A constructor can be used to create an empty table
+or to create a table and initialize some of its fields.
+The general syntax for constructors is
+
+
+Each field of the form [exp1] = exp2 adds to the new table an entry
+with key exp1 and value exp2.
+A field of the form name = exp is equivalent to
+["name"] = exp.
+Finally, fields of the form exp are equivalent to
+[i] = exp, where i are consecutive numerical integers,
+starting with 1.
+Fields in the other formats do not affect this counting.
+For example,
+
+
+ a = { [f(1)] = g; "x", "y"; x = 1, f(x), [30] = 23; 45 }
+
+is equivalent to
+
+
+ do
+ local t = {}
+ t[f(1)] = g
+ t[1] = "x" -- 1st exp
+ t[2] = "y" -- 2nd exp
+ t.x = 1 -- t["x"] = 1
+ t[3] = f(x) -- 3rd exp
+ t[30] = 23
+ t[4] = 45 -- 4th exp
+ a = t
+ end
+
+
+
+If the last field in the list has the form exp
+and the expression is a function call or a vararg expression,
+then all values returned by this expression enter the list consecutively
+(see §2.5.8).
+To avoid this,
+enclose the function call or the vararg expression
+in parentheses (see §2.5).
+
+
+
+The field list can have an optional trailing separator,
+as a convenience for machine-generated code.
+
+
+
+
+
+
+A function call in Lua has the following syntax:
+
+
+ functioncall ::= prefixexp args
+
+In a function call,
+first prefixexp and args are evaluated.
+If the value of prefixexp has type function,
+then this function is called
+with the given arguments.
+Otherwise, the prefixexp "call" metamethod is called,
+having as first parameter the value of prefixexp,
+followed by the original call arguments
+(see §2.8).
+
+
+
+The form
+
+
+ functioncall ::= prefixexp `:´ Name args
+
+can be used to call "methods".
+A call v:name(args)
+is syntactic sugar for v.name(v,args),
+except that v is evaluated only once.
+
+
+
+All argument expressions are evaluated before the call.
+A call of the form f{fields} is
+syntactic sugar for f({fields});
+that is, the argument list is a single new table.
+A call of the form f'string'
+(or f"string" or f[[string]])
+is syntactic sugar for f('string');
+that is, the argument list is a single literal string.
+
+
+
+As an exception to the free-format syntax of Lua,
+you cannot put a line break before the '(' in a function call.
+This restriction avoids some ambiguities in the language.
+If you write
+
+
+ a = f
+ (g).x(a)
+
+Lua would see that as a single statement, a = f(g).x(a).
+So, if you want two statements, you must add a semi-colon between them.
+If you actually want to call f,
+you must remove the line break before (g).
+
+
+
+A call of the form returnfunctioncall is called
+a tail call.
+Lua implements proper tail calls
+(or proper tail recursion):
+in a tail call,
+the called function reuses the stack entry of the calling function.
+Therefore, there is no limit on the number of nested tail calls that
+a program can execute.
+However, a tail call erases any debug information about the
+calling function.
+Note that a tail call only happens with a particular syntax,
+where the return has one single function call as argument;
+this syntax makes the calling function return exactly
+the returns of the called function.
+So, none of the following examples are tail calls:
+
+
+ return (f(x)) -- results adjusted to 1
+ return 2 * f(x)
+ return x, f(x) -- additional results
+ f(x); return -- results discarded
+ return x or f(x) -- results adjusted to 1
+
+ function ::= function funcbody
+ funcbody ::= `(´ [parlist] `)´ block end
+
+
+
+The following syntactic sugar simplifies function definitions:
+
+
+ stat ::= function funcname funcbody
+ stat ::= localfunction Name funcbody
+ funcname ::= Name {`.´ Name} [`:´ Name]
+
+The statement
+
+
+ function f () body end
+
+translates to
+
+
+ f = function () body end
+
+The statement
+
+
+ function t.a.b.c.f () body end
+
+translates to
+
+
+ t.a.b.c.f = function () body end
+
+The statement
+
+
+ local function f () body end
+
+translates to
+
+
+ local f; f = function () body end
+
+not to
+
+
+ local f = function () body end
+
+(This only makes a difference when the body of the function
+contains references to f.)
+
+
+
+A function definition is an executable expression,
+whose value has type function.
+When Lua pre-compiles a chunk,
+all its function bodies are pre-compiled too.
+Then, whenever Lua executes the function definition,
+the function is instantiated (or closed).
+This function instance (or closure)
+is the final value of the expression.
+Different instances of the same function
+can refer to different external local variables
+and can have different environment tables.
+
+
+
+Parameters act as local variables that are
+initialized with the argument values:
+
+
+ parlist ::= namelist [`,´ `...´] | `...´
+
+When a function is called,
+the list of arguments is adjusted to
+the length of the list of parameters,
+unless the function is a variadic or vararg function,
+which is
+indicated by three dots ('...') at the end of its parameter list.
+A vararg function does not adjust its argument list;
+instead, it collects all extra arguments and supplies them
+to the function through a vararg expression,
+which is also written as three dots.
+The value of this expression is a list of all actual extra arguments,
+similar to a function with multiple results.
+If a vararg expression is used inside another expression
+or in the middle of a list of expressions,
+then its return list is adjusted to one element.
+If the expression is used as the last element of a list of expressions,
+then no adjustment is made
+(unless that last expression is enclosed in parentheses).
+
+
+
+As an example, consider the following definitions:
+
+
+ function f(a, b) end
+ function g(a, b, ...) end
+ function r() return 1,2,3 end
+
+Then, we have the following mapping from arguments to parameters and
+to the vararg expression:
+
+
+Results are returned using the return statement (see §2.4.4).
+If control reaches the end of a function
+without encountering a return statement,
+then the function returns with no results.
+
+
+
+The colon syntax
+is used for defining methods,
+that is, functions that have an implicit extra parameter self.
+Thus, the statement
+
+
+
+Lua is a lexically scoped language.
+The scope of variables begins at the first statement after
+their declaration and lasts until the end of the innermost block that
+includes the declaration.
+Consider the following example:
+
+
+ x = 10 -- global variable
+ do -- new block
+ local x = x -- new 'x', with value 10
+ print(x) --> 10
+ x = x+1
+ do -- another block
+ local x = x+1 -- another 'x'
+ print(x) --> 12
+ end
+ print(x) --> 11
+ end
+ print(x) --> 10 (the global one)
+
+
+
+Notice that, in a declaration like local x = x,
+the new x being declared is not in scope yet,
+and so the second x refers to the outside variable.
+
+
+
+Because of the lexical scoping rules,
+local variables can be freely accessed by functions
+defined inside their scope.
+A local variable used by an inner function is called
+an upvalue, or external local variable,
+inside the inner function.
+
+
+
+Notice that each execution of a local statement
+defines new local variables.
+Consider the following example:
+
+
+ a = {}
+ local x = 20
+ for i=1,10 do
+ local y = 0
+ a[i] = function () y=y+1; return x+y end
+ end
+
+The loop creates ten closures
+(that is, ten instances of the anonymous function).
+Each of these closures uses a different y variable,
+while all of them share the same x.
+
+
+
+
+
+
+Because Lua is an embedded extension language,
+all Lua actions start from C code in the host program
+calling a function from the Lua library (see lua_pcall).
+Whenever an error occurs during Lua compilation or execution,
+control returns to C,
+which can take appropriate measures
+(such as printing an error message).
+
+
+
+Lua code can explicitly generate an error by calling the
+error function.
+If you need to catch errors in Lua,
+you can use the pcall function.
+
+
+
+
+
+
+Every value in Lua can have a metatable.
+This metatable is an ordinary Lua table
+that defines the behavior of the original value
+under certain special operations.
+You can change several aspects of the behavior
+of operations over a value by setting specific fields in its metatable.
+For instance, when a non-numeric value is the operand of an addition,
+Lua checks for a function in the field "__add" in its metatable.
+If it finds one,
+Lua calls this function to perform the addition.
+
+
+
+We call the keys in a metatable events
+and the values metamethods.
+In the previous example, the event is "add"
+and the metamethod is the function that performs the addition.
+
+
+
+You can query the metatable of any value
+through the getmetatable function.
+
+
+
+You can replace the metatable of tables
+through the setmetatable
+function.
+You cannot change the metatable of other types from Lua
+(except by using the debug library);
+you must use the C API for that.
+
+
+
+Tables and full userdata have individual metatables
+(although multiple tables and userdata can share their metatables).
+Values of all other types share one single metatable per type;
+that is, there is one single metatable for all numbers,
+one for all strings, etc.
+
+
+
+A metatable controls how an object behaves in arithmetic operations,
+order comparisons, concatenation, length operation, and indexing.
+A metatable also can define a function to be called when a userdata
+is garbage collected.
+For each of these operations Lua associates a specific key
+called an event.
+When Lua performs one of these operations over a value,
+it checks whether this value has a metatable with the corresponding event.
+If so, the value associated with that key (the metamethod)
+controls how Lua will perform the operation.
+
+
+
+Metatables control the operations listed next.
+Each operation is identified by its corresponding name.
+The key for each operation is a string with its name prefixed by
+two underscores, '__';
+for instance, the key for operation "add" is the
+string "__add".
+The semantics of these operations is better explained by a Lua function
+describing how the interpreter executes the operation.
+
+
+
+The code shown here in Lua is only illustrative;
+the real behavior is hard coded in the interpreter
+and it is much more efficient than this simulation.
+All functions used in these descriptions
+(rawget, tonumber, etc.)
+are described in §5.1.
+In particular, to retrieve the metamethod of a given object,
+we use the expression
+
+
+ metatable(obj)[event]
+
+This should be read as
+
+
+ rawget(getmetatable(obj) or {}, event)
+
+
+That is, the access to a metamethod does not invoke other metamethods,
+and the access to objects with no metatables does not fail
+(it simply results in nil).
+
+
+
+
+
+
"add":
+the + operation.
+
+
+
+
+The function getbinhandler below defines how Lua chooses a handler
+for a binary operation.
+First, Lua tries the first operand.
+If its type does not define a handler for the operation,
+then Lua tries the second operand.
+
+
+ function getbinhandler (op1, op2, event)
+ return metatable(op1)[event] or metatable(op2)[event]
+ end
+
+By using this function,
+the behavior of the op1 + op2 is
+
+
+ function add_event (op1, op2)
+ local o1, o2 = tonumber(op1), tonumber(op2)
+ if o1 and o2 then -- both operands are numeric?
+ return o1 + o2 -- '+' here is the primitive 'add'
+ else -- at least one of the operands is not numeric
+ local h = getbinhandler(op1, op2, "__add")
+ if h then
+ -- call the handler with both operands
+ return (h(op1, op2))
+ else -- no handler available: default behavior
+ error(···)
+ end
+ end
+ end
+
+
+
+
"sub":
+the - operation.
+
+Behavior similar to the "add" operation.
+
+
+
"mul":
+the * operation.
+
+Behavior similar to the "add" operation.
+
+
+
"div":
+the / operation.
+
+Behavior similar to the "add" operation.
+
+
+
"mod":
+the % operation.
+
+Behavior similar to the "add" operation,
+with the operation
+o1 - floor(o1/o2)*o2 as the primitive operation.
+
+
+
"pow":
+the ^ (exponentiation) operation.
+
+Behavior similar to the "add" operation,
+with the function pow (from the C math library)
+as the primitive operation.
+
+
+
"unm":
+the unary - operation.
+
+
+
+ function unm_event (op)
+ local o = tonumber(op)
+ if o then -- operand is numeric?
+ return -o -- '-' here is the primitive 'unm'
+ else -- the operand is not numeric.
+ -- Try to get a handler from the operand
+ local h = metatable(op).__unm
+ if h then
+ -- call the handler with the operand
+ return (h(op))
+ else -- no handler available: default behavior
+ error(···)
+ end
+ end
+ end
+
+ function concat_event (op1, op2)
+ if (type(op1) == "string" or type(op1) == "number") and
+ (type(op2) == "string" or type(op2) == "number") then
+ return op1 .. op2 -- primitive string concatenation
+ else
+ local h = getbinhandler(op1, op2, "__concat")
+ if h then
+ return (h(op1, op2))
+ else
+ error(···)
+ end
+ end
+ end
+
+
+
+
"len":
+the # operation.
+
+
+
+ function len_event (op)
+ if type(op) == "string" then
+ return strlen(op) -- primitive string length
+ elseif type(op) == "table" then
+ return #op -- primitive table length
+ else
+ local h = metatable(op).__len
+ if h then
+ -- call the handler with the operand
+ return (h(op))
+ else -- no handler available: default behavior
+ error(···)
+ end
+ end
+ end
+
+See §2.5.5 for a description of the length of a table.
+
+
+
"eq":
+the == operation.
+
+The function getcomphandler defines how Lua chooses a metamethod
+for comparison operators.
+A metamethod only is selected when both objects
+being compared have the same type
+and the same metamethod for the selected operation.
+
+
+ function getcomphandler (op1, op2, event)
+ if type(op1) ~= type(op2) then return nil end
+ local mm1 = metatable(op1)[event]
+ local mm2 = metatable(op2)[event]
+ if mm1 == mm2 then return mm1 else return nil end
+ end
+
+The "eq" event is defined as follows:
+
+
+ function eq_event (op1, op2)
+ if type(op1) ~= type(op2) then -- different types?
+ return false -- different objects
+ end
+ if op1 == op2 then -- primitive equal?
+ return true -- objects are equal
+ end
+ -- try metamethod
+ local h = getcomphandler(op1, op2, "__eq")
+ if h then
+ return (h(op1, op2))
+ else
+ return false
+ end
+ end
+
+a ~= b is equivalent to not (a == b).
+
+
+
"lt":
+the < operation.
+
+
+
+ function lt_event (op1, op2)
+ if type(op1) == "number" and type(op2) == "number" then
+ return op1 < op2 -- numeric comparison
+ elseif type(op1) == "string" and type(op2) == "string" then
+ return op1 < op2 -- lexicographic comparison
+ else
+ local h = getcomphandler(op1, op2, "__lt")
+ if h then
+ return (h(op1, op2))
+ else
+ error(···)
+ end
+ end
+ end
+
+a > b is equivalent to b < a.
+
+
+
"le":
+the <= operation.
+
+
+
+ function le_event (op1, op2)
+ if type(op1) == "number" and type(op2) == "number" then
+ return op1 <= op2 -- numeric comparison
+ elseif type(op1) == "string" and type(op2) == "string" then
+ return op1 <= op2 -- lexicographic comparison
+ else
+ local h = getcomphandler(op1, op2, "__le")
+ if h then
+ return (h(op1, op2))
+ else
+ h = getcomphandler(op1, op2, "__lt")
+ if h then
+ return not h(op2, op1)
+ else
+ error(···)
+ end
+ end
+ end
+ end
+
+a >= b is equivalent to b <= a.
+Note that, in the absence of a "le" metamethod,
+Lua tries the "lt", assuming that a <= b is
+equivalent to not (b < a).
+
+
+
"index":
+The indexing access table[key].
+
+
+
+ function gettable_event (table, key)
+ local h
+ if type(table) == "table" then
+ local v = rawget(table, key)
+ if v ~= nil then return v end
+ h = metatable(table).__index
+ if h == nil then return nil end
+ else
+ h = metatable(table).__index
+ if h == nil then
+ error(···)
+ end
+ end
+ if type(h) == "function" then
+ return (h(table, key)) -- call the handler
+ else return h[key] -- or repeat operation on it
+ end
+ end
+
+ function settable_event (table, key, value)
+ local h
+ if type(table) == "table" then
+ local v = rawget(table, key)
+ if v ~= nil then rawset(table, key, value); return end
+ h = metatable(table).__newindex
+ if h == nil then rawset(table, key, value); return end
+ else
+ h = metatable(table).__newindex
+ if h == nil then
+ error(···)
+ end
+ end
+ if type(h) == "function" then
+ h(table, key,value) -- call the handler
+ else h[key] = value -- or repeat operation on it
+ end
+ end
+
+
+
+
"call":
+called when Lua calls a value.
+
+
+
+ function function_event (func, ...)
+ if type(func) == "function" then
+ return func(...) -- primitive call
+ else
+ local h = metatable(func).__call
+ if h then
+ return h(func, ...)
+ else
+ error(···)
+ end
+ end
+ end
+
+Besides metatables,
+objects of types thread, function, and userdata
+have another table associated with them,
+called their environment.
+Like metatables, environments are regular tables and
+multiple objects can share the same environment.
+
+
+
+Threads are created sharing the environment of the creating thread.
+Userdata and C functions are created sharing the environment
+of the creating C function.
+Non-nested Lua functions
+(created by loadfile, loadstring or load)
+are created sharing the environment of the creating thread.
+Nested Lua functions are created sharing the environment of
+the creating Lua function.
+
+
+
+Environments associated with userdata have no meaning for Lua.
+It is only a convenience feature for programmers to associate a table to
+a userdata.
+
+
+
+Environments associated with threads are called
+global environments.
+They are used as the default environment for threads and
+non-nested Lua functions created by the thread
+and can be directly accessed by C code (see §3.3).
+
+
+
+The environment associated with a C function can be directly
+accessed by C code (see §3.3).
+It is used as the default environment for other C functions
+and userdata created by the function.
+
+
+
+Environments associated with Lua functions are used to resolve
+all accesses to global variables within the function (see §2.3).
+They are used as the default environment for nested Lua functions
+created by the function.
+
+
+
+You can change the environment of a Lua function or the
+running thread by calling setfenv.
+You can get the environment of a Lua function or the running thread
+by calling getfenv.
+To manipulate the environment of other objects
+(userdata, C functions, other threads) you must
+use the C API.
+
+
+
+
+
+
+Lua performs automatic memory management.
+This means that
+you have to worry neither about allocating memory for new objects
+nor about freeing it when the objects are no longer needed.
+Lua manages memory automatically by running
+a garbage collector from time to time
+to collect all dead objects
+(that is, objects that are no longer accessible from Lua).
+All memory used by Lua is subject to automatic management:
+tables, userdata, functions, threads, strings, etc.
+
+
+
+Lua implements an incremental mark-and-sweep collector.
+It uses two numbers to control its garbage-collection cycles:
+the garbage-collector pause and
+the garbage-collector step multiplier.
+Both use percentage points as units
+(so that a value of 100 means an internal value of 1).
+
+
+
+The garbage-collector pause
+controls how long the collector waits before starting a new cycle.
+Larger values make the collector less aggressive.
+Values smaller than 100 mean the collector will not wait to
+start a new cycle.
+A value of 200 means that the collector waits for the total memory in use
+to double before starting a new cycle.
+
+
+
+The step multiplier
+controls the relative speed of the collector relative to
+memory allocation.
+Larger values make the collector more aggressive but also increase
+the size of each incremental step.
+Values smaller than 100 make the collector too slow and
+can result in the collector never finishing a cycle.
+The default, 200, means that the collector runs at "twice"
+the speed of memory allocation.
+
+
+
+You can change these numbers by calling lua_gc in C
+or collectgarbage in Lua.
+With these functions you can also control
+the collector directly (e.g., stop and restart it).
+
+
+
+
+Using the C API,
+you can set garbage-collector metamethods for userdata (see §2.8).
+These metamethods are also called finalizers.
+Finalizers allow you to coordinate Lua's garbage collection
+with external resource management
+(such as closing files, network or database connections,
+or freeing your own memory).
+
+
+
+Garbage userdata with a field __gc in their metatables are not
+collected immediately by the garbage collector.
+Instead, Lua puts them in a list.
+After the collection,
+Lua does the equivalent of the following function
+for each userdata in that list:
+
+
+ function gc_event (udata)
+ local h = metatable(udata).__gc
+ if h then
+ h(udata)
+ end
+ end
+
+
+
+At the end of each garbage-collection cycle,
+the finalizers for userdata are called in reverse
+order of their creation,
+among those collected in that cycle.
+That is, the first finalizer to be called is the one associated
+with the userdata created last in the program.
+The userdata itself is freed only in the next garbage-collection cycle.
+
+
+
+
+
+
+A weak table is a table whose elements are
+weak references.
+A weak reference is ignored by the garbage collector.
+In other words,
+if the only references to an object are weak references,
+then the garbage collector will collect this object.
+
+
+
+A weak table can have weak keys, weak values, or both.
+A table with weak keys allows the collection of its keys,
+but prevents the collection of its values.
+A table with both weak keys and weak values allows the collection of
+both keys and values.
+In any case, if either the key or the value is collected,
+the whole pair is removed from the table.
+The weakness of a table is controlled by the
+__mode field of its metatable.
+If the __mode field is a string containing the character 'k',
+the keys in the table are weak.
+If __mode contains 'v',
+the values in the table are weak.
+
+
+
+After you use a table as a metatable,
+you should not change the value of its __mode field.
+Otherwise, the weak behavior of the tables controlled by this
+metatable is undefined.
+
+
+
+
+
+
+
+
+Lua supports coroutines,
+also called collaborative multithreading.
+A coroutine in Lua represents an independent thread of execution.
+Unlike threads in multithread systems, however,
+a coroutine only suspends its execution by explicitly calling
+a yield function.
+
+
+
+You create a coroutine with a call to coroutine.create.
+Its sole argument is a function
+that is the main function of the coroutine.
+The create function only creates a new coroutine and
+returns a handle to it (an object of type thread);
+it does not start the coroutine execution.
+
+
+
+When you first call coroutine.resume,
+passing as its first argument
+a thread returned by coroutine.create,
+the coroutine starts its execution,
+at the first line of its main function.
+Extra arguments passed to coroutine.resume are passed on
+to the coroutine main function.
+After the coroutine starts running,
+it runs until it terminates or yields.
+
+
+
+A coroutine can terminate its execution in two ways:
+normally, when its main function returns
+(explicitly or implicitly, after the last instruction);
+and abnormally, if there is an unprotected error.
+In the first case, coroutine.resume returns true,
+plus any values returned by the coroutine main function.
+In case of errors, coroutine.resume returns false
+plus an error message.
+
+
+
+A coroutine yields by calling coroutine.yield.
+When a coroutine yields,
+the corresponding coroutine.resume returns immediately,
+even if the yield happens inside nested function calls
+(that is, not in the main function,
+but in a function directly or indirectly called by the main function).
+In the case of a yield, coroutine.resume also returns true,
+plus any values passed to coroutine.yield.
+The next time you resume the same coroutine,
+it continues its execution from the point where it yielded,
+with the call to coroutine.yield returning any extra
+arguments passed to coroutine.resume.
+
+
+
+Like coroutine.create,
+the coroutine.wrap function also creates a coroutine,
+but instead of returning the coroutine itself,
+it returns a function that, when called, resumes the coroutine.
+Any arguments passed to this function
+go as extra arguments to coroutine.resume.
+coroutine.wrap returns all the values returned by coroutine.resume,
+except the first one (the boolean error code).
+Unlike coroutine.resume,
+coroutine.wrap does not catch errors;
+any error is propagated to the caller.
+
+
+
+As an example,
+consider the following code:
+
+
+ function foo (a)
+ print("foo", a)
+ return coroutine.yield(2*a)
+ end
+
+ co = coroutine.create(function (a,b)
+ print("co-body", a, b)
+ local r = foo(a+1)
+ print("co-body", r)
+ local r, s = coroutine.yield(a+b, a-b)
+ print("co-body", r, s)
+ return b, "end"
+ end)
+
+ print("main", coroutine.resume(co, 1, 10))
+ print("main", coroutine.resume(co, "r"))
+ print("main", coroutine.resume(co, "x", "y"))
+ print("main", coroutine.resume(co, "x", "y"))
+
+When you run it, it produces the following output:
+
+
+ co-body 1 10
+ foo 2
+
+ main true 4
+ co-body r
+ main true 11 -9
+ co-body x y
+ main true 10 end
+ main false cannot resume dead coroutine
+
+
+This section describes the C API for Lua, that is,
+the set of C functions available to the host program to communicate
+with Lua.
+All API functions and related types and constants
+are declared in the header file lua.h.
+
+
+
+Even when we use the term "function",
+any facility in the API may be provided as a macro instead.
+All such macros use each of their arguments exactly once
+(except for the first argument, which is always a Lua state),
+and so do not generate any hidden side-effects.
+
+
+
+As in most C libraries,
+the Lua API functions do not check their arguments for validity or consistency.
+However, you can change this behavior by compiling Lua
+with a proper definition for the macro luai_apicheck,
+in file luaconf.h.
+
+
+
+
+Lua uses a virtual stack to pass values to and from C.
+Each element in this stack represents a Lua value
+(nil, number, string, etc.).
+
+
+
+Whenever Lua calls C, the called function gets a new stack,
+which is independent of previous stacks and of stacks of
+C functions that are still active.
+This stack initially contains any arguments to the C function
+and it is where the C function pushes its results
+to be returned to the caller (see lua_CFunction).
+
+
+
+For convenience,
+most query operations in the API do not follow a strict stack discipline.
+Instead, they can refer to any element in the stack
+by using an index:
+A positive index represents an absolute stack position
+(starting at 1);
+a negative index represents an offset relative to the top of the stack.
+More specifically, if the stack has n elements,
+then index 1 represents the first element
+(that is, the element that was pushed onto the stack first)
+and
+index n represents the last element;
+index -1 also represents the last element
+(that is, the element at the top)
+and index -n represents the first element.
+We say that an index is valid
+if it lies between 1 and the stack top
+(that is, if 1 ≤ abs(index) ≤ top).
+
+
+
+
+
+
+
+When you interact with Lua API,
+you are responsible for ensuring consistency.
+In particular,
+you are responsible for controlling stack overflow.
+You can use the function lua_checkstack
+to grow the stack size.
+
+
+
+Whenever Lua calls C,
+it ensures that at least LUA_MINSTACK stack positions are available.
+LUA_MINSTACK is defined as 20,
+so that usually you do not have to worry about stack space
+unless your code has loops pushing elements onto the stack.
+
+
+
+Most query functions accept as indices any value inside the
+available stack space, that is, indices up to the maximum stack size
+you have set through lua_checkstack.
+Such indices are called acceptable indices.
+More formally, we define an acceptable index
+as follows:
+
+
+Unless otherwise noted,
+any function that accepts valid indices can also be called with
+pseudo-indices,
+which represent some Lua values that are accessible to C code
+but which are not in the stack.
+Pseudo-indices are used to access the thread environment,
+the function environment,
+the registry,
+and the upvalues of a C function (see §3.4).
+
+
+
+The thread environment (where global variables live) is
+always at pseudo-index LUA_GLOBALSINDEX.
+The environment of the running C function is always
+at pseudo-index LUA_ENVIRONINDEX.
+
+
+
+To access and change the value of global variables,
+you can use regular table operations over an environment table.
+For instance, to access the value of a global variable, do
+
+
+When a C function is created,
+it is possible to associate some values with it,
+thus creating a C closure;
+these values are called upvalues and are
+accessible to the function whenever it is called
+(see lua_pushcclosure).
+
+
+
+Whenever a C function is called,
+its upvalues are located at specific pseudo-indices.
+These pseudo-indices are produced by the macro
+lua_upvalueindex.
+The first value associated with a function is at position
+lua_upvalueindex(1), and so on.
+Any access to lua_upvalueindex(n),
+where n is greater than the number of upvalues of the
+current function (but not greater than 256),
+produces an acceptable (but invalid) index.
+
+
+
+
+
+
+Lua provides a registry,
+a pre-defined table that can be used by any C code to
+store whatever Lua value it needs to store.
+This table is always located at pseudo-index
+LUA_REGISTRYINDEX.
+Any C library can store data into this table,
+but it should take care to choose keys different from those used
+by other libraries, to avoid collisions.
+Typically, you should use as key a string containing your library name
+or a light userdata with the address of a C object in your code.
+
+
+
+The integer keys in the registry are used by the reference mechanism,
+implemented by the auxiliary library,
+and therefore should not be used for other purposes.
+
+
+
+
+
+
+Internally, Lua uses the C longjmp facility to handle errors.
+(You can also choose to use exceptions if you use C++;
+see file luaconf.h.)
+When Lua faces any error
+(such as memory allocation errors, type errors, syntax errors,
+and runtime errors)
+it raises an error;
+that is, it does a long jump.
+A protected environment uses setjmp
+to set a recover point;
+any error jumps to the most recent active recover point.
+
+
+
+Most functions in the API can throw an error,
+for instance due to a memory allocation error.
+The documentation for each function indicates whether
+it can throw errors.
+
+
+
+Inside a C function you can throw an error by calling lua_error.
+
+
+
+
+
+
+Here we list all functions and types from the C API in
+alphabetical order.
+Each function has an indicator like this:
+[-o, +p, x]
+
+
+
+The first field, o,
+is how many elements the function pops from the stack.
+The second field, p,
+is how many elements the function pushes onto the stack.
+(Any function always pushes its results after popping its arguments.)
+A field in the form x|y means the function can push (or pop)
+x or y elements,
+depending on the situation;
+an interrogation mark '?' means that
+we cannot know how many elements the function pops/pushes
+by looking only at its arguments
+(e.g., they may depend on what is on the stack).
+The third field, x,
+tells whether the function may throw errors:
+'-' means the function never throws any error;
+'m' means the function may throw an error
+only due to not enough memory;
+'e' means the function may throw other kinds of errors;
+'v' means the function may throw an error on purpose.
+
+
+
+
+The type of the memory-allocation function used by Lua states.
+The allocator function must provide a
+functionality similar to realloc,
+but not exactly the same.
+Its arguments are
+ud, an opaque pointer passed to lua_newstate;
+ptr, a pointer to the block being allocated/reallocated/freed;
+osize, the original size of the block;
+nsize, the new size of the block.
+ptr is NULL if and only if osize is zero.
+When nsize is zero, the allocator must return NULL;
+if osize is not zero,
+it should free the block pointed to by ptr.
+When nsize is not zero, the allocator returns NULL
+if and only if it cannot fill the request.
+When nsize is not zero and osize is zero,
+the allocator should behave like malloc.
+When nsize and osize are not zero,
+the allocator behaves like realloc.
+Lua assumes that the allocator never fails when
+osize >= nsize.
+
+
+
+Here is a simple implementation for the allocator function.
+It is used in the auxiliary library by luaL_newstate.
+
+
+This code assumes
+that free(NULL) has no effect and that
+realloc(NULL, size) is equivalent to malloc(size).
+ANSI C ensures both behaviors.
+
+
+
+
+
+
+Sets a new panic function and returns the old one.
+
+
+
+If an error happens outside any protected environment,
+Lua calls a panic function
+and then calls exit(EXIT_FAILURE),
+thus exiting the host application.
+Your panic function can avoid this exit by
+never returning (e.g., doing a long jump).
+
+
+
+The panic function can access the error message at the top of the stack.
+
+
+
+
+
+
void lua_call (lua_State *L, int nargs, int nresults);
+
+
+Calls a function.
+
+
+
+To call a function you must use the following protocol:
+first, the function to be called is pushed onto the stack;
+then, the arguments to the function are pushed
+in direct order;
+that is, the first argument is pushed first.
+Finally you call lua_call;
+nargs is the number of arguments that you pushed onto the stack.
+All arguments and the function value are popped from the stack
+when the function is called.
+The function results are pushed onto the stack when the function returns.
+The number of results is adjusted to nresults,
+unless nresults is LUA_MULTRET.
+In this case, all results from the function are pushed.
+Lua takes care that the returned values fit into the stack space.
+The function results are pushed onto the stack in direct order
+(the first result is pushed first),
+so that after the call the last result is on the top of the stack.
+
+
+
+Any error inside the called function is propagated upwards
+(with a longjmp).
+
+
+
+The following example shows how the host program can do the
+equivalent to this Lua code:
+
+
+ a = f("how", t.x, 14)
+
+Here it is in C:
+
+
+ lua_getfield(L, LUA_GLOBALSINDEX, "f"); /* function to be called */
+ lua_pushstring(L, "how"); /* 1st argument */
+ lua_getfield(L, LUA_GLOBALSINDEX, "t"); /* table to be indexed */
+ lua_getfield(L, -1, "x"); /* push result of t.x (2nd arg) */
+ lua_remove(L, -2); /* remove 't' from the stack */
+ lua_pushinteger(L, 14); /* 3rd argument */
+ lua_call(L, 3, 1); /* call 'f' with 3 arguments and 1 result */
+ lua_setfield(L, LUA_GLOBALSINDEX, "a"); /* set global 'a' */
+
+Note that the code above is "balanced":
+at its end, the stack is back to its original configuration.
+This is considered good programming practice.
+
+
+
+
+
+
+In order to communicate properly with Lua,
+a C function must use the following protocol,
+which defines the way parameters and results are passed:
+a C function receives its arguments from Lua in its stack
+in direct order (the first argument is pushed first).
+So, when the function starts,
+lua_gettop(L) returns the number of arguments received by the function.
+The first argument (if any) is at index 1
+and its last argument is at index lua_gettop(L).
+To return values to Lua, a C function just pushes them onto the stack,
+in direct order (the first result is pushed first),
+and returns the number of results.
+Any other value in the stack below the results will be properly
+discarded by Lua.
+Like a Lua function, a C function called by Lua can also return
+many results.
+
+
+
+As an example, the following function receives a variable number
+of numerical arguments and returns their average and sum:
+
+
+ static int foo (lua_State *L) {
+ int n = lua_gettop(L); /* number of arguments */
+ lua_Number sum = 0;
+ int i;
+ for (i = 1; i <= n; i++) {
+ if (!lua_isnumber(L, i)) {
+ lua_pushstring(L, "incorrect argument");
+ lua_error(L);
+ }
+ sum += lua_tonumber(L, i);
+ }
+ lua_pushnumber(L, sum/n); /* first result */
+ lua_pushnumber(L, sum); /* second result */
+ return 2; /* number of results */
+ }
+
+Ensures that there are at least extra free stack slots in the stack.
+It returns false if it cannot grow the stack to that size.
+This function never shrinks the stack;
+if the stack is already larger than the new size,
+it is left unchanged.
+
+
+
+
+
+
+Destroys all objects in the given Lua state
+(calling the corresponding garbage-collection metamethods, if any)
+and frees all dynamic memory used by this state.
+On several platforms, you may not need to call this function,
+because all resources are naturally released when the host program ends.
+On the other hand, long-running programs,
+such as a daemon or a web server,
+might need to release states as soon as they are not needed,
+to avoid growing too large.
+
+
+
+
+
+
+Concatenates the n values at the top of the stack,
+pops them, and leaves the result at the top.
+If n is 1, the result is the single value on the stack
+(that is, the function does nothing);
+if n is 0, the result is the empty string.
+Concatenation is performed following the usual semantics of Lua
+(see §2.5.4).
+
+
+
+
+
+
int lua_cpcall (lua_State *L, lua_CFunction func, void *ud);
+
+
+Calls the C function func in protected mode.
+func starts with only one element in its stack,
+a light userdata containing ud.
+In case of errors,
+lua_cpcall returns the same error codes as lua_pcall,
+plus the error object on the top of the stack;
+otherwise, it returns zero, and does not change the stack.
+All values returned by func are discarded.
+
+
+
+
+
+
void lua_createtable (lua_State *L, int narr, int nrec);
+
+
+Creates a new empty table and pushes it onto the stack.
+The new table has space pre-allocated
+for narr array elements and nrec non-array elements.
+This pre-allocation is useful when you know exactly how many elements
+the table will have.
+Otherwise you can use the function lua_newtable.
+
+
+
+
+
+
int lua_dump (lua_State *L, lua_Writer writer, void *data);
+
+
+Dumps a function as a binary chunk.
+Receives a Lua function on the top of the stack
+and produces a binary chunk that,
+if loaded again,
+results in a function equivalent to the one dumped.
+As it produces parts of the chunk,
+lua_dump calls function writer (see lua_Writer)
+with the given data
+to write them.
+
+
+
+The value returned is the error code returned by the last
+call to the writer;
+0 means no errors.
+
+
+
+This function does not pop the Lua function from the stack.
+
+
+
+
+
+
int lua_equal (lua_State *L, int index1, int index2);
+
+
+Returns 1 if the two values in acceptable indices index1 and
+index2 are equal,
+following the semantics of the Lua == operator
+(that is, may call metamethods).
+Otherwise returns 0.
+Also returns 0 if any of the indices is non valid.
+
+
+
+
+
+
+Generates a Lua error.
+The error message (which can actually be a Lua value of any type)
+must be on the stack top.
+This function does a long jump,
+and therefore never returns.
+(see luaL_error).
+
+
+
+
+
+
+This function performs several tasks,
+according to the value of the parameter what:
+
+
+
+
LUA_GCSTOP:
+stops the garbage collector.
+
+
+
LUA_GCRESTART:
+restarts the garbage collector.
+
+
+
LUA_GCCOLLECT:
+performs a full garbage-collection cycle.
+
+
+
LUA_GCCOUNT:
+returns the current amount of memory (in Kbytes) in use by Lua.
+
+
+
LUA_GCCOUNTB:
+returns the remainder of dividing the current amount of bytes of
+memory in use by Lua by 1024.
+
+
+
LUA_GCSTEP:
+performs an incremental step of garbage collection.
+The step "size" is controlled by data
+(larger values mean more steps) in a non-specified way.
+If you want to control the step size
+you must experimentally tune the value of data.
+The function returns 1 if the step finished a
+garbage-collection cycle.
+
+
+
LUA_GCSETPAUSE:
+sets data as the new value
+for the pause of the collector (see §2.10).
+The function returns the previous value of the pause.
+
+
+
LUA_GCSETSTEPMUL:
+sets data as the new value for the step multiplier of
+the collector (see §2.10).
+The function returns the previous value of the step multiplier.
+
+Returns the memory-allocation function of a given state.
+If ud is not NULL, Lua stores in *ud the
+opaque pointer passed to lua_newstate.
+
+
+
+
+
+
void lua_getfield (lua_State *L, int index, const char *k);
+
+
+Pushes onto the stack the value t[k],
+where t is the value at the given valid index.
+As in Lua, this function may trigger a metamethod
+for the "index" event (see §2.8).
+
+
+
+
+
+
+Pushes onto the stack the metatable of the value at the given
+acceptable index.
+If the index is not valid,
+or if the value does not have a metatable,
+the function returns 0 and pushes nothing on the stack.
+
+
+
+
+
+
+Pushes onto the stack the value t[k],
+where t is the value at the given valid index
+and k is the value at the top of the stack.
+
+
+
+This function pops the key from the stack
+(putting the resulting value in its place).
+As in Lua, this function may trigger a metamethod
+for the "index" event (see §2.8).
+
+
+
+
+
+
+Returns the index of the top element in the stack.
+Because indices start at 1,
+this result is equal to the number of elements in the stack
+(and so 0 means an empty stack).
+
+
+
+
+
+
+Moves the top element into the given valid index,
+shifting up the elements above this index to open space.
+Cannot be called with a pseudo-index,
+because a pseudo-index is not an actual stack position.
+
+
+
+
+
+
+Returns 1 if the given acceptable index is not valid
+(that is, it refers to an element outside the current stack)
+or if the value at this index is nil,
+and 0 otherwise.
+
+
+
+
+
+
+Returns 1 if the value at the given acceptable index is a string
+or a number (which is always convertible to a string),
+and 0 otherwise.
+
+
+
+
+
+
int lua_lessthan (lua_State *L, int index1, int index2);
+
+
+Returns 1 if the value at acceptable index index1 is smaller
+than the value at acceptable index index2,
+following the semantics of the Lua < operator
+(that is, may call metamethods).
+Otherwise returns 0.
+Also returns 0 if any of the indices is non valid.
+
+
+
+
+
+
+Loads a Lua chunk.
+If there are no errors,
+lua_load pushes the compiled chunk as a Lua
+function on top of the stack.
+Otherwise, it pushes an error message.
+The return values of lua_load are:
+
+
+
+
0: no errors;
+
+
LUA_ERRSYNTAX:
+syntax error during pre-compilation;
+This function only loads a chunk;
+it does not run it.
+
+
+
+lua_load automatically detects whether the chunk is text or binary,
+and loads it accordingly (see program luac).
+
+
+
+The lua_load function uses a user-supplied reader function
+to read the chunk (see lua_Reader).
+The data argument is an opaque value passed to the reader function.
+
+
+
+The chunkname argument gives a name to the chunk,
+which is used for error messages and in debug information (see §3.8).
+
+
+
+
+
+
+Creates a new, independent state.
+Returns NULL if cannot create the state
+(due to lack of memory).
+The argument f is the allocator function;
+Lua does all memory allocation for this state through this function.
+The second argument, ud, is an opaque pointer that Lua
+simply passes to the allocator in every call.
+
+
+
+
+
+
+Creates a new thread, pushes it on the stack,
+and returns a pointer to a lua_State that represents this new thread.
+The new state returned by this function shares with the original state
+all global objects (such as tables),
+but has an independent execution stack.
+
+
+
+There is no explicit function to close or to destroy a thread.
+Threads are subject to garbage collection,
+like any Lua object.
+
+
+
+
+
+
+This function allocates a new block of memory with the given size,
+pushes onto the stack a new full userdata with the block address,
+and returns this address.
+
+
+
+Userdata represent C values in Lua.
+A full userdata represents a block of memory.
+It is an object (like a table):
+you must create it, it can have its own metatable,
+and you can detect when it is being collected.
+A full userdata is only equal to itself (under raw equality).
+
+
+
+When Lua collects a full userdata with a gc metamethod,
+Lua calls the metamethod and marks the userdata as finalized.
+When this userdata is collected again then
+Lua frees its corresponding memory.
+
+
+
+
+
+
+Pops a key from the stack,
+and pushes a key-value pair from the table at the given index
+(the "next" pair after the given key).
+If there are no more elements in the table,
+then lua_next returns 0 (and pushes nothing).
+
+
+
+A typical traversal looks like this:
+
+
+ /* table is in the stack at index 't' */
+ lua_pushnil(L); /* first key */
+ while (lua_next(L, t) != 0) {
+ /* uses 'key' (at index -2) and 'value' (at index -1) */
+ printf("%s - %s\n",
+ lua_typename(L, lua_type(L, -2)),
+ lua_typename(L, lua_type(L, -1)));
+ /* removes 'value'; keeps 'key' for next iteration */
+ lua_pop(L, 1);
+ }
+
+
+
+While traversing a table,
+do not call lua_tolstring directly on a key,
+unless you know that the key is actually a string.
+Recall that lua_tolstringchanges
+the value at the given index;
+this confuses the next call to lua_next.
+
+
+
+
+
+
+Returns the "length" of the value at the given acceptable index:
+for strings, this is the string length;
+for tables, this is the result of the length operator ('#');
+for userdata, this is the size of the block of memory allocated
+for the userdata;
+for other values, it is 0.
+
+
+
+
+
+
int lua_pcall (lua_State *L, int nargs, int nresults, int errfunc);
+
+
+Calls a function in protected mode.
+
+
+
+Both nargs and nresults have the same meaning as
+in lua_call.
+If there are no errors during the call,
+lua_pcall behaves exactly like lua_call.
+However, if there is any error,
+lua_pcall catches it,
+pushes a single value on the stack (the error message),
+and returns an error code.
+Like lua_call,
+lua_pcall always removes the function
+and its arguments from the stack.
+
+
+
+If errfunc is 0,
+then the error message returned on the stack
+is exactly the original error message.
+Otherwise, errfunc is the stack index of an
+error handler function.
+(In the current implementation, this index cannot be a pseudo-index.)
+In case of runtime errors,
+this function will be called with the error message
+and its return value will be the message returned on the stack by lua_pcall.
+
+
+
+Typically, the error handler function is used to add more debug
+information to the error message, such as a stack traceback.
+Such information cannot be gathered after the return of lua_pcall,
+since by then the stack has unwound.
+
+
+
+The lua_pcall function returns 0 in case of success
+or one of the following error codes
+(defined in lua.h):
+
+
void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n);
+
+
+Pushes a new C closure onto the stack.
+
+
+
+When a C function is created,
+it is possible to associate some values with it,
+thus creating a C closure (see §3.4);
+these values are then accessible to the function whenever it is called.
+To associate values with a C function,
+first these values should be pushed onto the stack
+(when there are multiple values, the first value is pushed first).
+Then lua_pushcclosure
+is called to create and push the C function onto the stack,
+with the argument n telling how many values should be
+associated with the function.
+lua_pushcclosure also pops these values from the stack.
+
+
+
+Pushes a C function onto the stack.
+This function receives a pointer to a C function
+and pushes onto the stack a Lua value of type function that,
+when called, invokes the corresponding C function.
+
+
+
+Any function to be registered in Lua must
+follow the correct protocol to receive its parameters
+and return its results (see lua_CFunction).
+
+
+
+Pushes onto the stack a formatted string
+and returns a pointer to this string.
+It is similar to the C function sprintf,
+but has some important differences:
+
+
+
+
+You do not have to allocate space for the result:
+the result is a Lua string and Lua takes care of memory allocation
+(and deallocation, through garbage collection).
+
+
+
+The conversion specifiers are quite restricted.
+There are no flags, widths, or precisions.
+The conversion specifiers can only be
+'%%' (inserts a '%' in the string),
+'%s' (inserts a zero-terminated string, with no size restrictions),
+'%f' (inserts a lua_Number),
+'%p' (inserts a pointer as a hexadecimal numeral),
+'%d' (inserts an int), and
+'%c' (inserts an int as a character).
+
+Userdata represent C values in Lua.
+A light userdata represents a pointer.
+It is a value (like a number):
+you do not create it, it has no individual metatable,
+and it is not collected (as it was never created).
+A light userdata is equal to "any"
+light userdata with the same C address.
+
+
+
+
+
+
+This macro is equivalent to lua_pushlstring,
+but can be used only when s is a literal string.
+In these cases, it automatically provides the string length.
+
+
+
+
+
+
+Pushes the string pointed to by s with size len
+onto the stack.
+Lua makes (or reuses) an internal copy of the given string,
+so the memory at s can be freed or reused immediately after
+the function returns.
+The string can contain embedded zeros.
+
+
+
+
+
+
+Pushes the zero-terminated string pointed to by s
+onto the stack.
+Lua makes (or reuses) an internal copy of the given string,
+so the memory at s can be freed or reused immediately after
+the function returns.
+The string cannot contain embedded zeros;
+it is assumed to end at the first zero.
+
+
+
+
+
+
int lua_rawequal (lua_State *L, int index1, int index2);
+
+
+Returns 1 if the two values in acceptable indices index1 and
+index2 are primitively equal
+(that is, without calling metamethods).
+Otherwise returns 0.
+Also returns 0 if any of the indices are non valid.
+
+
+
+
+
+
void lua_rawgeti (lua_State *L, int index, int n);
+
+
+Pushes onto the stack the value t[n],
+where t is the value at the given valid index.
+The access is raw;
+that is, it does not invoke metamethods.
+
+
+
+
+
+
+The reader function used by lua_load.
+Every time it needs another piece of the chunk,
+lua_load calls the reader,
+passing along its data parameter.
+The reader must return a pointer to a block of memory
+with a new piece of the chunk
+and set size to the block size.
+The block must exist until the reader function is called again.
+To signal the end of the chunk,
+the reader must return NULL or set size to zero.
+The reader function may return pieces of any size greater than zero.
+
+
+
+
+
+
+Removes the element at the given valid index,
+shifting down the elements above this index to fill the gap.
+Cannot be called with a pseudo-index,
+because a pseudo-index is not an actual stack position.
+
+
+
+
+
+
+Moves the top element into the given position (and pops it),
+without shifting any element
+(therefore replacing the value at the given position).
+
+
+
+
+
+
+Starts and resumes a coroutine in a given thread.
+
+
+
+To start a coroutine, you first create a new thread
+(see lua_newthread);
+then you push onto its stack the main function plus any arguments;
+then you call lua_resume,
+with narg being the number of arguments.
+This call returns when the coroutine suspends or finishes its execution.
+When it returns, the stack contains all values passed to lua_yield,
+or all values returned by the body function.
+lua_resume returns
+LUA_YIELD if the coroutine yields,
+0 if the coroutine finishes its execution
+without errors,
+or an error code in case of errors (see lua_pcall).
+In case of errors,
+the stack is not unwound,
+so you can use the debug API over it.
+The error message is on the top of the stack.
+To restart a coroutine, you put on its stack only the values to
+be passed as results from yield,
+and then call lua_resume.
+
+
+
+
+
+
+Pops a table from the stack and sets it as
+the new environment for the value at the given index.
+If the value at the given index is
+neither a function nor a thread nor a userdata,
+lua_setfenv returns 0.
+Otherwise it returns 1.
+
+
+
+
+
+
+Does the equivalent to t[k] = v,
+where t is the value at the given valid index,
+v is the value at the top of the stack,
+and k is the value just below the top.
+
+
+
+This function pops both the key and the value from the stack.
+As in Lua, this function may trigger a metamethod
+for the "newindex" event (see §2.8).
+
+
+
+
+
+
+Accepts any acceptable index, or 0,
+and sets the stack top to this index.
+If the new top is larger than the old one,
+then the new elements are filled with nil.
+If index is 0, then all stack elements are removed.
+
+
+
+
+
+
+Opaque structure that keeps the whole state of a Lua interpreter.
+The Lua library is fully reentrant:
+it has no global variables.
+All information about a state is kept in this structure.
+
+
+
+A pointer to this state must be passed as the first argument to
+every function in the library, except to lua_newstate,
+which creates a Lua state from scratch.
+
+
+
+
+
+
+The status can be 0 for a normal thread,
+an error code if the thread finished its execution with an error,
+or LUA_YIELD if the thread is suspended.
+
+
+
+
+
+
+Converts the Lua value at the given acceptable index to a C boolean
+value (0 or 1).
+Like all tests in Lua,
+lua_toboolean returns 1 for any Lua value
+different from false and nil;
+otherwise it returns 0.
+It also returns 0 when called with a non-valid index.
+(If you want to accept only actual boolean values,
+use lua_isboolean to test the value's type.)
+
+
+
+
+
+
lua_Integer lua_tointeger (lua_State *L, int index);
+
+
+Converts the Lua value at the given acceptable index
+to the signed integral type lua_Integer.
+The Lua value must be a number or a string convertible to a number
+(see §2.2.1);
+otherwise, lua_tointeger returns 0.
+
+
+
+If the number is not an integer,
+it is truncated in some non-specified way.
+
+
+
+
+
+
const char *lua_tolstring (lua_State *L, int index, size_t *len);
+
+
+Converts the Lua value at the given acceptable index to a C string.
+If len is not NULL,
+it also sets *len with the string length.
+The Lua value must be a string or a number;
+otherwise, the function returns NULL.
+If the value is a number,
+then lua_tolstring also
+changes the actual value in the stack to a string.
+(This change confuses lua_next
+when lua_tolstring is applied to keys during a table traversal.)
+
+
+
+lua_tolstring returns a fully aligned pointer
+to a string inside the Lua state.
+This string always has a zero ('\0')
+after its last character (as in C),
+but can contain other zeros in its body.
+Because Lua has garbage collection,
+there is no guarantee that the pointer returned by lua_tolstring
+will be valid after the corresponding value is removed from the stack.
+
+
+
+
+
+
lua_Number lua_tonumber (lua_State *L, int index);
+
+
+Converts the Lua value at the given acceptable index
+to the C type lua_Number (see lua_Number).
+The Lua value must be a number or a string convertible to a number
+(see §2.2.1);
+otherwise, lua_tonumber returns 0.
+
+
+
+
+
+
const void *lua_topointer (lua_State *L, int index);
+
+
+Converts the value at the given acceptable index to a generic
+C pointer (void*).
+The value can be a userdata, a table, a thread, or a function;
+otherwise, lua_topointer returns NULL.
+Different objects will give different pointers.
+There is no way to convert the pointer back to its original value.
+
+
+
+Typically this function is used only for debug information.
+
+
+
+
+
+
lua_State *lua_tothread (lua_State *L, int index);
+
+
+Converts the value at the given acceptable index to a Lua thread
+(represented as lua_State*).
+This value must be a thread;
+otherwise, the function returns NULL.
+
+
+
+
+
+
+If the value at the given acceptable index is a full userdata,
+returns its block address.
+If the value is a light userdata,
+returns its pointer.
+Otherwise, returns NULL.
+
+
+
+
+
+
+Returns the type of the value in the given acceptable index,
+or LUA_TNONE for a non-valid index
+(that is, an index to an "empty" stack position).
+The types returned by lua_type are coded by the following constants
+defined in lua.h:
+LUA_TNIL,
+LUA_TNUMBER,
+LUA_TBOOLEAN,
+LUA_TSTRING,
+LUA_TTABLE,
+LUA_TFUNCTION,
+LUA_TUSERDATA,
+LUA_TTHREAD,
+and
+LUA_TLIGHTUSERDATA.
+
+
+
+
+
+
+The type of the writer function used by lua_dump.
+Every time it produces another piece of chunk,
+lua_dump calls the writer,
+passing along the buffer to be written (p),
+its size (sz),
+and the data parameter supplied to lua_dump.
+
+
+
+The writer returns an error code:
+0 means no errors;
+any other value means an error and stops lua_dump from
+calling the writer again.
+
+
+
+
+
+
+This function should only be called as the
+return expression of a C function, as follows:
+
+
+ return lua_yield (L, nresults);
+
+When a C function calls lua_yield in that way,
+the running coroutine suspends its execution,
+and the call to lua_resume that started this coroutine returns.
+The parameter nresults is the number of values from the stack
+that are passed as results to lua_resume.
+
+
+
+
+
+
+
+
+Lua has no built-in debugging facilities.
+Instead, it offers a special interface
+by means of functions and hooks.
+This interface allows the construction of different
+kinds of debuggers, profilers, and other tools
+that need "inside information" from the interpreter.
+
+
+
+
typedef struct lua_Debug {
+ int event;
+ const char *name; /* (n) */
+ const char *namewhat; /* (n) */
+ const char *what; /* (S) */
+ const char *source; /* (S) */
+ int currentline; /* (l) */
+ int nups; /* (u) number of upvalues */
+ int linedefined; /* (S) */
+ int lastlinedefined; /* (S) */
+ char short_src[LUA_IDSIZE]; /* (S) */
+ /* private part */
+ other fields
+} lua_Debug;
+
+
+A structure used to carry different pieces of
+information about an active function.
+lua_getstack fills only the private part
+of this structure, for later use.
+To fill the other fields of lua_Debug with useful information,
+call lua_getinfo.
+
+
+
+The fields of lua_Debug have the following meaning:
+
+
+
+
source:
+If the function was defined in a string,
+then source is that string.
+If the function was defined in a file,
+then source starts with a '@' followed by the file name.
+
+
+
short_src:
+a "printable" version of source, to be used in error messages.
+
+
+
linedefined:
+the line number where the definition of the function starts.
+
+
+
lastlinedefined:
+the line number where the definition of the function ends.
+
+
+
what:
+the string "Lua" if the function is a Lua function,
+"C" if it is a C function,
+"main" if it is the main part of a chunk,
+and "tail" if it was a function that did a tail call.
+In the latter case,
+Lua has no other information about the function.
+
+
+
currentline:
+the current line where the given function is executing.
+When no line information is available,
+currentline is set to -1.
+
+
+
name:
+a reasonable name for the given function.
+Because functions in Lua are first-class values,
+they do not have a fixed name:
+some functions can be the value of multiple global variables,
+while others can be stored only in a table field.
+The lua_getinfo function checks how the function was
+called to find a suitable name.
+If it cannot find a name,
+then name is set to NULL.
+
+
+
namewhat:
+explains the name field.
+The value of namewhat can be
+"global", "local", "method",
+"field", "upvalue", or "" (the empty string),
+according to how the function was called.
+(Lua uses the empty string when no other option seems to apply.)
+
int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar);
+
+
+Returns information about a specific function or function invocation.
+
+
+
+To get information about a function invocation,
+the parameter ar must be a valid activation record that was
+filled by a previous call to lua_getstack or
+given as argument to a hook (see lua_Hook).
+
+
+
+To get information about a function you push it onto the stack
+and start the what string with the character '>'.
+(In that case,
+lua_getinfo pops the function in the top of the stack.)
+For instance, to know in which line a function f was defined,
+you can write the following code:
+
+
+ lua_Debug ar;
+ lua_getfield(L, LUA_GLOBALSINDEX, "f"); /* get global 'f' */
+ lua_getinfo(L, ">S", &ar);
+ printf("%d\n", ar.linedefined);
+
+
+
+Each character in the string what
+selects some fields of the structure ar to be filled or
+a value to be pushed on the stack:
+
+
+
+
'n': fills in the field name and namewhat;
+
+
+
'S':
+fills in the fields source, short_src,
+linedefined, lastlinedefined, and what;
+
+
+
'l': fills in the field currentline;
+
+
+
'u': fills in the field nups;
+
+
+
'f':
+pushes onto the stack the function that is
+running at the given level;
+
+
+
'L':
+pushes onto the stack a table whose indices are the
+numbers of the lines that are valid on the function.
+(A valid line is a line with some associated code,
+that is, a line where you can put a break point.
+Non-valid lines include empty lines and comments.)
+
+
+
+
+
+This function returns 0 on error
+(for instance, an invalid option in what).
+
+
+
+
+
+
const char *lua_getlocal (lua_State *L, lua_Debug *ar, int n);
+
+
+Gets information about a local variable of a given activation record.
+The parameter ar must be a valid activation record that was
+filled by a previous call to lua_getstack or
+given as argument to a hook (see lua_Hook).
+The index n selects which local variable to inspect
+(1 is the first parameter or active local variable, and so on,
+until the last active local variable).
+lua_getlocal pushes the variable's value onto the stack
+and returns its name.
+
+
+
+Variable names starting with '(' (open parentheses)
+represent internal variables
+(loop control variables, temporaries, and C function locals).
+
+
+
+Returns NULL (and pushes nothing)
+when the index is greater than
+the number of active local variables.
+
+
+
+
+
+
int lua_getstack (lua_State *L, int level, lua_Debug *ar);
+
+
+Get information about the interpreter runtime stack.
+
+
+
+This function fills parts of a lua_Debug structure with
+an identification of the activation record
+of the function executing at a given level.
+Level 0 is the current running function,
+whereas level n+1 is the function that has called level n.
+When there are no errors, lua_getstack returns 1;
+when called with a level greater than the stack depth,
+it returns 0.
+
+
+
+
+
+
const char *lua_getupvalue (lua_State *L, int funcindex, int n);
+
+
+Gets information about a closure's upvalue.
+(For Lua functions,
+upvalues are the external local variables that the function uses,
+and that are consequently included in its closure.)
+lua_getupvalue gets the index n of an upvalue,
+pushes the upvalue's value onto the stack,
+and returns its name.
+funcindex points to the closure in the stack.
+(Upvalues have no particular order,
+as they are active through the whole function.
+So, they are numbered in an arbitrary order.)
+
+
+
+Returns NULL (and pushes nothing)
+when the index is greater than the number of upvalues.
+For C functions, this function uses the empty string ""
+as a name for all upvalues.
+
+
+
+
+
+
+Whenever a hook is called, its ar argument has its field
+event set to the specific event that triggered the hook.
+Lua identifies these events with the following constants:
+LUA_HOOKCALL, LUA_HOOKRET,
+LUA_HOOKTAILRET, LUA_HOOKLINE,
+and LUA_HOOKCOUNT.
+Moreover, for line events, the field currentline is also set.
+To get the value of any other field in ar,
+the hook must call lua_getinfo.
+For return events, event can be LUA_HOOKRET,
+the normal value, or LUA_HOOKTAILRET.
+In the latter case, Lua is simulating a return from
+a function that did a tail call;
+in this case, it is useless to call lua_getinfo.
+
+
+
+While Lua is running a hook, it disables other calls to hooks.
+Therefore, if a hook calls back Lua to execute a function or a chunk,
+this execution occurs without any calls to hooks.
+
+
+
+
+
+
int lua_sethook (lua_State *L, lua_Hook f, int mask, int count);
+
+
+Sets the debugging hook function.
+
+
+
+Argument f is the hook function.
+mask specifies on which events the hook will be called:
+it is formed by a bitwise or of the constants
+LUA_MASKCALL,
+LUA_MASKRET,
+LUA_MASKLINE,
+and LUA_MASKCOUNT.
+The count argument is only meaningful when the mask
+includes LUA_MASKCOUNT.
+For each event, the hook is called as explained below:
+
+
+
+
The call hook: is called when the interpreter calls a function.
+The hook is called just after Lua enters the new function,
+before the function gets its arguments.
+
+
+
The return hook: is called when the interpreter returns from a function.
+The hook is called just before Lua leaves the function.
+You have no access to the values to be returned by the function.
+
+
+
The line hook: is called when the interpreter is about to
+start the execution of a new line of code,
+or when it jumps back in the code (even to the same line).
+(This event only happens while Lua is executing a Lua function.)
+
+
+
The count hook: is called after the interpreter executes every
+count instructions.
+(This event only happens while Lua is executing a Lua function.)
+
+
+
+
+
+A hook is disabled by setting mask to zero.
+
+
+
+
+
+
const char *lua_setlocal (lua_State *L, lua_Debug *ar, int n);
+
+
+Sets the value of a local variable of a given activation record.
+Parameters ar and n are as in lua_getlocal
+(see lua_getlocal).
+lua_setlocal assigns the value at the top of the stack
+to the variable and returns its name.
+It also pops the value from the stack.
+
+
+
+Returns NULL (and pops nothing)
+when the index is greater than
+the number of active local variables.
+
+
+
+
+
+
const char *lua_setupvalue (lua_State *L, int funcindex, int n);
+
+
+Sets the value of a closure's upvalue.
+It assigns the value at the top of the stack
+to the upvalue and returns its name.
+It also pops the value from the stack.
+Parameters funcindex and n are as in the lua_getupvalue
+(see lua_getupvalue).
+
+
+
+Returns NULL (and pops nothing)
+when the index is greater than the number of upvalues.
+
+
+
+
+
+
+
+
+
+The auxiliary library provides several convenient functions
+to interface C with Lua.
+While the basic API provides the primitive functions for all
+interactions between C and Lua,
+the auxiliary library provides higher-level functions for some
+common tasks.
+
+
+
+All functions from the auxiliary library
+are defined in header file lauxlib.h and
+have a prefix luaL_.
+
+
+
+All functions in the auxiliary library are built on
+top of the basic API,
+and so they provide nothing that cannot be done with this API.
+
+
+
+Several functions in the auxiliary library are used to
+check C function arguments.
+Their names are always luaL_check* or luaL_opt*.
+All of these functions throw an error if the check is not satisfied.
+Because the error message is formatted for arguments
+(e.g., "bad argument #1"),
+you should not use these functions for other stack values.
+
+
+
+
+Adds the value at the top of the stack
+to the buffer B
+(see luaL_Buffer).
+Pops the value.
+
+
+
+This is the only function on string buffers that can (and must)
+be called with an extra element on the stack,
+which is the value to be added to the buffer.
+
+
+
+
+
+
+A string buffer allows C code to build Lua strings piecemeal.
+Its pattern of use is as follows:
+
+
+
+
First you declare a variable b of type luaL_Buffer.
+
+
Then you initialize it with a call luaL_buffinit(L, &b).
+
+
+Then you add string pieces to the buffer calling any of
+the luaL_add* functions.
+
+
+
+You finish by calling luaL_pushresult(&b).
+This call leaves the final string on the top of the stack.
+
+
+
+
+
+During its normal operation,
+a string buffer uses a variable number of stack slots.
+So, while using a buffer, you cannot assume that you know where
+the top of the stack is.
+You can use the stack between successive calls to buffer operations
+as long as that use is balanced;
+that is,
+when you call a buffer operation,
+the stack is at the same level
+it was immediately after the previous buffer operation.
+(The only exception to this rule is luaL_addvalue.)
+After calling luaL_pushresult the stack is back to its
+level when the buffer was initialized,
+plus the final string on its top.
+
+
+
+
+
+
int luaL_callmeta (lua_State *L, int obj, const char *e);
+
+
+Calls a metamethod.
+
+
+
+If the object at index obj has a metatable and this
+metatable has a field e,
+this function calls this field and passes the object as its only argument.
+In this case this function returns 1 and pushes onto the
+stack the value returned by the call.
+If there is no metatable or no metamethod,
+this function returns 0 (without pushing any value on the stack).
+
+
+
+
+
+
int luaL_checkoption (lua_State *L,
+ int narg,
+ const char *def,
+ const char *const lst[]);
+
+
+Checks whether the function argument narg is a string and
+searches for this string in the array lst
+(which must be NULL-terminated).
+Returns the index in the array where the string was found.
+Raises an error if the argument is not a string or
+if the string cannot be found.
+
+
+
+If def is not NULL,
+the function uses def as a default value when
+there is no argument narg or if this argument is nil.
+
+
+
+This is a useful function for mapping strings to C enums.
+(The usual convention in Lua libraries is
+to use strings instead of numbers to select options.)
+
+
+
+
+
+
void luaL_checkstack (lua_State *L, int sz, const char *msg);
+
+
+Grows the stack size to top + sz elements,
+raising an error if the stack cannot grow to that size.
+msg is an additional text to go into the error message.
+
+
+
+
+
+
int luaL_error (lua_State *L, const char *fmt, ...);
+
+
+Raises an error.
+The error message format is given by fmt
+plus any extra arguments,
+following the same rules of lua_pushfstring.
+It also adds at the beginning of the message the file name and
+the line number where the error occurred,
+if this information is available.
+
+
+
+This function never returns,
+but it is an idiom to use it in C functions
+as return luaL_error(args).
+
+
+
+
+
+
int luaL_getmetafield (lua_State *L, int obj, const char *e);
+
+
+Pushes onto the stack the field e from the metatable
+of the object at index obj.
+If the object does not have a metatable,
+or if the metatable does not have this field,
+returns 0 and pushes nothing.
+
+
+
+
+
+
+Creates a copy of string s by replacing
+any occurrence of the string p
+with the string r.
+Pushes the resulting string on the stack and returns it.
+
+
+
+
+
+
int luaL_loadfile (lua_State *L, const char *filename);
+
+
+Loads a file as a Lua chunk.
+This function uses lua_load to load the chunk in the file
+named filename.
+If filename is NULL,
+then it loads from the standard input.
+The first line in the file is ignored if it starts with a #.
+
+
+
+This function returns the same results as lua_load,
+but it has an extra error code LUA_ERRFILE
+if it cannot open/read the file.
+
+
+
+As lua_load, this function only loads the chunk;
+it does not run it.
+
+
+
+
+
+
int luaL_newmetatable (lua_State *L, const char *tname);
+
+
+If the registry already has the key tname,
+returns 0.
+Otherwise,
+creates a new table to be used as a metatable for userdata,
+adds it to the registry with key tname,
+and returns 1.
+
+
+
+In both cases pushes onto the stack the final value associated
+with tname in the registry.
+
+
+
+
+
+
+Creates a new Lua state.
+It calls lua_newstate with an
+allocator based on the standard C realloc function
+and then sets a panic function (see lua_atpanic) that prints
+an error message to the standard error output in case of fatal
+errors.
+
+
+
+Returns the new state,
+or NULL if there is a memory allocation error.
+
+
+
+
+
+
+If the function argument narg is a number,
+returns this number cast to an int.
+If this argument is absent or is nil,
+returns d.
+Otherwise, raises an error.
+
+
+
+
+
+
lua_Integer luaL_optinteger (lua_State *L,
+ int narg,
+ lua_Integer d);
+
+
+If the function argument narg is a number,
+returns this number cast to a lua_Integer.
+If this argument is absent or is nil,
+returns d.
+Otherwise, raises an error.
+
+
+
+
+
+
long luaL_optlong (lua_State *L, int narg, long d);
+
+
+If the function argument narg is a number,
+returns this number cast to a long.
+If this argument is absent or is nil,
+returns d.
+Otherwise, raises an error.
+
+
+
+
+
+
+If the function argument narg is a string,
+returns this string.
+If this argument is absent or is nil,
+returns d.
+Otherwise, raises an error.
+
+
+
+If l is not NULL,
+fills the position *l with the results's length.
+
+
+
+
+
+
lua_Number luaL_optnumber (lua_State *L, int narg, lua_Number d);
+
+
+If the function argument narg is a number,
+returns this number.
+If this argument is absent or is nil,
+returns d.
+Otherwise, raises an error.
+
+
+
+
+
+
+If the function argument narg is a string,
+returns this string.
+If this argument is absent or is nil,
+returns d.
+Otherwise, raises an error.
+
+
+
+
+
+
+Returns an address to a space of size LUAL_BUFFERSIZE
+where you can copy a string to be added to buffer B
+(see luaL_Buffer).
+After copying the string into this space you must call
+luaL_addsize with the size of the string to actually add
+it to the buffer.
+
+
+
+
+
+
+Creates and returns a reference,
+in the table at index t,
+for the object at the top of the stack (and pops the object).
+
+
+
+A reference is a unique integer key.
+As long as you do not manually add integer keys into table t,
+luaL_ref ensures the uniqueness of the key it returns.
+You can retrieve an object referred by reference r
+by calling lua_rawgeti(L, t, r).
+Function luaL_unref frees a reference and its associated object.
+
+
+
+If the object at the top of the stack is nil,
+luaL_ref returns the constant LUA_REFNIL.
+The constant LUA_NOREF is guaranteed to be different
+from any reference returned by luaL_ref.
+
+
+
+
+
+
+Type for arrays of functions to be registered by
+luaL_register.
+name is the function name and func is a pointer to
+the function.
+Any array of luaL_Reg must end with an sentinel entry
+in which both name and func are NULL.
+
+
+
+
+
+
+When called with libname equal to NULL,
+it simply registers all functions in the list l
+(see luaL_Reg) into the table on the top of the stack.
+
+
+
+When called with a non-null libname,
+luaL_register creates a new table t,
+sets it as the value of the global variable libname,
+sets it as the value of package.loaded[libname],
+and registers on it all functions in the list l.
+If there is a table in package.loaded[libname] or in
+variable libname,
+reuses this table instead of creating a new one.
+
+
+
+In any case the function leaves the table
+on the top of the stack.
+
+
+
+
+
+
+Releases reference ref from the table at index t
+(see luaL_ref).
+The entry is removed from the table,
+so that the referred object can be collected.
+The reference ref is also freed to be used again.
+
+
+
+Pushes onto the stack a string identifying the current position
+of the control at level lvl in the call stack.
+Typically this string has the following format:
+
+
+ chunkname:currentline:
+
+Level 0 is the running function,
+level 1 is the function that called the running function,
+etc.
+
+
+
+This function is used to build a prefix for error messages.
+
+
+
+
+
+
+
+
+The standard Lua libraries provide useful functions
+that are implemented directly through the C API.
+Some of these functions provide essential services to the language
+(e.g., type and getmetatable);
+others provide access to "outside" services (e.g., I/O);
+and others could be implemented in Lua itself,
+but are quite useful or have critical performance requirements that
+deserve an implementation in C (e.g., table.sort).
+
+
+
+All libraries are implemented through the official C API
+and are provided as separate C modules.
+Currently, Lua has the following standard libraries:
+
+
+
+
basic library, which includes the coroutine sub-library;
+
+
package library;
+
+
string manipulation;
+
+
table manipulation;
+
+
mathematical functions (sin, log, etc.);
+
+
input and output;
+
+
operating system facilities;
+
+
debug facilities.
+
+
+Except for the basic and package libraries,
+each library provides all its functions as fields of a global table
+or as methods of its objects.
+
+
+
+To have access to these libraries,
+the C host program should call the luaL_openlibs function,
+which opens all standard libraries.
+Alternatively,
+it can open them individually by calling
+luaopen_base (for the basic library),
+luaopen_package (for the package library),
+luaopen_string (for the string library),
+luaopen_table (for the table library),
+luaopen_math (for the mathematical library),
+luaopen_io (for the I/O library),
+luaopen_os (for the Operating System library),
+and luaopen_debug (for the debug library).
+These functions are declared in lualib.h
+and should not be called directly:
+you must call them like any other Lua C function,
+e.g., by using lua_call.
+
+
+
+
+The basic library provides some core functions to Lua.
+If you do not include this library in your application,
+you should check carefully whether you need to provide
+implementations for some of its facilities.
+
+
+
+Issues an error when
+the value of its argument v is false (i.e., nil or false);
+otherwise, returns all its arguments.
+message is an error message;
+when absent, it defaults to "assertion failed!"
+
+
+
+
+
+This function is a generic interface to the garbage collector.
+It performs different functions according to its first argument, opt:
+
+
+
+
"collect":
+performs a full garbage-collection cycle.
+This is the default option.
+
+
+
"stop":
+stops the garbage collector.
+
+
+
"restart":
+restarts the garbage collector.
+
+
+
"count":
+returns the total memory in use by Lua (in Kbytes).
+
+
+
"step":
+performs a garbage-collection step.
+The step "size" is controlled by arg
+(larger values mean more steps) in a non-specified way.
+If you want to control the step size
+you must experimentally tune the value of arg.
+Returns true if the step finished a collection cycle.
+
+
+
"setpause":
+sets arg as the new value for the pause of
+the collector (see §2.10).
+Returns the previous value for pause.
+
+
+
"setstepmul":
+sets arg as the new value for the step multiplier of
+the collector (see §2.10).
+Returns the previous value for step.
+
+Opens the named file and executes its contents as a Lua chunk.
+When called without arguments,
+dofile executes the contents of the standard input (stdin).
+Returns all values returned by the chunk.
+In case of errors, dofile propagates the error
+to its caller (that is, dofile does not run in protected mode).
+
+
+
+
+
+Terminates the last protected function called
+and returns message as the error message.
+Function error never returns.
+
+
+
+Usually, error adds some information about the error position
+at the beginning of the message.
+The level argument specifies how to get the error position.
+With level 1 (the default), the error position is where the
+error function was called.
+Level 2 points the error to where the function
+that called error was called; and so on.
+Passing a level 0 avoids the addition of error position information
+to the message.
+
+
+
+
+
+A global variable (not a function) that
+holds the global environment (that is, _G._G = _G).
+Lua itself does not use this variable;
+changing its value does not affect any environment,
+nor vice-versa.
+(Use setfenv to change environments.)
+
+
+
+
+
+Returns the current environment in use by the function.
+f can be a Lua function or a number
+that specifies the function at that stack level:
+Level 1 is the function calling getfenv.
+If the given function is not a Lua function,
+or if f is 0,
+getfenv returns the global environment.
+The default for f is 1.
+
+
+
+
+
+If object does not have a metatable, returns nil.
+Otherwise,
+if the object's metatable has a "__metatable" field,
+returns the associated value.
+Otherwise, returns the metatable of the given object.
+
+
+
+
+
+Loads a chunk using function func to get its pieces.
+Each call to func must return a string that concatenates
+with previous results.
+A return of an empty string, nil, or no value signals the end of the chunk.
+
+
+
+If there are no errors,
+returns the compiled chunk as a function;
+otherwise, returns nil plus the error message.
+The environment of the returned function is the global environment.
+
+
+
+chunkname is used as the chunk name for error messages
+and debug information.
+When absent,
+it defaults to "=(load)".
+
+
+
+
+
+Allows a program to traverse all fields of a table.
+Its first argument is a table and its second argument
+is an index in this table.
+next returns the next index of the table
+and its associated value.
+When called with nil as its second argument,
+next returns an initial index
+and its associated value.
+When called with the last index,
+or with nil in an empty table,
+next returns nil.
+If the second argument is absent, then it is interpreted as nil.
+In particular,
+you can use next(t) to check whether a table is empty.
+
+
+
+The order in which the indices are enumerated is not specified,
+even for numeric indices.
+(To traverse a table in numeric order,
+use a numerical for or the ipairs function.)
+
+
+
+The behavior of next is undefined if,
+during the traversal,
+you assign any value to a non-existent field in the table.
+You may however modify existing fields.
+In particular, you may clear existing fields.
+
+
+
+
+
+Calls function f with
+the given arguments in protected mode.
+This means that any error inside f is not propagated;
+instead, pcall catches the error
+and returns a status code.
+Its first result is the status code (a boolean),
+which is true if the call succeeds without errors.
+In such case, pcall also returns all results from the call,
+after this first result.
+In case of any error, pcall returns false plus the error message.
+
+
+
+
+
+Receives any number of arguments,
+and prints their values to stdout,
+using the tostring function to convert them to strings.
+print is not intended for formatted output,
+but only as a quick way to show a value,
+typically for debugging.
+For formatted output, use string.format.
+
+
+
+
+
+Sets the real value of table[index] to value,
+without invoking any metamethod.
+table must be a table,
+index any value different from nil,
+and value any Lua value.
+
+
+
+If index is a number,
+returns all arguments after argument number index.
+Otherwise, index must be the string "#",
+and select returns the total number of extra arguments it received.
+
+
+
+
+
+Sets the environment to be used by the given function.
+f can be a Lua function or a number
+that specifies the function at that stack level:
+Level 1 is the function calling setfenv.
+setfenv returns the given function.
+
+
+
+As a special case, when f is 0 setfenv changes
+the environment of the running thread.
+In this case, setfenv returns no values.
+
+
+
+
+
+Sets the metatable for the given table.
+(You cannot change the metatable of other types from Lua, only from C.)
+If metatable is nil,
+removes the metatable of the given table.
+If the original metatable has a "__metatable" field,
+raises an error.
+
+
+
+Tries to convert its argument to a number.
+If the argument is already a number or a string convertible
+to a number, then tonumber returns this number;
+otherwise, it returns nil.
+
+
+
+An optional argument specifies the base to interpret the numeral.
+The base may be any integer between 2 and 36, inclusive.
+In bases above 10, the letter 'A' (in either upper or lower case)
+represents 10, 'B' represents 11, and so forth,
+with 'Z' representing 35.
+In base 10 (the default), the number can have a decimal part,
+as well as an optional exponent part (see §2.1).
+In other bases, only unsigned integers are accepted.
+
+
+
+
+
+Receives an argument of any type and
+converts it to a string in a reasonable format.
+For complete control of how numbers are converted,
+use string.format.
+
+
+
+If the metatable of e has a "__tostring" field,
+then tostring calls the corresponding value
+with e as argument,
+and uses the result of the call as its result.
+
+
+
+
+
+Returns the type of its only argument, coded as a string.
+The possible results of this function are
+"nil" (a string, not the value nil),
+"number",
+"string",
+"boolean",
+"table",
+"function",
+"thread",
+and "userdata".
+
+
+
+
+
+Returns the elements from the given table.
+This function is equivalent to
+
+
+ return list[i], list[i+1], ···, list[j]
+
+except that the above code can be written only for a fixed number
+of elements.
+By default, i is 1 and j is the length of the list,
+as defined by the length operator (see §2.5.5).
+
+
+
+
+
+A global variable (not a function) that
+holds a string containing the current interpreter version.
+The current contents of this variable is "Lua 5.1".
+
+
+
+
+
+This function is similar to pcall,
+except that you can set a new error handler.
+
+
+
+xpcall calls function f in protected mode,
+using err as the error handler.
+Any error inside f is not propagated;
+instead, xpcall catches the error,
+calls the err function with the original error object,
+and returns a status code.
+Its first result is the status code (a boolean),
+which is true if the call succeeds without errors.
+In this case, xpcall also returns all results from the call,
+after this first result.
+In case of any error,
+xpcall returns false plus the result from err.
+
+
+
+
+
+
+
+
+The operations related to coroutines comprise a sub-library of
+the basic library and come inside the table coroutine.
+See §2.11 for a general description of coroutines.
+
+
+
+Starts or continues the execution of coroutine co.
+The first time you resume a coroutine,
+it starts running its body.
+The values val1, ··· are passed
+as the arguments to the body function.
+If the coroutine has yielded,
+resume restarts it;
+the values val1, ··· are passed
+as the results from the yield.
+
+
+
+If the coroutine runs without any errors,
+resume returns true plus any values passed to yield
+(if the coroutine yields) or any values returned by the body function
+(if the coroutine terminates).
+If there is any error,
+resume returns false plus the error message.
+
+
+
+
+
+Returns the status of coroutine co, as a string:
+"running",
+if the coroutine is running (that is, it called status);
+"suspended", if the coroutine is suspended in a call to yield,
+or if it has not started running yet;
+"normal" if the coroutine is active but not running
+(that is, it has resumed another coroutine);
+and "dead" if the coroutine has finished its body function,
+or if it has stopped with an error.
+
+
+
+
+
+Creates a new coroutine, with body f.
+f must be a Lua function.
+Returns a function that resumes the coroutine each time it is called.
+Any arguments passed to the function behave as the
+extra arguments to resume.
+Returns the same values returned by resume,
+except the first boolean.
+In case of error, propagates the error.
+
+
+
+
+
+Suspends the execution of the calling coroutine.
+The coroutine cannot be running a C function,
+a metamethod, or an iterator.
+Any arguments to yield are passed as extra results to resume.
+
+
+
+
+
+
+
+
+The package library provides basic
+facilities for loading and building modules in Lua.
+It exports two of its functions directly in the global environment:
+require and module.
+Everything else is exported in a table package.
+
+
+
+Creates a module.
+If there is a table in package.loaded[name],
+this table is the module.
+Otherwise, if there is a global table t with the given name,
+this table is the module.
+Otherwise creates a new table t and
+sets it as the value of the global name and
+the value of package.loaded[name].
+This function also initializes t._NAME with the given name,
+t._M with the module (t itself),
+and t._PACKAGE with the package name
+(the full module name minus last component; see below).
+Finally, module sets t as the new environment
+of the current function and the new value of package.loaded[name],
+so that require returns t.
+
+
+
+If name is a compound name
+(that is, one with components separated by dots),
+module creates (or reuses, if they already exist)
+tables for each component.
+For instance, if name is a.b.c,
+then module stores the module table in field c of
+field b of global a.
+
+
+
+This function can receive optional options after
+the module name,
+where each option is a function to be applied over the module.
+
+
+
+
+
+Loads the given module.
+The function starts by looking into the package.loaded table
+to determine whether modname is already loaded.
+If it is, then require returns the value stored
+at package.loaded[modname].
+Otherwise, it tries to find a loader for the module.
+
+
+
+To find a loader,
+require is guided by the package.loaders array.
+By changing this array,
+we can change how require looks for a module.
+The following explanation is based on the default configuration
+for package.loaders.
+
+
+
+First require queries package.preload[modname].
+If it has a value,
+this value (which should be a function) is the loader.
+Otherwise require searches for a Lua loader using the
+path stored in package.path.
+If that also fails, it searches for a C loader using the
+path stored in package.cpath.
+If that also fails,
+it tries an all-in-one loader (see package.loaders).
+
+
+
+Once a loader is found,
+require calls the loader with a single argument, modname.
+If the loader returns any value,
+require assigns the returned value to package.loaded[modname].
+If the loader returns no value and
+has not assigned any value to package.loaded[modname],
+then require assigns true to this entry.
+In any case, require returns the
+final value of package.loaded[modname].
+
+
+
+If there is any error loading or running the module,
+or if it cannot find any loader for the module,
+then require signals an error.
+
+
+
+
+
+The path used by require to search for a C loader.
+
+
+
+Lua initializes the C path package.cpath in the same way
+it initializes the Lua path package.path,
+using the environment variable LUA_CPATH
+or a default path defined in luaconf.h.
+
+
+
+
+
+A table used by require to control which
+modules are already loaded.
+When you require a module modname and
+package.loaded[modname] is not false,
+require simply returns the value stored there.
+
+
+
+
+
+A table used by require to control how to load modules.
+
+
+
+Each entry in this table is a searcher function.
+When looking for a module,
+require calls each of these searchers in ascending order,
+with the module name (the argument given to require) as its
+sole parameter.
+The function can return another function (the module loader)
+or a string explaining why it did not find that module
+(or nil if it has nothing to say).
+Lua initializes this table with four functions.
+
+
+
+The first searcher simply looks for a loader in the
+package.preload table.
+
+
+
+The second searcher looks for a loader as a Lua library,
+using the path stored at package.path.
+A path is a sequence of templates separated by semicolons.
+For each template,
+the searcher will change each interrogation
+mark in the template by filename,
+which is the module name with each dot replaced by a
+"directory separator" (such as "/" in Unix);
+then it will try to open the resulting file name.
+So, for instance, if the Lua path is the string
+
+
+ "./?.lua;./?.lc;/usr/local/?/init.lua"
+
+the search for a Lua file for module foo
+will try to open the files
+./foo.lua, ./foo.lc, and
+/usr/local/foo/init.lua, in that order.
+
+
+
+The third searcher looks for a loader as a C library,
+using the path given by the variable package.cpath.
+For instance,
+if the C path is the string
+
+
+ "./?.so;./?.dll;/usr/local/?/init.so"
+
+the searcher for module foo
+will try to open the files ./foo.so, ./foo.dll,
+and /usr/local/foo/init.so, in that order.
+Once it finds a C library,
+this searcher first uses a dynamic link facility to link the
+application with the library.
+Then it tries to find a C function inside the library to
+be used as the loader.
+The name of this C function is the string "luaopen_"
+concatenated with a copy of the module name where each dot
+is replaced by an underscore.
+Moreover, if the module name has a hyphen,
+its prefix up to (and including) the first hyphen is removed.
+For instance, if the module name is a.v1-b.c,
+the function name will be luaopen_b_c.
+
+
+
+The fourth searcher tries an all-in-one loader.
+It searches the C path for a library for
+the root name of the given module.
+For instance, when requiring a.b.c,
+it will search for a C library for a.
+If found, it looks into it for an open function for
+the submodule;
+in our example, that would be luaopen_a_b_c.
+With this facility, a package can pack several C submodules
+into one single library,
+with each submodule keeping its original open function.
+
+
+
+
+
+Dynamically links the host program with the C library libname.
+Inside this library, looks for a function funcname
+and returns this function as a C function.
+(So, funcname must follow the protocol (see lua_CFunction)).
+
+
+
+This is a low-level function.
+It completely bypasses the package and module system.
+Unlike require,
+it does not perform any path searching and
+does not automatically adds extensions.
+libname must be the complete file name of the C library,
+including if necessary a path and extension.
+funcname must be the exact name exported by the C library
+(which may depend on the C compiler and linker used).
+
+
+
+This function is not supported by ANSI C.
+As such, it is only available on some platforms
+(Windows, Linux, Mac OS X, Solaris, BSD,
+plus other Unix systems that support the dlfcn standard).
+
+
+
+
+
+The path used by require to search for a Lua loader.
+
+
+
+At start-up, Lua initializes this variable with
+the value of the environment variable LUA_PATH or
+with a default path defined in luaconf.h,
+if the environment variable is not defined.
+Any ";;" in the value of the environment variable
+is replaced by the default path.
+
+
+
+
+
+Sets a metatable for module with
+its __index field referring to the global environment,
+so that this module inherits values
+from the global environment.
+To be used as an option to function module.
+
+
+
+
+
+
+
+
+This library provides generic functions for string manipulation,
+such as finding and extracting substrings, and pattern matching.
+When indexing a string in Lua, the first character is at position 1
+(not at 0, as in C).
+Indices are allowed to be negative and are interpreted as indexing backwards,
+from the end of the string.
+Thus, the last character is at position -1, and so on.
+
+
+
+The string library provides all its functions inside the table
+string.
+It also sets a metatable for strings
+where the __index field points to the string table.
+Therefore, you can use the string functions in object-oriented style.
+For instance, string.byte(s, i)
+can be written as s:byte(i).
+
+
+
+The string library assumes one-byte character encodings.
+
+
+
+Receives zero or more integers.
+Returns a string with length equal to the number of arguments,
+in which each character has the internal numerical code equal
+to its corresponding argument.
+
+
+
+Note that numerical codes are not necessarily portable across platforms.
+
+
+
+
+
+Returns a string containing a binary representation of the given function,
+so that a later loadstring on this string returns
+a copy of the function.
+function must be a Lua function without upvalues.
+
+
+
+
+
+Looks for the first match of
+pattern in the string s.
+If it finds a match, then find returns the indices of s
+where this occurrence starts and ends;
+otherwise, it returns nil.
+A third, optional numerical argument init specifies
+where to start the search;
+its default value is 1 and can be negative.
+A value of true as a fourth, optional argument plain
+turns off the pattern matching facilities,
+so the function does a plain "find substring" operation,
+with no characters in pattern being considered "magic".
+Note that if plain is given, then init must be given as well.
+
+
+
+If the pattern has captures,
+then in a successful match
+the captured values are also returned,
+after the two indices.
+
+
+
+
+
+Returns a formatted version of its variable number of arguments
+following the description given in its first argument (which must be a string).
+The format string follows the same rules as the printf family of
+standard C functions.
+The only differences are that the options/modifiers
+*, l, L, n, p,
+and h are not supported
+and that there is an extra option, q.
+The q option formats a string in a form suitable to be safely read
+back by the Lua interpreter:
+the string is written between double quotes,
+and all double quotes, newlines, embedded zeros,
+and backslashes in the string
+are correctly escaped when written.
+For instance, the call
+
+
+ string.format('%q', 'a string with "quotes" and \n new line')
+
+will produce the string:
+
+
+ "a string with \"quotes\" and \
+ new line"
+
+
+
+The options c, d, E, e, f,
+g, G, i, o, u, X, and x all
+expect a number as argument,
+whereas q and s expect a string.
+
+
+
+This function does not accept string values
+containing embedded zeros,
+except as arguments to the q option.
+
+
+
+
+
+Returns an iterator function that,
+each time it is called,
+returns the next captures from pattern over string s.
+If pattern specifies no captures,
+then the whole match is produced in each call.
+
+
+
+As an example, the following loop
+
+
+ s = "hello world from Lua"
+ for w in string.gmatch(s, "%a+") do
+ print(w)
+ end
+
+will iterate over all the words from string s,
+printing one per line.
+The next example collects all pairs key=value from the
+given string into a table:
+
+
+ t = {}
+ s = "from=world, to=Lua"
+ for k, v in string.gmatch(s, "(%w+)=(%w+)") do
+ t[k] = v
+ end
+
+
+
+For this function, a '^' at the start of a pattern does not
+work as an anchor, as this would prevent the iteration.
+
+
+
+
+
+Returns a copy of s
+in which all (or the first n, if given)
+occurrences of the pattern have been
+replaced by a replacement string specified by repl,
+which can be a string, a table, or a function.
+gsub also returns, as its second value,
+the total number of matches that occurred.
+
+
+
+If repl is a string, then its value is used for replacement.
+The character % works as an escape character:
+any sequence in repl of the form %n,
+with n between 1 and 9,
+stands for the value of the n-th captured substring (see below).
+The sequence %0 stands for the whole match.
+The sequence %% stands for a single %.
+
+
+
+If repl is a table, then the table is queried for every match,
+using the first capture as the key;
+if the pattern specifies no captures,
+then the whole match is used as the key.
+
+
+
+If repl is a function, then this function is called every time a
+match occurs, with all captured substrings passed as arguments,
+in order;
+if the pattern specifies no captures,
+then the whole match is passed as a sole argument.
+
+
+
+If the value returned by the table query or by the function call
+is a string or a number,
+then it is used as the replacement string;
+otherwise, if it is false or nil,
+then there is no replacement
+(that is, the original match is kept in the string).
+
+
+
+Here are some examples:
+
+
+ x = string.gsub("hello world", "(%w+)", "%1 %1")
+ --> x="hello hello world world"
+
+ x = string.gsub("hello world", "%w+", "%0 %0", 1)
+ --> x="hello hello world"
+
+ x = string.gsub("hello world from Lua", "(%w+)%s*(%w+)", "%2 %1")
+ --> x="world hello Lua from"
+
+ x = string.gsub("home = $HOME, user = $USER", "%$(%w+)", os.getenv)
+ --> x="home = /home/roberto, user = roberto"
+
+ x = string.gsub("4+5 = $return 4+5$", "%$(.-)%$", function (s)
+ return loadstring(s)()
+ end)
+ --> x="4+5 = 9"
+
+ local t = {name="lua", version="5.1"}
+ x = string.gsub("$name-$version.tar.gz", "%$(%w+)", t)
+ --> x="lua-5.1.tar.gz"
+
+Receives a string and returns a copy of this string with all
+uppercase letters changed to lowercase.
+All other characters are left unchanged.
+The definition of what an uppercase letter is depends on the current locale.
+
+
+
+
+
+Looks for the first match of
+pattern in the string s.
+If it finds one, then match returns
+the captures from the pattern;
+otherwise it returns nil.
+If pattern specifies no captures,
+then the whole match is returned.
+A third, optional numerical argument init specifies
+where to start the search;
+its default value is 1 and can be negative.
+
+
+
+
+
+Returns the substring of s that
+starts at i and continues until j;
+i and j can be negative.
+If j is absent, then it is assumed to be equal to -1
+(which is the same as the string length).
+In particular,
+the call string.sub(s,1,j) returns a prefix of s
+with length j,
+and string.sub(s, -i) returns a suffix of s
+with length i.
+
+
+
+
+
+Receives a string and returns a copy of this string with all
+lowercase letters changed to uppercase.
+All other characters are left unchanged.
+The definition of what a lowercase letter is depends on the current locale.
+
+
+
+
+A character class is used to represent a set of characters.
+The following combinations are allowed in describing a character class:
+
+
+
+
x:
+(where x is not one of the magic characters
+^$()%.[]*+-?)
+represents the character x itself.
+
+
+
.: (a dot) represents all characters.
+
+
%a: represents all letters.
+
+
%c: represents all control characters.
+
+
%d: represents all digits.
+
+
%l: represents all lowercase letters.
+
+
%p: represents all punctuation characters.
+
+
%s: represents all space characters.
+
+
%u: represents all uppercase letters.
+
+
%w: represents all alphanumeric characters.
+
+
%x: represents all hexadecimal digits.
+
+
%z: represents the character with representation 0.
+
+
%x: (where x is any non-alphanumeric character)
+represents the character x.
+This is the standard way to escape the magic characters.
+Any punctuation character (even the non magic)
+can be preceded by a '%'
+when used to represent itself in a pattern.
+
+
+
[set]:
+represents the class which is the union of all
+characters in set.
+A range of characters can be specified by
+separating the end characters of the range with a '-'.
+All classes %x described above can also be used as
+components in set.
+All other characters in set represent themselves.
+For example, [%w_] (or [_%w])
+represents all alphanumeric characters plus the underscore,
+[0-7] represents the octal digits,
+and [0-7%l%-] represents the octal digits plus
+the lowercase letters plus the '-' character.
+
+
+
+The interaction between ranges and classes is not defined.
+Therefore, patterns like [%a-z] or [a-%%]
+have no meaning.
+
+
+
[^set]:
+represents the complement of set,
+where set is interpreted as above.
+
+
+
+For all classes represented by single letters (%a, %c, etc.),
+the corresponding uppercase letter represents the complement of the class.
+For instance, %S represents all non-space characters.
+
+
+
+The definitions of letter, space, and other character groups
+depend on the current locale.
+In particular, the class [a-z] may not be equivalent to %l.
+
+
+
+
+
+
Pattern Item:
+A pattern item can be
+
+
+
+
+a single character class,
+which matches any single character in the class;
+
+
+
+a single character class followed by '*',
+which matches 0 or more repetitions of characters in the class.
+These repetition items will always match the longest possible sequence;
+
+
+
+a single character class followed by '+',
+which matches 1 or more repetitions of characters in the class.
+These repetition items will always match the longest possible sequence;
+
+
+
+a single character class followed by '-',
+which also matches 0 or more repetitions of characters in the class.
+Unlike '*',
+these repetition items will always match the shortest possible sequence;
+
+
+
+a single character class followed by '?',
+which matches 0 or 1 occurrence of a character in the class;
+
+
+
+%n, for n between 1 and 9;
+such item matches a substring equal to the n-th captured string
+(see below);
+
+
+
+%bxy, where x and y are two distinct characters;
+such item matches strings that start with x, end with y,
+and where the x and y are balanced.
+This means that, if one reads the string from left to right,
+counting +1 for an x and -1 for a y,
+the ending y is the first y where the count reaches 0.
+For instance, the item %b() matches expressions with
+balanced parentheses.
+
+
+
+
+
+
+
+
Pattern:
+A pattern is a sequence of pattern items.
+A '^' at the beginning of a pattern anchors the match at the
+beginning of the subject string.
+A '$' at the end of a pattern anchors the match at the
+end of the subject string.
+At other positions,
+'^' and '$' have no special meaning and represent themselves.
+
+
+
+
+
+
Captures:
+A pattern can contain sub-patterns enclosed in parentheses;
+they describe captures.
+When a match succeeds, the substrings of the subject string
+that match captures are stored (captured) for future use.
+Captures are numbered according to their left parentheses.
+For instance, in the pattern "(a*(.)%w(%s*))",
+the part of the string matching "a*(.)%w(%s*)" is
+stored as the first capture (and therefore has number 1);
+the character matching "." is captured with number 2,
+and the part matching "%s*" has number 3.
+
+
+
+As a special case, the empty capture () captures
+the current string position (a number).
+For instance, if we apply the pattern "()aa()" on the
+string "flaaap", there will be two captures: 3 and 5.
+
+
+
+This library provides generic functions for table manipulation.
+It provides all its functions inside the table table.
+
+
+
+Most functions in the table library assume that the table
+represents an array or a list.
+For these functions, when we talk about the "length" of a table
+we mean the result of the length operator.
+
+
+
+Given an array where all elements are strings or numbers,
+returns table[i]..sep..table[i+1] ··· sep..table[j].
+The default value for sep is the empty string,
+the default for i is 1,
+and the default for j is the length of the table.
+If i is greater than j, returns the empty string.
+
+
+
+
+
+Inserts element value at position pos in table,
+shifting up other elements to open space, if necessary.
+The default value for pos is n+1,
+where n is the length of the table (see §2.5.5),
+so that a call table.insert(t,x) inserts x at the end
+of table t.
+
+
+
+
+
+Returns the largest positive numerical index of the given table,
+or zero if the table has no positive numerical indices.
+(To do its job this function does a linear traversal of
+the whole table.)
+
+
+
+
+
+Removes from table the element at position pos,
+shifting down other elements to close the space, if necessary.
+Returns the value of the removed element.
+The default value for pos is n,
+where n is the length of the table,
+so that a call table.remove(t) removes the last element
+of table t.
+
+
+
+
+
+Sorts table elements in a given order, in-place,
+from table[1] to table[n],
+where n is the length of the table.
+If comp is given,
+then it must be a function that receives two table elements,
+and returns true
+when the first is less than the second
+(so that not comp(a[i+1],a[i]) will be true after the sort).
+If comp is not given,
+then the standard Lua operator < is used instead.
+
+
+
+The sort algorithm is not stable;
+that is, elements considered equal by the given order
+may have their relative positions changed by the sort.
+
+
+
+
+
+
+
+
+Returns the arc tangent of y/x (in radians),
+but uses the signs of both parameters to find the
+quadrant of the result.
+(It also handles correctly the case of x being zero.)
+
+
+
+
+
+This function is an interface to the simple
+pseudo-random generator function rand provided by ANSI C.
+(No guarantees can be given for its statistical properties.)
+
+
+
+When called without arguments,
+returns a uniform pseudo-random real number
+in the range [0,1).
+When called with an integer number m,
+math.random returns
+a uniform pseudo-random integer in the range [1, m].
+When called with two integer numbers m and n,
+math.random returns a uniform pseudo-random
+integer in the range [m, n].
+
+
+
+
+
+The I/O library provides two different styles for file manipulation.
+The first one uses implicit file descriptors;
+that is, there are operations to set a default input file and a
+default output file,
+and all input/output operations are over these default files.
+The second style uses explicit file descriptors.
+
+
+
+When using implicit file descriptors,
+all operations are supplied by table io.
+When using explicit file descriptors,
+the operation io.open returns a file descriptor
+and then all operations are supplied as methods of the file descriptor.
+
+
+
+The table io also provides
+three predefined file descriptors with their usual meanings from C:
+io.stdin, io.stdout, and io.stderr.
+The I/O library never closes these files.
+
+
+
+Unless otherwise stated,
+all I/O functions return nil on failure
+(plus an error message as a second result and
+a system-dependent error code as a third result)
+and some value different from nil on success.
+
+
+
+When called with a file name, it opens the named file (in text mode),
+and sets its handle as the default input file.
+When called with a file handle,
+it simply sets this file handle as the default input file.
+When called without parameters,
+it returns the current default input file.
+
+
+
+In case of errors this function raises the error,
+instead of returning an error code.
+
+
+
+
+
+Opens the given file name in read mode
+and returns an iterator function that,
+each time it is called,
+returns a new line from the file.
+Therefore, the construction
+
+
+ for line in io.lines(filename) do body end
+
+will iterate over all lines of the file.
+When the iterator function detects the end of file,
+it returns nil (to finish the loop) and automatically closes the file.
+
+
+
+The call io.lines() (with no file name) is equivalent
+to io.input():lines();
+that is, it iterates over the lines of the default input file.
+In this case it does not close the file when the loop ends.
+
+
+
+
+
+This function opens a file,
+in the mode specified in the string mode.
+It returns a new file handle,
+or, in case of errors, nil plus an error message.
+
+
+
+The mode string can be any of the following:
+
+
+
"r": read mode (the default);
+
"w": write mode;
+
"a": append mode;
+
"r+": update mode, all previous data is preserved;
+
"w+": update mode, all previous data is erased;
+
"a+": append update mode, previous data is preserved,
+ writing is only allowed at the end of file.
+
+The mode string can also have a 'b' at the end,
+which is needed in some systems to open the file in binary mode.
+This string is exactly what is used in the
+standard C function fopen.
+
+
+
+
+
+Starts program prog in a separated process and returns
+a file handle that you can use to read data from this program
+(if mode is "r", the default)
+or to write data to this program
+(if mode is "w").
+
+
+
+This function is system dependent and is not available
+on all platforms.
+
+
+
+
+
+Checks whether obj is a valid file handle.
+Returns the string "file" if obj is an open file handle,
+"closed file" if obj is a closed file handle,
+or nil if obj is not a file handle.
+
+
+
+
+
+Closes file.
+Note that files are automatically closed when
+their handles are garbage collected,
+but that takes an unpredictable amount of time to happen.
+
+
+
+
+
+Reads the file file,
+according to the given formats, which specify what to read.
+For each format,
+the function returns a string (or a number) with the characters read,
+or nil if it cannot read data with the specified format.
+When called without formats,
+it uses a default format that reads the entire next line
+(see below).
+
+
+
+The available formats are
+
+
+
+
"*n":
+reads a number;
+this is the only format that returns a number instead of a string.
+
+
+
"*a":
+reads the whole file, starting at the current position.
+On end of file, it returns the empty string.
+
+
+
"*l":
+reads the next line (skipping the end of line),
+returning nil on end of file.
+This is the default format.
+
+
+
number:
+reads a string with up to this number of characters,
+returning nil on end of file.
+If number is zero,
+it reads nothing and returns an empty string,
+or nil on end of file.
+
+Sets and gets the file position,
+measured from the beginning of the file,
+to the position given by offset plus a base
+specified by the string whence, as follows:
+
+
+
"set": base is position 0 (beginning of the file);
+
"cur": base is current position;
+
"end": base is end of file;
+
+In case of success, function seek returns the final file position,
+measured in bytes from the beginning of the file.
+If this function fails, it returns nil,
+plus a string describing the error.
+
+
+
+The default value for whence is "cur",
+and for offset is 0.
+Therefore, the call file:seek() returns the current
+file position, without changing it;
+the call file:seek("set") sets the position to the
+beginning of the file (and returns 0);
+and the call file:seek("end") sets the position to the
+end of the file, and returns its size.
+
+
+
+
+
+Writes the value of each of its arguments to
+the file.
+The arguments must be strings or numbers.
+To write other values,
+use tostring or string.format before write.
+
+
+
+
+
+
+
+
+Returns a string or a table containing date and time,
+formatted according to the given string format.
+
+
+
+If the time argument is present,
+this is the time to be formatted
+(see the os.time function for a description of this value).
+Otherwise, date formats the current time.
+
+
+
+If format starts with '!',
+then the date is formatted in Coordinated Universal Time.
+After this optional character,
+if format is the string "*t",
+then date returns a table with the following fields:
+year (four digits), month (1--12), day (1--31),
+hour (0--23), min (0--59), sec (0--61),
+wday (weekday, Sunday is 1),
+yday (day of the year),
+and isdst (daylight saving flag, a boolean).
+
+
+
+If format is not "*t",
+then date returns the date as a string,
+formatted according to the same rules as the C function strftime.
+
+
+
+When called without arguments,
+date returns a reasonable date and time representation that depends on
+the host system and on the current locale
+(that is, os.date() is equivalent to os.date("%c")).
+
+
+
+
+
+This function is equivalent to the C function system.
+It passes command to be executed by an operating system shell.
+It returns a status code, which is system-dependent.
+If command is absent, then it returns nonzero if a shell is available
+and zero otherwise.
+
+
+
+
+
+Deletes the file or directory with the given name.
+Directories must be empty to be removed.
+If this function fails, it returns nil,
+plus a string describing the error.
+
+
+
+
+
+Sets the current locale of the program.
+locale is a string specifying a locale;
+category is an optional string describing which category to change:
+"all", "collate", "ctype",
+"monetary", "numeric", or "time";
+the default category is "all".
+The function returns the name of the new locale,
+or nil if the request cannot be honored.
+
+
+
+If locale is the empty string,
+the current locale is set to an implementation-defined native locale.
+If locale is the string "C",
+the current locale is set to the standard C locale.
+
+
+
+When called with nil as the first argument,
+this function only returns the name of the current locale
+for the given category.
+
+
+
+
+
+Returns the current time when called without arguments,
+or a time representing the date and time specified by the given table.
+This table must have fields year, month, and day,
+and may have fields hour, min, sec, and isdst
+(for a description of these fields, see the os.date function).
+
+
+
+The returned value is a number, whose meaning depends on your system.
+In POSIX, Windows, and some other systems, this number counts the number
+of seconds since some given start time (the "epoch").
+In other systems, the meaning is not specified,
+and the number returned by time can be used only as an argument to
+date and difftime.
+
+
+
+
+
+Returns a string with a file name that can
+be used for a temporary file.
+The file must be explicitly opened before its use
+and explicitly removed when no longer needed.
+
+
+
+On some systems (POSIX),
+this function also creates a file with that name,
+to avoid security risks.
+(Someone else might create the file with wrong permissions
+in the time between getting the name and creating the file.)
+You still have to open the file to use it
+and to remove it (even if you do not use it).
+
+
+
+When possible,
+you may prefer to use io.tmpfile,
+which automatically removes the file when the program ends.
+
+
+
+
+
+
+
+
+This library provides
+the functionality of the debug interface to Lua programs.
+You should exert care when using this library.
+The functions provided here should be used exclusively for debugging
+and similar tasks, such as profiling.
+Please resist the temptation to use them as a
+usual programming tool:
+they can be very slow.
+Moreover, several of these functions
+violate some assumptions about Lua code
+(e.g., that variables local to a function
+cannot be accessed from outside or
+that userdata metatables cannot be changed by Lua code)
+and therefore can compromise otherwise secure code.
+
+
+
+All functions in this library are provided
+inside the debug table.
+All functions that operate over a thread
+have an optional first argument which is the
+thread to operate over.
+The default is always the current thread.
+
+
+
+Enters an interactive mode with the user,
+running each string that the user enters.
+Using simple commands and other debug facilities,
+the user can inspect global and local variables,
+change their values, evaluate expressions, and so on.
+A line containing only the word cont finishes this function,
+so that the caller continues its execution.
+
+
+
+Note that commands for debug.debug are not lexically nested
+within any function, and so have no direct access to local variables.
+
+
+
+
+
+Returns the current hook settings of the thread, as three values:
+the current hook function, the current hook mask,
+and the current hook count
+(as set by the debug.sethook function).
+
+
+
+
+
+Returns a table with information about a function.
+You can give the function directly,
+or you can give a number as the value of function,
+which means the function running at level function of the call stack
+of the given thread:
+level 0 is the current function (getinfo itself);
+level 1 is the function that called getinfo;
+and so on.
+If function is a number larger than the number of active functions,
+then getinfo returns nil.
+
+
+
+The returned table can contain all the fields returned by lua_getinfo,
+with the string what describing which fields to fill in.
+The default for what is to get all information available,
+except the table of valid lines.
+If present,
+the option 'f'
+adds a field named func with the function itself.
+If present,
+the option 'L'
+adds a field named activelines with the table of
+valid lines.
+
+
+
+For instance, the expression debug.getinfo(1,"n").name returns
+a table with a name for the current function,
+if a reasonable name can be found,
+and the expression debug.getinfo(print)
+returns a table with all available information
+about the print function.
+
+
+
+
+
+This function returns the name and the value of the local variable
+with index local of the function at level level of the stack.
+(The first parameter or local variable has index 1, and so on,
+until the last active local variable.)
+The function returns nil if there is no local
+variable with the given index,
+and raises an error when called with a level out of range.
+(You can call debug.getinfo to check whether the level is valid.)
+
+
+
+Variable names starting with '(' (open parentheses)
+represent internal variables
+(loop control variables, temporaries, and C function locals).
+
+
+
+
+
+This function returns the name and the value of the upvalue
+with index up of the function func.
+The function returns nil if there is no upvalue with the given index.
+
+
+
+
+
+Sets the given function as a hook.
+The string mask and the number count describe
+when the hook will be called.
+The string mask may have the following characters,
+with the given meaning:
+
+
+
"c": the hook is called every time Lua calls a function;
+
"r": the hook is called every time Lua returns from a function;
+
"l": the hook is called every time Lua enters a new line of code.
+
+With a count different from zero,
+the hook is called after every count instructions.
+
+
+
+When called without arguments,
+debug.sethook turns off the hook.
+
+
+
+When the hook is called, its first parameter is a string
+describing the event that has triggered its call:
+"call", "return" (or "tail return",
+when simulating a return from a tail call),
+"line", and "count".
+For line events,
+the hook also gets the new line number as its second parameter.
+Inside a hook,
+you can call getinfo with level 2 to get more information about
+the running function
+(level 0 is the getinfo function,
+and level 1 is the hook function),
+unless the event is "tail return".
+In this case, Lua is only simulating the return,
+and a call to getinfo will return invalid data.
+
+
+
+
+
+This function assigns the value value to the local variable
+with index local of the function at level level of the stack.
+The function returns nil if there is no local
+variable with the given index,
+and raises an error when called with a level out of range.
+(You can call getinfo to check whether the level is valid.)
+Otherwise, it returns the name of the local variable.
+
+
+
+
+
+This function assigns the value value to the upvalue
+with index up of the function func.
+The function returns nil if there is no upvalue
+with the given index.
+Otherwise, it returns the name of the upvalue.
+
+
+
+
+
+Returns a string with a traceback of the call stack.
+An optional message string is appended
+at the beginning of the traceback.
+An optional level number tells at which level
+to start the traceback
+(default is 1, the function calling traceback).
+
+
+
+
+
+
+
+
+Although Lua has been designed as an extension language,
+to be embedded in a host C program,
+it is also frequently used as a stand-alone language.
+An interpreter for Lua as a stand-alone language,
+called simply lua,
+is provided with the standard distribution.
+The stand-alone interpreter includes
+all standard libraries, including the debug library.
+Its usage is:
+
+
+ lua [options] [script [args]]
+
+The options are:
+
+
+
-e stat: executes string stat;
+
-l mod: "requires" mod;
+
-i: enters interactive mode after running script;
+
-v: prints version information;
+
--: stops handling options;
+
-: executes stdin as a file and stops handling options.
+
+After handling its options, lua runs the given script,
+passing to it the given args as string arguments.
+When called without arguments,
+lua behaves as lua -v -i
+when the standard input (stdin) is a terminal,
+and as lua - otherwise.
+
+
+
+Before running any argument,
+the interpreter checks for an environment variable LUA_INIT.
+If its format is @filename,
+then lua executes the file.
+Otherwise, lua executes the string itself.
+
+
+
+All options are handled in order, except -i.
+For instance, an invocation like
+
+
+ $ lua -e'a=1' -e 'print(a)' script.lua
+
+will first set a to 1, then print the value of a (which is '1'),
+and finally run the file script.lua with no arguments.
+(Here $ is the shell prompt. Your prompt may be different.)
+
+
+
+Before starting to run the script,
+lua collects all arguments in the command line
+in a global table called arg.
+The script name is stored at index 0,
+the first argument after the script name goes to index 1,
+and so on.
+Any arguments before the script name
+(that is, the interpreter name plus the options)
+go to negative indices.
+For instance, in the call
+
+
+ $ lua -la b.lua t1 t2
+
+the interpreter first runs the file a.lua,
+then creates a table
+
+
+and finally runs the file b.lua.
+The script is called with arg[1], arg[2], ···
+as arguments;
+it can also access these arguments with the vararg expression '...'.
+
+
+
+In interactive mode,
+if you write an incomplete statement,
+the interpreter waits for its completion
+by issuing a different prompt.
+
+
+
+If the global variable _PROMPT contains a string,
+then its value is used as the prompt.
+Similarly, if the global variable _PROMPT2 contains a string,
+its value is used as the secondary prompt
+(issued during incomplete statements).
+Therefore, both prompts can be changed directly on the command line
+or in any Lua programs by assigning to _PROMPT.
+See the next example:
+
+
+ $ lua -e"_PROMPT='myprompt> '" -i
+
+(The outer pair of quotes is for the shell,
+the inner pair is for Lua.)
+Note the use of -i to enter interactive mode;
+otherwise,
+the program would just end silently
+right after the assignment to _PROMPT.
+
+
+
+To allow the use of Lua as a
+script interpreter in Unix systems,
+the stand-alone interpreter skips
+the first line of a chunk if it starts with #.
+Therefore, Lua scripts can be made into executable programs
+by using chmod +x and the #! form,
+as in
+
+
+ #!/usr/local/bin/lua
+
+(Of course,
+the location of the Lua interpreter may be different in your machine.
+If lua is in your PATH,
+then
+
+
+Here we list the incompatibilities that you may find when moving a program
+from Lua 5.0 to Lua 5.1.
+You can avoid most of the incompatibilities compiling Lua with
+appropriate options (see file luaconf.h).
+However,
+all these compatibility options will be removed in the next version of Lua.
+
+
+
+
+The vararg system changed from the pseudo-argument arg with a
+table with the extra arguments to the vararg expression.
+(See compile-time option LUA_COMPAT_VARARG in luaconf.h.)
+
+
+
+There was a subtle change in the scope of the implicit
+variables of the for statement and for the repeat statement.
+
+
+
+The long string/long comment syntax ([[string]])
+does not allow nesting.
+You can use the new syntax ([=[string]=]) in these cases.
+(See compile-time option LUA_COMPAT_LSTR in luaconf.h.)
+
+Function string.gfind was renamed string.gmatch.
+(See compile-time option LUA_COMPAT_GFIND in luaconf.h.)
+
+
+
+When string.gsub is called with a function as its
+third argument,
+whenever this function returns nil or false the
+replacement string is the whole match,
+instead of the empty string.
+
+
+
+Function table.setn was deprecated.
+Function table.getn corresponds
+to the new length operator (#);
+use the operator instead of the function.
+(See compile-time option LUA_COMPAT_GETN in luaconf.h.)
+
+
+
+Function loadlib was renamed package.loadlib.
+(See compile-time option LUA_COMPAT_LOADLIB in luaconf.h.)
+
+
+
+Function math.mod was renamed math.fmod.
+(See compile-time option LUA_COMPAT_MOD in luaconf.h.)
+
+
+
+Functions table.foreach and table.foreachi are deprecated.
+You can use a for loop with pairs or ipairs instead.
+
+
+
+There were substantial changes in function require due to
+the new module system.
+However, the new behavior is mostly compatible with the old,
+but require gets the path from package.path instead
+of from LUA_PATH.
+
+
+
+Function collectgarbage has different arguments.
+Function gcinfo is deprecated;
+use collectgarbage("count") instead.
+
+The luaopen_* functions (to open libraries)
+cannot be called directly,
+like a regular C function.
+They must be called through Lua,
+like a Lua function.
+
+
+
+Function lua_open was replaced by lua_newstate to
+allow the user to set a memory-allocation function.
+You can use luaL_newstate from the standard library to
+create a state with a standard allocation function
+(based on realloc).
+
+
+
+Functions luaL_getn and luaL_setn
+(from the auxiliary library) are deprecated.
+Use lua_objlen instead of luaL_getn
+and nothing instead of luaL_setn.
+
+
+
+Function luaL_openlib was replaced by luaL_register.
+
+
+
+Function luaL_checkudata now throws an error when the given value
+is not a userdata of the expected type.
+(In Lua 5.0 it returned NULL.)
+