]> rtime.felk.cvut.cz Git - l4.git/blobdiff - l4/pkg/lua/lib/contrib/src/liolib.c
update
[l4.git] / l4 / pkg / lua / lib / contrib / src / liolib.c
index e79ed1cb2e216a412c74833a522863c6761b4af6..23d342ed0e6e4bf60aa535e2652c6a7c6e2bdb96 100644 (file)
@@ -9,6 +9,7 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
+#include <ctype.h>
 
 #define liolib_c
 #define LUA_LIB
@@ -18,7 +19,8 @@
 #include "lauxlib.h"
 #include "lualib.h"
 
-
+#include "lnum.h"
+#include "llex.h"
 
 #define IO_INPUT       1
 #define IO_OUTPUT      2
@@ -269,16 +271,66 @@ static int io_lines (lua_State *L) {
 ** =======================================================
 */
 
+/*
+* NOTE: Lua's usual '*n' format specifier reads numbers as floating point,
+*       and converts to integer if they are. IN ORDER TO NOT LOSE ACCURACY,
+*       a new '*i' format specifier is added (will also be speedier, on non-
+*       FPU systems).
+*/
 
 static int read_number (lua_State *L, FILE *f) {
   lua_Number d;
   if (fscanf(f, LUA_NUMBER_SCAN, &d) == 1) {
+#ifdef LUA_TINT
+    lua_Integer tmp;
+    lua_number2integer(tmp, d);
+    if (cast_num(tmp) == d)
+        lua_pushinteger(L, tmp);
+    else
+#endif
     lua_pushnumber(L, d);
     return 1;
   }
   else return 0;  /* read fails */
 }
 
+static int read_integer (lua_State *L, FILE *f) {
+  lua_Integer i;
+  if (fscanf(f, LUA_INTEGER_SCAN, &i) == 1) {
+    lua_pushinteger(L, i);
+    return 1;
+  }
+  else return 0;  /* read fails */
+}
+
+#ifdef LNUM_COMPLEX
+static int read_complex (lua_State *L, FILE *f) {
+  /* NNN / NNNi / NNN+MMMi / NNN-MMMi */
+  lua_Number a,b;
+  if (fscanf(f, LUA_NUMBER_SCAN, &a) == 1) {
+    int c=fgetc(f);
+    switch(c) {
+        case 'i':
+            lua_pushcomplex(L, a*I);
+            return 1;
+        case '+':
+        case '-':
+            /* "i" is consumed if at the end; just 'NNN+MMM' will most likely
+             * behave as if "i" was there? (TBD: test)
+             */
+            if (fscanf(f, LUA_NUMBER_SCAN "i", &b) == 1) {
+                lua_pushcomplex(L, a+ (c=='+' ? b:-b)*I);
+                return 1;
+            }
+    }
+    ungetc( c,f );
+    lua_pushnumber(L,a);  /*real part only*/
+    return 1;
+  }
+  return 0;  /* read fails */
+}
+#endif
+
 
 static int test_eof (lua_State *L, FILE *f) {
   int c = getc(f);
@@ -352,6 +404,14 @@ static int g_read (lua_State *L, FILE *f, int first) {
           case 'n':  /* number */
             success = read_number(L, f);
             break;
+          case 'i':  /* integer (full accuracy) */
+            success = read_integer(L, f);
+            break;
+#ifdef LNUM_COMPLEX
+          case 'c':  /* complex */
+            success = read_complex(L, f);
+            break;
+#endif
           case 'l':  /* line */
             success = read_line(L, f);
             break;
@@ -412,9 +472,10 @@ static int g_write (lua_State *L, FILE *f, int arg) {
   int status = 1;
   for (; nargs--; arg++) {
     if (lua_type(L, arg) == LUA_TNUMBER) {
-      /* optimization: could be done exactly as for strings */
-      status = status &&
-          fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
+      if (lua_isinteger(L,arg))
+          status = status && fprintf(f, LUA_INTEGER_FMT, lua_tointeger(L, arg)) > 0;
+      else
+          status = status && fprintf(f, LUA_NUMBER_FMT, lua_tonumber(L, arg)) > 0;
     }
     else {
       size_t l;
@@ -457,7 +518,7 @@ static int f_setvbuf (lua_State *L) {
   static const char *const modenames[] = {"no", "full", "line", NULL};
   FILE *f = tofile(L);
   int op = luaL_checkoption(L, 2, NULL, modenames);
-  lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE);
+  size_t sz = luaL_optint32(L, 3, LUAL_BUFFERSIZE);
   int res = setvbuf(f, NULL, mode[op], sz);
   return pushresult(L, res == 0, NULL);
 }