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
|
"use strict";
const assert = require('assert');
const fs = require('fs');
const lua = require('./lua.js');
const lauxlib = require('./lauxlib.js');
const IO_PREFIX = "_IO_";
const IOPREF_LEN = IO_PREFIX.length;
const IO_INPUT = lua.to_luastring(IO_PREFIX + "input");
const IO_OUTPUT = lua.to_luastring(IO_PREFIX + "output");
const tolstream = function(L) {
return lauxlib.luaL_checkudata(L, 1, lauxlib.LUA_FILEHANDLE);
};
const isclosed = function(p) {
return p.closef === null;
};
const f_tostring = function(L) {
let p = tolstream(L);
if (isclosed(p))
lua.lua_pushliteral(L, "file (closed)");
else
lua.lua_pushstring(L, lua.to_luastring(`file (${p.f.toString()})`));
return 1;
};
const tofile = function(L) {
let p = tolstream(L);
if (isclosed(p))
lauxlib.luaL_error(L, "attempt to use a closed file");
assert(p.f);
return p.f;
};
const newprefile = function(L) {
let p = lua.lua_newuserdata(L);
p.f = null;
p.closef = null;
lauxlib.luaL_setmetatable(L, lauxlib.LUA_FILEHANDLE);
return p;
};
const getiofile = function(L, findex) {
lua.lua_getfield(L, lua.LUA_REGISTRYINDEX, findex);
let p = lua.lua_touserdata(L, -1);
if (isclosed(p))
lauxlib.luaL_error(L, lua.to_luastring(`standard ${lua.to_jsstring(findex.slice(IOPREF_LEN))} file is closed`));
return p.f;
};
const g_write = function(L, f, arg) {
let nargs = lua.lua_gettop(L) - arg;
let status = true;
let err;
for (; nargs--; arg++) {
let s = lauxlib.luaL_checklstring(L, arg);
try {
status = status && (fs.writeSync(f.fd, Uint8Array.from(s)) === s.length);
} catch (e) {
status = false;
err = e;
}
}
if (status) return 1; /* file handle already on stack top */
else return lauxlib.luaL_fileresult(L, status, null, err);
};
const io_write = function(L) {
return g_write(L, getiofile(L, IO_OUTPUT), 1);
};
const f_write = function(L) {
let f = tofile(L);
lua.lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */
return g_write(L, f, 2);
};
const iolib = {
"write": io_write
};
const flib = {
"write": f_write,
"__tostring": f_tostring
};
const createmeta = function(L) {
lauxlib.luaL_newmetatable(L, lauxlib.LUA_FILEHANDLE); /* create metatable for file handles */
lua.lua_pushvalue(L, -1); /* push metatable */
lua.lua_setfield(L, -2, lua.to_luastring("__index", true)); /* metatable.__index = metatable */
lauxlib.luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */
lua.lua_pop(L, 1); /* pop new metatable */
};
const io_noclose = function(L) {
let p = tolstream(L);
p.closef = io_noclose;
lua.lua_pushnil(L);
lua.lua_pushliteral(L, "cannot close standard file");
return 2;
};
const createstdfile = function(L, f, k, fname) {
let p = newprefile(L);
p.f = f;
p.closef = io_noclose;
if (k !== null) {
lua.lua_pushvalue(L, -1);
lua.lua_setfield(L, lua.LUA_REGISTRYINDEX, k); /* add file to registry */
}
lua.lua_setfield(L, -2, fname); /* add file to module */
};
const luaopen_io = function(L) {
lauxlib.luaL_newlib(L, iolib);
createmeta(L);
/* create (and set) default files */
createstdfile(L, process.stdin, IO_INPUT, lua.to_luastring("stdin"));
createstdfile(L, process.stdout, IO_OUTPUT, lua.to_luastring("stdout"));
createstdfile(L, process.stderr, null, lua.to_luastring("stderr"));
return 1;
};
module.exports.luaopen_io = luaopen_io;
|