~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/lua/src/liolib.c

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
** $Id: liolib.c,v 2.111 2013/03/21 13:57:27 roberto Exp $
 
3
** Standard I/O (and system) library
 
4
** See Copyright Notice in lua.h
 
5
*/
 
6
 
 
7
 
 
8
/*
 
9
** POSIX idiosyncrasy!
 
10
** This definition must come before the inclusion of 'stdio.h'; it
 
11
** should not affect non-POSIX systems
 
12
*/
 
13
#if !defined(_FILE_OFFSET_BITS)
 
14
#define _FILE_OFFSET_BITS 64
 
15
#endif
 
16
 
 
17
 
 
18
#include <errno.h>
 
19
#include <stdio.h>
 
20
#include <stdlib.h>
 
21
#include <string.h>
 
22
 
 
23
#define liolib_c
 
24
#define LUA_LIB
 
25
 
 
26
#include "lua.h"
 
27
 
 
28
#include "lauxlib.h"
 
29
#include "lualib.h"
 
30
 
 
31
 
 
32
#if !defined(lua_checkmode)
 
33
 
 
34
/*
 
35
** Check whether 'mode' matches '[rwa]%+?b?'.
 
36
** Change this macro to accept other modes for 'fopen' besides
 
37
** the standard ones.
 
38
*/
 
39
#define lua_checkmode(mode) \
 
40
        (*mode != '\0' && strchr("rwa", *(mode++)) != NULL &&   \
 
41
        (*mode != '+' || ++mode) &&  /* skip if char is '+' */  \
 
42
        (*mode != 'b' || ++mode) &&  /* skip if char is 'b' */  \
 
43
        (*mode == '\0'))
 
44
 
 
45
#endif
 
46
 
 
47
/*
 
48
** {======================================================
 
49
** lua_popen spawns a new process connected to the current
 
50
** one through the file streams.
 
51
** =======================================================
 
52
*/
 
53
 
 
54
#if !defined(lua_popen) /* { */
 
55
 
 
56
#if defined(LUA_USE_POPEN)      /* { */
 
57
 
 
58
#define lua_popen(L,c,m)        ((void)L, fflush(NULL), popen(c,m))
 
59
#define lua_pclose(L,file)      ((void)L, pclose(file))
 
60
 
 
61
#elif defined(LUA_WIN)          /* }{ */
 
62
 
 
63
#define lua_popen(L,c,m)                ((void)L, _popen(c,m))
 
64
#define lua_pclose(L,file)              ((void)L, _pclose(file))
 
65
 
 
66
 
 
67
#else                           /* }{ */
 
68
 
 
69
#define lua_popen(L,c,m)                ((void)((void)c, m),  \
 
70
                luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0)
 
71
#define lua_pclose(L,file)              ((void)((void)L, file), -1)
 
72
 
 
73
 
 
74
#endif                          /* } */
 
75
 
 
76
#endif                  /* } */
 
77
 
 
78
/* }====================================================== */
 
79
 
 
80
 
 
81
/*
 
82
** {======================================================
 
83
** lua_fseek/lua_ftell: configuration for longer offsets
 
84
** =======================================================
 
85
*/
 
86
 
 
87
#if !defined(lua_fseek) /* { */
 
88
 
 
89
#if defined(LUA_USE_POSIX)
 
90
 
 
91
#define l_fseek(f,o,w)          fseeko(f,o,w)
 
92
#define l_ftell(f)              ftello(f)
 
93
#define l_seeknum               off_t
 
94
 
 
95
#elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \
 
96
   && defined(_MSC_VER) && (_MSC_VER >= 1400)
 
97
/* Windows (but not DDK) and Visual C++ 2005 or higher */
 
98
 
 
99
#define l_fseek(f,o,w)          _fseeki64(f,o,w)
 
100
#define l_ftell(f)              _ftelli64(f)
 
101
#define l_seeknum               __int64
 
102
 
 
103
#else
 
104
 
 
105
#define l_fseek(f,o,w)          fseek(f,o,w)
 
106
#define l_ftell(f)              ftell(f)
 
107
#define l_seeknum               long
 
108
 
 
109
#endif
 
110
 
 
111
#endif                  /* } */
 
112
 
 
113
/* }====================================================== */
 
114
 
 
115
 
 
116
#define IO_PREFIX       "_IO_"
 
117
#define IO_INPUT        (IO_PREFIX "input")
 
118
#define IO_OUTPUT       (IO_PREFIX "output")
 
119
 
 
120
 
 
121
typedef luaL_Stream LStream;
 
122
 
 
123
 
 
124
#define tolstream(L)    ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
 
125
 
 
126
#define isclosed(p)     ((p)->closef == NULL)
 
127
 
 
128
 
 
129
static int io_type (lua_State *L) {
 
130
  LStream *p;
 
131
  luaL_checkany(L, 1);
 
132
  p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE);
 
133
  if (p == NULL)
 
134
    lua_pushnil(L);  /* not a file */
 
135
  else if (isclosed(p))
 
136
    lua_pushliteral(L, "closed file");
 
137
  else
 
138
    lua_pushliteral(L, "file");
 
139
  return 1;
 
140
}
 
141
 
 
142
 
 
143
static int f_tostring (lua_State *L) {
 
144
  LStream *p = tolstream(L);
 
145
  if (isclosed(p))
 
146
    lua_pushliteral(L, "file (closed)");
 
147
  else
 
148
    lua_pushfstring(L, "file (%p)", p->f);
 
149
  return 1;
 
150
}
 
151
 
 
152
 
 
153
static FILE *tofile (lua_State *L) {
 
154
  LStream *p = tolstream(L);
 
155
  if (isclosed(p))
 
156
    luaL_error(L, "attempt to use a closed file");
 
157
  lua_assert(p->f);
 
158
  return p->f;
 
159
}
 
160
 
 
161
 
 
162
/*
 
163
** When creating file handles, always creates a `closed' file handle
 
164
** before opening the actual file; so, if there is a memory error, the
 
165
** file is not left opened.
 
166
*/
 
167
static LStream *newprefile (lua_State *L) {
 
168
  LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream));
 
169
  p->closef = NULL;  /* mark file handle as 'closed' */
 
170
  luaL_setmetatable(L, LUA_FILEHANDLE);
 
171
  return p;
 
172
}
 
173
 
 
174
 
 
175
static int aux_close (lua_State *L) {
 
176
  LStream *p = tolstream(L);
 
177
  lua_CFunction cf = p->closef;
 
178
  p->closef = NULL;  /* mark stream as closed */
 
179
  return (*cf)(L);  /* close it */
 
180
}
 
181
 
 
182
 
 
183
static int io_close (lua_State *L) {
 
184
  if (lua_isnone(L, 1))  /* no argument? */
 
185
    lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT);  /* use standard output */
 
186
  tofile(L);  /* make sure argument is an open stream */
 
187
  return aux_close(L);
 
188
}
 
189
 
 
190
 
 
191
static int f_gc (lua_State *L) {
 
192
  LStream *p = tolstream(L);
 
193
  if (!isclosed(p) && p->f != NULL)
 
194
    aux_close(L);  /* ignore closed and incompletely open files */
 
195
  return 0;
 
196
}
 
197
 
 
198
 
 
199
/*
 
200
** function to close regular files
 
201
*/
 
202
static int io_fclose (lua_State *L) {
 
203
  LStream *p = tolstream(L);
 
204
  int res = fclose(p->f);
 
205
  return luaL_fileresult(L, (res == 0), NULL);
 
206
}
 
207
 
 
208
 
 
209
static LStream *newfile (lua_State *L) {
 
210
  LStream *p = newprefile(L);
 
211
  p->f = NULL;
 
212
  p->closef = &io_fclose;
 
213
  return p;
 
214
}
 
215
 
 
216
 
 
217
static void opencheck (lua_State *L, const char *fname, const char *mode) {
 
218
  LStream *p = newfile(L);
 
219
  p->f = fopen(fname, mode);
 
220
  if (p->f == NULL)
 
221
    luaL_error(L, "cannot open file " LUA_QS " (%s)", fname, strerror(errno));
 
222
}
 
223
 
 
224
 
 
225
static int io_open (lua_State *L) {
 
226
  const char *filename = luaL_checkstring(L, 1);
 
227
  const char *mode = luaL_optstring(L, 2, "r");
 
228
  LStream *p = newfile(L);
 
229
  const char *md = mode;  /* to traverse/check mode */
 
230
  luaL_argcheck(L, lua_checkmode(md), 2, "invalid mode");
 
231
  p->f = fopen(filename, mode);
 
232
  return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
 
233
}
 
234
 
 
235
 
 
236
/*
 
237
** function to close 'popen' files
 
238
*/
 
239
static int io_pclose (lua_State *L) {
 
240
  LStream *p = tolstream(L);
 
241
  return luaL_execresult(L, lua_pclose(L, p->f));
 
242
}
 
243
 
 
244
 
 
245
static int io_popen (lua_State *L) {
 
246
  const char *filename = luaL_checkstring(L, 1);
 
247
  const char *mode = luaL_optstring(L, 2, "r");
 
248
  LStream *p = newprefile(L);
 
249
  p->f = lua_popen(L, filename, mode);
 
250
  p->closef = &io_pclose;
 
251
  return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1;
 
252
}
 
253
 
 
254
 
 
255
static int io_tmpfile (lua_State *L) {
 
256
  LStream *p = newfile(L);
 
257
  p->f = tmpfile();
 
258
  return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1;
 
259
}
 
260
 
 
261
 
 
262
static FILE *getiofile (lua_State *L, const char *findex) {
 
263
  LStream *p;
 
264
  lua_getfield(L, LUA_REGISTRYINDEX, findex);
 
265
  p = (LStream *)lua_touserdata(L, -1);
 
266
  if (isclosed(p))
 
267
    luaL_error(L, "standard %s file is closed", findex + strlen(IO_PREFIX));
 
268
  return p->f;
 
269
}
 
270
 
 
271
 
 
272
static int g_iofile (lua_State *L, const char *f, const char *mode) {
 
273
  if (!lua_isnoneornil(L, 1)) {
 
274
    const char *filename = lua_tostring(L, 1);
 
275
    if (filename)
 
276
      opencheck(L, filename, mode);
 
277
    else {
 
278
      tofile(L);  /* check that it's a valid file handle */
 
279
      lua_pushvalue(L, 1);
 
280
    }
 
281
    lua_setfield(L, LUA_REGISTRYINDEX, f);
 
282
  }
 
283
  /* return current value */
 
284
  lua_getfield(L, LUA_REGISTRYINDEX, f);
 
285
  return 1;
 
286
}
 
287
 
 
288
 
 
289
static int io_input (lua_State *L) {
 
290
  return g_iofile(L, IO_INPUT, "r");
 
291
}
 
292
 
 
293
 
 
294
static int io_output (lua_State *L) {
 
295
  return g_iofile(L, IO_OUTPUT, "w");
 
296
}
 
297
 
 
298
 
 
299
static int io_readline (lua_State *L);
 
300
 
 
301
 
 
302
static void aux_lines (lua_State *L, int toclose) {
 
303
  int i;
 
304
  int n = lua_gettop(L) - 1;  /* number of arguments to read */
 
305
  /* ensure that arguments will fit here and into 'io_readline' stack */
 
306
  luaL_argcheck(L, n <= LUA_MINSTACK - 3, LUA_MINSTACK - 3, "too many options");
 
307
  lua_pushvalue(L, 1);  /* file handle */
 
308
  lua_pushinteger(L, n);  /* number of arguments to read */
 
309
  lua_pushboolean(L, toclose);  /* close/not close file when finished */
 
310
  for (i = 1; i <= n; i++) lua_pushvalue(L, i + 1);  /* copy arguments */
 
311
  lua_pushcclosure(L, io_readline, 3 + n);
 
312
}
 
313
 
 
314
 
 
315
static int f_lines (lua_State *L) {
 
316
  tofile(L);  /* check that it's a valid file handle */
 
317
  aux_lines(L, 0);
 
318
  return 1;
 
319
}
 
320
 
 
321
 
 
322
static int io_lines (lua_State *L) {
 
323
  int toclose;
 
324
  if (lua_isnone(L, 1)) lua_pushnil(L);  /* at least one argument */
 
325
  if (lua_isnil(L, 1)) {  /* no file name? */
 
326
    lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT);  /* get default input */
 
327
    lua_replace(L, 1);  /* put it at index 1 */
 
328
    tofile(L);  /* check that it's a valid file handle */
 
329
    toclose = 0;  /* do not close it after iteration */
 
330
  }
 
331
  else {  /* open a new file */
 
332
    const char *filename = luaL_checkstring(L, 1);
 
333
    opencheck(L, filename, "r");
 
334
    lua_replace(L, 1);  /* put file at index 1 */
 
335
    toclose = 1;  /* close it after iteration */
 
336
  }
 
337
  aux_lines(L, toclose);
 
338
  return 1;
 
339
}
 
340
 
 
341
 
 
342
/*
 
343
** {======================================================
 
344
** READ
 
345
** =======================================================
 
346
*/
 
347
 
 
348
 
 
349
static int read_number (lua_State *L, FILE *f) {
 
350
  lua_Number d;
 
351
  if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
 
352
    lua_pushnumber(L, d);
 
353
    return 1;
 
354
  }
 
355
  else {
 
356
   lua_pushnil(L);  /* "result" to be removed */
 
357
   return 0;  /* read fails */
 
358
  }
 
359
}
 
360
 
 
361
 
 
362
static int test_eof (lua_State *L, FILE *f) {
 
363
  int c = getc(f);
 
364
  ungetc(c, f);
 
365
  lua_pushlstring(L, NULL, 0);
 
366
  return (c != EOF);
 
367
}
 
368
 
 
369
 
 
370
static int read_line (lua_State *L, FILE *f, int chop) {
 
371
  luaL_Buffer b;
 
372
  luaL_buffinit(L, &b);
 
373
  for (;;) {
 
374
    size_t l;
 
375
    char *p = luaL_prepbuffer(&b);
 
376
    if (fgets(p, LUAL_BUFFERSIZE, f) == NULL) {  /* eof? */
 
377
      luaL_pushresult(&b);  /* close buffer */
 
378
      return (lua_rawlen(L, -1) > 0);  /* check whether read something */
 
379
    }
 
380
    l = strlen(p);
 
381
    if (l == 0 || p[l-1] != '\n')
 
382
      luaL_addsize(&b, l);
 
383
    else {
 
384
      luaL_addsize(&b, l - chop);  /* chop 'eol' if needed */
 
385
      luaL_pushresult(&b);  /* close buffer */
 
386
      return 1;  /* read at least an `eol' */
 
387
    }
 
388
  }
 
389
}
 
390
 
 
391
 
 
392
#define MAX_SIZE_T      (~(size_t)0)
 
393
 
 
394
static void read_all (lua_State *L, FILE *f) {
 
395
  size_t rlen = LUAL_BUFFERSIZE;  /* how much to read in each cycle */
 
396
  luaL_Buffer b;
 
397
  luaL_buffinit(L, &b);
 
398
  for (;;) {
 
399
    char *p = luaL_prepbuffsize(&b, rlen);
 
400
    size_t nr = fread(p, sizeof(char), rlen, f);
 
401
    luaL_addsize(&b, nr);
 
402
    if (nr < rlen) break;  /* eof? */
 
403
    else if (rlen <= (MAX_SIZE_T / 4))  /* avoid buffers too large */
 
404
      rlen *= 2;  /* double buffer size at each iteration */
 
405
  }
 
406
  luaL_pushresult(&b);  /* close buffer */
 
407
}
 
408
 
 
409
 
 
410
static int read_chars (lua_State *L, FILE *f, size_t n) {
 
411
  size_t nr;  /* number of chars actually read */
 
412
  char *p;
 
413
  luaL_Buffer b;
 
414
  luaL_buffinit(L, &b);
 
415
  p = luaL_prepbuffsize(&b, n);  /* prepare buffer to read whole block */
 
416
  nr = fread(p, sizeof(char), n, f);  /* try to read 'n' chars */
 
417
  luaL_addsize(&b, nr);
 
418
  luaL_pushresult(&b);  /* close buffer */
 
419
  return (nr > 0);  /* true iff read something */
 
420
}
 
421
 
 
422
 
 
423
static int g_read (lua_State *L, FILE *f, int first) {
 
424
  int nargs = lua_gettop(L) - 1;
 
425
  int success;
 
426
  int n;
 
427
  clearerr(f);
 
428
  if (nargs == 0) {  /* no arguments? */
 
429
    success = read_line(L, f, 1);
 
430
    n = first+1;  /* to return 1 result */
 
431
  }
 
432
  else {  /* ensure stack space for all results and for auxlib's buffer */
 
433
    luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments");
 
434
    success = 1;
 
435
    for (n = first; nargs-- && success; n++) {
 
436
      if (lua_type(L, n) == LUA_TNUMBER) {
 
437
        size_t l = (size_t)lua_tointeger(L, n);
 
438
        success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l);
 
439
      }
 
440
      else {
 
441
        const char *p = lua_tostring(L, n);
 
442
        luaL_argcheck(L, p && p[0] == '*', n, "invalid option");
 
443
        switch (p[1]) {
 
444
          case 'n':  /* number */
 
445
            success = read_number(L, f);
 
446
            break;
 
447
          case 'l':  /* line */
 
448
            success = read_line(L, f, 1);
 
449
            break;
 
450
          case 'L':  /* line with end-of-line */
 
451
            success = read_line(L, f, 0);
 
452
            break;
 
453
          case 'a':  /* file */
 
454
            read_all(L, f);  /* read entire file */
 
455
            success = 1; /* always success */
 
456
            break;
 
457
          default:
 
458
            return luaL_argerror(L, n, "invalid format");
 
459
        }
 
460
      }
 
461
    }
 
462
  }
 
463
  if (ferror(f))
 
464
    return luaL_fileresult(L, 0, NULL);
 
465
  if (!success) {
 
466
    lua_pop(L, 1);  /* remove last result */
 
467
    lua_pushnil(L);  /* push nil instead */
 
468
  }
 
469
  return n - first;
 
470
}
 
471
 
 
472
 
 
473
static int io_read (lua_State *L) {
 
474
  return g_read(L, getiofile(L, IO_INPUT), 1);
 
475
}
 
476
 
 
477
 
 
478
static int f_read (lua_State *L) {
 
479
  return g_read(L, tofile(L), 2);
 
480
}
 
481
 
 
482
 
 
483
static int io_readline (lua_State *L) {
 
484
  LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1));
 
485
  int i;
 
486
  int n = (int)lua_tointeger(L, lua_upvalueindex(2));
 
487
  if (isclosed(p))  /* file is already closed? */
 
488
    return luaL_error(L, "file is already closed");
 
489
  lua_settop(L , 1);
 
490
  for (i = 1; i <= n; i++)  /* push arguments to 'g_read' */
 
491
    lua_pushvalue(L, lua_upvalueindex(3 + i));
 
492
  n = g_read(L, p->f, 2);  /* 'n' is number of results */
 
493
  lua_assert(n > 0);  /* should return at least a nil */
 
494
  if (!lua_isnil(L, -n))  /* read at least one value? */
 
495
    return n;  /* return them */
 
496
  else {  /* first result is nil: EOF or error */
 
497
    if (n > 1) {  /* is there error information? */
 
498
      /* 2nd result is error message */
 
499
      return luaL_error(L, "%s", lua_tostring(L, -n + 1));
 
500
    }
 
501
    if (lua_toboolean(L, lua_upvalueindex(3))) {  /* generator created file? */
 
502
      lua_settop(L, 0);
 
503
      lua_pushvalue(L, lua_upvalueindex(1));
 
504
      aux_close(L);  /* close it */
 
505
    }
 
506
    return 0;
 
507
  }
 
508
}
 
509
 
 
510
/* }====================================================== */
 
511
 
 
512
 
 
513
static int g_write (lua_State *L, FILE *f, int arg) {
 
514
  int nargs = lua_gettop(L) - arg;
 
515
  int status = 1;
 
516
  for (; nargs--; arg++) {
 
517
    if (lua_type(L, arg) == LUA_TNUMBER) {
 
518
      /* optimization: could be done exactly as for strings */
 
519
      status = status &&
 
520
          fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
 
521
    }
 
522
    else {
 
523
      size_t l;
 
524
      const char *s = luaL_checklstring(L, arg, &l);
 
525
      status = status && (fwrite(s, sizeof(char), l, f) == l);
 
526
    }
 
527
  }
 
528
  if (status) return 1;  /* file handle already on stack top */
 
529
  else return luaL_fileresult(L, status, NULL);
 
530
}
 
531
 
 
532
 
 
533
static int io_write (lua_State *L) {
 
534
  return g_write(L, getiofile(L, IO_OUTPUT), 1);
 
535
}
 
536
 
 
537
 
 
538
static int f_write (lua_State *L) {
 
539
  FILE *f = tofile(L);
 
540
  lua_pushvalue(L, 1);  /* push file at the stack top (to be returned) */
 
541
  return g_write(L, f, 2);
 
542
}
 
543
 
 
544
 
 
545
static int f_seek (lua_State *L) {
 
546
  static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END};
 
547
  static const char *const modenames[] = {"set", "cur", "end", NULL};
 
548
  FILE *f = tofile(L);
 
549
  int op = luaL_checkoption(L, 2, "cur", modenames);
 
550
  lua_Number p3 = luaL_optnumber(L, 3, 0);
 
551
  l_seeknum offset = (l_seeknum)p3;
 
552
  luaL_argcheck(L, (lua_Number)offset == p3, 3,
 
553
                  "not an integer in proper range");
 
554
  op = l_fseek(f, offset, mode[op]);
 
555
  if (op)
 
556
    return luaL_fileresult(L, 0, NULL);  /* error */
 
557
  else {
 
558
    lua_pushnumber(L, (lua_Number)l_ftell(f));
 
559
    return 1;
 
560
  }
 
561
}
 
562
 
 
563
 
 
564
static int f_setvbuf (lua_State *L) {
 
565
  static const int mode[] = {_IONBF, _IOFBF, _IOLBF};
 
566
  static const char *const modenames[] = {"no", "full", "line", NULL};
 
567
  FILE *f = tofile(L);
 
568
  int op = luaL_checkoption(L, 2, NULL, modenames);
 
569
  lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
 
570
  int res = setvbuf(f, NULL, mode[op], sz);
 
571
  return luaL_fileresult(L, res == 0, NULL);
 
572
}
 
573
 
 
574
 
 
575
 
 
576
static int io_flush (lua_State *L) {
 
577
  return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL);
 
578
}
 
579
 
 
580
 
 
581
static int f_flush (lua_State *L) {
 
582
  return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL);
 
583
}
 
584
 
 
585
 
 
586
/*
 
587
** functions for 'io' library
 
588
*/
 
589
static const luaL_Reg iolib[] = {
 
590
  {"close", io_close},
 
591
  {"flush", io_flush},
 
592
  {"input", io_input},
 
593
  {"lines", io_lines},
 
594
  {"open", io_open},
 
595
  {"output", io_output},
 
596
  {"popen", io_popen},
 
597
  {"read", io_read},
 
598
  {"tmpfile", io_tmpfile},
 
599
  {"type", io_type},
 
600
  {"write", io_write},
 
601
  {NULL, NULL}
 
602
};
 
603
 
 
604
 
 
605
/*
 
606
** methods for file handles
 
607
*/
 
608
static const luaL_Reg flib[] = {
 
609
  {"close", io_close},
 
610
  {"flush", f_flush},
 
611
  {"lines", f_lines},
 
612
  {"read", f_read},
 
613
  {"seek", f_seek},
 
614
  {"setvbuf", f_setvbuf},
 
615
  {"write", f_write},
 
616
  {"__gc", f_gc},
 
617
  {"__tostring", f_tostring},
 
618
  {NULL, NULL}
 
619
};
 
620
 
 
621
 
 
622
static void createmeta (lua_State *L) {
 
623
  luaL_newmetatable(L, LUA_FILEHANDLE);  /* create metatable for file handles */
 
624
  lua_pushvalue(L, -1);  /* push metatable */
 
625
  lua_setfield(L, -2, "__index");  /* metatable.__index = metatable */
 
626
  luaL_setfuncs(L, flib, 0);  /* add file methods to new metatable */
 
627
  lua_pop(L, 1);  /* pop new metatable */
 
628
}
 
629
 
 
630
 
 
631
/*
 
632
** function to (not) close the standard files stdin, stdout, and stderr
 
633
*/
 
634
static int io_noclose (lua_State *L) {
 
635
  LStream *p = tolstream(L);
 
636
  p->closef = &io_noclose;  /* keep file opened */
 
637
  lua_pushnil(L);
 
638
  lua_pushliteral(L, "cannot close standard file");
 
639
  return 2;
 
640
}
 
641
 
 
642
 
 
643
static void createstdfile (lua_State *L, FILE *f, const char *k,
 
644
                           const char *fname) {
 
645
  LStream *p = newprefile(L);
 
646
  p->f = f;
 
647
  p->closef = &io_noclose;
 
648
  if (k != NULL) {
 
649
    lua_pushvalue(L, -1);
 
650
    lua_setfield(L, LUA_REGISTRYINDEX, k);  /* add file to registry */
 
651
  }
 
652
  lua_setfield(L, -2, fname);  /* add file to module */
 
653
}
 
654
 
 
655
 
 
656
LUAMOD_API int luaopen_io (lua_State *L) {
 
657
  luaL_newlib(L, iolib);  /* new module */
 
658
  createmeta(L);
 
659
  /* create (and set) default files */
 
660
  createstdfile(L, stdin, IO_INPUT, "stdin");
 
661
  createstdfile(L, stdout, IO_OUTPUT, "stdout");
 
662
  createstdfile(L, stderr, NULL, "stderr");
 
663
  return 1;
 
664
}
 
665