-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathclc.cpp
185 lines (185 loc) · 6.53 KB
/
clc.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
/* ------------------------------------------------------------------------- */
// Compile with: cls; g++ -O3 --std c++20 -Iinclude/lua clc.cpp lua.a -o clc
/* ------------------------------------------------------------------------- */
#include <exception> // std::exception
#include <functional> // std::function
#include <iomanip> // std::precision
#include <iostream> // std::cout
#include <memory> // std::unique_ptr
/* ------------------------------------------------------------------------- */
#include <lua.h> // Lua base
#include <lualib.h> // Lua api
#include <lauxlib.h> // Lua aux api
/* ------------------------------------------------------------------------- */
int main(int iArgC, char **cpaArgV) try
{ // If not enough argumemts?
if(iArgC <= 1)
{ // Show usage
std::cout << "Usage: "
<< *cpaArgV
<< " [expression]."
<< std::endl
<< "Compiled: " __TIMESTAMP__ "."
<< std::endl
<< "Lua version: " LUA_RELEASE "."
<< std::endl;
// Return error staus
return 1;
} // Prototype for lua context self release state
typedef std::unique_ptr<lua_State,
std::function<decltype(lua_close)>> LuaPtr;
// Make STL ask LUA to create a new state and if successful?
if(const LuaPtr lpState{
// Call back memory allocation function
lua_newstate([](void*const, void*const vpPtr, size_t, size_t stSize)->void*
{ // (Re)allocate if memory needed and return
if(stSize) return realloc(vpPtr, stSize);
// Zero for free memory
free(vpPtr);
// Return nothing
return nullptr;
}, nullptr), lua_close }) try
{ // Get address of LUA state data
lua_State*const lsState = lpState.get();
// Set panic callback that throws and error
lua_atpanic(lsState, [](lua_State*const lsState)->int
{ throw std::runtime_error{ lua_tostring(lsState, 1) }; });
// Build mathemetics api function table
luaopen_math(lsState);
// Assign it to the global index
lua_rawseti(lsState, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);
// Space character
const std::string strSpace{ " " };
// Concatenate string buffer from command line
std::string strBuffer; strBuffer.reserve(1024);
const int iArgCM1 = iArgC-1;
for(int iArg = 1; iArg < iArgCM1; ++iArg)
{ strBuffer += cpaArgV[iArg]; strBuffer += strSpace; }
strBuffer += cpaArgV[iArgCM1];
// Compile the specified code snipped and capture result
const std::string strSnippet{ "return (" + strBuffer + ");" };
switch(const int iResult = luaL_loadbuffer(lsState, strSnippet.c_str(),
strSnippet.length(), strBuffer.c_str()))
{ // No error? Break to execution
case 0: break;
// Syntax error?
case LUA_ERRSYNTAX:
{ // Inform user
std::cout << "Compile error! > "
<< lua_tostring(lsState, 1)
<< std::endl;
// Exit failure
return 2;
} // Memory allocation error?
case LUA_ERRMEM:
{ // Inform user
std::cout << "Lua is out of memory error compiling!"
<< std::endl;
// Exit failure
return 3;
} // Unknown error?
default:
{ // Inform user
std::cout << "Unknown compile error "
<< iResult
<< '!' << std::endl;
// Exit failure
return 4;
}
} // Execute function with no parameters
switch(const int iResult = lua_pcall(lsState, 0, 1, 0))
{ // No error so break to show result
case 0: break;
// Runtime error?
case LUA_ERRRUN:
{ // Inform user
std::cout << "Run-time error! > "
<< lua_tostring(lsState, 1)
<< std::endl;
// Exit failure
return 5;
} // Memory allocation error
case LUA_ERRMEM:
{ // Inform user
std::cout << "Lua is out of memory error executing!" << std::endl;
// Exit failure
return 6;
} // Error + error in error handler
case LUA_ERRERR:
{ // Inform user
std::cout << "Lua got error in error handler!" << std::endl;
// Exit failure
return 7;
} // Unknown error?
default:
{ // Inform user
std::cout << "Unknown run-time error " << iResult << '!' << std::endl;
// Exit failure
return 8;
}
} // Begin printing result
std::cout << "The result of '"
<< strBuffer
<< "' is ";
// What type of LUA variable was returned?
switch(const int iType = lua_type(lsState, 1))
{ // A number value?
case LUA_TNUMBER:
{ // If not actually an integer?
if(!lua_isinteger(lsState, 1))
{ // Write as normal floating-point number
std::cout << "a number of "
<< std::setprecision(12)
<< std::fixed
<< lua_tonumber(lsState, 1);
} // Get actual integer?
else
{ // Get the integer value and inform user
const lua_Integer liValue = lua_tointeger(lsState, 1);
std::cout << "an integer of "
<< liValue
<< std::hex
<< " [0x"
<< liValue
<< ']';
// Print unsigned value if needed
if(liValue < 0)
std::cout << std::endl
<< "or an unsigned value of "
<< std::dec
<< static_cast<lua_Unsigned>(liValue);
} // Done
break;
} // Who knows? Function? Userdata?
default:
{ // Write as unknown type
std::cout << "(type "
<< iType
<< ") not a number";
// Done
break;
}
} // Write rest of line
std::cout << '!' << std::endl;
} // Exception occured in sandbox?
catch(const std::exception &e)
{ // Inform user
std::cout << "Sandbox exception: " << e.what() << "!" << std::endl;
// Exit failure
return 9;
} // Lua failed to create state?
else
{ // Inform user
std::cout << "Error creating lua state!" << std::endl;
// Exit failure
return 10;
} // Exit success
return 0;
} // Exception occured in root?
catch(const std::exception &e)
{ // Inform user
std::cout << "Exception: " << e.what() << "!" << std::endl;
// Exit failure
return 11;
}
/* ------------------------------------------------------------------------- */