lmtiolibext.c /size: 44 Kb    last modification: 2024-01-16 10:22
1/*
2    See license.txt in the root of this project.
3*/
4
5/*tex
6
7    Lua doesn't have cardinals so basically we could stick to integers and accept that we have a
8    limited range.
9
10*/
11
12# include "luametatex.h"
13
14# ifdef _WIN32
15
16    # define lua_popen(L,c,m)   ((void)L, _popen(c,m))
17    # define lua_pclose(L,file) ((void)L, _pclose(file))
18
19# else
20
21    # define lua_popen(L,c,m)   ((void)L, fflush(NULL), popen(c,m))
22    # define lua_pclose(L,file) ((void)L, pclose(file))
23
24# endif
25
26/* Mojca: we need to sort this out! */
27
28# ifdef LUA_USE_POSIX
29
30    # define l_fseek(f,o,w) fseeko(f,o,w)
31    # define l_ftell(f)     ftello(f)
32    # define l_seeknum      off_t
33
34# elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) && defined(_MSC_VER) && (_MSC_VER >= 1400)
35
36    # define l_fseek(f,o,w) _fseeki64(f,o,w)
37    # define l_ftell(f)     _ftelli64(f)
38    # define l_seeknum      __int64
39
40# elif defined(__MINGW32__)
41
42    # define l_fseek(f,o,w) fseeko64(f,o,w)
43    # define l_ftell(f)     ftello64(f)
44    # define l_seeknum      int64_t
45
46# else
47
48    # define l_fseek(f,o,w) fseek(f,o,w)
49    # define l_ftell(f)     ftell(f)
50    # define l_seeknum      long
51
52# endif
53
54# define uchar(c) ((unsigned char)(c))
55
56/*tex
57
58    A few helpers to avoid reading numbers as strings. For now we put them in their own namespace.
59    We also have a few helpers that can make \IO\ functions \TEX\ friendly.
60
61*/
62
63static int fiolib_readcardinal1(lua_State *L) {
64    FILE *f = lmt_valid_file(L);
65    if (f) {
66        lua_Integer a = getc(f);
67        if (a == EOF) {
68            lua_pushnil(L);
69        } else {
70            lua_pushinteger(L, a);
71        }
72        return 1;
73    } else {
74        return 0;
75    }
76}
77
78static int siolib_readcardinal1(lua_State *L) {
79    size_t ls = 0;
80    const char *s = luaL_checklstring(L, 1, &ls);
81    lua_Integer p =  luaL_checkinteger(L, 2) - 1;
82    lua_Integer l = (lua_Integer) ls;
83    if (p >= l) {
84        lua_pushnil(L);
85    } else {
86        lua_Integer a = uchar(s[p]);
87        lua_pushinteger(L, a);
88    }
89    return 1;
90}
91
92static int fiolib_readcardinal2(lua_State *L) {
93    FILE *f = lmt_valid_file(L);
94    if (f) {
95        lua_Integer a = getc(f);
96        lua_Integer b = getc(f);
97        if (b == EOF) {
98            lua_pushnil(L);
99        } else {
100            /* (a<<8) | b */
101            lua_pushinteger(L, 0x100 * a + b);
102        }
103        return 1;
104    } else {
105        return 0;
106    }
107}
108
109static int fiolib_readcardinal2_le(lua_State *L) {
110    FILE *f = lmt_valid_file(L);
111    if (f) {
112        lua_Integer b = getc(f);
113        lua_Integer a = getc(f);
114        if (a == EOF) {
115            lua_pushnil(L);
116        } else {
117            /* (a<<8) | b */
118            lua_pushinteger(L, 0x100 * a + b);
119        }
120        return 1;
121    } else {
122        return 0;
123    }
124}
125
126static int siolib_readcardinal2(lua_State *L) {
127    size_t ls = 0;
128    const char *s = luaL_checklstring(L, 1, &ls);
129    lua_Integer p = luaL_checkinteger(L, 2) - 1;
130    lua_Integer l = (lua_Integer) ls;
131    if ((p + 1) >= l) {
132        lua_pushnil(L);
133    } else {
134        lua_Integer a = uchar(s[p++]);
135        lua_Integer b = uchar(s[p]);
136        lua_pushinteger(L, 0x100 * a + b);
137    }
138    return 1;
139}
140
141static int siolib_readcardinal2_le(lua_State *L) {
142    size_t ls = 0;
143    const char *s = luaL_checklstring(L, 1, &ls);
144    lua_Integer p = luaL_checkinteger(L, 2) - 1;
145    lua_Integer l = (lua_Integer) ls;
146    if ((p + 1) >= l) {
147        lua_pushnil(L);
148    } else {
149        lua_Integer b = uchar(s[p++]);
150        lua_Integer a = uchar(s[p]);
151        lua_pushinteger(L, 0x100 * a + b);
152    }
153    return 1;
154}
155
156static int fiolib_readcardinal3(lua_State *L) {
157    FILE *f = lmt_valid_file(L);
158    if (f) {
159        lua_Integer a = getc(f);
160        lua_Integer b = getc(f);
161        lua_Integer c = getc(f);
162        if (c == EOF) {
163            lua_pushnil(L);
164        } else {
165            /* (a<<16) | (b<<8) | c */
166            lua_pushinteger(L, 0x10000 * a + 0x100 * b + c);
167        }
168        return 1;
169    } else {
170        return 0;
171    }
172}
173
174static int fiolib_readcardinal3_le(lua_State *L) {
175    FILE *f = lmt_valid_file(L);
176    if (f) {
177        lua_Integer c = getc(f);
178        lua_Integer b = getc(f);
179        lua_Integer a = getc(f);
180        if (a == EOF) {
181            lua_pushnil(L);
182        } else {
183            /* (a<<16) | (b<<8) | c */
184            lua_pushinteger(L, 0x10000 * a + 0x100 * b + c);
185        }
186        return 1;
187    } else {
188        return 0;
189    }
190}
191
192static int siolib_readcardinal3(lua_State *L) {
193    size_t ls = 0;
194    const char *s = luaL_checklstring(L, 1, &ls);
195    lua_Integer p = luaL_checkinteger(L, 2) - 1;
196    lua_Integer l = (lua_Integer) ls;
197    if ((p + 2) >= l) {
198        lua_pushnil(L);
199    } else {
200        lua_Integer a = uchar(s[p++]);
201        lua_Integer b = uchar(s[p++]);
202        lua_Integer c = uchar(s[p]);
203        lua_pushinteger(L, 0x10000 * a + 0x100 * b + c);
204    }
205    return 1;
206}
207
208static int siolib_readcardinal3_le(lua_State *L) {
209    size_t ls = 0;
210    const char *s = luaL_checklstring(L, 1, &ls);
211    lua_Integer p = luaL_checkinteger(L, 2) - 1;
212    lua_Integer l = (lua_Integer) ls;
213    if ((p + 2) >= l) {
214        lua_pushnil(L);
215    } else {
216        lua_Integer c = uchar(s[p++]);
217        lua_Integer b = uchar(s[p++]);
218        lua_Integer a = uchar(s[p]);
219        lua_pushinteger(L, 0x10000 * a + 0x100 * b + c);
220    }
221    return 1;
222}
223
224static int fiolib_readcardinal4(lua_State *L) {
225    FILE *f = lmt_valid_file(L);
226    if (f) {
227        lua_Integer a = getc(f);
228        lua_Integer b = getc(f);
229        lua_Integer c = getc(f);
230        lua_Integer d = getc(f);
231        if (d == EOF) {
232            lua_pushnil(L);
233        } else {
234            /* (a<<24) | (b<<16) | (c<<8) | d */
235            lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d);
236        }
237        return 1;
238    } else {
239        return 0;
240    }
241}
242
243static int fiolib_readcardinal4_le(lua_State *L) {
244    FILE *f = lmt_valid_file(L);
245    if (f) {
246        lua_Integer d = getc(f);
247        lua_Integer c = getc(f);
248        lua_Integer b = getc(f);
249        lua_Integer a = getc(f);
250        if (a == EOF) {
251            lua_pushnil(L);
252        } else {
253            /* (a<<24) | (b<<16) | (c<<8) | d */
254            lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d);
255        }
256        return 1;
257    } else {
258        return 0;
259    }
260}
261
262static int siolib_readcardinal4(lua_State *L) {
263    size_t ls = 0;
264    const char *s = luaL_checklstring(L, 1, &ls);
265    lua_Integer p = luaL_checkinteger(L, 2) - 1;
266    lua_Integer l = (lua_Integer) ls;
267    if ((p + 3) >= l) {
268        lua_pushnil(L);
269    } else {
270        lua_Integer a = uchar(s[p++]);
271        lua_Integer b = uchar(s[p++]);
272        lua_Integer c = uchar(s[p++]);
273        lua_Integer d = uchar(s[p]);
274        lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d);
275    }
276    return 1;
277}
278
279static int siolib_readcardinal4_le(lua_State *L) {
280    size_t ls = 0;
281    const char *s = luaL_checklstring(L, 1, &ls);
282    lua_Integer p = luaL_checkinteger(L, 2) - 1;
283    lua_Integer l = (lua_Integer) ls;
284    if ((p + 3) >= l) {
285        lua_pushnil(L);
286    } else {
287        lua_Integer d = uchar(s[p++]);
288        lua_Integer c = uchar(s[p++]);
289        lua_Integer b = uchar(s[p++]);
290        lua_Integer a = uchar(s[p]);
291        lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d);
292    }
293    return 1;
294}
295
296static int fiolib_readcardinaltable(lua_State *L) {
297    FILE *f = lmt_valid_file(L);
298    if (f) {
299        lua_Integer n = lua_tointeger(L, 2);
300        lua_Integer m = lua_tointeger(L, 3);
301        lua_createtable(L, (int) n, 0);
302        switch (m) {
303            case 1:
304                for (lua_Integer i = 1; i <= n; i++) {
305                    lua_Integer a = getc(f);
306                    if (a == EOF) {
307                        break;
308                    } else {
309                        lua_pushinteger(L, a);
310                        lua_rawseti(L, -2, i);
311                    }
312                }
313                break;
314            case 2:
315                for (lua_Integer i = 1; i <= n; i++) {
316                    lua_Integer a = getc(f);
317                    lua_Integer b = getc(f);
318                    if (b == EOF) {
319                        break;
320                    } else {
321                        /* (a<<8) | b */
322                        lua_pushinteger(L, 0x100 * a + b);
323                        lua_rawseti(L, -2, i);
324                    }
325                }
326                break;
327            case 3:
328                for (lua_Integer i = 1; i <= n; i++) {
329                    lua_Integer a = getc(f);
330                    lua_Integer b = getc(f);
331                    lua_Integer c = getc(f);
332                    if (c == EOF) {
333                        break;
334                    } else {
335                        /* (a<<16) | (b<<8) | c */
336                        lua_pushinteger(L, 0x10000 * a + 0x100 * b + c);
337                        lua_rawseti(L, -2, i);
338                    }
339                }
340                break;
341            case 4:
342                for (lua_Integer i = 1; i <= n; i++) {
343                    lua_Integer a = getc(f);
344                    lua_Integer b = getc(f);
345                    lua_Integer c = getc(f);
346                    lua_Integer d = getc(f);
347                    if (d == EOF) {
348                        break;
349                    } else {
350                        /* (a<<24) | (b<<16) | (c<<8) | d */
351                        lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d);
352                        lua_rawseti(L, -2, i);
353                    }
354                }
355                break;
356            default:
357                break;
358        }
359        return 1;
360    } else {
361        return 0;
362    }
363}
364
365static int siolib_readcardinaltable(lua_State *L) {
366    size_t ls = 0;
367    const char *s = luaL_checklstring(L, 1, &ls);
368    lua_Integer p = luaL_checkinteger(L, 2) - 1;
369    lua_Integer n = lua_tointeger(L, 3);
370    lua_Integer m = lua_tointeger(L, 4);
371    lua_Integer l = (lua_Integer) ls;
372    lua_createtable(L, (int) n, 0);
373    switch (m) {
374        case 1:
375            for (lua_Integer i = 1; i <= n; i++) {
376                if (p >= l) {
377                    break;
378                } else {
379                    lua_Integer a = uchar(s[p++]);
380                    lua_pushinteger(L, a);
381                    lua_rawseti(L, -2, i);
382                }
383            }
384            break;
385        case 2:
386            for (lua_Integer i = 1; i <= n; i++) {
387                if ((p + 1) >= l) {
388                    break;
389                } else {
390                    lua_Integer a = uchar(s[p++]);
391                    lua_Integer b = uchar(s[p++]);
392                    lua_pushinteger(L, 0x100 * a + b);
393                    lua_rawseti(L, -2, i);
394                }
395            }
396            break;
397        case 3:
398            for (lua_Integer i = 1; i <= n; i++) {
399                if ((p + 2) >= l) {
400                    break;
401                } else {
402                    lua_Integer a = uchar(s[p++]);
403                    lua_Integer b = uchar(s[p++]);
404                    lua_Integer c = uchar(s[p++]);
405                    lua_pushinteger(L, 0x10000 * a + 0x100 * b + c);
406                    lua_rawseti(L, -2, i);
407                }
408            }
409            break;
410        case 4:
411            for (lua_Integer i = 1; i <= n; i++) {
412                if ((p + 3) >= l) {
413                    break;
414                } else {
415                    lua_Integer a = uchar(s[p++]);
416                    lua_Integer b = uchar(s[p++]);
417                    lua_Integer c = uchar(s[p++]);
418                    lua_Integer d = uchar(s[p++]);
419                    lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d);
420                    lua_rawseti(L, -2, i);
421                }
422            }
423            break;
424        default:
425            break;
426    }
427    return 1;
428}
429
430static int fiolib_readinteger1(lua_State *L) {
431    FILE *f = lmt_valid_file(L);
432    if (f) {
433        lua_Integer a = getc(f);
434        if (a == EOF) {
435            lua_pushnil(L);
436        } else if (a >= 0x80) {
437            lua_pushinteger(L, a - 0x100);
438        } else {
439            lua_pushinteger(L, a);
440        }
441        return 1;
442    } else {
443        return 0;
444    }
445}
446
447static int siolib_readinteger1(lua_State *L) {
448    size_t ls = 0;
449    const char *s = luaL_checklstring(L, 1, &ls);
450    lua_Integer p = luaL_checkinteger(L, 2) - 1;
451    lua_Integer l = (lua_Integer) ls;
452    if (p >= l) {
453        lua_pushnil(L);
454    } else {
455        lua_Integer a = uchar(s[p]);
456        if (a >= 0x80) {
457            lua_pushinteger(L, a - 0x100);
458        } else {
459            lua_pushinteger(L, a);
460        }
461    }
462    return 1;
463}
464
465static int fiolib_readinteger2(lua_State *L) {
466    FILE *f = lmt_valid_file(L);
467    if (f) {
468        lua_Integer a = getc(f);
469        lua_Integer b = getc(f);
470        if (b == EOF) {
471            lua_pushnil(L);
472        } else if (a >= 0x80) {
473            lua_pushinteger(L, 0x100 * a + b - 0x10000);
474        } else {
475            lua_pushinteger(L, 0x100 * a + b);
476        }
477        return 1;
478    } else {
479        return 0;
480    }
481}
482
483static int fiolib_readinteger2_le(lua_State *L) {
484    FILE *f = lmt_valid_file(L);
485    if (f) {
486        lua_Integer b = getc(f);
487        lua_Integer a = getc(f);
488        if (a == EOF) {
489            lua_pushnil(L);
490        } else if (a >= 0x80) {
491            lua_pushinteger(L, 0x100 * a + b - 0x10000);
492        } else {
493            lua_pushinteger(L, 0x100 * a + b);
494        }
495        return 1;
496    } else {
497        return 0;
498    }
499}
500
501static int siolib_readinteger2(lua_State *L) {
502    size_t ls = 0;
503    const char *s = luaL_checklstring(L, 1, &ls);
504    lua_Integer p = luaL_checkinteger(L, 2) - 1;
505    lua_Integer l = (lua_Integer) ls;
506    if ((p + 1) >= l) {
507        lua_pushnil(L);
508    } else {
509        lua_Integer a = uchar(s[p++]);
510        lua_Integer b = uchar(s[p]);
511        if (a >= 0x80) {
512            lua_pushinteger(L, 0x100 * a + b - 0x10000);
513        } else {
514            lua_pushinteger(L, 0x100 * a + b);
515        }
516    }
517    return 1;
518}
519
520static int siolib_readinteger2_le(lua_State *L) {
521    size_t ls = 0;
522    const char *s = luaL_checklstring(L, 1, &ls);
523    lua_Integer p = luaL_checkinteger(L, 2) - 1;
524    lua_Integer l = (lua_Integer) ls;
525    if ((p + 1) >= l) {
526        lua_pushnil(L);
527    } else {
528        lua_Integer b = uchar(s[p++]);
529        lua_Integer a = uchar(s[p]);
530        if (a >= 0x80) {
531            lua_pushinteger(L, 0x100 * a + b - 0x10000);
532        } else {
533            lua_pushinteger(L, 0x100 * a + b);
534        }
535    }
536    return 1;
537}
538
539static int fiolib_readinteger3(lua_State *L) {
540    FILE *f = lmt_valid_file(L);
541    if (f) {
542        lua_Integer a = getc(f);
543        lua_Integer b = getc(f);
544        lua_Integer c = getc(f);
545        if (c == EOF) {
546            lua_pushnil(L);
547        } else if (a >= 0x80) {
548            lua_pushinteger(L, 0x10000 * a + 0x100 * b + c - 0x1000000);
549        } else {
550            lua_pushinteger(L, 0x10000 * a + 0x100 * b + c);
551        }
552        return 1;
553    } else {
554        return 0;
555    }
556}
557
558static int fiolib_readinteger3_le(lua_State *L) {
559    FILE *f = lmt_valid_file(L);
560    if (f) {
561        lua_Integer c = getc(f);
562        lua_Integer b = getc(f);
563        lua_Integer a = getc(f);
564        if (a == EOF) {
565            lua_pushnil(L);
566        } else if (a >= 0x80) {
567            lua_pushinteger(L, 0x10000 * a + 0x100 * b + c - 0x1000000);
568        } else {
569            lua_pushinteger(L, 0x10000 * a + 0x100 * b + c);
570        }
571        return 1;
572    } else {
573        return 0;
574    }
575}
576
577static int siolib_readinteger3(lua_State *L) {
578    size_t ls = 0;
579    const char *s = luaL_checklstring(L, 1, &ls);
580    lua_Integer p = luaL_checkinteger(L, 2) - 1;
581    lua_Integer l = (lua_Integer) ls;
582    if ((p + 2) >= l) {
583        lua_pushnil(L);
584    } else {
585        lua_Integer a = uchar(s[p++]);
586        lua_Integer b = uchar(s[p++]);
587        lua_Integer c = uchar(s[p]);
588        if (a >= 0x80) {
589            lua_pushinteger(L, 0x10000 * a + 0x100 * b + c - 0x1000000);
590        } else {
591            lua_pushinteger(L, 0x10000 * a + 0x100 * b + c);
592        }
593    }
594    return 1;
595}
596
597static int siolib_readinteger3_le(lua_State *L) {
598    size_t ls = 0;
599    const char *s = luaL_checklstring(L, 1, &ls);
600    lua_Integer p = luaL_checkinteger(L, 2) - 1;
601    lua_Integer l = (lua_Integer) ls;
602    if ((p + 2) >= l) {
603        lua_pushnil(L);
604    } else {
605        lua_Integer c = uchar(s[p++]);
606        lua_Integer b = uchar(s[p++]);
607        lua_Integer a = uchar(s[p]);
608        if (a >= 0x80) {
609            lua_pushinteger(L, 0x10000 * a + 0x100 * b + c - 0x1000000);
610        } else {
611            lua_pushinteger(L, 0x10000 * a + 0x100 * b + c);
612        }
613    }
614    return 1;
615}
616
617static int fiolib_readinteger4(lua_State *L) {
618    FILE *f = lmt_valid_file(L);
619    if (f) {
620        lua_Integer a = getc(f);
621        lua_Integer b = getc(f);
622        lua_Integer c = getc(f);
623        lua_Integer d = getc(f);
624        if (d == EOF) {
625            lua_pushnil(L);
626        } else if (a >= 0x80) {
627            lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000);
628        } else {
629            lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d);
630        }
631        return 1;
632    } else {
633        return 0;
634    }
635}
636
637static int fiolib_readinteger4_le(lua_State *L) {
638    FILE *f = lmt_valid_file(L);
639    if (f) {
640        lua_Integer d = getc(f);
641        lua_Integer c = getc(f);
642        lua_Integer b = getc(f);
643        lua_Integer a = getc(f);
644        if (a == EOF) {
645            lua_pushnil(L);
646        } else if (a >= 0x80) {
647            lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000);
648        } else {
649            lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d);
650        }
651        return 1;
652    } else {
653        return 0;
654    }
655}
656
657static int siolib_readinteger4(lua_State *L) {
658    size_t ls = 0;
659    const char *s = luaL_checklstring(L, 1, &ls);
660    lua_Integer p = luaL_checkinteger(L, 2) - 1;
661    lua_Integer l = (lua_Integer) ls;
662    if ((p + 3) >= l) {
663        lua_pushnil(L);
664    } else {
665        lua_Integer a = uchar(s[p++]);
666        lua_Integer b = uchar(s[p++]);
667        lua_Integer c = uchar(s[p++]);
668        lua_Integer d = uchar(s[p]);
669        if (a >= 0x80) {
670            lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000);
671        } else {
672            lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d);
673        }
674    }
675    return 1;
676}
677
678static int siolib_readinteger4_le(lua_State *L) {
679    size_t ls = 0;
680    const char *s = luaL_checklstring(L, 1, &ls);
681    lua_Integer p = luaL_checkinteger(L, 2) - 1;
682    lua_Integer l = (lua_Integer) ls;
683    if ((p + 3) >= l) {
684        lua_pushnil(L);
685    } else {
686        lua_Integer d = uchar(s[p++]);
687        lua_Integer c = uchar(s[p++]);
688        lua_Integer b = uchar(s[p++]);
689        lua_Integer a = uchar(s[p]);
690        if (a >= 0x80) {
691            lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000);
692        } else {
693            lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d);
694        }
695    }
696    return 1;
697}
698
699static int fiolib_readintegertable(lua_State *L) {
700    FILE *f = lmt_valid_file(L);
701    if (f) {
702        lua_Integer n = lua_tointeger(L, 2);
703        lua_Integer m = lua_tointeger(L, 3);
704        lua_createtable(L, (int) n, 0);
705        switch (m) {
706            case 1:
707                for (lua_Integer i = 1; i <= n; i++) {
708                    lua_Integer a = getc(f);
709                    if (a == EOF) {
710                        break;
711                    } else if (a >= 0x80) {
712                        lua_pushinteger(L, a - 0x100);
713                    } else {
714                        lua_pushinteger(L, a);
715                    }
716                    lua_rawseti(L, -2, i);
717                }
718                break;
719            case 2:
720                for (lua_Integer i = 1; i <= n; i++) {
721                    lua_Integer a = getc(f);
722                    lua_Integer b = getc(f);
723                    if (b == EOF) {
724                        break;
725                    } else if (a >= 0x80) {
726                        lua_pushinteger(L, 0x100 * a + b - 0x10000);
727                    } else {
728                        lua_pushinteger(L, 0x100 * a + b);
729                    }
730                    lua_rawseti(L, -2, i);
731                }
732                break;
733            case 3:
734                for (lua_Integer i = 1; i <= n; i++) {
735                    lua_Integer a = getc(f);
736                    lua_Integer b = getc(f);
737                    lua_Integer c = getc(f);
738                    if (c == EOF) {
739                        break;
740                    } else if (a >= 0x80) {
741                        lua_pushinteger(L, 0x10000 * a + 0x100 * b + c - 0x1000000);
742                    } else {
743                        lua_pushinteger(L, 0x10000 * a + 0x100 * b + c);
744                    }
745                    lua_rawseti(L, -2, i);
746                }
747                break;
748            case 4:
749                for (lua_Integer i = 1; i <= n; i++) {
750                    lua_Integer a = getc(f);
751                    lua_Integer b = getc(f);
752                    lua_Integer c = getc(f);
753                    lua_Integer d = getc(f);
754                    if (d == EOF) {
755                        break;
756                    } else if (a >= 0x80) {
757                        lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000);
758                    } else {
759                        lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d);
760                    }
761                    lua_rawseti(L, -2, i);
762                }
763                break;
764            default:
765                break;
766        }
767        return 1;
768    } else {
769        return 0;
770    }
771}
772
773static int siolib_readintegertable(lua_State *L) {
774    size_t ls = 0;
775    const char *s = luaL_checklstring(L, 1, &ls);
776    lua_Integer p = luaL_checkinteger(L, 2) - 1;
777    lua_Integer n = lua_tointeger(L, 3);
778    lua_Integer m = lua_tointeger(L, 4);
779    lua_Integer l = (lua_Integer) ls;
780    lua_createtable(L, (int) n, 0);
781    switch (m) {
782        case 1:
783            for (lua_Integer i = 1; i <= n; i++) {
784                if (p >= l) {
785                    break;
786                } else {
787                    lua_Integer a = uchar(s[p++]);
788                    if (a >= 0x80) {
789                        lua_pushinteger(L, a - 0x100);
790                    } else {
791                        lua_pushinteger(L, a);
792                    }
793                    lua_rawseti(L, -2, i);
794                }
795            }
796            break;
797        case 2:
798            for (lua_Integer i = 1; i <= n; i++) {
799                if ((p + 1) >= l) {
800                    break;
801                } else {
802                    lua_Integer a = uchar(s[p++]);
803                    lua_Integer b = uchar(s[p++]);
804                    if (a >= 0x80) {
805                        lua_pushinteger(L, 0x100 * a + b - 0x10000);
806                    } else {
807                        lua_pushinteger(L, 0x100 * a + b);
808                    }
809                    lua_rawseti(L, -2, i);
810                }
811            }
812            break;
813        case 3:
814            for (lua_Integer i = 1; i <= n; i++) {
815                if ((p + 2) >= l) {
816                    break;
817                } else {
818                    lua_Integer a = uchar(s[p++]);
819                    lua_Integer b = uchar(s[p++]);
820                    lua_Integer c = uchar(s[p++]);
821                    if (a >= 0x80) {
822                        lua_pushinteger(L, 0x10000 * a + 0x100 * b + c - 0x1000000);
823                    } else {
824                        lua_pushinteger(L, 0x10000 * a + 0x100 * b + c);
825                    }
826                    lua_rawseti(L, -2, i);
827                }
828            }
829            break;
830        case 4:
831            for (lua_Integer i = 1; i <= n; i++) {
832                if ((p + 3) >= l) {
833                    break;
834                } else {
835                    lua_Integer a = uchar(s[p++]);
836                    lua_Integer b = uchar(s[p++]);
837                    lua_Integer c = uchar(s[p++]);
838                    lua_Integer d = uchar(s[p++]);
839                    if (a >= 0x80) {
840                        lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d - 0x100000000);
841                    } else {
842                        lua_pushinteger(L, 0x1000000 * a + 0x10000 * b + 0x100 * c + d);
843                    }
844                    lua_rawseti(L, -2, i);
845                }
846            }
847            break;
848        default:
849            break;
850    }
851    return 1;
852}
853
854/* from ff */
855
856static int fiolib_readfixed2(lua_State *L) {
857    FILE *f = lmt_valid_file(L);
858    if (f) {
859        int a = getc(f);
860        int b = getc(f);
861        if (b == EOF) {
862            lua_pushnil(L);
863        } else {
864            int n = 0x100 * a + b; /* really an int because we shift */
865            lua_pushnumber(L, (double) ((n>>8) + ((n&0xff)/256.0)));
866        }
867        return 1;
868    } else {
869        return 0;
870    }
871}
872
873static int siolib_readfixed2(lua_State *L) {
874    size_t ls = 0;
875    const char *s = luaL_checklstring(L, 1, &ls);
876    lua_Integer p = luaL_checkinteger(L, 2) - 1;
877    lua_Integer l = (lua_Integer) ls;
878    if ((p + 3) >= l) {
879        lua_pushnil(L);
880    } else {
881        int a = uchar(s[p++]);
882        int b = uchar(s[p]);
883        int n = 0x100 * a + b; /* really an int because we shift */
884        lua_pushnumber(L, (double) ((n>>8) + ((n&0xff)/256.0)));
885    }
886    return 1;
887}
888
889static int fiolib_readfixed4(lua_State *L) {
890    FILE *f = lmt_valid_file(L);
891    if (f) {
892        int a = getc(f);
893        int b = getc(f);
894        int c = getc(f);
895        int d = getc(f);
896        if (d == EOF) {
897            lua_pushnil(L);
898        } else {
899            int n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d; /* really an int because we shift */
900            lua_pushnumber(L, (double) ((n>>16) + ((n&0xffff)/65536.0)));
901        }
902        return 1;
903    } else {
904        return 0;
905    }
906}
907
908static int siolib_readfixed4(lua_State *L) {
909    size_t ls = 0;
910    const char *s = luaL_checklstring(L, 1, &ls);
911    lua_Integer p = luaL_checkinteger(L, 2) - 1;
912    lua_Integer l = (lua_Integer) ls;
913    if ((p + 3) >= l) {
914        lua_pushnil(L);
915    } else {
916        int a = uchar(s[p++]);
917        int b = uchar(s[p++]);
918        int c = uchar(s[p++]);
919        int d = uchar(s[p]);
920        int n = 0x1000000 * a + 0x10000 * b + 0x100 * c + d; /* really an int because we shift */
921        lua_pushnumber(L, (double) ((n>>16) + ((n&0xffff)/65536.0)));
922    }
923    return 1;
924}
925
926static int fiolib_read2dot14(lua_State *L) {
927    FILE *f = lmt_valid_file(L);
928    if (f) {
929        int a = getc(f);
930        int b = getc(f);
931        if (b == EOF) {
932            lua_pushnil(L);
933        } else {
934            int n = 0x100 * a + b; /* really an int because we shift */
935            /* from ff */
936            lua_pushnumber(L, (double) (((n<<16)>>(16+14)) + ((n&0x3fff)/16384.0)));
937        }
938        return 1;
939    } else {
940        return 0;
941    }
942}
943
944static int siolib_read2dot14(lua_State *L) {
945    size_t ls = 0;
946    const char *s = luaL_checklstring(L, 1, &ls);
947    lua_Integer p = luaL_checkinteger(L, 2) - 1;
948    lua_Integer l = (lua_Integer) ls;
949    if ((p + 1) >= l) {
950        lua_pushnil(L);
951    } else {
952        int a = uchar(s[p++]);
953        int b = uchar(s[p]);
954        int n = 0x100 * a + b; /* really an int because we shift */
955        lua_pushnumber(L, (double) (((n<<16)>>(16+14)) + ((n&0x3fff)/16384.0)));
956    }
957    return 1;
958}
959
960static int fiolib_getposition(lua_State *L) {
961    FILE *f = lmt_valid_file(L);
962    if (f) {
963        long p = ftell(f);
964        if (p < 0) {
965            lua_pushnil(L);
966        } else {
967            lua_pushinteger(L, p);
968        }
969        return 1;
970    } else {
971        return 0;
972    }
973}
974
975static int fiolib_setposition(lua_State *L) {
976    FILE *f = lmt_valid_file(L);
977    if (f) {
978        long p = lmt_tolong(L, 2);
979        p = fseek(f, p, SEEK_SET);
980        if (p < 0) {
981            lua_pushnil(L);
982        } else {
983            lua_pushinteger(L, p);
984        }
985        return 1;
986    } else {
987        return 0;
988    }
989}
990
991static int fiolib_skipposition(lua_State *L) {
992    FILE *f = lmt_valid_file(L);
993    if (f) {
994        long p = lmt_tolong(L, 2);
995        p = fseek(f, ftell(f) + p, SEEK_SET);
996        if (p < 0) {
997            lua_pushnil(L);
998        } else {
999            lua_pushinteger(L, p);
1000        }
1001        return 1;
1002    } else {
1003        return 0;
1004    }
1005}
1006
1007static int fiolib_readbytetable(lua_State *L) {
1008    FILE *f = lmt_valid_file(L);
1009    if (f) {
1010        lua_Integer n = lua_tointeger(L, 2);
1011        lua_createtable(L, (int) n, 0);
1012        for (lua_Integer i = 1; i <= n; i++) {
1013            lua_Integer a = getc(f);
1014            if (a == EOF) {
1015                break;
1016            } else {
1017                /*
1018                    lua_pushinteger(L, i);
1019                    lua_pushinteger(L, a);
1020                    lua_rawset(L, -3);
1021                */
1022                lua_pushinteger(L, a);
1023                lua_rawseti(L, -2, i);
1024            }
1025        }
1026        return 1;
1027    } else {
1028        return 0;
1029    }
1030}
1031
1032static int siolib_readbytetable(lua_State *L) {
1033    size_t ls = 0;
1034    const char *s = luaL_checklstring(L, 1, &ls);
1035    lua_Integer p = luaL_checkinteger(L, 2) - 1;
1036    lua_Integer n = lua_tointeger(L, 3);
1037    lua_Integer l = (lua_Integer) ls;
1038    if (p >= l) {
1039        lua_pushnil(L);
1040    } else {
1041        if (p + n >= l) {
1042            n = l - p ;
1043        }
1044        lua_createtable(L, (int) n, 0);
1045        for (lua_Integer i = 1; i <= n; i++) {
1046            lua_Integer a = uchar(s[p++]);
1047            lua_pushinteger(L, a);
1048            lua_rawseti(L, -2, i);
1049        }
1050    }
1051    return 1;
1052}
1053
1054static int fiolib_readbytes(lua_State *L) {
1055    FILE *f = lmt_valid_file(L);
1056    if (f) {
1057        lua_Integer n = lua_tointeger(L, 2);
1058        for (lua_Integer i = 1; i <= n; i++) {
1059            lua_Integer a = getc(f);
1060            if (a == EOF) {
1061                return (int) (i - 1);
1062            } else {
1063                lua_pushinteger(L, a);
1064            }
1065        }
1066        return (int) n;
1067    } else {
1068        return 0;
1069    }
1070}
1071
1072static int siolib_readbytes(lua_State *L) {
1073    size_t ls = 0;
1074    const char *s = luaL_checklstring(L, 1, &ls);
1075    lua_Integer p = luaL_checkinteger(L, 2) - 1;
1076    lua_Integer n = lua_tointeger(L, 3);
1077    lua_Integer l = (lua_Integer) ls;
1078    if (p >= l) {
1079        return 0;
1080    } else {
1081        if (p + n >= l) {
1082            n = l - p ;
1083        }
1084        lua_createtable(L, (int) n, 0);
1085        for (lua_Integer i = 1; i <= n; i++) {
1086            lua_Integer a = uchar(s[p++]);
1087            lua_pushinteger(L, a);
1088        }
1089        return (int) n;
1090    }
1091}
1092
1093static int fiolib_readcline(lua_State *L)
1094{
1095    FILE *f = lmt_valid_file(L);
1096    if (f) {
1097        luaL_Buffer buf;
1098        int c = 0;
1099        int n = 0;
1100        luaL_buffinit(L, &buf);
1101        do {
1102            char *b = luaL_prepbuffer(&buf);
1103            int i = 0;
1104            while (i < LUAL_BUFFERSIZE) {
1105                c = fgetc(f);
1106                if (c == '\n') {
1107                    goto GOOD;
1108                } else if (c == '\r') {
1109                    c = fgetc(f);
1110                    if (c != EOF && c != '\n') {
1111                        ungetc((int) c, f);
1112                    }
1113                    goto GOOD;
1114                } else {
1115                    n++;
1116                    b[i++] = (char) c;
1117                }
1118            }
1119        }  while (c != EOF);
1120        goto BAD;
1121      GOOD:
1122        if (n > 0) {
1123            luaL_addsize(&buf, n);
1124            luaL_pushresult(&buf);
1125        } else {
1126            lua_pushnil(L);
1127        }
1128        lua_pushinteger(L, ftell(f));
1129        return 2;
1130    }
1131  BAD:
1132    lua_pushnil(L);
1133    return 1;
1134}
1135
1136
1137static int siolib_readcline(lua_State *L)
1138{
1139    size_t ls = 0;
1140    const char *s = luaL_checklstring(L, 1, &ls);
1141    lua_Integer p = luaL_checkinteger(L, 2) - 1;
1142    lua_Integer l = (lua_Integer) ls;
1143    if (p < l) {
1144        lua_Integer i = p;
1145        int n = 0;
1146        while  (p < l) {
1147            int c = uchar(s[p++]);
1148            if (c == '\n') {
1149                goto GOOD;
1150            } else if (c == '\r') {
1151                if (p < l) {
1152                    c = uchar(s[p++]);
1153                    if (c != EOF && c != '\n') {
1154                        --p;
1155                    }
1156                }
1157                goto GOOD;
1158            } else {
1159                n++;
1160            }
1161        }
1162        goto BAD;
1163      GOOD:
1164        if (n > 0) {
1165            lua_pushlstring(L, &s[i], n);
1166            lua_pushinteger(L, p);
1167            return 2;
1168        }
1169    }
1170  BAD:
1171    lua_pushnil(L);
1172    lua_pushinteger(L, p + 1);
1173    return 2;
1174}
1175
1176static int fiolib_readcstring(lua_State *L)
1177{
1178    FILE *f = lmt_valid_file(L);
1179    if (f) {
1180        luaL_Buffer buf;
1181        int c = 0;
1182        int n = 0;
1183        luaL_buffinit(L, &buf);
1184        do {
1185            char *b = luaL_prepbuffer(&buf);
1186            int i = 0;
1187            while (i < LUAL_BUFFERSIZE) {
1188                c = fgetc(f);
1189                if (c == '\0') {
1190                    goto GOOD;
1191                } else {
1192                    n++;
1193                    b[i++] = (char) c;
1194                }
1195            }
1196        }  while (c != EOF);
1197        goto BAD;
1198      GOOD:
1199        if (n > 0) {
1200            luaL_addsize(&buf, n);
1201            luaL_pushresult(&buf);
1202        } else {
1203            lua_pushliteral(L,"");
1204        }
1205        lua_pushinteger(L, ftell(f));
1206        return 2;
1207    }
1208  BAD:
1209    lua_pushnil(L);
1210    return 1;
1211}
1212
1213static int siolib_readcstring(lua_State *L)
1214{
1215    size_t ls = 0;
1216    const char *s = luaL_checklstring(L, 1, &ls);
1217    lua_Integer p = luaL_checkinteger(L, 2) - 1;
1218    lua_Integer l = (lua_Integer) ls;
1219    if (p < l) {
1220        lua_Integer i = p;
1221        int n = 0;
1222        while (p < l) {
1223            int c = uchar(s[p++]);
1224            if (c == '\0') {
1225                goto GOOD;
1226            } else {
1227                n++;
1228            }
1229        };
1230        goto BAD;
1231      GOOD:
1232        if (n > 0) {
1233            lua_pushlstring(L, &s[i], n);
1234        } else {
1235            lua_pushliteral(L,"");
1236        }
1237        lua_pushinteger(L, p + 1);
1238        return 2;
1239    }
1240  BAD:
1241    lua_pushnil(L);
1242    lua_pushinteger(L, p + 1);
1243    return 2;
1244}
1245
1246/* will be completed */
1247
1248static int fiolib_writecardinal1(lua_State *L)
1249{
1250    FILE *f = lmt_valid_file(L);
1251    if (f) {
1252        lua_Integer n = lua_tointeger(L, 2);
1253        putc(n & 0xFF, f);
1254    }
1255    return 0;
1256}
1257
1258static int siolib_tocardinal1(lua_State *L)
1259{
1260    lua_Integer n = lua_tointeger(L, 1);
1261    char buffer[1] = { n & 0xFF };
1262    lua_pushlstring(L, buffer, 1);
1263    return 1;
1264}
1265
1266static int fiolib_writecardinal2(lua_State *L)
1267{
1268    FILE *f = lmt_valid_file(L);
1269    if (f) {
1270        lua_Integer n = lua_tointeger(L, 2);
1271        putc((n >> 8) & 0xFF, f);
1272        putc( n       & 0xFF, f);
1273    }
1274    return 0;
1275}
1276
1277static int siolib_tocardinal2(lua_State *L)
1278{
1279    lua_Integer n = lua_tointeger(L, 1);
1280    char buffer[2] = { (n >> 8) & 0xFF, n & 0xFF };
1281    lua_pushlstring(L, buffer, 2);
1282    return 1;
1283}
1284
1285static int fiolib_writecardinal2_le(lua_State *L)
1286{
1287    FILE *f = lmt_valid_file(L);
1288    if (f) {
1289        lua_Integer n = lua_tointeger(L, 2);
1290        putc( n       & 0xFF, f);
1291        putc((n >> 8) & 0xFF, f);
1292    }
1293    return 0;
1294}
1295
1296static int siolib_tocardinal2_le(lua_State *L)
1297{
1298    lua_Integer n = lua_tointeger(L, 1);
1299    char buffer[2] = { n & 0xFF, (n >> 8) & 0xFF };
1300    lua_pushlstring(L, buffer, 2);
1301    return 1;
1302}
1303
1304static int fiolib_writecardinal3(lua_State *L)
1305{
1306    FILE *f = lmt_valid_file(L);
1307    if (f) {
1308        lua_Integer n = lua_tointeger(L, 2);
1309        putc((n >> 16) & 0xFF, f);
1310        putc((n >>  8) & 0xFF, f);
1311        putc( n        & 0xFF, f);
1312    }
1313    return 0;
1314}
1315
1316static int siolib_tocardinal3(lua_State *L)
1317{
1318    lua_Integer n = lua_tointeger(L, 1);
1319    char buffer[3] = { (n >> 16) & 0xFF, (n >>  8) & 0xFF, n & 0xFF };
1320    lua_pushlstring(L, buffer, 3);
1321    return 1;
1322}
1323
1324
1325static int fiolib_writecardinal3_le(lua_State *L)
1326{
1327    FILE *f = lmt_valid_file(L);
1328    if (f) {
1329        lua_Integer n = lua_tointeger(L, 2);
1330        putc( n        & 0xFF, f);
1331        putc((n >>  8) & 0xFF, f);
1332        putc((n >> 16) & 0xFF, f);
1333    }
1334    return 0;
1335}
1336
1337static int siolib_tocardinal3_le(lua_State *L)
1338{
1339    lua_Integer n = lua_tointeger(L, 1);
1340    char buffer[3] = { n & 0xFF, (n >> 8) & 0xFF, (n >> 16) & 0xFF };
1341    lua_pushlstring(L, buffer, 3);
1342    return 1;
1343}
1344
1345static int fiolib_writecardinal4(lua_State *L)
1346{
1347    FILE *f = lmt_valid_file(L);
1348    if (f) {
1349        lua_Integer n = lua_tointeger(L, 2);
1350        putc((n >> 24) & 0xFF, f);
1351        putc((n >> 16) & 0xFF, f);
1352        putc((n >>  8) & 0xFF, f);
1353        putc( n        & 0xFF, f);
1354    }
1355    return 0;
1356}
1357
1358static int siolib_tocardinal4(lua_State *L)
1359{
1360    lua_Integer n = lua_tointeger(L, 1);
1361    char buffer[4] = { (n >> 24) & 0xFF, (n >> 16) & 0xFF, (n >>  8) & 0xFF, n & 0xFF };
1362    lua_pushlstring(L, buffer, 4);
1363    return 1;
1364}
1365
1366static int fiolib_writecardinal4_le(lua_State *L)
1367{
1368    FILE *f = lmt_valid_file(L);
1369    if (f) {
1370        lua_Integer n = lua_tointeger(L, 2);
1371        putc( n        & 0xFF, f);
1372        putc((n >>  8) & 0xFF, f);
1373        putc((n >> 16) & 0xFF, f);
1374        putc((n >> 24) & 0xFF, f);
1375    }
1376    return 0;
1377}
1378
1379static int siolib_tocardinal4_le(lua_State *L)
1380{
1381    lua_Integer n = lua_tointeger(L, 1);
1382    char buffer[4] = { n & 0xFF, (n >>  8) & 0xFF, (n >> 16) & 0xFF, (n >> 24) & 0xFF };
1383    lua_pushlstring(L, buffer, 4);
1384    return 1;
1385}
1386
1387/* */
1388
1389static const luaL_Reg fiolib_function_list[] = {
1390    /* helpers */
1391
1392    { "readcardinal1",     fiolib_readcardinal1     },
1393    { "readcardinal2",     fiolib_readcardinal2     },
1394    { "readcardinal3",     fiolib_readcardinal3     },
1395    { "readcardinal4",     fiolib_readcardinal4     },
1396
1397    { "readcardinal1le",   fiolib_readcardinal1     },
1398    { "readcardinal2le",   fiolib_readcardinal2_le  },
1399    { "readcardinal3le",   fiolib_readcardinal3_le  },
1400    { "readcardinal4le",   fiolib_readcardinal4_le  },
1401
1402    { "readcardinaltable", fiolib_readcardinaltable },
1403
1404    { "readinteger1",      fiolib_readinteger1      },
1405    { "readinteger2",      fiolib_readinteger2      },
1406    { "readinteger3",      fiolib_readinteger3      },
1407    { "readinteger4",      fiolib_readinteger4      },
1408
1409    { "readinteger1le",    fiolib_readinteger1      },
1410    { "readinteger2le",    fiolib_readinteger2_le   },
1411    { "readinteger3le",    fiolib_readinteger3_le   },
1412    { "readinteger4le",    fiolib_readinteger4_le   },
1413
1414    { "readintegertable",  fiolib_readintegertable  },
1415
1416    { "readfixed2",        fiolib_readfixed2        },
1417    { "readfixed4",        fiolib_readfixed4        },
1418
1419    { "read2dot14",        fiolib_read2dot14        },
1420
1421    { "setposition",       fiolib_setposition       },
1422    { "getposition",       fiolib_getposition       },
1423    { "skipposition",      fiolib_skipposition      },
1424
1425    { "readbytes",         fiolib_readbytes         },
1426    { "readbytetable",     fiolib_readbytetable     },
1427
1428    { "readcline",         fiolib_readcline         },
1429    { "readcstring",       fiolib_readcstring       },
1430
1431    { "writecardinal1",    fiolib_writecardinal1    },
1432    { "writecardinal2",    fiolib_writecardinal2    },
1433    { "writecardinal3",    fiolib_writecardinal3    },
1434    { "writecardinal4",    fiolib_writecardinal4    },
1435
1436    { "writecardinal1le",  fiolib_writecardinal1    },
1437    { "writecardinal2le",  fiolib_writecardinal2_le },
1438    { "writecardinal3le",  fiolib_writecardinal3_le },
1439    { "writecardinal4le",  fiolib_writecardinal4_le },
1440
1441    { NULL,                NULL                     }
1442};
1443
1444static const luaL_Reg siolib_function_list[] = {
1445
1446    { "readcardinal1",     siolib_readcardinal1     },
1447    { "readcardinal2",     siolib_readcardinal2     },
1448    { "readcardinal3",     siolib_readcardinal3     },
1449    { "readcardinal4",     siolib_readcardinal4     },
1450
1451    { "readcardinal1le",   siolib_readcardinal1     },
1452    { "readcardinal2le",   siolib_readcardinal2_le  },
1453    { "readcardinal3le",   siolib_readcardinal3_le  },
1454    { "readcardinal4le",   siolib_readcardinal4_le  },
1455
1456    { "readcardinaltable", siolib_readcardinaltable },
1457
1458    { "readinteger1",      siolib_readinteger1      },
1459    { "readinteger2",      siolib_readinteger2      },
1460    { "readinteger3",      siolib_readinteger3      },
1461    { "readinteger4",      siolib_readinteger4      },
1462
1463    { "readinteger1le",    siolib_readinteger1      },
1464    { "readinteger2le",    siolib_readinteger2_le   },
1465    { "readinteger3le",    siolib_readinteger3_le   },
1466    { "readinteger4le",    siolib_readinteger4_le   },
1467
1468    { "readintegertable",  siolib_readintegertable  },
1469
1470    { "readfixed2",        siolib_readfixed2        },
1471    { "readfixed4",        siolib_readfixed4        },
1472    { "read2dot14",        siolib_read2dot14        },
1473
1474    { "readbytes",         siolib_readbytes         },
1475    { "readbytetable",     siolib_readbytetable     },
1476
1477    { "readcline",         siolib_readcline         },
1478    { "readcstring",       siolib_readcstring       },
1479
1480    { "tocardinal1",       siolib_tocardinal1       },
1481    { "tocardinal2",       siolib_tocardinal2       },
1482    { "tocardinal3",       siolib_tocardinal3       },
1483    { "tocardinal4",       siolib_tocardinal4       },
1484
1485    { "tocardinal1le",     siolib_tocardinal1       },
1486    { "tocardinal2le",     siolib_tocardinal2_le    },
1487    { "tocardinal3le",     siolib_tocardinal3_le    },
1488    { "tocardinal4le",     siolib_tocardinal4_le    },
1489
1490    { NULL,                NULL                     }
1491};
1492
1493/*tex
1494
1495    The sio helpers might be handy at some point. Speed-wise there is no gain over file access
1496    because with ssd and caching we basically operate in memory too. We keep them as complement to
1497    the file ones. I did consider using an userdata object for the position etc but some simple
1498    tests demonstrated that there is no real gain and the current ones permits to wrap up whatever
1499    interface one likes.
1500
1501*/
1502
1503int luaopen_fio(lua_State *L) {
1504    lua_newtable(L);
1505    luaL_setfuncs(L, fiolib_function_list, 0);
1506    return 1;
1507}
1508
1509int luaopen_sio(lua_State *L) {
1510    lua_newtable(L);
1511    luaL_setfuncs(L, siolib_function_list, 0);
1512    return 1;
1513}
1514
1515/* We patch a function in the standard |io| library. */
1516
1517/*tex
1518
1519    The following code overloads the |io.open| function to deal with so called wide characters on
1520    windows.
1521
1522*/
1523
1524/* a variant on read_line but with nothing catched */
1525
1526static int io_gobble(lua_State *L) 
1527{
1528    FILE *f = lmt_valid_file(L);
1529    if (f) {
1530        int c;
1531        int n = 0;
1532        while ((c = getc(f)) != EOF && c != '\n') {
1533            n = 1;
1534        }
1535        lua_pushboolean(L, ((c == '\n') || n));
1536    } else { 
1537        lua_pushnil(L);
1538    }
1539    return 1;
1540}
1541
1542# if _WIN32
1543
1544#   define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE))
1545
1546    static int l_checkmode(const char *mode) {
1547        return (
1548            *mode != '\0'
1549         && strchr("rwa", *(mode++))
1550         && (*mode != '+' || ((void)(++mode), 1))
1551         && (strspn(mode, "b") == strlen(mode))
1552        );
1553    }
1554
1555    typedef luaL_Stream LStream;
1556
1557    static LStream *newprefile(lua_State *L) {
1558        LStream *p = (LStream *)lua_newuserdatauv(L, sizeof(LStream), 0);
1559        p->closef = NULL;
1560        luaL_setmetatable(L, LUA_FILEHANDLE);
1561        return p;
1562    }
1563
1564    static int io_fclose(lua_State *L) {
1565        LStream *p = tolstream(L);
1566        int res = fclose(p->f);
1567        return luaL_fileresult(L, (res == 0), NULL);
1568    }
1569
1570    static LStream *newfile(lua_State *L) {
1571        /*tex Watch out: lua 5.4 has different closers. */
1572        LStream *p = newprefile(L);
1573        p->f = NULL;
1574        p->closef = &io_fclose;
1575        return p;
1576    }
1577
1578    static int io_open(lua_State *L)
1579    {
1580        const char *filename = luaL_checkstring(L, 1);
1581        const char *mode = luaL_optstring(L, 2, "r");
1582        LStream *p = newfile(L);
1583        const char *md = mode;  /* to traverse/check mode */
1584        luaL_argcheck(L, l_checkmode(md), 2, "invalid mode");
1585        p->f = aux_utf8_fopen(filename, mode);
1586        return (p->f) ? 1 : luaL_fileresult(L, 0, filename);
1587    }
1588
1589    static int io_pclose(lua_State *L) {
1590        LStream *p = tolstream(L);
1591        return luaL_execresult(L, _pclose(p->f));
1592    }
1593
1594    static int io_popen(lua_State *L)
1595    {
1596        const char *filename = luaL_checkstring(L, 1);
1597        const char *mode = luaL_optstring(L, 2, "r");
1598        LStream *p = newprefile(L);
1599        p->f = aux_utf8_popen(filename, mode);
1600        p->closef = &io_pclose;
1601        return (p->f) ? 1 : luaL_fileresult(L, 0, filename);
1602    }
1603
1604    int luaextend_io(lua_State *L)
1605    {
1606        lua_getglobal(L, "io");
1607        lua_pushcfunction(L, io_open);  lua_setfield(L, -2, "open");
1608        lua_pushcfunction(L, io_popen); lua_setfield(L, -2, "popen");
1609        lua_pushcfunction(L, io_gobble); lua_setfield(L, -2, "gobble");
1610        lua_pop(L, 1);
1611         /*tex
1612            Larger doesn't work and limits to 512 but then no amount is okay as there's always more
1613            to demand.
1614        */
1615        _setmaxstdio(2048);
1616        return 1;
1617    }
1618
1619# else
1620
1621 // int luaextend_io(lua_State *L)
1622 // {
1623 //     (void) L;
1624 //     return 1;
1625 // }
1626
1627    int luaextend_io(lua_State *L)
1628    {
1629        lua_getglobal(L, "io");
1630        lua_pushcfunction(L, io_gobble); lua_setfield(L, -2, "gobble");
1631        lua_pop(L, 1);
1632        return 1;
1633    }
1634
1635# endif
1636