summaryrefslogtreecommitdiff
path: root/src/bin
diff options
context:
space:
mode:
authorDaniel Kolesa <d.kolesa@samsung.com>2014-12-12 12:04:10 +0000
committerDaniel Kolesa <d.kolesa@samsung.com>2014-12-12 12:04:10 +0000
commit4a1bfdeb4d771f39c49f9d8fc65aa0cde2700de0 (patch)
tree9963277f3cbe4129a9dbaed21d5b1071fe8cdfe7 /src/bin
parent784045df9ae73f4f74b52b5f2cc7a6254b9b7c1d (diff)
elua: move io extensions to library
Diffstat (limited to 'src/bin')
-rw-r--r--src/bin/elua/io.c370
-rw-r--r--src/bin/elua/main.c4
2 files changed, 1 insertions, 373 deletions
diff --git a/src/bin/elua/io.c b/src/bin/elua/io.c
deleted file mode 100644
index 9d4ad17803..0000000000
--- a/src/bin/elua/io.c
+++ /dev/null
@@ -1,370 +0,0 @@
1#include "config.h"
2
3/* elua io extras, largely taken from lua io lib source */
4
5#include "main.h"
6
7/* expand fname to full path name (so that PATH is ignored) plus turn
8 * stuff into a command, and also verify whether the path exists */
9static char *
10get_cmdline_from_argv(const char *fname, const char **argv)
11{
12 Eina_Strbuf *buf;
13 char *ret;
14 char pbuf[PATH_MAX];
15 const char *arg = NULL;
16
17 FILE *testf = fopen(fname, "r");
18 if (!testf)
19 return NULL;
20
21 fclose(testf);
22
23 /* for windows, we have realpath in evil, no need for GetFullPathName */
24 if (!realpath(fname, pbuf))
25 return NULL;
26
27 buf = eina_strbuf_new();
28 eina_strbuf_append_char(buf, '"');
29 eina_strbuf_append(buf, pbuf);
30 eina_strbuf_append_char(buf, '"');
31
32 while ((arg = *(argv++)))
33 {
34 char c;
35 eina_strbuf_append_char(buf, ' ');
36 eina_strbuf_append_char(buf, '"');
37
38 while ((c = *(arg++)))
39 {
40#ifndef _WIN32
41 if (c == '"' || c == '$') eina_strbuf_append_char(buf, '\\');
42 eina_strbuf_append_char(buf, c);
43#else
44 if (c == '"') eina_strbuf_append_char(buf, '\\');
45 else if (c == '%') eina_strbuf_append_char(buf, '"');
46 eina_strbuf_append_char(buf, c);
47 if (c == '%') eina_strbuf_append_char(buf, '"');
48#endif
49 }
50
51 eina_strbuf_append_char(buf, '"');
52 }
53
54 ret = strdup(eina_strbuf_string_get(buf));
55 eina_strbuf_free(buf);
56 return ret;
57}
58
59static FILE *
60elua_popen_c(const char *path, const char *md, const char *argv[])
61{
62 FILE *ret;
63
64 char *cmdline = get_cmdline_from_argv(path, argv);
65 if (!cmdline) return NULL;
66
67#ifndef _WIN32
68 ret = popen(cmdline, md);
69#else
70 ret = _popen(cmdline, md);
71#endif
72
73 free(cmdline);
74
75 if (!ret) return NULL;
76
77 return ret;
78}
79
80static int
81push_ret(lua_State *L, int i, const char *fname)
82{
83 int en = errno;
84 if (i)
85 {
86 lua_pushboolean(L, 1);
87 return 1;
88 }
89 else
90 {
91 lua_pushnil(L);
92 if (fname)
93 lua_pushfstring(L, "%s: %s", fname, strerror(en));
94 else
95 lua_pushfstring(L, "%s", strerror(en));
96 lua_pushinteger(L, en);
97 return 3;
98 }
99}
100
101static FILE *
102tofile(lua_State *L)
103{
104 FILE **f = (FILE**)luaL_checkudata(L, 1, "ELUA_FILE*");
105 if (!*f)
106 {
107 luaL_error(L, "attempt to use a closed file");
108 }
109 return *f;
110}
111
112static int
113elua_close(lua_State *L)
114{
115 FILE **f = (FILE**)luaL_checkudata(L, 1, "ELUA_FILE*");
116 int ok = (fclose(*f) == 0);
117 if (ok) *f = NULL;
118 return push_ret(L, ok, NULL);
119}
120
121static int
122elua_flush(lua_State *L)
123{
124 return push_ret(L, fflush(tofile(L)) == 0, NULL);
125}
126
127static int elua_readline(lua_State *L);
128
129static int
130elua_lines(lua_State *L)
131{
132 lua_pushvalue(L, 1);
133 lua_pushcclosure(L, elua_readline, 1);
134 return 1;
135}
136
137static int
138read_number(lua_State *L, FILE *f)
139{
140 lua_Number d;
141 if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1)
142 {
143 lua_pushnumber(L, d);
144 return 1;
145 }
146 return 0;
147}
148
149static int
150test_eof(lua_State *L, FILE *f)
151{
152 int c = getc(f);
153 ungetc(c, f);
154 lua_pushlstring(L, NULL, 0);
155 return (c != EOF);
156}
157
158static int
159read_line(lua_State *L, FILE *f)
160{
161 luaL_Buffer b;
162 luaL_buffinit(L, &b);
163 for (;;)
164 {
165 size_t l;
166 char *p = luaL_prepbuffer(&b);
167 if (fgets(p, LUAL_BUFFERSIZE, f) == NULL)
168 {
169 luaL_pushresult(&b);
170 return (lua_strlen(L, -1) > 0);
171 }
172 l = strlen(p);
173 if (!l || p[l - 1] != '\n')
174 luaL_addsize(&b, l);
175 else
176 {
177 luaL_addsize(&b, l - 1);
178 luaL_pushresult(&b);
179 return 1;
180 }
181 }
182}
183
184static int
185read_chars(lua_State *L, FILE *f, size_t n)
186{
187 size_t rlen;
188 size_t nr;
189 luaL_Buffer b;
190 luaL_buffinit(L, &b);
191 rlen = LUAL_BUFFERSIZE;
192 do
193 {
194 char *p = luaL_prepbuffer(&b);
195 if (rlen > n) rlen = n;
196 nr = fread(p, sizeof(char), rlen, f);
197 luaL_addsize(&b, nr);
198 n -= nr;
199 } while (n > 0 && nr == rlen);
200 luaL_pushresult(&b);
201 return (n == 0 || lua_strlen(L, -1) > 0);
202}
203
204static int
205elua_readline(lua_State *L)
206{
207 FILE *f = *(FILE**)lua_touserdata(L, lua_upvalueindex(1));
208 int success;
209 if (!f)
210 {
211 luaL_error(L, "file is already closed");
212 return 0; /* shut up coverity; luaL_error does a longjmp */
213 }
214 success = read_line(L, f);
215 if (ferror(f))
216 return luaL_error(L, "%s", strerror(errno));
217 return success;
218}
219
220static int
221elua_read(lua_State *L)
222{
223 FILE *f = tofile(L);
224 int nargs = lua_gettop(L) - 1;
225 int first = 2;
226 int success, n;
227 clearerr(f);
228 if (!nargs)
229 {
230 success = read_line(L, f);
231 n = first + 1;
232 }
233 else
234 {
235 luaL_checkstack(L, nargs + LUA_MINSTACK, "too many arguments");
236 success = 1;
237 for (n = first; nargs-- && success; ++n)
238 {
239 if (lua_type(L, n) == LUA_TNUMBER)
240 {
241 size_t l = (size_t)lua_tointeger(L, n);
242 success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
243 }
244 else
245 {
246 const char *p = lua_tostring(L, n);
247 luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
248 switch (p[1])
249 {
250 case 'n':
251 success = read_number(L, f);
252 break;
253 case 'l':
254 success = read_line(L, f);
255 break;
256 case 'a':
257 read_chars(L, f, ~((size_t)0));
258 success = 1;
259 break;
260 default:
261 return luaL_argerror(L, n, "invalid format");
262 }
263 }
264 }
265 }
266 if (ferror(f))
267 return push_ret(L, 0, NULL);
268 if (!success)
269 {
270 lua_pop(L, 1);
271 lua_pushnil(L);
272 }
273 return n - first;
274}
275
276static int
277elua_write(lua_State *L)
278{
279 FILE *f = tofile(L);
280 int nargs = lua_gettop(L) - 1;
281 int status = 1, arg = 2;
282 for (; nargs--; ++arg)
283 {
284 if (lua_type(L, arg) == LUA_TNUMBER)
285 status = status && (fprintf(f, LUA_NUMBER_FMT,
286 lua_tonumber(L, arg)) > 0);
287 else
288 {
289 size_t l;
290 const char *s = luaL_checklstring(L, arg, &l);
291 status = status && (fwrite(s, sizeof(char), l, f) == l);
292 }
293 }
294 return push_ret(L, status, NULL);
295}
296
297static int
298elua_fgc(lua_State *L)
299{
300 FILE **f = (FILE**)luaL_checkudata(L, 1, "ELUA_FILE*");
301 if (*f)
302 {
303 fclose(*f);
304 *f = NULL;
305 }
306 return 0;
307}
308
309static int
310elua_ftostring(lua_State *L)
311{
312 FILE *f = *((FILE**)luaL_checkudata(L, 1, "ELUA_FILE*"));
313 if (!f)
314 lua_pushliteral(L, "file (closed)");
315 else
316 lua_pushfstring(L, "file (%p)", f);
317 return 1;
318}
319
320static const luaL_reg elua_popenlib[] =
321{
322 { "close" , elua_close },
323 { "flush" , elua_flush },
324 { "lines" , elua_lines },
325 { "read" , elua_read },
326 { "write" , elua_write },
327 { "__gc" , elua_fgc },
328 { "__tostring", elua_ftostring },
329 { NULL , NULL }
330};
331
332static FILE **
333elua_newfile(lua_State *L)
334{
335 FILE **f = (FILE**)lua_newuserdata(L, sizeof(FILE*));
336 *f = NULL;
337 if (luaL_newmetatable(L, "ELUA_FILE*"))
338 {
339 lua_pushvalue(L, -1);
340 lua_setfield (L, -2, "__index");
341 luaL_register(L, NULL, elua_popenlib);
342 }
343 lua_setmetatable(L, -2);
344 return f;
345}
346
347int
348elua_popen(lua_State *L)
349{
350 const char *fname = luaL_checkstring(L, 1);
351 const char *mode = luaL_optstring(L, 2, "r");
352 int nargs = lua_gettop(L) - 2;
353 FILE **pf = elua_newfile(L);
354 if (nargs > 0)
355 {
356 const char **argv = (const char**)alloca((nargs + 1) * sizeof(char*));
357 memset(argv, 0, (nargs + 1) * sizeof(char*));
358 for (; nargs; --nargs)
359 {
360 argv[nargs - 1] = lua_tostring(L, nargs + 2);
361 }
362 *pf = elua_popen_c(fname, mode, argv);
363 }
364 else
365 {
366 const char *argv = NULL;
367 *pf = elua_popen_c(fname, mode, &argv);
368 }
369 return (!*pf) ? push_ret(L, 0, fname) : 1;
370}
diff --git a/src/bin/elua/main.c b/src/bin/elua/main.c
index 789ee06a9f..5ff7487bef 100644
--- a/src/bin/elua/main.c
+++ b/src/bin/elua/main.c
@@ -316,13 +316,11 @@ struct Main_Data
316 int status; 316 int status;
317}; 317};
318 318
319int elua_popen(lua_State *L);
320
321const luaL_reg cutillib[] = 319const luaL_reg cutillib[] =
322{ 320{
323 { "init_module" , elua_init_module }, 321 { "init_module" , elua_init_module },
324 { "register_callbacks", elua_register_callbacks }, 322 { "register_callbacks", elua_register_callbacks },
325 { "popenv" , elua_popen }, 323 { "popenv" , elua_io_popen },
326 { NULL , NULL } 324 { NULL , NULL }
327}; 325};
328 326