Line data Source code
1 : /*
2 : ** $Id: liolib.c,v 2.151.1.1 2017/04/19 17:29:57 roberto Exp $
3 : ** Standard I/O (and system) library
4 : ** See Copyright Notice in lua.h
5 : */
6 :
7 : #define liolib_c
8 : #define LUA_LIB
9 :
10 : #include "lprefix.h"
11 :
12 :
13 : #include <ctype.h>
14 : #include <errno.h>
15 : #include <locale.h>
16 : #include <stdio.h>
17 : #include <stdlib.h>
18 : #include <string.h>
19 :
20 : #include "lua.h"
21 :
22 : #include "lauxlib.h"
23 : #include "lualib.h"
24 :
25 : #if defined(ARDUPILOT_BUILD)
26 : #pragma GCC diagnostic ignored "-Wunused-function"
27 : #endif
28 :
29 :
30 : /*
31 : ** Change this macro to accept other modes for 'fopen' besides
32 : ** the standard ones.
33 : */
34 : #if !defined(l_checkmode)
35 :
36 : /* accepted extensions to 'mode' in 'fopen' */
37 : #if !defined(L_MODEEXT)
38 : #define L_MODEEXT "b"
39 : #endif
40 :
41 : /* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */
42 2 : static int l_checkmode (const char *mode) {
43 2 : return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL &&
44 6 : (*mode != '+' || (++mode, 1)) && /* skip if char is '+' */
45 2 : (strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */
46 : }
47 :
48 : #endif
49 :
50 : /*
51 : ** {======================================================
52 : ** l_popen spawns a new process connected to the current
53 : ** one through the file streams.
54 : ** =======================================================
55 : */
56 :
57 : #if !defined(l_popen) /* { */
58 :
59 : #if defined(LUA_USE_POSIX) /* { */
60 :
61 : #define l_popen(L,c,m) (fflush(NULL), popen(c,m))
62 : #define l_pclose(L,file) (pclose(file))
63 :
64 : #elif defined(LUA_USE_WINDOWS) /* }{ */
65 :
66 : #define l_popen(L,c,m) (_popen(c,m))
67 : #define l_pclose(L,file) (_pclose(file))
68 :
69 : #else /* }{ */
70 :
71 : /* ISO C definitions */
72 : #define l_popen(L,c,m) \
73 : ((void)((void)c, m), \
74 : luaL_error(L, "'popen' not supported"), \
75 : (FILE*)0)
76 : #define l_pclose(L,file) ((void)L, (void)file, -1)
77 :
78 : #endif /* } */
79 :
80 : #endif /* } */
81 :
82 : /* }====================================================== */
83 :
84 :
85 : #if !defined(l_getc) /* { */
86 :
87 : #if defined(LUA_USE_POSIX)
88 : #define l_getc(f) getc_unlocked(f)
89 : #define l_lockfile(f) flockfile(f)
90 : #define l_unlockfile(f) funlockfile(f)
91 : #else
92 : #define l_getc(f) getc(f)
93 : #define l_lockfile(f) ((void)0)
94 : #define l_unlockfile(f) ((void)0)
95 : #endif
96 :
97 : #endif /* } */
98 :
99 :
100 : /*
101 : ** {======================================================
102 : ** l_fseek: configuration for longer offsets
103 : ** =======================================================
104 : */
105 :
106 : #if !defined(l_fseek) /* { */
107 :
108 : #if defined(LUA_USE_POSIX) /* { */
109 :
110 : #include <sys/types.h>
111 :
112 : #define l_fseek(f,o,w) fseeko(f,o,w)
113 : #define l_ftell(f) ftello(f)
114 : #define l_seeknum off_t
115 :
116 : #elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \
117 : && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */
118 :
119 : /* Windows (but not DDK) and Visual C++ 2005 or higher */
120 : #define l_fseek(f,o,w) _fseeki64(f,o,w)
121 : #define l_ftell(f) _ftelli64(f)
122 : #define l_seeknum __int64
123 :
124 : #else /* }{ */
125 :
126 : /* ISO C definitions */
127 : #define l_fseek(f,o,w) fseek(f,o,w)
128 : #define l_ftell(f) ftell(f)
129 : #define l_seeknum long
130 :
131 : #endif /* } */
132 :
133 : #endif /* } */
134 :
135 : /* }====================================================== */
136 :
137 :
138 : #define IO_PREFIX "_IO_"
139 : #define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1)
140 : #define IO_INPUT (IO_PREFIX "input")
141 : #define IO_OUTPUT (IO_PREFIX "output")
142 :
143 :
144 : typedef luaL_Stream LStream;
145 :
146 :
147 : #define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
148 :
149 : #define isclosed(p) ((p)->closef == NULL)
150 :
151 :
152 0 : static int io_type (lua_State *L) {
153 : LStream *p;
154 0 : luaL_checkany(L, 1);
155 0 : p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
156 0 : if (p == NULL)
157 0 : lua_pushnil(L); /* not a file */
158 0 : else if (isclosed(p))
159 0 : lua_pushliteral(L, "closed file");
160 : else
161 0 : lua_pushliteral(L, "file");
162 0 : return 1;
163 : }
164 :
165 :
166 0 : static int f_tostring (lua_State *L) {
167 0 : LStream *p = tolstream(L);
168 0 : if (isclosed(p))
169 0 : lua_pushliteral(L, "file (closed)");
170 : else
171 0 : lua_pushfstring(L, "file (%p)", p->f);
172 0 : return 1;
173 : }
174 :
175 :
176 102 : static FILE *tofile (lua_State *L) {
177 102 : LStream *p = tolstream(L);
178 102 : if (isclosed(p))
179 0 : luaL_error(L, "attempt to use a closed file");
180 : lua_assert(p->f);
181 102 : return p->f;
182 : }
183 :
184 :
185 : /*
186 : ** When creating file handles, always creates a 'closed' file handle
187 : ** before opening the actual file; so, if there is a memory error, the
188 : ** handle is in a consistent state.
189 : */
190 278 : static LStream *newprefile (lua_State *L) {
191 278 : LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
192 278 : p->closef = NULL; /* mark file handle as 'closed' */
193 278 : luaL_setmetatable(L, LUA_FILEHANDLE);
194 278 : return p;
195 : }
196 :
197 :
198 : /*
199 : ** Calls the 'close' function from a file handle. The 'volatile' avoids
200 : ** a bug in some versions of the Clang compiler (e.g., clang 3.0 for
201 : ** 32 bits).
202 : */
203 184 : static int aux_close (lua_State *L) {
204 184 : LStream *p = tolstream(L);
205 184 : volatile lua_CFunction cf = p->closef;
206 184 : p->closef = NULL; /* mark stream as closed */
207 184 : return (*cf)(L); /* close it */
208 : }
209 :
210 :
211 0 : static int lf_close (lua_State *L) {
212 0 : tofile(L); /* make sure argument is an open stream */
213 0 : return aux_close(L);
214 : }
215 :
216 :
217 0 : static int io_close (lua_State *L) {
218 0 : if (lua_isnone(L, 1)) /* no argument? */
219 0 : lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */
220 0 : return lf_close(L);
221 : }
222 :
223 :
224 185 : static int f_gc (lua_State *L) {
225 185 : LStream *p = tolstream(L);
226 185 : if (!isclosed(p) && p->f != NULL)
227 184 : aux_close(L); /* ignore closed and incompletely open files */
228 185 : return 0;
229 : }
230 :
231 :
232 : /*
233 : ** function to close regular files
234 : */
235 1 : static int io_fclose (lua_State *L) {
236 1 : LStream *p = tolstream(L);
237 1 : int res = fclose(p->f);
238 1 : return luaL_fileresult(L, (res == 0), NULL);
239 : }
240 :
241 :
242 2 : static LStream *newfile (lua_State *L) {
243 2 : LStream *p = newprefile(L);
244 2 : p->f = NULL;
245 2 : p->closef = &io_fclose;
246 2 : return p;
247 : }
248 :
249 :
250 0 : static void opencheck (lua_State *L, const char *fname, const char *mode) {
251 0 : LStream *p = newfile(L);
252 0 : p->f = fopen(fname, mode);
253 0 : if (p->f == NULL)
254 0 : luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno));
255 0 : }
256 :
257 :
258 2 : static int io_open (lua_State *L) {
259 2 : const char *filename = luaL_checkstring(L, 1);
260 2 : const char *mode = luaL_optstring(L, 2, "r");
261 2 : LStream *p = newfile(L);
262 2 : const char *md = mode; /* to traverse/check mode */
263 2 : luaL_argcheck(L, l_checkmode(md), 2, "invalid mode");
264 2 : p->f = fopen(filename, mode);
265 2 : return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
266 : }
267 :
268 :
269 : /*
270 : ** function to close 'popen' files
271 : */
272 0 : static int io_pclose (lua_State *L) {
273 0 : LStream *p = tolstream(L);
274 0 : return luaL_execresult(L, l_pclose(L, p->f));
275 : }
276 :
277 :
278 0 : static int io_popen (lua_State *L) {
279 0 : const char *filename = luaL_checkstring(L, 1);
280 0 : const char *mode = luaL_optstring(L, 2, "r");
281 0 : LStream *p = newprefile(L);
282 0 : luaL_argcheck(L, ((mode[0] == 'r' || mode[0] == 'w') && mode[1] == '\0'),
283 : 2, "invalid mode");
284 0 : p->f = l_popen(L, filename, mode);
285 0 : p->closef = &io_pclose;
286 0 : return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
287 : }
288 :
289 :
290 0 : static int io_tmpfile (lua_State *L) {
291 0 : LStream *p = newfile(L);
292 0 : p->f = tmpfile();
293 0 : return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
294 : }
295 :
296 :
297 0 : static FILE *getiofile (lua_State *L, const char *findex) {
298 : LStream *p;
299 0 : lua_getfield(L, LUA_REGISTRYINDEX, findex);
300 0 : p = (LStream *)lua_touserdata(L, -1);
301 0 : if (isclosed(p))
302 0 : luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN);
303 0 : return p->f;
304 : }
305 :
306 :
307 0 : static int g_iofile (lua_State *L, const char *f, const char *mode) {
308 0 : if (!lua_isnoneornil(L, 1)) {
309 0 : const char *filename = lua_tostring(L, 1);
310 0 : if (filename)
311 0 : opencheck(L, filename, mode);
312 : else {
313 0 : tofile(L); /* check that it's a valid file handle */
314 0 : lua_pushvalue(L, 1);
315 : }
316 0 : lua_setfield(L, LUA_REGISTRYINDEX, f);
317 : }
318 : /* return current value */
319 0 : lua_getfield(L, LUA_REGISTRYINDEX, f);
320 0 : return 1;
321 : }
322 :
323 :
324 0 : static int io_input (lua_State *L) {
325 0 : return g_iofile(L, IO_INPUT, "r");
326 : }
327 :
328 :
329 0 : static int io_output (lua_State *L) {
330 0 : return g_iofile(L, IO_OUTPUT, "w");
331 : }
332 :
333 :
334 : static int io_readline (lua_State *L);
335 :
336 :
337 : /*
338 : ** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit
339 : ** in the limit for upvalues of a closure)
340 : */
341 : #define MAXARGLINE 250
342 :
343 0 : static void aux_lines (lua_State *L, int toclose) {
344 0 : int n = lua_gettop(L) - 1; /* number of arguments to read */
345 0 : luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments");
346 0 : lua_pushinteger(L, n); /* number of arguments to read */
347 0 : lua_pushboolean(L, toclose); /* close/not close file when finished */
348 0 : lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */
349 0 : lua_pushcclosure(L, io_readline, 3 + n);
350 0 : }
351 :
352 :
353 0 : static int f_lines (lua_State *L) {
354 0 : tofile(L); /* check that it's a valid file handle */
355 0 : aux_lines(L, 0);
356 0 : return 1;
357 : }
358 :
359 :
360 0 : static int io_lines (lua_State *L) {
361 : int toclose;
362 0 : if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */
363 0 : if (lua_isnil(L, 1)) { /* no file name? */
364 0 : lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */
365 0 : lua_replace(L, 1); /* put it at index 1 */
366 0 : tofile(L); /* check that it's a valid file handle */
367 0 : toclose = 0; /* do not close it after iteration */
368 : }
369 : else { /* open a new file */
370 0 : const char *filename = luaL_checkstring(L, 1);
371 0 : opencheck(L, filename, "r");
372 0 : lua_replace(L, 1); /* put file at index 1 */
373 0 : toclose = 1; /* close it after iteration */
374 : }
375 0 : aux_lines(L, toclose);
376 0 : return 1;
377 : }
378 :
379 :
380 : /*
381 : ** {======================================================
382 : ** READ
383 : ** =======================================================
384 : */
385 :
386 :
387 : /* maximum length of a numeral */
388 : #if !defined (L_MAXLENNUM)
389 : #define L_MAXLENNUM 200
390 : #endif
391 :
392 :
393 : /* auxiliary structure used by 'read_number' */
394 : typedef struct {
395 : FILE *f; /* file being read */
396 : int c; /* current character (look ahead) */
397 : int n; /* number of elements in buffer 'buff' */
398 : char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */
399 : } RN;
400 :
401 :
402 : /*
403 : ** Add current char to buffer (if not out of space) and read next one
404 : */
405 0 : static int nextc (RN *rn) {
406 0 : if (rn->n >= L_MAXLENNUM) { /* buffer overflow? */
407 0 : rn->buff[0] = '\0'; /* invalidate result */
408 0 : return 0; /* fail */
409 : }
410 : else {
411 0 : rn->buff[rn->n++] = rn->c; /* save current char */
412 0 : rn->c = l_getc(rn->f); /* read next one */
413 0 : return 1;
414 : }
415 : }
416 :
417 :
418 : /*
419 : ** Accept current char if it is in 'set' (of size 2)
420 : */
421 0 : static int test2 (RN *rn, const char *set) {
422 0 : if (rn->c == set[0] || rn->c == set[1])
423 0 : return nextc(rn);
424 0 : else return 0;
425 : }
426 :
427 :
428 : /*
429 : ** Read a sequence of (hex)digits
430 : */
431 0 : static int readdigits (RN *rn, int hex) {
432 0 : int count = 0;
433 0 : while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn))
434 0 : count++;
435 0 : return count;
436 : }
437 :
438 :
439 : /*
440 : ** Read a number: first reads a valid prefix of a numeral into a buffer.
441 : ** Then it calls 'lua_stringtonumber' to check whether the format is
442 : ** correct and to convert it to a Lua number
443 : */
444 0 : static int read_number (lua_State *L, FILE *f) {
445 : RN rn;
446 0 : int count = 0;
447 0 : int hex = 0;
448 : char decp[2];
449 0 : rn.f = f; rn.n = 0;
450 0 : decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */
451 0 : decp[1] = '.'; /* always accept a dot */
452 : l_lockfile(rn.f);
453 0 : do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */
454 0 : test2(&rn, "-+"); /* optional signal */
455 0 : if (test2(&rn, "00")) {
456 0 : if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */
457 0 : else count = 1; /* count initial '0' as a valid digit */
458 : }
459 0 : count += readdigits(&rn, hex); /* integral part */
460 0 : if (test2(&rn, decp)) /* decimal point? */
461 0 : count += readdigits(&rn, hex); /* fractional part */
462 0 : if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */
463 0 : test2(&rn, "-+"); /* exponent signal */
464 0 : readdigits(&rn, 0); /* exponent digits */
465 : }
466 0 : ungetc(rn.c, rn.f); /* unread look-ahead char */
467 : l_unlockfile(rn.f);
468 0 : rn.buff[rn.n] = '\0'; /* finish string */
469 0 : if (lua_stringtonumber(L, rn.buff)) /* is this a valid number? */
470 0 : return 1; /* ok */
471 : else { /* invalid format */
472 0 : lua_pushnil(L); /* "result" to be removed */
473 0 : return 0; /* read fails */
474 : }
475 : }
476 :
477 :
478 0 : static int test_eof (lua_State *L, FILE *f) {
479 0 : int c = getc(f);
480 0 : ungetc(c, f); /* no-op when c == EOF */
481 0 : lua_pushliteral(L, "");
482 0 : return (c != EOF);
483 : }
484 :
485 :
486 102 : static int read_line (lua_State *L, FILE *f, int chop) {
487 : luaL_Buffer b;
488 102 : int c = '\0';
489 102 : luaL_buffinit(L, &b);
490 204 : while (c != EOF && c != '\n') { /* repeat until end of line */
491 102 : char *buff = luaL_prepbuffer(&b); /* preallocate buffer */
492 102 : int i = 0;
493 : l_lockfile(f); /* no memory errors can happen inside the lock */
494 3892 : while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n')
495 3790 : buff[i++] = c;
496 : l_unlockfile(f);
497 102 : luaL_addsize(&b, i);
498 : }
499 102 : if (!chop && c == '\n') /* want a newline and have one? */
500 0 : luaL_addchar(&b, c); /* add ending newline to result */
501 102 : luaL_pushresult(&b); /* close buffer */
502 : /* return ok if read something (either a newline or something else) */
503 102 : return (c == '\n' || lua_rawlen(L, -1) > 0);
504 : }
505 :
506 :
507 0 : static void read_all (lua_State *L, FILE *f) {
508 : size_t nr;
509 : luaL_Buffer b;
510 0 : luaL_buffinit(L, &b);
511 : do { /* read file in chunks of LUAL_BUFFERSIZE bytes */
512 0 : char *p = luaL_prepbuffer(&b);
513 0 : nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f);
514 0 : luaL_addsize(&b, nr);
515 0 : } while (nr == LUAL_BUFFERSIZE);
516 0 : luaL_pushresult(&b); /* close buffer */
517 0 : }
518 :
519 :
520 0 : static int read_chars (lua_State *L, FILE *f, size_t n) {
521 : size_t nr; /* number of chars actually read */
522 : char *p;
523 : luaL_Buffer b;
524 0 : luaL_buffinit(L, &b);
525 0 : p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */
526 0 : nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */
527 0 : luaL_addsize(&b, nr);
528 0 : luaL_pushresult(&b); /* close buffer */
529 0 : return (nr > 0); /* true iff read something */
530 : }
531 :
532 :
533 102 : static int g_read (lua_State *L, FILE *f, int first) {
534 102 : int nargs = lua_gettop(L) - 1;
535 : int success;
536 : int n;
537 102 : clearerr(f);
538 102 : if (nargs == 0) { /* no arguments? */
539 102 : success = read_line(L, f, 1);
540 102 : n = first+1; /* to return 1 result */
541 : }
542 : else { /* ensure stack space for all results and for auxlib's buffer */
543 0 : luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
544 0 : success = 1;
545 0 : for (n = first; nargs-- && success; n++) {
546 0 : if (lua_type(L, n) == LUA_TNUMBER) {
547 0 : size_t l = (size_t)luaL_checkinteger(L, n);
548 0 : success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
549 : }
550 : else {
551 0 : const char *p = luaL_checkstring(L, n);
552 0 : if (*p == '*') p++; /* skip optional '*' (for compatibility) */
553 0 : switch (*p) {
554 0 : case 'n': /* number */
555 0 : success = read_number(L, f);
556 0 : break;
557 0 : case 'l': /* line */
558 0 : success = read_line(L, f, 1);
559 0 : break;
560 0 : case 'L': /* line with end-of-line */
561 0 : success = read_line(L, f, 0);
562 0 : break;
563 0 : case 'a': /* file */
564 0 : read_all(L, f); /* read entire file */
565 0 : success = 1; /* always success */
566 0 : break;
567 0 : default:
568 0 : return luaL_argerror(L, n, "invalid format");
569 : }
570 : }
571 : }
572 : }
573 102 : if (ferror(f))
574 0 : return luaL_fileresult(L, 0, NULL);
575 102 : if (!success) {
576 1 : lua_pop(L, 1); /* remove last result */
577 1 : lua_pushnil(L); /* push nil instead */
578 : }
579 102 : return n - first;
580 : }
581 :
582 :
583 0 : static int io_read (lua_State *L) {
584 0 : return g_read(L, getiofile(L, IO_INPUT), 1);
585 : }
586 :
587 :
588 102 : static int lf_read (lua_State *L) {
589 102 : return g_read(L, tofile(L), 2);
590 : }
591 :
592 :
593 0 : static int io_readline (lua_State *L) {
594 0 : LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
595 : int i;
596 0 : int n = (int)lua_tointeger(L, lua_upvalueindex(2));
597 0 : if (isclosed(p)) /* file is already closed? */
598 0 : return luaL_error(L, "file is already closed");
599 0 : lua_settop(L , 1);
600 0 : luaL_checkstack(L, n, "too many arguments");
601 0 : for (i = 1; i <= n; i++) /* push arguments to 'g_read' */
602 0 : lua_pushvalue(L, lua_upvalueindex(3 + i));
603 0 : n = g_read(L, p->f, 2); /* 'n' is number of results */
604 : lua_assert(n > 0); /* should return at least a nil */
605 0 : if (lua_toboolean(L, -n)) /* read at least one value? */
606 0 : return n; /* return them */
607 : else { /* first result is nil: EOF or error */
608 0 : if (n > 1) { /* is there error information? */
609 : /* 2nd result is error message */
610 0 : return luaL_error(L, "%s", lua_tostring(L, -n + 1));
611 : }
612 0 : if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */
613 0 : lua_settop(L, 0);
614 0 : lua_pushvalue(L, lua_upvalueindex(1));
615 0 : aux_close(L); /* close it */
616 : }
617 0 : return 0;
618 : }
619 : }
620 :
621 : /* }====================================================== */
622 :
623 :
624 0 : static int g_write (lua_State *L, FILE *f, int arg) {
625 0 : int nargs = lua_gettop(L) - arg;
626 0 : int status = 1;
627 0 : for (; nargs--; arg++) {
628 0 : if (lua_type(L, arg) == LUA_TNUMBER) {
629 : /* optimization: could be done exactly as for strings */
630 0 : int len = lua_isinteger(L, arg)
631 0 : ? fprintf(f, LUA_INTEGER_FMT,
632 : (LUAI_UACINT)lua_tointeger(L, arg))
633 0 : : fprintf(f, LUA_NUMBER_FMT,
634 : (LUAI_UACNUMBER)lua_tonumber(L, arg));
635 0 : status = status && (len > 0);
636 : }
637 : else {
638 : size_t l;
639 0 : const char *s = luaL_checklstring(L, arg, &l);
640 0 : status = status && (fwrite(s, sizeof(char), l, f) == l);
641 : }
642 : }
643 0 : if (status) return 1; /* file handle already on stack top */
644 0 : else return luaL_fileresult(L, status, NULL);
645 : }
646 :
647 :
648 0 : static int io_write (lua_State *L) {
649 0 : return g_write(L, getiofile(L, IO_OUTPUT), 1);
650 : }
651 :
652 :
653 0 : static int lf_write (lua_State *L) {
654 0 : FILE *f = tofile(L);
655 0 : lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */
656 0 : return g_write(L, f, 2);
657 : }
658 :
659 :
660 0 : static int f_seek (lua_State *L) {
661 : static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
662 : static const char *const modenames[] = {"set", "cur", "end", NULL};
663 0 : FILE *f = tofile(L);
664 0 : int op = luaL_checkoption(L, 2, "cur", modenames);
665 0 : lua_Integer p3 = luaL_optinteger(L, 3, 0);
666 0 : l_seeknum offset = (l_seeknum)p3;
667 0 : luaL_argcheck(L, (lua_Integer)offset == p3, 3,
668 : "not an integer in proper range");
669 0 : op = l_fseek(f, offset, mode[op]);
670 0 : if (op)
671 0 : return luaL_fileresult(L, 0, NULL); /* error */
672 : else {
673 0 : lua_pushinteger(L, (lua_Integer)l_ftell(f));
674 0 : return 1;
675 : }
676 : }
677 :
678 :
679 : #if 0
680 : static int f_setvbuf (lua_State *L) {
681 : static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
682 : static const char *const modenames[] = {"no", "full", "line", NULL};
683 : FILE *f = tofile(L);
684 : int op = luaL_checkoption(L, 2, NULL, modenames);
685 : lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
686 : int res = setvbuf(f, NULL, mode[op], (size_t)sz);
687 : return luaL_fileresult(L, res == 0, NULL);
688 : }
689 : #endif
690 :
691 :
692 0 : static int io_flush (lua_State *L) {
693 0 : return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
694 : }
695 :
696 :
697 0 : static int f_flush (lua_State *L) {
698 0 : return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
699 : }
700 :
701 :
702 : /*
703 : ** functions for 'io' library
704 : */
705 : static const luaL_Reg iolib[] = {
706 : {"close", io_close},
707 : {"flush", io_flush},
708 : {"input", io_input},
709 : {"lines", io_lines},
710 : {"open", io_open},
711 : {"output", io_output},
712 : // {"popen", io_popen},
713 : {"read", io_read},
714 : // {"tmpfile", io_tmpfile},
715 : {"type", io_type},
716 : {"write", io_write},
717 : {NULL, NULL}
718 : };
719 :
720 :
721 : /*
722 : ** methods for file handles
723 : */
724 : static const luaL_Reg flib[] = {
725 : {"close", lf_close},
726 : {"flush", f_flush},
727 : {"lines", f_lines},
728 : {"read", lf_read},
729 : {"seek", f_seek},
730 : // {"setvbuf", f_setvbuf},
731 : {"write", lf_write},
732 : {"__gc", f_gc},
733 : {"__tostring", f_tostring},
734 : {NULL, NULL}
735 : };
736 :
737 :
738 92 : static void createmeta (lua_State *L) {
739 92 : luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */
740 92 : lua_pushvalue(L, -1); /* push metatable */
741 92 : lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */
742 92 : luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */
743 92 : lua_pop(L, 1); /* pop new metatable */
744 92 : }
745 :
746 :
747 : /*
748 : ** function to (not) close the standard files stdin, stdout, and stderr
749 : */
750 183 : static int io_noclose (lua_State *L) {
751 183 : LStream *p = tolstream(L);
752 183 : p->closef = &io_noclose; /* keep file opened */
753 183 : lua_pushnil(L);
754 183 : lua_pushliteral(L, "cannot close standard file");
755 183 : return 2;
756 : }
757 :
758 :
759 276 : static void createstdfile (lua_State *L, FILE *f, const char *k,
760 : const char *fname) {
761 276 : LStream *p = newprefile(L);
762 276 : p->f = f;
763 276 : p->closef = &io_noclose;
764 276 : if (k != NULL) {
765 184 : lua_pushvalue(L, -1);
766 184 : lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */
767 : }
768 276 : lua_setfield(L, -2, fname); /* add file to module */
769 276 : }
770 :
771 :
772 92 : LUAMOD_API int luaopen_io (lua_State *L) {
773 92 : luaL_newlib(L, iolib); /* new module */
774 92 : createmeta(L);
775 : /* create (and set) default files */
776 92 : createstdfile(L, stdin, IO_INPUT, "stdin");
777 92 : createstdfile(L, stdout, IO_OUTPUT, "stdout");
778 92 : createstdfile(L, stderr, NULL, "stderr");
779 92 : return 1;
780 : }
781 :
|