diff --git a/README.md b/README.md
index 9c73ad70..f4cf9c85 100644
--- a/README.md
+++ b/README.md
@@ -24,10 +24,26 @@ Tencent QQ group: 309957875
- fix wifi smart connect
- add spi module (done)
- add mqtt module (done)
-- add coap module
-- cross compiler
+- add coap module (in coap branch)
+- cross compiler (done)
# Change log
+2015-02-13
+add node.compile() api to compile lua text file into lua bytecode file.
+this will reduce memory usage noticeably when require modules into NodeMCU.
+raise internal LUA_BUFFERSIZE from 1024 to 4096.
+lua require("mod") will load "mod.lc" file first if exist.
+build latest pre_build bin.
+
+2015-02-12
+fix float print.
+update spiffs, add file.rename api to file module.
+fix some file system bug. need more tests.
+add support to 8Mbyte, 16Mbyte flash.
+remove node.led() and node.key() api.
+some update to lua_modules and examples.
+build latest pre_build bin.
+
2015-01-27
support floating point LUA.
use macro LUA_NUMBER_INTEGRAL in user_config.h control this feature.
@@ -44,27 +60,6 @@ added LUA examples and modules [by dvv](https://github.com/dvv).
added node.readvdd33() API [by alonewolfx2](https://github.com/alonewolfx2).
build pre_build bin.
-2015-01-24
-migrate to sdk 0.9.5 release.
-tmr.time() now return second(not precise yet).
-build pre_build bin.
-
-2015-01-23
-merge mqtt branch to master.
-build pre_build bin.
-
-2015-01-18
-merge mqtt module to [new branch mqtt](https://github.com/nodemcu/nodemcu-firmware/tree/mqtt) from [https://github.com/tuanpmt/esp_mqtt](https://github.com/tuanpmt/esp_mqtt).
-merge spi module from iabdalkader:spi.
-fix #110,set local port to random in client mode.
-modify gpio.read to NOT set pin to input mode automatic.
-add PATH env with C:\MinGW\bin;C:\MinGW\msys\1.0\bin;C:\Python27 in eclipse project. resolve #103.
-
-2015-01-08
-fix net.socket:send() issue when multi sends are called.
-*NOTE*: if data length is bigger than 1460, send next packet AFTER "sent" callback is called.
-fix file.read() api, take 0xFF as a regular byte, not EOF.
-pre_build/latest/nodemcu_512k_latest.bin is removed. use pre_build/latest/nodemcu_latest.bin instead.
[more change log](https://github.com/nodemcu/nodemcu-firmware/wiki)
@@ -309,6 +304,7 @@ cu:send("hello")
####Use DS18B20 module extends your esp8266
```lua
-- read temperature with DS18B20
+ node.compile("ds18b20.lua") -- run this only once to compile and save to "ds18b20.lc"
t=require("ds18b20")
t.setup(9)
addrs=t.addrs()
diff --git a/app/include/user_config.h b/app/include/user_config.h
index 66cf8a15..77a43ddb 100644
--- a/app/include/user_config.h
+++ b/app/include/user_config.h
@@ -7,12 +7,16 @@
#define NODE_VERSION_INTERNAL 0U
#define NODE_VERSION "NodeMCU 0.9.5"
-#define BUILD_DATE "build 20150127"
+#define BUILD_DATE "build 20150214"
+
+// #define DEVKIT_VERSION_0_9 1 // define this only if you use NodeMCU devkit v0.9
// #define FLASH_512K
// #define FLASH_1M
// #define FLASH_2M
// #define FLASH_4M
+// #define FLASH_8M
+// #define FLASH_16M
#define FLASH_AUTOSIZE
// #define DEVELOP_VERSION
#define FULL_VERSION_FOR_USER
@@ -48,6 +52,7 @@
#define BUILD_SPIFFS 1
#define LUA_USE_MODULES
+
#ifdef LUA_USE_MODULES
#define LUA_USE_MODULES_NODE
#define LUA_USE_MODULES_FILE
@@ -64,13 +69,16 @@
#define LUA_USE_MODULES_BIT
#define LUA_USE_MODULES_U8G
#define LUA_USE_MODULES_MQTT
-#define LUA_USE_MODULES_WS2812
+// #define LUA_USE_MODULES_WS2812 // TODO: put this device specific module to device driver section.
#endif /* LUA_USE_MODULES */
+// TODO: put device specific module to device driver section.
+#ifdef LUA_USE_DEVICE_DRIVER
+#define LUA_USE_DEVICE_WS2812
+#endif /* LUA_USE_DEVICE_DRIVER */
+
+
// #define LUA_NUMBER_INTEGRAL
-#ifndef LUA_NUMBER_INTEGRAL
-#define PRINTF_LONG_SUPPORT
-#endif
#define LUA_OPTRAM
#ifdef LUA_OPTRAM
@@ -80,6 +88,8 @@
#endif /* LUA_OPTRAM */
#define READLINE_INTERVAL 80
+
+#ifdef DEVKIT_VERSION_0_9
#define KEY_SHORT_MS 200
#define KEY_LONG_MS 3000
#define KEY_SHORT_COUNT (KEY_SHORT_MS / READLINE_INTERVAL)
@@ -87,6 +97,7 @@
#define LED_HIGH_COUNT_DEFAULT 10
#define LED_LOW_COUNT_DEFAULT 0
+#endif
// Configure U8glib fonts
diff --git a/app/libc/c_stdio.c b/app/libc/c_stdio.c
index 43d7bd24..03e64581 100644
--- a/app/libc/c_stdio.c
+++ b/app/libc/c_stdio.c
@@ -58,423 +58,1049 @@ int c_stderr = 1001;
#else
-/*
-File: printf.c
+#define FLOATINGPT 1
+#define NEWFP 1
+#define ENDIAN_LITTLE 1234
+#define ENDIAN_BIG 4321
+#define ENDIAN_PDP 3412
+#define ENDIAN ENDIAN_BIG
-Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or other
-materials provided with the distribution.
-
-Neither the name of the Kustaa Nyholm or SpareTimeLabs nor the names of its
-contributors may be used to endorse or promote products derived from this software
-without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
-IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
-INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
-NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
-OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
-OF SUCH DAMAGE.
-
-----------------------------------------------------------------------
-
-This library is realy just two files: 'printf.h' and 'printf.c'.
-
-They provide a simple and small (+200 loc) printf functionality to
-be used in embedded systems.
-
-I've found them so usefull in debugging that I do not bother with a
-debugger at all.
-
-They are distributed in source form, so to use them, just compile them
-into your project.
-
-Two printf variants are provided: printf and sprintf.
-
-The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'.
-
-Zero padding and field width are also supported.
-
-If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the
-long specifier is also
-supported. Note that this will pull in some long math routines (pun intended!)
-and thus make your executable noticably longer.
-
-The memory foot print of course depends on the target cpu, compiler and
-compiler options, but a rough guestimate (based on a H8S target) is about
-1.4 kB for code and some twenty 'int's and 'char's, say 60 bytes of stack space.
-Not too bad. Your milage may vary. By hacking the source code you can
-get rid of some hunred bytes, I'm sure, but personally I feel the balance of
-functionality and flexibility versus code size is close to optimal for
-many embedded systems.
-
-To use the printf you need to supply your own character output function,
-something like :
-
-void putc ( void* p, char c)
- {
- while (!SERIAL_PORT_EMPTY) ;
- SERIAL_PORT_TX_REGISTER = c;
- }
-
-Before you can call printf you need to initialize it to use your
-character output function with something like:
-
-init_printf(NULL,putc);
-
-Notice the 'NULL' in 'init_printf' and the parameter 'void* p' in 'putc',
-the NULL (or any pointer) you pass into the 'init_printf' will eventually be
-passed to your 'putc' routine. This allows you to pass some storage space (or
-anything realy) to the character output function, if necessary.
-This is not often needed but it was implemented like that because it made
-implementing the sprintf function so neat (look at the source code).
-
-The code is re-entrant, except for the 'init_printf' function, so it
-is safe to call it from interupts too, although this may result in mixed output.
-If you rely on re-entrancy, take care that your 'putc' function is re-entrant!
-
-The printf and sprintf functions are actually macros that translate to
-'tfp_printf' and 'tfp_sprintf'. This makes it possible
-to use them along with 'stdio.h' printf's in a single source file.
-You just need to undef the names before you include the 'stdio.h'.
-Note that these are not function like macros, so if you have variables
-or struct members with these names, things will explode in your face.
-Without variadic macros this is the best we can do to wrap these
-fucnction. If it is a problem just give up the macros and use the
-functions directly or rename them.
-
-For further details see source code.
-
-regs Kusti, 23.10.2004
-*/
+/* $Id: strichr.c,v 1.1.1.1 2006/08/23 17:03:06 pefo Exp $ */
/*
-Add lightweight %g support by vowstar,
-NodeMCU Team, 26.1.2015
-*/
+ * Copyright (c) 2000-2002 Opsycon AB (www.opsycon.se)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Opsycon AB.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+//#include
+#include "c_string.h"
-typedef void (*putcf) (void *, char);
-
-#ifdef PRINTF_LONG_SUPPORT
-
-static int uli2a(unsigned long int num, unsigned int base, int uc, char *bf)
+char *
+strichr(char *p, int c)
{
- int n = 0;
- unsigned long int d = 1;
- int len = 1;
- while (num / d >= base)
- {
- d *= base;
- len ++;
- }
- while (d != 0)
- {
- int dgt = num / d;
- num %= d;
- d /= base;
- if (n || dgt > 0 || d == 0)
- {
- *bf++ = dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10);
- ++n;
+ char *t;
+
+ if (p != NULL) {
+ for(t = p; *t; t++);
+ for (; t >= p; t--) {
+ *(t + 1) = *t;
}
+ *p = c;
}
- *bf = 0;
- return len;
+ return (p);
}
-static int li2a (long num, char *bf)
+/* $Id: str_fmt.c,v 1.1.1.1 2006/08/23 17:03:06 pefo Exp $ */
+
+/*
+ * Copyright (c) 2000-2002 Opsycon AB (www.opsycon.se)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Opsycon AB.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+//#include
+#include "c_string.h"
+
+#define FMT_RJUST 0
+#define FMT_LJUST 1
+#define FMT_RJUST0 2
+#define FMT_CENTER 3
+
+/*
+ * Format string by inserting blanks.
+ */
+
+void
+str_fmt(char *p, int size, int fmt)
{
- int len = 0;
- if (num < 0)
- {
- num = -num;
- *bf++ = '-';
- len ++;
+ int n, m, len;
+
+ len = strlen (p);
+ switch (fmt) {
+ case FMT_RJUST:
+ for (n = size - len; n > 0; n--)
+ strichr (p, ' ');
+ break;
+ case FMT_LJUST:
+ for (m = size - len; m > 0; m--)
+ strcat (p, " ");
+ break;
+ case FMT_RJUST0:
+ for (n = size - len; n > 0; n--)
+ strichr (p, '0');
+ break;
+ case FMT_CENTER:
+ m = (size - len) / 2;
+ n = size - (len + m);
+ for (; m > 0; m--)
+ strcat (p, " ");
+ for (; n > 0; n--)
+ strichr (p, ' ');
+ break;
}
- len += uli2a(num, 10, 0, bf);
- return len;
}
+/* $Id: strtoupp.c,v 1.1.1.1 2006/08/23 17:03:06 pefo Exp $ */
+
+/*
+ * Copyright (c) 2000-2002 Opsycon AB (www.opsycon.se)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Opsycon AB.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+//#include
+//#include
+#include "c_string.h"
+#include "c_ctype.h"
+
+void
+strtoupper(char *p)
+{
+ if(!p)
+ return;
+ for (; *p; p++)
+ *p = toupper (*p);
+}
+
+/* $Id: atob.c,v 1.1.1.1 2006/08/23 17:03:06 pefo Exp $ */
+
+/*
+ * Copyright (c) 2000-2002 Opsycon AB (www.opsycon.se)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Opsycon AB.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+//#include
+//#include
+//#include
+#include "c_string.h"
+typedef int int32_t;
+typedef unsigned int u_int32_t;
+typedef unsigned int u_int;
+typedef unsigned long u_long;
+typedef int32_t register_t;
+typedef long long quad_t;
+typedef unsigned long long u_quad_t;
+typedef double rtype;
+
+#ifndef __P
+#define __P(args) args
#endif
-static int ui2a(unsigned int num, unsigned int base, int uc, char *bf)
+static char * _getbase __P((char *, int *));
+static int _atob __P((unsigned long long *, char *p, int));
+
+static char *
+_getbase(char *p, int *basep)
{
- int n = 0;
- unsigned int d = 1;
- int len = 1;
- while (num / d >= base)
- {
- d *= base;
- len ++;
+ if (p[0] == '0') {
+ switch (p[1]) {
+ case 'x':
+ *basep = 16;
+ break;
+ case 't': case 'n':
+ *basep = 10;
+ break;
+ case 'o':
+ *basep = 8;
+ break;
+ default:
+ *basep = 10;
+ return (p);
+ }
+ return (p + 2);
}
- while (d != 0)
- {
- int dgt = num / d;
- num %= d;
- d /= base;
- if (n || dgt > 0 || d == 0)
- {
- *bf++ = dgt + (dgt < 10 ? '0' : (uc ? 'A' : 'a') - 10);
- ++n;
+ *basep = 10;
+ return (p);
+}
+
+
+/*
+ * _atob(vp,p,base)
+ */
+static int
+_atob (u_quad_t *vp, char *p, int base)
+{
+ u_quad_t value, v1, v2;
+ char *q, tmp[20];
+ int digit;
+
+ if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
+ base = 16;
+ p += 2;
+ }
+
+ if (base == 16 && (q = strchr (p, '.')) != 0) {
+ if (q - p > sizeof(tmp) - 1)
+ return (0);
+
+ strncpy (tmp, p, q - p);
+ tmp[q - p] = '\0';
+ if (!_atob (&v1, tmp, 16))
+ return (0);
+
+ q++;
+ if (strchr (q, '.'))
+ return (0);
+
+ if (!_atob (&v2, q, 16))
+ return (0);
+ *vp = (v1 << 16) + v2;
+ return (1);
+ }
+
+ value = *vp = 0;
+ for (; *p; p++) {
+ if (*p >= '0' && *p <= '9')
+ digit = *p - '0';
+ else if (*p >= 'a' && *p <= 'f')
+ digit = *p - 'a' + 10;
+ else if (*p >= 'A' && *p <= 'F')
+ digit = *p - 'A' + 10;
+ else
+ return (0);
+
+ if (digit >= base)
+ return (0);
+ value *= base;
+ value += digit;
+ }
+ *vp = value;
+ return (1);
+}
+
+/*
+ * atob(vp,p,base)
+ * converts p to binary result in vp, rtn 1 on success
+ */
+int
+atob(u_int32_t *vp, char *p, int base)
+{
+ u_quad_t v;
+
+ if (base == 0)
+ p = _getbase (p, &base);
+ if (_atob (&v, p, base)) {
+ *vp = v;
+ return (1);
+ }
+ return (0);
+}
+
+
+/*
+ * llatob(vp,p,base)
+ * converts p to binary result in vp, rtn 1 on success
+ */
+int
+llatob(u_quad_t *vp, char *p, int base)
+{
+ if (base == 0)
+ p = _getbase (p, &base);
+ return _atob(vp, p, base);
+}
+
+
+/*
+ * char *btoa(dst,value,base)
+ * converts value to ascii, result in dst
+ */
+char *
+btoa(char *dst, u_int value, int base)
+{
+ char buf[34], digit;
+ int i, j, rem, neg;
+
+ if (value == 0) {
+ dst[0] = '0';
+ dst[1] = 0;
+ return (dst);
+ }
+
+ neg = 0;
+ if (base == -10) {
+ base = 10;
+ if (value & (1L << 31)) {
+ value = (~value) + 1;
+ neg = 1;
}
}
- *bf = 0;
- return len;
-}
-static int i2a (int num, char *bf)
-{
- int len = 0;
- if (num < 0)
- {
- num = -num;
- *bf++ = '-';
- len ++;
- }
- len += ui2a(num, 10, 0, bf);
- return len;
-}
-
-// Converts a floating point number to string.
-static int d2a(double num, char *bf)
-{
- int len = 0;
- double ipart = 0;
- double fpart = 0;
- double absnum = num;
-
- // Add sign
- if (absnum < 0)
- {
- absnum = -absnum;
- *bf++ = '-';
- // len must add 1 when return
- // but can't add at here
+ for (i = 0; value != 0; i++) {
+ rem = value % base;
+ value /= base;
+ if (rem >= 0 && rem <= 9)
+ digit = rem + '0';
+ else if (rem >= 10 && rem <= 36)
+ digit = (rem - 10) + 'a';
+ buf[i] = digit;
}
- // Extract integer part
- ipart = (int)absnum;
+ buf[i] = 0;
+ if (neg)
+ strcat (buf, "-");
- // Extract floating part
- fpart = absnum - (double)ipart;
+ /* reverse the string */
+ for (i = 0, j = strlen (buf) - 1; j >= 0; i++, j--)
+ dst[i] = buf[j];
+ dst[i] = 0;
+ return (dst);
+}
- // convert integer part to string
-#ifdef PRINTF_LONG_SUPPORT
- len += li2a(ipart, bf);
+/*
+ * char *btoa(dst,value,base)
+ * converts value to ascii, result in dst
+ */
+char *
+llbtoa(char *dst, u_quad_t value, int base)
+{
+ char buf[66], digit;
+ int i, j, rem, neg;
+
+ if (value == 0) {
+ dst[0] = '0';
+ dst[1] = 0;
+ return (dst);
+ }
+
+ neg = 0;
+ if (base == -10) {
+ base = 10;
+ if (value & (1LL << 63)) {
+ value = (~value) + 1;
+ neg = 1;
+ }
+ }
+
+ for (i = 0; value != 0; i++) {
+ rem = value % base;
+ value /= base;
+ if (rem >= 0 && rem <= 9)
+ digit = rem + '0';
+ else if (rem >= 10 && rem <= 36)
+ digit = (rem - 10) + 'a';
+ buf[i] = digit;
+ }
+
+ buf[i] = 0;
+ if (neg)
+ strcat (buf, "-");
+
+ /* reverse the string */
+ for (i = 0, j = strlen (buf) - 1; j >= 0; i++, j--)
+ dst[i] = buf[j];
+ dst[i] = 0;
+ return (dst);
+}
+
+/*
+ * gethex(vp,p,n)
+ * convert n hex digits from p to binary, result in vp,
+ * rtn 1 on success
+ */
+int
+gethex(int32_t *vp, char *p, int n)
+{
+ u_long v;
+ int digit;
+
+ for (v = 0; n > 0; n--) {
+ if (*p == 0)
+ return (0);
+ if (*p >= '0' && *p <= '9')
+ digit = *p - '0';
+ else if (*p >= 'a' && *p <= 'f')
+ digit = *p - 'a' + 10;
+ else if (*p >= 'A' && *p <= 'F')
+ digit = *p - 'A' + 10;
+ else
+ return (0);
+
+ v <<= 4;
+ v |= digit;
+ p++;
+ }
+ *vp = v;
+ return (1);
+}
+
+/* $Id: vsprintf.c,v 1.1.1.1 2006/08/23 17:03:06 pefo Exp $ */
+
+/*
+ * Copyright (c) 2000-2002 Opsycon AB (www.opsycon.se)
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Opsycon AB.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+//#include
+//#include
+//#include
+//#include
+//#include
+#include "c_stdarg.h"
+#include "c_string.h"
+#include "c_ctype.h"
+
+/*
+ * int vsprintf(d,s,ap)
+ */
+int
+vsprintf (char *d, const char *s, va_list ap)
+{
+ const char *t;
+ char *p, *dst, tmp[40];
+ unsigned int n;
+ int fmt, trunc, haddot, width, base, longlong;
+#ifdef FLOATINGPT
+ double dbl;
+
+#ifndef NEWFP
+ EP ex;
+#endif
+#endif
+
+ dst = d;
+ for (; *s;) {
+ if (*s == '%') {
+ s++;
+ fmt = FMT_RJUST;
+ width = trunc = haddot = longlong = 0;
+ for (; *s; s++) {
+ if (strchr("bcdefgilopPrRsuxX%", *s))
+ break;
+ else if (*s == '-')
+ fmt = FMT_LJUST;
+ else if (*s == '0')
+ fmt = FMT_RJUST0;
+ else if (*s == '~')
+ fmt = FMT_CENTER;
+ else if (*s == '*') {
+ if (haddot)
+ trunc = va_arg(ap, int);
+ else
+ width = va_arg(ap, int);
+ } else if (*s >= '1' && *s <= '9') {
+ for (t = s; isdigit(*s); s++);
+ strncpy(tmp, t, s - t);
+ tmp[s - t] = '\0';
+ atob(&n, tmp, 10);
+ if (haddot)
+ trunc = n;
+ else
+ width = n;
+ s--;
+ } else if (*s == '.')
+ haddot = 1;
+ }
+ if (*s == '%') {
+ *d++ = '%';
+ *d = 0;
+ } else if (*s == 's') {
+ p = va_arg(ap, char *);
+
+ if (p)
+ strcpy(d, p);
+ else
+ strcpy(d, "(null)");
+ } else if (*s == 'c') {
+ n = va_arg (ap, int);
+ *d = n;
+ d[1] = 0;
+ } else {
+ if (*s == 'l') {
+ if (*++s == 'l') {
+ longlong = 1;
+ ++s;
+ }
+ }
+ if (strchr("bdiopPrRxXu", *s)) {
+ if (*s == 'd' || *s == 'i')
+ base = -10;
+ else if (*s == 'u')
+ base = 10;
+ else if (*s == 'x' || *s == 'X')
+ base = 16;
+ else if(*s == 'p' || *s == 'P') {
+ base = 16;
+ if (*s == 'p') {
+ *d++ = '0';
+ *d++ = 'x';
+ }
+ fmt = FMT_RJUST0;
+ if (sizeof(long) > 4) {
+ width = 16;
+ longlong = 1;
+ } else {
+ width = 8;
+ }
+ }
+ else if(*s == 'r' || *s == 'R') {
+ base = 16;
+ if (*s == 'r') {
+ *d++ = '0';
+ *d++ = 'x';
+ }
+ fmt = FMT_RJUST0;
+ if (sizeof(register_t) > 4) {
+ width = 16;
+ longlong = 1;
+ } else {
+ width = 8;
+ }
+ }
+ else if (*s == 'o')
+ base = 8;
+ else if (*s == 'b')
+ base = 2;
+ if (longlong)
+ llbtoa(d, va_arg (ap, quad_t),
+ base);
+ else
+ btoa(d, va_arg (ap, int), base);
+
+ if (*s == 'X')
+ strtoupper(d);
+ }
+#ifdef FLOATINGPT
+ else if (strchr ("eEfgG", *s)) {
+//static void dtoa (char *, double, int, int, int);
+void dtoa (char *dbuf, rtype arg, int fmtch, int width, int prec);
+ dbl = va_arg(ap, double);
+ dtoa(d, dbl, *s, width, trunc);
+ trunc = 0;
+ }
+#endif
+ }
+ if (trunc)
+ d[trunc] = 0;
+ if (width)
+ str_fmt (d, width, fmt);
+ for (; *d; d++);
+ s++;
+ } else
+ *d++ = *s++;
+ }
+ *d = 0;
+ return (d - dst);
+}
+
+#ifdef FLOATINGPT
+/*
+ * Floating point output, cvt() onward lifted from BSD sources:
+ *
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+
+#define MAX_FCONVERSION 512 /* largest possible real conversion */
+#define MAX_EXPT 5 /* largest possible exponent field */
+#define MAX_FRACT 39 /* largest possible fraction field */
+
+#define TESTFLAG(x) 0
+
+
+typedef double rtype;
+
+extern double modf(double, double *);
+#define to_char(n) ((n) + '0')
+#define to_digit(c) ((c) - '0')
+#define _isNan(arg) ((arg) != (arg))
+
+static int cvt (rtype arg, int prec, char *signp, int fmtch,
+ char *startp, char *endp);
+static char *c_round (double fract, int *exp, char *start, char *end,
+ char ch, char *signp);
+static char *exponent(char *p, int exp, int fmtch);
+
+
+/*
+ * _finite arg not Infinity or Nan
+ */
+static int _finite(rtype d)
+{
+#if ENDIAN == ENDIAN_LITTLE
+ struct IEEEdp {
+ unsigned manl:32;
+ unsigned manh:20;
+ unsigned exp:11;
+ unsigned sign:1;
+ } *ip;
#else
- len += i2a(ipart, bf);
+ struct IEEEdp {
+ unsigned sign:1;
+ unsigned exp:11;
+ unsigned manh:20;
+ unsigned manl:32;
+ } *ip;
#endif
-#ifndef EPSILON
-#define EPSILON ((double)(0.00000001))
-#endif
- if (fpart < EPSILON)
- {
- // fpart is zero
+ ip = (struct IEEEdp *)&d;
+ return (ip->exp != 0x7ff);
+}
+
+
+void dtoa (char *dbuf, rtype arg, int fmtch, int width, int prec)
+{
+ char buf[MAX_FCONVERSION+1], *cp;
+ char sign;
+ int size;
+
+ if( !_finite(arg) ) {
+ if( _isNan(arg) )
+ strcpy (dbuf, "NaN");
+ else if( arg < 0)
+ strcpy (dbuf, "-Infinity");
+ else
+ strcpy (dbuf, "Infinity");
+ return;
+ }
+
+ if (prec == 0)
+ prec = 6;
+ else if (prec > MAX_FRACT)
+ prec = MAX_FRACT;
+
+ /* leave room for sign at start of buffer */
+ cp = buf + 1;
+
+ /*
+ * cvt may have to round up before the "start" of
+ * its buffer, i.e. ``intf("%.2f", (double)9.999);'';
+ * if the first character is still NUL, it did.
+ * softsign avoids negative 0 if _double < 0 but
+ * no significant digits will be shown.
+ */
+ *cp = '\0';
+ size = cvt (arg, prec, &sign, fmtch, cp, buf + sizeof(buf));
+ if (*cp == '\0')
+ cp++;
+
+ if (sign)
+ *--cp = sign, size++;
+
+ cp[size] = 0;
+ memcpy (dbuf, cp, size + 1);
+}
+
+
+static int
+cvt(rtype number, int prec, char *signp, int fmtch, char *startp, char *endp)
+{
+ register char *p, *t;
+ register double fract;
+ double integer, tmp;
+ int dotrim, expcnt, gformat;
+
+ dotrim = expcnt = gformat = 0;
+ if (number < 0) {
+ number = -number;
+ *signp = '-';
+ } else
+ *signp = 0;
+
+ fract = modf(number, &integer);
+
+ /* get an extra slot for rounding. */
+ t = ++startp;
+
+ /*
+ * get integer portion of number; put into the end of the buffer; the
+ * .01 is added for modf(356.0 / 10, &integer) returning .59999999...
+ */
+ for (p = endp - 1; integer; ++expcnt) {
+ tmp = modf(integer / 10, &integer);
+ *p-- = to_char((int)((tmp + .01) * 10));
+ }
+ switch (fmtch) {
+ case 'f':
+ /* reverse integer into beginning of buffer */
+ if (expcnt)
+ for (; ++p < endp; *t++ = *p);
+ else
+ *t++ = '0';
+ /*
+ * if precision required or alternate flag set, add in a
+ * decimal point.
+ */
+ if (prec || TESTFLAG(ALTERNATE_FORM))
+ *t++ = '.';
+ /* if requires more precision and some fraction left */
+ if (fract) {
+ if (prec)
+ do {
+ fract = modf(fract * 10, &tmp);
+ *t++ = to_char((int)tmp);
+ } while (--prec && fract);
+ if (fract)
+ startp = c_round(fract, (int *)NULL, startp,
+ t - 1, (char)0, signp);
+ }
+ for (; prec--; *t++ = '0');
+ break;
+ case 'e':
+ case 'E':
+eformat: if (expcnt) {
+ *t++ = *++p;
+ if (prec || TESTFLAG(ALTERNATE_FORM))
+ *t++ = '.';
+ /* if requires more precision and some integer left */
+ for (; prec && ++p < endp; --prec)
+ *t++ = *p;
+ /*
+ * if done precision and more of the integer component,
+ * round using it; adjust fract so we don't re-round
+ * later.
+ */
+ if (!prec && ++p < endp) {
+ fract = 0;
+ startp = c_round((double)0, &expcnt, startp,
+ t - 1, *p, signp);
+ }
+ /* adjust expcnt for digit in front of decimal */
+ --expcnt;
+ }
+ /* until first fractional digit, decrement exponent */
+ else if (fract) {
+ /* adjust expcnt for digit in front of decimal */
+ for (expcnt = -1;; --expcnt) {
+ fract = modf(fract * 10, &tmp);
+ if (tmp)
+ break;
+ }
+ *t++ = to_char((int)tmp);
+ if (prec || TESTFLAG(ALTERNATE_FORM))
+ *t++ = '.';
+ }
+ else {
+ *t++ = '0';
+ if (prec || TESTFLAG(ALTERNATE_FORM))
+ *t++ = '.';
+ }
+ /* if requires more precision and some fraction left */
+ if (fract) {
+ if (prec)
+ do {
+ fract = modf(fract * 10, &tmp);
+ *t++ = to_char((int)tmp);
+ } while (--prec && fract);
+ if (fract)
+ startp = c_round(fract, &expcnt, startp,
+ t - 1, (char)0, signp);
+ }
+ /* if requires more precision */
+ for (; prec--; *t++ = '0');
+
+ /* unless alternate flag, trim any g/G format trailing 0's */
+ if (gformat && !TESTFLAG(ALTERNATE_FORM)) {
+ while (t > startp && *--t == '0');
+ if (*t == '.')
+ --t;
+ ++t;
+ }
+ t = exponent(t, expcnt, fmtch);
+ break;
+ case 'g':
+ case 'G':
+ /* a precision of 0 is treated as a precision of 1. */
+ if (!prec)
+ ++prec;
+ /*
+ * ``The style used depends on the value converted; style e
+ * will be used only if the exponent resulting from the
+ * conversion is less than -4 or greater than the precision.''
+ * -- ANSI X3J11
+ */
+ if (expcnt > prec || (!expcnt && fract && fract < .0001)) {
+ /*
+ * g/G format counts "significant digits, not digits of
+ * precision; for the e/E format, this just causes an
+ * off-by-one problem, i.e. g/G considers the digit
+ * before the decimal point significant and e/E doesn't
+ * count it as precision.
+ */
+ --prec;
+ fmtch -= 2; /* G->E, g->e */
+ gformat = 1;
+ goto eformat;
+ }
+ /*
+ * reverse integer into beginning of buffer,
+ * note, decrement precision
+ */
+ if (expcnt)
+ for (; ++p < endp; *t++ = *p, --prec);
+ else
+ *t++ = '0';
+ /*
+ * if precision required or alternate flag set, add in a
+ * decimal point. If no digits yet, add in leading 0.
+ */
+ if (prec || TESTFLAG(ALTERNATE_FORM)) {
+ dotrim = 1;
+ *t++ = '.';
+ }
+ else
+ dotrim = 0;
+ /* if requires more precision and some fraction left */
+ if (fract) {
+ if (prec) {
+ do {
+ fract = modf(fract * 10, &tmp);
+ *t++ = to_char((int)tmp);
+ } while(!tmp && !expcnt);
+ while (--prec && fract) {
+ fract = modf(fract * 10, &tmp);
+ *t++ = to_char((int)tmp);
+ }
+ }
+ if (fract)
+ startp = c_round(fract, (int *)NULL, startp,
+ t - 1, (char)0, signp);
+ }
+ /* alternate format, adds 0's for precision, else trim 0's */
+ if (TESTFLAG(ALTERNATE_FORM))
+ for (; prec--; *t++ = '0');
+ else if (dotrim) {
+ while (t > startp && *--t == '0');
+ if (*t != '.')
+ ++t;
+ }
+ }
+ return (t - startp);
+}
+
+
+static char *
+c_round(double fract, int *exp, char *start, char *end, char ch, char *signp)
+{
+ double tmp;
+
+ if (fract)
+ (void)modf(fract * 10, &tmp);
+ else
+ tmp = to_digit(ch);
+ if (tmp > 4)
+ for (;; --end) {
+ if (*end == '.')
+ --end;
+ if (++*end <= '9')
+ break;
+ *end = '0';
+ if (end == start) {
+ if (exp) { /* e/E; increment exponent */
+ *end = '1';
+ ++*exp;
+ }
+ else { /* f; add extra digit */
+ *--end = '1';
+ --start;
+ }
+ break;
+ }
+ }
+ /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
+ else if (*signp == '-')
+ for (;; --end) {
+ if (*end == '.')
+ --end;
+ if (*end != '0')
+ break;
+ if (end == start)
+ *signp = 0;
+ }
+ return (start);
+}
+
+static char *
+exponent(char *p, int exp, int fmtch)
+{
+ char *t;
+ char expbuf[MAX_FCONVERSION];
+
+ *p++ = fmtch;
+ if (exp < 0) {
+ exp = -exp;
+ *p++ = '-';
}
else
- {
- bf += len;
- // add dot
- *bf ++ = '.';
- len += 1;
- // add zero after dot
- while (fpart < 0.1)
- {
- fpart *= 10;
- *bf ++ = '0';
- len += 1;
- }
- while ((fpart < (double)1.0 / EPSILON) && ((fpart - (int)fpart) > EPSILON))
- {
- fpart = fpart * 10;
- }
-#ifdef PRINTF_LONG_SUPPORT
- len += li2a((int)fpart, bf);
-#else
- len += i2a((int)fpart, bf);
-#endif
+ *p++ = '+';
+ t = expbuf + MAX_FCONVERSION;
+ if (exp > 9) {
+ do {
+ *--t = to_char(exp % 10);
+ } while ((exp /= 10) > 9);
+ *--t = to_char(exp);
+ for (; t < expbuf + MAX_FCONVERSION; *p++ = *t++);
}
-#undef EPSILON
- if (num < 0)
- {
- len ++;
+ else {
+ *p++ = '0';
+ *p++ = to_char(exp);
}
- return len;
-}
-
-static int a2d(char ch)
-{
- if (ch >= '0' && ch <= '9')
- return ch - '0';
- else if (ch >= 'a' && ch <= 'f')
- return ch - 'a' + 10;
- else if (ch >= 'A' && ch <= 'F')
- return ch - 'A' + 10;
- else return -1;
-}
-
-static char a2i(char ch, char **src, int base, int *nump)
-{
- char *p = *src;
- int num = 0;
- int digit;
- while ((digit = a2d(ch)) >= 0)
- {
- if (digit > base) break;
- num = num * base + digit;
- ch = *p++;
- }
- *src = p;
- *nump = num;
- return ch;
-}
-
-static void putchw(void *putp, putcf putf, int n, char z, char *bf)
-{
- char fc = z ? '0' : ' ';
- char ch;
- char *p = bf;
- while (*p++ && n > 0)
- n--;
- while (n-- > 0)
- putf(putp, fc);
- while ((ch = *bf++))
- putf(putp, ch);
-}
-
-void c_format(void *putp, putcf putf, char *fmt, va_list va)
-{
- char bf[12];
-
- char ch;
-
-
- while ((ch = *(fmt++)))
- {
- if (ch != '%')
- putf(putp, ch);
- else
- {
- char lz = 0;
-#ifdef PRINTF_LONG_SUPPORT
- char lng = 0;
-#endif
- int w = 0;
- ch = *(fmt++);
- if (ch == '0')
- {
- ch = *(fmt++);
- lz = 1;
- }
- if (ch >= '0' && ch <= '9')
- {
- ch = a2i(ch, &fmt, 10, &w);
- }
-#ifdef PRINTF_LONG_SUPPORT
- if (ch == 'l')
- {
- ch = *(fmt++);
- lng = 1;
- }
-#endif
- switch (ch)
- {
- case 0:
- goto abort;
- case 'u' :
- {
-#ifdef PRINTF_LONG_SUPPORT
- if (lng)
- uli2a(va_arg(va, unsigned long int), 10, 0, bf);
- else
-#endif
- ui2a(va_arg(va, unsigned int), 10, 0, bf);
- putchw(putp, putf, w, lz, bf);
- break;
- }
- case 'o' :
- {
-#ifdef PRINTF_LONG_SUPPORT
- if (lng)
- uli2a(va_arg(va, unsigned long int), 8, 0, bf);
- else
-#endif
- ui2a(va_arg(va, unsigned int), 8, 0, bf);
- putchw(putp, putf, w, lz, bf);
- break;
- }
- case 'd' : case 'i':
- {
-#ifdef PRINTF_LONG_SUPPORT
- if (lng)
- li2a(va_arg(va, unsigned long int), bf);
- else
-#endif
- i2a(va_arg(va, int), bf);
- putchw(putp, putf, w, lz, bf);
- break;
- }
- case 'x': case 'X' :
-#ifdef PRINTF_LONG_SUPPORT
- if (lng)
- uli2a(va_arg(va, unsigned long int), 16, (ch == 'X'), bf);
- else
-#endif
- ui2a(va_arg(va, unsigned int), 16, (ch == 'X'), bf);
- putchw(putp, putf, w, lz, bf);
- break;
- case 'e': case 'E': case 'f':
- case 'g': case 'G':
- {
- d2a(va_arg(va, double), bf);
- putchw(putp, putf, w, lz, bf);
- break;
- }
- case 'c' :
- putf(putp, (char)(va_arg(va, int)));
- break;
- case 's' :
- putchw(putp, putf, w, 0, va_arg(va, char *));
- break;
- case '%' :
- putf(putp, ch);
- default:
- break;
- }
- }
- }
-abort:;
-}
-
-
-static void putcp(void *p, char c)
-{
- *(*((char **)p))++ = c;
+ return (p);
}
+#endif /* FLOATINGPT */
void c_sprintf(char *s, char *fmt, ...)
{
- va_list va;
- va_start(va, fmt);
- c_format(&s, putcp, fmt, va);
- putcp(&s, 0);
- va_end(va);
+ va_list arg;
+ va_start(arg, fmt);
+ vsprintf(s, fmt, arg);
+ va_end(arg);
}
#endif
diff --git a/app/libc/c_stdlib.c b/app/libc/c_stdlib.c
index fffd47b5..a180cad8 100644
--- a/app/libc/c_stdlib.c
+++ b/app/libc/c_stdlib.c
@@ -3,68 +3,65 @@
#include "c_types.h"
#include "c_string.h"
#include "user_interface.h"
+#include "user_config.h"
// const char *lua_init_value = "print(\"Hello world\")";
const char *lua_init_value = "@init.lua";
// int c_abs(int x){
-// return x>0?x:0-x;
+// return x>0?x:0-x;
// }
// void c_exit(int e){
// }
-const char *c_getenv(const char *__string){
- if (c_strcmp(__string, "LUA_INIT") == 0){
- return lua_init_value;
- }
- return NULL;
+const char *c_getenv(const char *__string)
+{
+ if (c_strcmp(__string, "LUA_INIT") == 0)
+ {
+ return lua_init_value;
+ }
+ return NULL;
}
// make sure there is enough memory before real malloc, otherwise malloc will panic and reset
// void *c_malloc(size_t __size){
-// if(__size>system_get_free_heap_size()){
-// NODE_ERR("malloc: not enough memory\n");
-// return NULL;
-// }
-// return (void *)os_malloc(__size);
+// if(__size>system_get_free_heap_size()){
+// NODE_ERR("malloc: not enough memory\n");
+// return NULL;
+// }
+// return (void *)os_malloc(__size);
// }
// void *c_zalloc(size_t __size){
-// if(__size>system_get_free_heap_size()){
-// NODE_ERR("zalloc: not enough memory\n");
-// return NULL;
-// }
-// return (void *)os_zalloc(__size);
+// if(__size>system_get_free_heap_size()){
+// NODE_ERR("zalloc: not enough memory\n");
+// return NULL;
+// }
+// return (void *)os_zalloc(__size);
// }
// void c_free(void *p){
-// // NODE_ERR("free1: %d\n", system_get_free_heap_size());
-// os_free(p);
-// // NODE_ERR("-free1: %d\n", system_get_free_heap_size());
+// // NODE_ERR("free1: %d\n", system_get_free_heap_size());
+// os_free(p);
+// // NODE_ERR("-free1: %d\n", system_get_free_heap_size());
// }
-// int c_rand(void){
+// int c_rand(void){
// }
// void c_srand(unsigned int __seed){
// }
-// int c_atoi(const char *__nptr){
+// int c_atoi(const char *__nptr){
// }
#include <_ansi.h>
//#include
#include
//#include "mprec.h"
-double c_strtod(const char *string, char **endPtr)
+double powersOf10[] ICACHE_STORE_ATTR ICACHE_RODATA_ATTR = /* Table giving binary powers of 10. Entry */
{
- int maxExponent = 511; /* Largest possible base 10 exponent. Any
- * exponent larger than this will already
- * produce underflow or overflow, so there's
- * no need to worry about additional digits.
- */
- double powersOf10[] = { /* Table giving binary powers of 10. Entry */
- 10., /* is 10^2^i. Used to convert decimal */
- 100., /* exponents into floating-point numbers. */
+ 10., /* is 10^2^i. Used to convert decimal */
+ 100., /* exponents into floating-point numbers. */
1.0e4,
1.0e8,
1.0e16,
@@ -72,43 +69,57 @@ double c_strtod(const char *string, char **endPtr)
1.0e64,
1.0e128,
1.0e256
- };
+};
+
+double c_strtod(const char *string, char **endPtr)
+{
+ int maxExponent = 511; /* Largest possible base 10 exponent. Any
+ * exponent larger than this will already
+ * produce underflow or overflow, so there's
+ * no need to worry about additional digits.
+ */
+
int sign, expSign = FALSE;
double fraction, dblExp, *d;
register const char *p;
register int c;
- int exp = 0; /* Exponent read from "EX" field. */
- int fracExp = 0; /* Exponent that derives from the fractional
- * part. Under normal circumstatnces, it is
- * the negative of the number of digits in F.
- * However, if I is very long, the last digits
- * of I get dropped (otherwise a long I with a
- * large negative exponent could cause an
- * unnecessary overflow on I alone). In this
- * case, fracExp is incremented one for each
- * dropped digit. */
- int mantSize; /* Number of digits in mantissa. */
- int decPt; /* Number of mantissa digits BEFORE decimal
- * point. */
- const char *pExp; /* Temporarily holds location of exponent
- * in string. */
+ int exp = 0; /* Exponent read from "EX" field. */
+ int fracExp = 0; /* Exponent that derives from the fractional
+ * part. Under normal circumstatnces, it is
+ * the negative of the number of digits in F.
+ * However, if I is very long, the last digits
+ * of I get dropped (otherwise a long I with a
+ * large negative exponent could cause an
+ * unnecessary overflow on I alone). In this
+ * case, fracExp is incremented one for each
+ * dropped digit. */
+ int mantSize; /* Number of digits in mantissa. */
+ int decPt; /* Number of mantissa digits BEFORE decimal
+ * point. */
+ const char *pExp; /* Temporarily holds location of exponent
+ * in string. */
/*
* Strip off leading blanks and check for a sign.
*/
p = string;
- while (isspace((unsigned char)(*p))) {
- p += 1;
+ while (isspace((unsigned char)(*p)))
+ {
+ p += 1;
}
- if (*p == '-') {
- sign = TRUE;
- p += 1;
- } else {
- if (*p == '+') {
- p += 1;
- }
- sign = FALSE;
+ if (*p == '-')
+ {
+ sign = TRUE;
+ p += 1;
+ }
+ else
+ {
+ if (*p == '+')
+ {
+ p += 1;
+ }
+ sign = FALSE;
}
/*
@@ -119,14 +130,16 @@ double c_strtod(const char *string, char **endPtr)
decPt = -1;
for (mantSize = 0; ; mantSize += 1)
{
- c = *p;
- if (!isdigit(c)) {
- if ((c != '.') || (decPt >= 0)) {
- break;
- }
- decPt = mantSize;
- }
- p += 1;
+ c = *p;
+ if (!isdigit(c))
+ {
+ if ((c != '.') || (decPt >= 0))
+ {
+ break;
+ }
+ decPt = mantSize;
+ }
+ p += 1;
}
/*
@@ -135,49 +148,60 @@ double c_strtod(const char *string, char **endPtr)
* If the mantissa has more than 18 digits, ignore the extras, since
* they can't affect the value anyway.
*/
-
+
pExp = p;
p -= mantSize;
- if (decPt < 0) {
- decPt = mantSize;
- } else {
- mantSize -= 1; /* One of the digits was the point. */
+ if (decPt < 0)
+ {
+ decPt = mantSize;
}
- if (mantSize > 18) {
- fracExp = decPt - 18;
- mantSize = 18;
- } else {
- fracExp = decPt - mantSize;
+ else
+ {
+ mantSize -= 1; /* One of the digits was the point. */
}
- if (mantSize == 0) {
- fraction = 0.0;
- p = string;
- goto done;
- } else {
- int frac1, frac2;
- frac1 = 0;
- for ( ; mantSize > 9; mantSize -= 1)
- {
- c = *p;
- p += 1;
- if (c == '.') {
- c = *p;
- p += 1;
- }
- frac1 = 10*frac1 + (c - '0');
- }
- frac2 = 0;
- for (; mantSize > 0; mantSize -= 1)
- {
- c = *p;
- p += 1;
- if (c == '.') {
- c = *p;
- p += 1;
- }
- frac2 = 10*frac2 + (c - '0');
- }
- fraction = (1.0e9 * frac1) + frac2;
+ if (mantSize > 18)
+ {
+ fracExp = decPt - 18;
+ mantSize = 18;
+ }
+ else
+ {
+ fracExp = decPt - mantSize;
+ }
+ if (mantSize == 0)
+ {
+ fraction = 0.0;
+ p = string;
+ goto done;
+ }
+ else
+ {
+ int frac1, frac2;
+ frac1 = 0;
+ for ( ; mantSize > 9; mantSize -= 1)
+ {
+ c = *p;
+ p += 1;
+ if (c == '.')
+ {
+ c = *p;
+ p += 1;
+ }
+ frac1 = 10 * frac1 + (c - '0');
+ }
+ frac2 = 0;
+ for (; mantSize > 0; mantSize -= 1)
+ {
+ c = *p;
+ p += 1;
+ if (c == '.')
+ {
+ c = *p;
+ p += 1;
+ }
+ frac2 = 10 * frac2 + (c - '0');
+ }
+ fraction = (1.0e9 * frac1) + frac2;
}
/*
@@ -185,30 +209,40 @@ double c_strtod(const char *string, char **endPtr)
*/
p = pExp;
- if ((*p == 'E') || (*p == 'e')) {
- p += 1;
- if (*p == '-') {
- expSign = TRUE;
- p += 1;
- } else {
- if (*p == '+') {
- p += 1;
- }
- expSign = FALSE;
- }
- if (!isdigit((unsigned char)(*p))) {
- p = pExp;
- goto done;
- }
- while (isdigit((unsigned char)(*p))) {
- exp = exp * 10 + (*p - '0');
- p += 1;
- }
+ if ((*p == 'E') || (*p == 'e'))
+ {
+ p += 1;
+ if (*p == '-')
+ {
+ expSign = TRUE;
+ p += 1;
+ }
+ else
+ {
+ if (*p == '+')
+ {
+ p += 1;
+ }
+ expSign = FALSE;
+ }
+ if (!isdigit((unsigned char)(*p)))
+ {
+ p = pExp;
+ goto done;
+ }
+ while (isdigit((unsigned char)(*p)))
+ {
+ exp = exp * 10 + (*p - '0');
+ p += 1;
+ }
}
- if (expSign) {
- exp = fracExp - exp;
- } else {
- exp = fracExp + exp;
+ if (expSign)
+ {
+ exp = fracExp - exp;
+ }
+ else
+ {
+ exp = fracExp + exp;
}
/*
@@ -217,41 +251,52 @@ double c_strtod(const char *string, char **endPtr)
* many powers of 2 of 10. Then combine the exponent with the
* fraction.
*/
-
- if (exp < 0) {
- expSign = TRUE;
- exp = -exp;
- } else {
- expSign = FALSE;
+
+ if (exp < 0)
+ {
+ expSign = TRUE;
+ exp = -exp;
}
- if (exp > maxExponent) {
- exp = maxExponent;
- // errno = ERANGE;
+ else
+ {
+ expSign = FALSE;
+ }
+ if (exp > maxExponent)
+ {
+ exp = maxExponent;
+ // errno = ERANGE;
}
dblExp = 1.0;
- for (d = powersOf10; exp != 0; exp >>= 1, d += 1) {
- if (exp & 01) {
- dblExp *= *d;
- }
+ for (d = powersOf10; exp != 0; exp >>= 1, d += 1)
+ {
+ if (exp & 01)
+ {
+ dblExp *= *d;
+ }
}
- if (expSign) {
- fraction /= dblExp;
- } else {
- fraction *= dblExp;
+ if (expSign)
+ {
+ fraction /= dblExp;
+ }
+ else
+ {
+ fraction *= dblExp;
}
done:
- if (endPtr != NULL) {
- *endPtr = (char *) p;
+ if (endPtr != NULL)
+ {
+ *endPtr = (char *) p;
}
- if (sign) {
- return -fraction;
+ if (sign)
+ {
+ return -fraction;
}
return fraction;
}
-// long c_strtol(const char *__n, char **__end_PTR, int __base){
+// long c_strtol(const char *__n, char **__end_PTR, int __base){
// }
// unsigned long c_strtoul(const char *__n, char **__end_PTR, int __base){
// }
diff --git a/app/lua/lauxlib.c b/app/lua/lauxlib.c
index fedd7c56..64618f1b 100644
--- a/app/lua/lauxlib.c
+++ b/app/lua/lauxlib.c
@@ -652,7 +652,8 @@ LUALIB_API int luaL_loadfile (lua_State *L, const char *filename) {
typedef struct LoadFSF {
int extraline;
int f;
- char buff[LUAL_BUFFERSIZE];
+ char *buff;
+ int len;
} LoadFSF;
@@ -665,7 +666,7 @@ static const char *getFSF (lua_State *L, void *ud, size_t *size) {
return "\n";
}
if (fs_eof(lf->f)) return NULL;
- *size = fs_read(lf->f, lf->buff, sizeof(lf->buff));
+ *size = fs_read(lf->f, lf->buff, (lf->len));
return (*size > 0) ? lf->buff : NULL;
}
@@ -684,6 +685,9 @@ LUALIB_API int luaL_loadfsfile (lua_State *L, const char *filename) {
int c;
int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */
lf.extraline = 0;
+ // lf.len = LUAL_BUFFERSIZE;
+ lf.len = 0;
+ lf.buff = NULL;
if (filename == NULL) {
return luaL_error(L, "filename is NULL");
}
@@ -692,6 +696,10 @@ LUALIB_API int luaL_loadfsfile (lua_State *L, const char *filename) {
lf.f = fs_open(filename, FS_RDONLY);
if (lf.f < FS_OPEN_OK) return errfsfile(L, "open", fnameindex);
}
+ lf.len = fs_size(lf.f) + 32;
+ lf.buff = c_zalloc(lf.len);
+ if(!lf.buff) return LUA_ERRMEM;
+
c = fs_getc(lf.f);
if (c == '#') { /* Unix exec. file? */
lf.extraline = 1;
@@ -701,7 +709,13 @@ LUALIB_API int luaL_loadfsfile (lua_State *L, const char *filename) {
if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */
fs_close(lf.f);
lf.f = fs_open(filename, FS_RDONLY); /* reopen in binary mode */
- if (lf.f < FS_OPEN_OK) return errfsfile(L, "reopen", fnameindex);
+ if (lf.f < FS_OPEN_OK){
+ if(lf.buff)
+ c_free(lf.buff);
+ lf.buff = NULL;
+ lf.len = 0;
+ return errfsfile(L, "reopen", fnameindex);
+ }
/* skip eventual `#!...' */
while ((c = fs_getc(lf.f)) != EOF && c != LUA_SIGNATURE[0]) ;
lf.extraline = 0;
@@ -711,6 +725,9 @@ LUALIB_API int luaL_loadfsfile (lua_State *L, const char *filename) {
if (filename) fs_close(lf.f); /* close file (even in case of errors) */
lua_remove(L, fnameindex);
+ if(lf.buff)
+ c_free(lf.buff);
+ lf.buff = NULL;
return status;
}
diff --git a/app/lua/lua.c b/app/lua/lua.c
index ef9113f4..27bb3b4b 100644
--- a/app/lua/lua.c
+++ b/app/lua/lua.c
@@ -30,10 +30,13 @@ lua_Load gLoad;
static const char *progname = LUA_PROGNAME;
+#ifdef DEVKIT_VERSION_0_9
static int key_press_count = 0;
int led_high_count = LED_HIGH_COUNT_DEFAULT;
int led_low_count = LED_LOW_COUNT_DEFAULT;
static int led_count = 0;
+#endif
+
#if 0
static void lstop (lua_State *L, lua_Debug *ar) {
(void)ar; /* unused arg. */
@@ -541,6 +544,7 @@ void dojob(lua_Load *load){
// NODE_DBG("dojob() is called with firstline.\n");
}
+#ifdef DEVKIT_VERSION_0_9
extern void key_long_press(void *arg);
extern void key_short_press(void *arg);
static bool key_short_pressed = false;
@@ -579,6 +583,7 @@ void update_key_led(){
}
}
}
+#endif
#ifndef uart_putc
#define uart_putc uart0_putc
@@ -590,7 +595,9 @@ extern uint16_t need_len;
extern int16_t end_char;
void readline(lua_Load *load){
// NODE_DBG("readline() is called.\n");
+#ifdef DEVKIT_VERSION_0_9
update_key_led();
+#endif
char ch;
while (uart_getc(&ch))
{
diff --git a/app/lua/luaconf.h b/app/lua/luaconf.h
index 08c50c59..d1078468 100644
--- a/app/lua/luaconf.h
+++ b/app/lua/luaconf.h
@@ -108,7 +108,7 @@
#define LUA_CDIR LUA_ROOT "lib/lua/5.1/"
#ifndef LUA_RPC
-#define LUA_PATH_DEFAULT "?.lua;?.lc"
+#define LUA_PATH_DEFAULT "?.lc;?.lua"
#define LUA_CPATH_DEFAULT ""
#else // #ifndef LUA_RPC
#define LUA_PATH_DEFAULT \
@@ -601,8 +601,7 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
#endif // #if !defined LUA_INTEGRAL_LONGLONG
#else
#define LUA_NUMBER_SCAN "%lf"
-//#define LUA_NUMBER_FMT "%.14g"
-#define LUA_NUMBER_FMT "%g"
+#define LUA_NUMBER_FMT "%.14g"
#endif // #if defined LUA_NUMBER_INTEGRAL
#define lua_number2str(s,n) c_sprintf((s), LUA_NUMBER_FMT, (n))
#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */
diff --git a/app/modules/file.c b/app/modules/file.c
index f6548890..c402bbf2 100644
--- a/app/modules/file.c
+++ b/app/modules/file.c
@@ -125,7 +125,7 @@ static int file_remove( lua_State* L )
if( len > FS_NAME_MAX_LENGTH )
return luaL_error(L, "filename too long");
file_close(L);
- SPIFFS_remove(&fs, fname);
+ SPIFFS_remove(&fs, (char *)fname);
return 0;
}
@@ -150,6 +150,31 @@ static int file_check( lua_State* L )
}
#endif
+// Lua: rename("oldname", "newname")
+static int file_rename( lua_State* L )
+{
+ size_t len;
+ if((FS_OPEN_OK - 1)!=file_fd){
+ fs_close(file_fd);
+ file_fd = FS_OPEN_OK - 1;
+ }
+
+ const char *oldname = luaL_checklstring( L, 1, &len );
+ if( len > FS_NAME_MAX_LENGTH )
+ return luaL_error(L, "filename too long");
+
+ const char *newname = luaL_checklstring( L, 2, &len );
+ if( len > FS_NAME_MAX_LENGTH )
+ return luaL_error(L, "filename too long");
+
+ if(SPIFFS_OK==myspiffs_rename( oldname, newname )){
+ lua_pushboolean(L, 1);
+ } else {
+ lua_pushboolean(L, 0);
+ }
+ return 1;
+}
+
#endif
// g_read()
@@ -282,6 +307,7 @@ const LUA_REG_TYPE file_map[] =
{ LSTRKEY( "seek" ), LFUNCVAL( file_seek ) },
{ LSTRKEY( "flush" ), LFUNCVAL( file_flush ) },
// { LSTRKEY( "check" ), LFUNCVAL( file_check ) },
+ { LSTRKEY( "rename" ), LFUNCVAL( file_rename ) },
#endif
#if LUA_OPTIMIZE_MEMORY > 0
diff --git a/app/modules/net.c b/app/modules/net.c
index 51639b54..5b9dba9d 100644
--- a/app/modules/net.c
+++ b/app/modules/net.c
@@ -1241,6 +1241,31 @@ static int net_socket_unhold( lua_State* L )
return 0;
}
+// Lua: ip,port = sk:getpeer()
+static int net_socket_getpeer( lua_State* L )
+{
+ lnet_userdata *nud;
+ const char *mt = "net.socket";
+ nud = (lnet_userdata *)luaL_checkudata(L, 1, mt);
+ luaL_argcheck(L, nud, 1, "Server/Socket expected");
+
+ if(nud!=NULL && nud->pesp_conn!=NULL ){
+ char temp[20] = {0};
+ c_sprintf(temp, IPSTR, IP2STR( &(nud->pesp_conn->proto.tcp->remote_ip) ) );
+ if ( nud->pesp_conn->proto.tcp->remote_port != 0 ) {
+ lua_pushstring( L, temp );
+ lua_pushinteger( L, nud->pesp_conn->proto.tcp->remote_port );
+ } else {
+ lua_pushnil( L );
+ lua_pushnil( L );
+ }
+ } else {
+ lua_pushnil( L );
+ lua_pushnil( L );
+ }
+ return 2;
+}
+
// Lua: socket:dns( string, function(ip) )
static int net_socket_dns( lua_State* L )
{
@@ -1302,6 +1327,7 @@ static const LUA_REG_TYPE net_socket_map[] =
{ LSTRKEY( "hold" ), LFUNCVAL ( net_socket_hold ) },
{ LSTRKEY( "unhold" ), LFUNCVAL ( net_socket_unhold ) },
{ LSTRKEY( "dns" ), LFUNCVAL ( net_socket_dns ) },
+ { LSTRKEY( "getpeer" ), LFUNCVAL ( net_socket_getpeer ) },
// { LSTRKEY( "delete" ), LFUNCVAL ( net_socket_delete ) },
{ LSTRKEY( "__gc" ), LFUNCVAL ( net_socket_delete ) },
#if LUA_OPTIMIZE_MEMORY > 0
diff --git a/app/modules/node.c b/app/modules/node.c
index 11b7b6b6..90dd0d96 100644
--- a/app/modules/node.c
+++ b/app/modules/node.c
@@ -1,8 +1,16 @@
// Module for interfacing with system
-//#include "lua.h"
-#include "lualib.h"
+#include "lua.h"
#include "lauxlib.h"
+
+#include "ldo.h"
+#include "lfunc.h"
+#include "lmem.h"
+#include "lobject.h"
+#include "lopcodes.h"
+#include "lstring.h"
+#include "lundump.h"
+
#include "platform.h"
#include "auxmods.h"
#include "lrotable.h"
@@ -14,6 +22,7 @@
//#include "spi_flash.h"
#include "user_interface.h"
#include "flash_api.h"
+#include "flash_fs.h"
// Lua: restart()
static int node_restart( lua_State* L )
@@ -124,6 +133,9 @@ static int node_heap( lua_State* L )
return 1;
}
+static lua_State *gL = NULL;
+
+#ifdef DEVKIT_VERSION_0_9
extern int led_high_count; // this is defined in lua.c
extern int led_low_count;
// Lua: led(low, high)
@@ -155,7 +167,6 @@ static int node_led( lua_State* L )
static int long_key_ref = LUA_NOREF;
static int short_key_ref = LUA_NOREF;
-static lua_State *gL = NULL;
void default_long_press(void *arg){
if(led_high_count == 12 && led_low_count == 12){
@@ -228,6 +239,7 @@ static int node_key( lua_State* L )
return 0;
}
+#endif
extern lua_Load gLoad;
extern os_timer_t lua_timer;
@@ -308,6 +320,73 @@ static int node_output( lua_State* L )
return 0;
}
+static int writer(lua_State* L, const void* p, size_t size, void* u)
+{
+ UNUSED(L);
+ int file_fd = *( (int *)u );
+ if((FS_OPEN_OK - 1)==file_fd)
+ return 1;
+ NODE_DBG("get fd:%d,size:%d\n",file_fd,size);
+
+ if(size!=0 && (size!=fs_write(file_fd, (const char *)p, size)) )
+ return 1;
+ NODE_DBG("write fd:%d,size:%d\n",file_fd,size);
+ return 0;
+}
+
+#define toproto(L,i) (clvalue(L->top+(i))->l.p)
+// Lua: compile(filename) -- compile lua file into lua bytecode, and save to .lc
+static int node_compile( lua_State* L )
+{
+ Proto* f;
+ int file_fd = FS_OPEN_OK - 1;
+ size_t len;
+ const char *fname = luaL_checklstring( L, 1, &len );
+ if( len > FS_NAME_MAX_LENGTH )
+ return luaL_error(L, "filename too long");
+
+ char output[FS_NAME_MAX_LENGTH];
+ c_strcpy(output, fname);
+ // check here that filename end with ".lua".
+ if(len<4 || (c_strcmp( output+len-4,".lua")!=0) )
+ return luaL_error(L, "not a .lua file");
+
+ output[c_strlen(output)-2] = 'c';
+ output[c_strlen(output)-1] = '\0';
+ NODE_DBG(output);
+ NODE_DBG("\n");
+ if (luaL_loadfsfile(L,fname)!=0){
+ return luaL_error(L, lua_tostring(L,-1));
+ }
+
+ f = toproto(L,-1);
+
+ int stripping = 1; /* strip debug information? */
+
+ file_fd = fs_open(output, fs_mode2flag("w+"));
+ if(file_fd < FS_OPEN_OK)
+ {
+ return luaL_error(L, "cannot open/write to file");
+ }
+
+ lua_lock(L);
+ int result=luaU_dump(L,f,writer,&file_fd,stripping);
+ lua_unlock(L);
+
+ fs_flush(file_fd);
+ fs_close(file_fd);
+ file_fd = FS_OPEN_OK - 1;
+
+ if (result==LUA_ERR_CC_INTOVERFLOW){
+ return luaL_error(L, "value too big or small for target integer type");
+ }
+ if (result==LUA_ERR_CC_NOTINTEGER){
+ return luaL_error(L, "target lua_Number is integral but fractional value found");
+ }
+
+ return 0;
+}
+
// Module function map
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
@@ -320,11 +399,14 @@ const LUA_REG_TYPE node_map[] =
{ LSTRKEY( "flashid" ), LFUNCVAL( node_flashid ) },
{ LSTRKEY( "flashsize" ), LFUNCVAL( node_flashsize) },
{ LSTRKEY( "heap" ), LFUNCVAL( node_heap ) },
+#ifdef DEVKIT_VERSION_0_9
{ LSTRKEY( "key" ), LFUNCVAL( node_key ) },
{ LSTRKEY( "led" ), LFUNCVAL( node_led ) },
+#endif
{ LSTRKEY( "input" ), LFUNCVAL( node_input ) },
{ LSTRKEY( "output" ), LFUNCVAL( node_output ) },
{ LSTRKEY( "readvdd33" ), LFUNCVAL( node_readvdd33) },
+ { LSTRKEY( "compile" ), LFUNCVAL( node_compile) },
// Combined to dsleep(us, option)
// { LSTRKEY( "dsleepsetoption" ), LFUNCVAL( node_deepsleep_setoption) },
#if LUA_OPTIMIZE_MEMORY > 0
diff --git a/app/modules/wifi.c b/app/modules/wifi.c
index 4acdd304..635625c6 100644
--- a/app/modules/wifi.c
+++ b/app/modules/wifi.c
@@ -256,8 +256,19 @@ static int wifi_setip( lua_State* L, uint8_t mode )
ip = parse_key(L, "gateway");
if(ip!=0)
pTempIp.gw.addr = ip;
- wifi_station_dhcpc_stop();
- lua_pushboolean(L,wifi_set_ip_info(mode, &pTempIp));
+
+ if(STATION_IF == mode)
+ {
+ wifi_station_dhcpc_stop();
+ lua_pushboolean(L,wifi_set_ip_info(mode, &pTempIp));
+ }
+ else
+ {
+ wifi_softap_dhcps_stop();
+ lua_pushboolean(L,wifi_set_ip_info(mode, &pTempIp));
+ wifi_softap_dhcps_start();
+ }
+
return 1;
}
diff --git a/app/platform/cpu_esp8266.h b/app/platform/cpu_esp8266.h
index 6e98e18a..75a238dc 100644
--- a/app/platform/cpu_esp8266.h
+++ b/app/platform/cpu_esp8266.h
@@ -25,6 +25,10 @@
#define FLASH_SEC_NUM 0x200
#elif defined(FLASH_4M)
#define FLASH_SEC_NUM 0x400
+#elif defined(FLASH_8M)
+#define FLASH_SEC_NUM 0x800
+#elif defined(FLASH_16M)
+#define FLASH_SEC_NUM 0x1000
#elif defined(FLASH_AUTOSIZE)
#define FLASH_SEC_NUM (flash_get_sec_num())
#else
diff --git a/app/platform/flash_api.c b/app/platform/flash_api.c
index f98621ab..3fde416b 100644
--- a/app/platform/flash_api.c
+++ b/app/platform/flash_api.c
@@ -56,6 +56,12 @@ uint32_t flash_get_size_byte(void)
case SIZE_32MBIT:
// 32Mbit, 4MByte
flash_size = 4 * 1024 * 1024;
+ case SIZE_64MBIT:
+ // 64Mbit, 8MByte
+ flash_size = 8 * 1024 * 1024;
+ case SIZE_128MBIT:
+ // 128Mbit, 16MByte
+ flash_size = 16 * 1024 * 1024;
break;
default:
// Unknown flash size, fall back mode.
diff --git a/app/platform/flash_api.h b/app/platform/flash_api.h
index 929ca998..82d681e3 100644
--- a/app/platform/flash_api.h
+++ b/app/platform/flash_api.h
@@ -52,6 +52,8 @@ typedef struct
SIZE_8MBIT = 2,
SIZE_16MBIT = 3,
SIZE_32MBIT = 4,
+ SIZE_64MBIT = 5,
+ SIZE_128MBIT = 6,
} size : 4;
} ICACHE_STORE_TYPEDEF_ATTR SPIFlashInfo;
diff --git a/app/platform/flash_fs.h b/app/platform/flash_fs.h
index 3ab0421a..9d9da7c7 100644
--- a/app/platform/flash_fs.h
+++ b/app/platform/flash_fs.h
@@ -68,6 +68,8 @@
#define fs_format myspiffs_format
#define fs_check myspiffs_check
+#define fs_rename myspiffs_rename
+#define fs_size myspiffs_size
#define FS_NAME_MAX_LENGTH SPIFFS_OBJ_NAME_LEN
diff --git a/app/platform/platform.c b/app/platform/platform.c
index 3c247c4b..40aa50ad 100644
--- a/app/platform/platform.c
+++ b/app/platform/platform.c
@@ -185,6 +185,8 @@ uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int pari
{
switch( baud )
{
+ case BIT_RATE_300:
+ case BIT_RATE_600:
case BIT_RATE_1200:
case BIT_RATE_2400:
case BIT_RATE_4800:
@@ -195,8 +197,11 @@ uint32_t platform_uart_setup( unsigned id, uint32_t baud, int databits, int pari
case BIT_RATE_74880:
case BIT_RATE_115200:
case BIT_RATE_230400:
+ case BIT_RATE_256000:
case BIT_RATE_460800:
case BIT_RATE_921600:
+ case BIT_RATE_1843200:
+ case BIT_RATE_3686400:
UartDev.baut_rate = baud;
break;
default:
diff --git a/app/spiffs/LICENSE b/app/spiffs/LICENSE
new file mode 100644
index 00000000..e9b0c677
--- /dev/null
+++ b/app/spiffs/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013-2015 Peter Andersson (pelleplutt1976gmail.com)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of
+this software and associated documentation files (the "Software"), to deal in
+the Software without restriction, including without limitation the rights to
+use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+the Software, and to permit persons to whom the Software is furnished to do so,
+subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/app/spiffs/docs/INTEGRATION b/app/spiffs/docs/INTEGRATION
index 703197e4..085ed8fc 100644
--- a/app/spiffs/docs/INTEGRATION
+++ b/app/spiffs/docs/INTEGRATION
@@ -40,7 +40,7 @@ Also, toss up some of the needed buffers:
static u8_t spiffs_work_buf[LOG_PAGE_SIZE*2];
static u8_t spiffs_fds[32*4];
- static u8_t spiffs_cache[(LOG_PAGE_SIZE+32)*4];
+ static u8_t spiffs_cache_buf[(LOG_PAGE_SIZE+32)*4];
Now, write the my_spiffs_mount function:
@@ -50,7 +50,7 @@ Now, write the my_spiffs_mount function:
cfg.phys_addr = 0; // start spiffs at start of spi flash
cfg.phys_erase_block = 65536; // according to datasheet
cfg.log_block_size = 65536; // let us not complicate things
- cfg.log_block_size = LOG_PAGE_SIZE; // as we said
+ cfg.log_page_size = LOG_PAGE_SIZE; // as we said
cfg.hal_read_f = my_spi_read;
cfg.hal_write_f = my_spi_write;
@@ -61,8 +61,8 @@ Now, write the my_spiffs_mount function:
spiffs_work_buf,
spiffs_fds,
sizeof(spiffs_fds),
- spiffs_cache,
- sizeof(spiffs_cache),
+ spiffs_cache_buf,
+ sizeof(spiffs_cache_buf),
0);
printf("mount res: %i\n", res);
}
@@ -127,6 +127,29 @@ Compile, run, cross fingers hard, and you'll get the output:
Got errors? Check spiffs.h for error definitions to get a clue what went voodoo.
+* THINGS TO CHECK
+
+When you alter the spiffs_config values, make sure you also check the typedefs
+in spiffs_config.h:
+
+ - spiffs_block_ix
+ - spiffs_page_ix
+ - spiffs_obj_id
+ - spiffs_span_ix
+
+The sizes of these typedefs must not underflow, else spiffs might end up in
+eternal loops. Each typedef is commented what check for.
+
+Also, if you alter the code or just want to verify your configuration, you can
+run
+
+ > make test
+
+in the spiffs folder. This will run all testcases using the configuration in
+default/spiffs_config.h and test/params_test.h. The tests are written for linux
+but should run under cygwin also.
+
+
* INTEGRATING SPIFFS
In order to integrate spiffs to your embedded target, you will basically need:
diff --git a/app/spiffs/params_test.h b/app/spiffs/params_test.h
deleted file mode 100644
index 38809167..00000000
--- a/app/spiffs/params_test.h
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * params_test.h
- *
- * Created on: May 26, 2013
- * Author: petera
- */
-
-#ifndef PARAMS_TEST_H_
-#define PARAMS_TEST_H_
-
-// // total emulated spi flash size
-// #define PHYS_FLASH_SIZE (16*1024*1024)
-// // spiffs file system size
-// #define SPIFFS_FLASH_SIZE (2*1024*1024)
-// // spiffs file system offset in emulated spi flash
-// #define SPIFFS_PHYS_ADDR (4*1024*1024)
-
-// #define SECTOR_SIZE 65536
-// #define LOG_BLOCK (SECTOR_SIZE*2)
-// #define LOG_PAGE (SECTOR_SIZE/256)
-
-// #define FD_BUF_SIZE 64*6
-// #define CACHE_BUF_SIZE (LOG_PAGE + 32)*8
-
-// #define ASSERT(c, m) real_assert((c),(m), __FILE__, __LINE__);
-
-typedef signed int s32_t;
-typedef unsigned int u32_t;
-typedef signed short s16_t;
-typedef unsigned short u16_t;
-typedef signed char s8_t;
-typedef unsigned char u8_t;
-
-void real_assert(int c, const char *n, const char *file, int l);
-
-#endif /* PARAMS_TEST_H_ */
diff --git a/app/spiffs/spiffs.c b/app/spiffs/spiffs.c
index 4795ae5a..df749e09 100644
--- a/app/spiffs/spiffs.c
+++ b/app/spiffs/spiffs.c
@@ -98,7 +98,7 @@ int myspiffs_check( void )
}
int myspiffs_open(const char *name, int flags){
- return (int)SPIFFS_open(&fs, name, (spiffs_flags)flags, 0);
+ return (int)SPIFFS_open(&fs, (char *)name, (spiffs_flags)flags, 0);
}
int myspiffs_close( int fd ){
@@ -162,6 +162,12 @@ int myspiffs_error( int fd ){
void myspiffs_clearerr( int fd ){
fs.errno = SPIFFS_OK;
}
+int myspiffs_rename( const char *old, const char *newname ){
+ return SPIFFS_rename(&fs, (char *)old, (char *)newname);
+}
+size_t myspiffs_size( int fd ){
+ return SPIFFS_size(&fs, (spiffs_file)fd);
+}
#if 0
void test_spiffs() {
char buf[12];
diff --git a/app/spiffs/spiffs.h b/app/spiffs/spiffs.h
index 9875590c..c4077ede 100644
--- a/app/spiffs/spiffs.h
+++ b/app/spiffs/spiffs.h
@@ -36,6 +36,7 @@
#define SPIFFS_ERR_INDEX_INVALID -10020
#define SPIFFS_ERR_NOT_WRITABLE -10021
#define SPIFFS_ERR_NOT_READABLE -10022
+#define SPIFFS_ERR_CONFLICTING_NAME -10023
#define SPIFFS_ERR_INTERNAL -10050
@@ -225,6 +226,7 @@ struct spiffs_dirent {
u8_t name[SPIFFS_OBJ_NAME_LEN];
spiffs_obj_type type;
u32_t size;
+ spiffs_page_ix pix;
};
typedef struct {
@@ -265,7 +267,7 @@ void SPIFFS_unmount(spiffs *fs);
* @param path the path of the new file
* @param mode ignored, for posix compliance
*/
-s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode);
+s32_t SPIFFS_creat(spiffs *fs, char *path, spiffs_mode mode);
/**
* Opens/creates a file.
@@ -276,7 +278,23 @@ s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode);
* SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT
* @param mode ignored, for posix compliance
*/
-spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode);
+spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode mode);
+
+
+/**
+ * Opens a file by given dir entry.
+ * Optimization purposes, when traversing a file system with SPIFFS_readdir
+ * a normal SPIFFS_open would need to traverse the filesystem again to find
+ * the file, whilst SPIFFS_open_by_dirent already knows where the file resides.
+ * @param fs the file system struct
+ * @param path the dir entry to the file
+ * @param flags the flags for the open command, can be combinations of
+ * SPIFFS_APPEND, SPIFFS_TRUNC, SPIFFS_CREAT, SPIFFS_RD_ONLY,
+ * SPIFFS_WR_ONLY, SPIFFS_RDWR, SPIFFS_DIRECT.
+ * SPIFFS_CREAT will have no effect in this case.
+ * @param mode ignored, for posix compliance
+ */
+spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode);
/**
* Reads from given filehandle.
@@ -314,7 +332,7 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence);
* @param fs the file system struct
* @param path the path of the file to remove
*/
-s32_t SPIFFS_remove(spiffs *fs, const char *path);
+s32_t SPIFFS_remove(spiffs *fs, char *path);
/**
* Removes a file by filehandle
@@ -329,7 +347,7 @@ s32_t SPIFFS_fremove(spiffs *fs, spiffs_file fh);
* @param path the path of the file to stat
* @param s the stat struct to populate
*/
-s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s);
+s32_t SPIFFS_stat(spiffs *fs, char *path, spiffs_stat *s);
/**
* Gets file status by filehandle
@@ -353,6 +371,14 @@ s32_t SPIFFS_fflush(spiffs *fs, spiffs_file fh);
*/
void SPIFFS_close(spiffs *fs, spiffs_file fh);
+/**
+ * Renames a file
+ * @param fs the file system struct
+ * @param old path of file to rename
+ * @param new new path of file
+ */
+s32_t SPIFFS_rename(spiffs *fs, char *old, char *new);
+
/**
* Returns last error of last file operation.
* @param fs the file system struct
@@ -368,7 +394,7 @@ s32_t SPIFFS_errno(spiffs *fs);
* @param name the name of the directory
* @param d pointer the directory stream to be populated
*/
-spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d);
+spiffs_DIR *SPIFFS_opendir(spiffs *fs, char *name, spiffs_DIR *d);
/**
* Closes a directory stream
@@ -397,6 +423,7 @@ s32_t SPIFFS_check(spiffs *fs);
*/
s32_t SPIFFS_eof(spiffs *fs, spiffs_file fh);
s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh);
+s32_t SPIFFS_size(spiffs *fs, spiffs_file fh);
#if SPIFFS_TEST_VISUALISATION
/**
@@ -438,5 +465,6 @@ int myspiffs_flush( int fd );
int myspiffs_error( int fd );
void myspiffs_clearerr( int fd );
int myspiffs_check( void );
+int myspiffs_rename( const char *old, const char *newname );
#endif /* SPIFFS_H_ */
diff --git a/app/spiffs/spiffs_cache.c b/app/spiffs/spiffs_cache.c
index 7c1c6d50..6de0e493 100644
--- a/app/spiffs/spiffs_cache.c
+++ b/app/spiffs/spiffs_cache.c
@@ -124,6 +124,7 @@ s32_t spiffs_phys_rd(
u32_t addr,
u32_t len,
u8_t *dst) {
+ (void)fh;
s32_t res = SPIFFS_OK;
spiffs_cache *cache = spiffs_get_cache(fs);
spiffs_cache_page *cp = spiffs_cache_page_get(fs, SPIFFS_PADDR_TO_PAGE(fs, addr));
@@ -172,6 +173,7 @@ s32_t spiffs_phys_wr(
u32_t addr,
u32_t len,
u8_t *src) {
+ (void)fh;
spiffs_page_ix pix = SPIFFS_PADDR_TO_PAGE(fs, addr);
spiffs_cache *cache = spiffs_get_cache(fs);
spiffs_cache_page *cp = spiffs_cache_page_get(fs, pix);
@@ -249,7 +251,7 @@ spiffs_cache_page *spiffs_cache_page_allocate_by_fd(spiffs *fs, spiffs_fd *fd) {
// unrefers all fds that this cache page refers to and releases the cache page
void spiffs_cache_fd_release(spiffs *fs, spiffs_cache_page *cp) {
if (cp == 0) return;
- int i;
+ u32_t i;
spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
for (i = 0; i < fs->fd_count; i++) {
spiffs_fd *cur_fd = &fds[i];
@@ -282,7 +284,7 @@ void spiffs_cache_init(spiffs *fs) {
spiffs_cache cache;
c_memset(&cache, 0, sizeof(spiffs_cache));
cache.cpage_count = cache_entries;
- cache.cpages = (u8_t *)(fs->cache) + sizeof(spiffs_cache);
+ cache.cpages = (u8_t *)((u8_t *)fs->cache + sizeof(spiffs_cache));
cache.cpage_use_map = 0xffffffff;
cache.cpage_use_mask = cache_mask;
diff --git a/app/spiffs/spiffs_check.c b/app/spiffs/spiffs_check.c
index 3ccdc592..dbe0e80f 100644
--- a/app/spiffs/spiffs_check.c
+++ b/app/spiffs/spiffs_check.c
@@ -156,6 +156,8 @@ static s32_t spiffs_delete_obj_lazy(spiffs *fs, spiffs_obj_id obj_id) {
// validates the given look up entry
static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, spiffs_page_header *p_hdr,
spiffs_page_ix cur_pix, spiffs_block_ix cur_block, int cur_entry, int *reload_lu) {
+ (void)cur_block;
+ (void)cur_entry;
u8_t delete_page = 0;
s32_t res = SPIFFS_OK;
spiffs_page_ix objix_pix;
@@ -327,7 +329,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
} else if (((lu_obj_id & SPIFFS_OBJ_ID_IX_FLAG) && (p_hdr->flags & SPIFFS_PH_FLAG_INDEX)) ||
((lu_obj_id & SPIFFS_OBJ_ID_IX_FLAG) == 0 && (p_hdr->flags & SPIFFS_PH_FLAG_INDEX) == 0)) {
SPIFFS_CHECK_DBG("LU: %04x lu/page index marking differ\n", cur_pix);
- spiffs_page_ix data_pix, objix_pix;
+ spiffs_page_ix data_pix, objix_pix_d;
// see if other data page exists for given obj id and span index
res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id & ~SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, &data_pix);
if (res == SPIFFS_ERR_NOT_FOUND) {
@@ -336,20 +338,20 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
}
SPIFFS_CHECK_RES(res);
// see if other object index exists for given obj id and span index
- res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, &objix_pix);
+ res = spiffs_obj_lu_find_id_and_span(fs, lu_obj_id | SPIFFS_OBJ_ID_IX_FLAG, p_hdr->span_ix, cur_pix, &objix_pix_d);
if (res == SPIFFS_ERR_NOT_FOUND) {
res = SPIFFS_OK;
- objix_pix = 0;
+ objix_pix_d = 0;
}
SPIFFS_CHECK_RES(res);
delete_page = 1;
// if other data page exists and object index exists, just delete page
- if (data_pix && objix_pix) {
+ if (data_pix && objix_pix_d) {
SPIFFS_CHECK_DBG("LU: FIXUP: other index and data page exists, simply remove\n");
} else
// if only data page exists, make this page index
- if (data_pix && objix_pix == 0) {
+ if (data_pix && objix_pix_d == 0) {
SPIFFS_CHECK_DBG("LU: FIXUP: other data page exists, make this index\n");
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_INDEX, lu_obj_id, p_hdr->span_ix);
spiffs_page_header new_ph;
@@ -365,7 +367,7 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
SPIFFS_CHECK_RES(res);
} else
// if only index exists, make data page
- if (data_pix == 0 && objix_pix) {
+ if (data_pix == 0 && objix_pix_d) {
SPIFFS_CHECK_DBG("LU: FIXUP: other index page exists, make this data\n");
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_FIX_LOOKUP, lu_obj_id, p_hdr->span_ix);
spiffs_page_header new_ph;
@@ -426,6 +428,8 @@ static s32_t spiffs_lookup_check_validate(spiffs *fs, spiffs_obj_id lu_obj_id, s
static s32_t spiffs_lookup_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_block_ix cur_block, int cur_entry,
u32_t user_data, void *user_p) {
+ (void)user_data;
+ (void)user_p;
s32_t res = SPIFFS_OK;
spiffs_page_header p_hdr;
spiffs_page_ix cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, cur_block, cur_entry);
@@ -453,6 +457,7 @@ static s32_t spiffs_lookup_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_bloc
// Scans all object look up. For each entry, corresponding page header is checked for validity.
// If an object index header page is found, this is also checked
s32_t spiffs_lookup_consistency_check(spiffs *fs, u8_t check_all_objects) {
+ (void)check_all_objects;
s32_t res = SPIFFS_OK;
if (fs->check_cb_f) fs->check_cb_f(SPIFFS_CHECK_LOOKUP, SPIFFS_CHECK_PROGRESS, 0, 0);
@@ -689,8 +694,8 @@ static s32_t spiffs_page_consistency_check_i(spiffs *fs) {
spiffs_page_ix objix_pix;
spiffs_page_ix rpix;
- int byte_ix;
- int bit_ix;
+ u32_t byte_ix;
+ u8_t bit_ix;
for (byte_ix = 0; !restart && byte_ix < SPIFFS_CFG_LOG_PAGE_SZ(fs); byte_ix++) {
for (bit_ix = 0; !restart && bit_ix < 8/bits; bit_ix ++) {
u8_t bitmask = (fs->work[byte_ix] >> (bit_ix * bits)) & 0x7;
@@ -838,7 +843,7 @@ s32_t spiffs_page_consistency_check(spiffs *fs) {
// searches for given object id in temporary object id index,
// returns the index or -1
static int spiffs_object_index_search(spiffs *fs, spiffs_obj_id obj_id) {
- int i;
+ u32_t i;
spiffs_obj_id *obj_table = (spiffs_obj_id *)fs->work;
obj_id &= ~SPIFFS_OBJ_ID_IX_FLAG;
for (i = 0; i < SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id); i++) {
@@ -849,8 +854,9 @@ static int spiffs_object_index_search(spiffs *fs, spiffs_obj_id obj_id) {
return -1;
}
-s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_block_ix cur_block,
+static s32_t spiffs_object_index_consistency_check_v(spiffs *fs, spiffs_obj_id obj_id, spiffs_block_ix cur_block,
int cur_entry, u32_t user_data, void *user_p) {
+ (void)user_data;
s32_t res_c = SPIFFS_VIS_COUNTINUE;
s32_t res = SPIFFS_OK;
u32_t *log_ix = (u32_t *)user_p;
diff --git a/app/spiffs/spiffs_gc.c b/app/spiffs/spiffs_gc.c
index cfcf3a1d..4d6c8971 100644
--- a/app/spiffs/spiffs_gc.c
+++ b/app/spiffs/spiffs_gc.c
@@ -35,7 +35,7 @@ static s32_t spiffs_gc_erase_block(
#if SPIFFS_CACHE
{
- int i;
+ u32_t i;
for (i = 0; i < SPIFFS_PAGES_PER_BLOCK(fs); i++) {
spiffs_cache_drop_page(fs, SPIFFS_PAGE_FOR_BLOCK(fs, bix) + i);
}
@@ -61,7 +61,7 @@ s32_t spiffs_gc_quick(
fs->stats_gc_runs++;
#endif
- u32_t entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
+ int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
// find fully deleted blocks
// check each block
@@ -70,29 +70,33 @@ s32_t spiffs_gc_quick(
int obj_lookup_page = 0;
// check each object lookup page
- while (res == SPIFFS_OK && obj_lookup_page < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
+ while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
int entry_offset = obj_lookup_page * entries_per_page;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
// check each entry
while (res == SPIFFS_OK &&
- cur_entry - entry_offset < entries_per_page && cur_entry < SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
+ cur_entry - entry_offset < entries_per_page &&
+ cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
if (obj_id == SPIFFS_OBJ_ID_DELETED) {
deleted_pages_in_block++;
} else if (obj_id == SPIFFS_OBJ_ID_FREE) {
// kill scan, go for next block
obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
+ res = 1; // kill object lu loop
break;
} else {
// kill scan, go for next block
obj_lookup_page = SPIFFS_OBJ_LOOKUP_PAGES(fs);
+ res = 1; // kill object lu loop
break;
}
cur_entry++;
} // per entry
obj_lookup_page++;
} // per object lookup page
+ if (res == 1) res = SPIFFS_OK;
if (res == SPIFFS_OK && deleted_pages_in_block == SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
// found a fully deleted block
@@ -184,20 +188,20 @@ s32_t spiffs_gc_erase_page_stats(
spiffs_block_ix bix) {
s32_t res = SPIFFS_OK;
int obj_lookup_page = 0;
- u32_t entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
+ int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
int cur_entry = 0;
u32_t dele = 0;
u32_t allo = 0;
// check each object lookup page
- while (res == SPIFFS_OK && obj_lookup_page < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
+ while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
int entry_offset = obj_lookup_page * entries_per_page;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
// check each entry
while (res == SPIFFS_OK &&
- cur_entry - entry_offset < entries_per_page && cur_entry < SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
+ cur_entry - entry_offset < entries_per_page && cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
if (obj_id == SPIFFS_OBJ_ID_FREE) {
} else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
@@ -239,7 +243,7 @@ s32_t spiffs_gc_find_candidate(
*block_candidates = cand_blocks;
- u32_t entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
+ int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
// check each block
while (res == SPIFFS_OK && blocks--) {
@@ -248,16 +252,18 @@ s32_t spiffs_gc_find_candidate(
int obj_lookup_page = 0;
// check each object lookup page
- while (res == SPIFFS_OK && obj_lookup_page < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
+ while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
int entry_offset = obj_lookup_page * entries_per_page;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
// check each entry
while (res == SPIFFS_OK &&
- cur_entry - entry_offset < entries_per_page && cur_entry < SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
+ cur_entry - entry_offset < entries_per_page &&
+ cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
if (obj_id == SPIFFS_OBJ_ID_FREE) {
// when a free entry is encountered, scan logic ensures that all following entries are free also
+ res = 1; // kill object lu loop
break;
} else if (obj_id == SPIFFS_OBJ_ID_DELETED) {
deleted_pages_in_block++;
@@ -268,6 +274,7 @@ s32_t spiffs_gc_find_candidate(
} // per entry
obj_lookup_page++;
} // per object lookup page
+ if (res == 1) res = SPIFFS_OK;
// calculate score and insert into candidate table
// stoneage sort, but probably not so many blocks
@@ -352,7 +359,7 @@ typedef struct {
//
s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
s32_t res = SPIFFS_OK;
- u32_t entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
+ int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
int cur_entry = 0;
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
spiffs_gc gc;
@@ -380,14 +387,14 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
int obj_lookup_page = cur_entry / entries_per_page;
u8_t scan = 1;
// check each object lookup page
- while (scan && res == SPIFFS_OK && obj_lookup_page < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
+ while (scan && res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
int entry_offset = obj_lookup_page * entries_per_page;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page),
SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
// check each entry
while (scan && res == SPIFFS_OK &&
- cur_entry - entry_offset < entries_per_page && cur_entry < SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
+ cur_entry - entry_offset < entries_per_page && cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
cur_pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, cur_entry);
@@ -526,7 +533,6 @@ s32_t spiffs_gc_clean(spiffs *fs, spiffs_block_ix bix) {
SPIFFS_CHECK_RES(res);
} else {
// store object index page
- spiffs_page_ix new_objix_pix;
res = spiffs_page_move(fs, 0, fs->work, gc.cur_obj_id | SPIFFS_OBJ_ID_IX_FLAG, 0, gc.cur_objix_pix, &new_objix_pix);
SPIFFS_GC_DBG("gc_clean: MOVE_DATA store modified objix page, %04x:%04x\n", new_objix_pix, objix->p_hdr.span_ix);
SPIFFS_CHECK_RES(res);
diff --git a/app/spiffs/spiffs_hydrogen.c b/app/spiffs/spiffs_hydrogen.c
index fcedfb72..20e45ecf 100644
--- a/app/spiffs/spiffs_hydrogen.c
+++ b/app/spiffs/spiffs_hydrogen.c
@@ -51,7 +51,9 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
addr_lsb = (u8_t)(((u32_t)cache) & (ptr_size-1));
// #pragma GCC diagnostic pop
if (addr_lsb) {
- cache = (u8_t *)cache + (ptr_size-addr_lsb);
+ u8_t *cache_8 = (u8_t *)cache;
+ cache_8 += (ptr_size-addr_lsb);
+ cache = cache_8;
cache_size -= (ptr_size-addr_lsb);
}
if (cache_size & (ptr_size-1)) {
@@ -85,7 +87,7 @@ s32_t SPIFFS_mount(spiffs *fs, spiffs_config *config, u8_t *work,
void SPIFFS_unmount(spiffs *fs) {
if (!SPIFFS_CHECK_MOUNT(fs)) return;
SPIFFS_LOCK(fs);
- int i;
+ u32_t i;
spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
for (i = 0; i < fs->fd_count; i++) {
spiffs_fd *cur_fd = &fds[i];
@@ -104,21 +106,23 @@ s32_t SPIFFS_errno(spiffs *fs) {
return fs->errno;
}
-s32_t SPIFFS_creat(spiffs *fs, const char *path, spiffs_mode mode) {
+s32_t SPIFFS_creat(spiffs *fs, char *path, spiffs_mode mode) {
+ (void)mode;
SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs);
spiffs_obj_id obj_id;
s32_t res;
- res = spiffs_obj_lu_find_free_obj_id(fs, &obj_id);
+ res = spiffs_obj_lu_find_free_obj_id(fs, &obj_id, (u8_t *)path);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- res = spiffs_object_create(fs, obj_id, (u8_t*)path, SPIFFS_TYPE_FILE, 0);
+ res = spiffs_object_create(fs, obj_id, (u8_t *)path, SPIFFS_TYPE_FILE, 0);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
SPIFFS_UNLOCK(fs);
return 0;
}
-spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs_mode mode) {
+spiffs_file SPIFFS_open(spiffs *fs, char *path, spiffs_flags flags, spiffs_mode mode) {
+ (void)mode;
SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs);
@@ -138,7 +142,8 @@ spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs
if ((flags & SPIFFS_CREAT) && res == SPIFFS_ERR_NOT_FOUND) {
spiffs_obj_id obj_id;
- res = spiffs_obj_lu_find_free_obj_id(fs, &obj_id);
+ // no need to enter conflicting name here, already looked for it above
+ res = spiffs_obj_lu_find_free_obj_id(fs, &obj_id, 0);
if (res < SPIFFS_OK) {
spiffs_fd_return(fs, fd->file_nbr);
}
@@ -155,7 +160,36 @@ spiffs_file SPIFFS_open(spiffs *fs, const char *path, spiffs_flags flags, spiffs
}
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
}
- res = spiffs_object_open_by_page(fs, pix, fd, flags, flags);
+ res = spiffs_object_open_by_page(fs, pix, fd, flags, mode);
+ if (res < SPIFFS_OK) {
+ spiffs_fd_return(fs, fd->file_nbr);
+ }
+ SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
+ if (flags & SPIFFS_TRUNC) {
+ res = spiffs_object_truncate(fd, 0, 0);
+ if (res < SPIFFS_OK) {
+ spiffs_fd_return(fs, fd->file_nbr);
+ }
+ SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
+ }
+
+ fd->fdoffset = 0;
+
+ SPIFFS_UNLOCK(fs);
+
+ return fd->file_nbr;
+}
+
+spiffs_file SPIFFS_open_by_dirent(spiffs *fs, struct spiffs_dirent *e, spiffs_flags flags, spiffs_mode mode) {
+ SPIFFS_API_CHECK_MOUNT(fs);
+ SPIFFS_LOCK(fs);
+
+ spiffs_fd *fd;
+
+ s32_t res = spiffs_fd_find_new(fs, &fd);
+ SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
+
+ res = spiffs_object_open_by_page(fs, e->pix, fd, flags, mode);
if (res < SPIFFS_OK) {
spiffs_fd_return(fs, fd->file_nbr);
}
@@ -201,12 +235,13 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, u32_t len) {
SPIFFS_API_CHECK_RES_UNLOCK(fs, SPIFFS_ERR_END_OF_OBJECT);
}
res = spiffs_object_read(fd, fd->fdoffset, avail, (u8_t*)buf);
- if (res == SPIFFS_OK) {
+ if (res == SPIFFS_ERR_END_OF_OBJECT) {
fd->fdoffset += avail;
SPIFFS_UNLOCK(fs);
return avail;
} else {
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
+ len = avail;
}
} else {
// reading within file size
@@ -221,14 +256,17 @@ s32_t SPIFFS_read(spiffs *fs, spiffs_file fh, void *buf, u32_t len) {
}
static s32_t spiffs_hydro_write(spiffs *fs, spiffs_fd *fd, void *buf, u32_t offset, s32_t len) {
+ (void)fs;
s32_t res = SPIFFS_OK;
s32_t remaining = len;
if (fd->size != SPIFFS_UNDEFINED_LEN && offset < fd->size) {
- s32_t m_len = MIN(fd->size - offset, len);
+ s32_t m_len = MIN((s32_t)(fd->size - offset), len);
res = spiffs_object_modify(fd, offset, (u8_t *)buf, m_len);
SPIFFS_CHECK_RES(res);
remaining -= m_len;
- buf = (u8_t *)buf + m_len;
+ u8_t *buf_8 = (u8_t *)buf;
+ buf_8 += m_len;
+ buf = buf_8;
offset += m_len;
}
if (remaining > 0) {
@@ -280,7 +318,7 @@ s32_t SPIFFS_write(spiffs *fs, spiffs_file fh, void *buf, u32_t len) {
#if SPIFFS_CACHE_WR
if ((fd->flags & SPIFFS_DIRECT) == 0) {
- if (len < SPIFFS_CFG_LOG_PAGE_SZ(fs)) {
+ if (len < (s32_t)SPIFFS_CFG_LOG_PAGE_SZ(fs)) {
// small write, try to cache it
u8_t alloc_cpage = 1;
if (fd->cache_page) {
@@ -379,7 +417,7 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
break;
}
- if (offs > fd->size) {
+ if (offs > (s32_t)fd->size) {
res = SPIFFS_ERR_END_OF_OBJECT;
}
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
@@ -401,7 +439,7 @@ s32_t SPIFFS_lseek(spiffs *fs, spiffs_file fh, s32_t offs, int whence) {
return 0;
}
-s32_t SPIFFS_remove(spiffs *fs, const char *path) {
+s32_t SPIFFS_remove(spiffs *fs, char *path) {
SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs);
@@ -412,7 +450,7 @@ s32_t SPIFFS_remove(spiffs *fs, const char *path) {
res = spiffs_fd_find_new(fs, &fd);
SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
- res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)path, &pix);
+ res = spiffs_object_find_object_index_header_by_name(fs, (u8_t *)path, &pix);
if (res != SPIFFS_OK) {
spiffs_fd_return(fs, fd->file_nbr);
}
@@ -482,7 +520,7 @@ static s32_t spiffs_stat_pix(spiffs *fs, spiffs_page_ix pix, spiffs_file fh, spi
return res;
}
-s32_t SPIFFS_stat(spiffs *fs, const char *path, spiffs_stat *s) {
+s32_t SPIFFS_stat(spiffs *fs, char *path, spiffs_stat *s) {
SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs);
@@ -580,7 +618,48 @@ void SPIFFS_close(spiffs *fs, spiffs_file fh) {
SPIFFS_UNLOCK(fs);
}
-spiffs_DIR *SPIFFS_opendir(spiffs *fs, const char *name, spiffs_DIR *d) {
+s32_t SPIFFS_rename(spiffs *fs, char *old, char *new) {
+ SPIFFS_API_CHECK_MOUNT(fs);
+ SPIFFS_LOCK(fs);
+
+ spiffs_page_ix pix_old, pix_dummy;
+ spiffs_fd *fd;
+
+ s32_t res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)old, &pix_old);
+ SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
+
+ res = spiffs_object_find_object_index_header_by_name(fs, (u8_t*)new, &pix_dummy);
+ if (res == SPIFFS_ERR_NOT_FOUND) {
+ res = SPIFFS_OK;
+ } else if (res == SPIFFS_OK) {
+ res = SPIFFS_ERR_CONFLICTING_NAME;
+ }
+ SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
+
+ res = spiffs_fd_find_new(fs, &fd);
+ SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
+
+ res = spiffs_object_open_by_page(fs, pix_old, fd, 0, 0);
+ if (res != SPIFFS_OK) {
+ spiffs_fd_return(fs, fd->file_nbr);
+ }
+ SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
+
+ res = spiffs_object_update_index_hdr(fs, fd, fd->obj_id, fd->objix_hdr_pix, 0, (u8_t*)new,
+ 0, &pix_dummy);
+
+ if (res != SPIFFS_OK) {
+ spiffs_fd_return(fs, fd->file_nbr);
+ }
+ SPIFFS_API_CHECK_RES_UNLOCK(fs, res);
+
+ SPIFFS_UNLOCK(fs);
+
+ return res;
+}
+
+spiffs_DIR *SPIFFS_opendir(spiffs *fs, char *name, spiffs_DIR *d) {
+ (void)name;
if (!SPIFFS_CHECK_MOUNT(fs)) {
fs->errno = SPIFFS_ERR_NOT_MOUNTED;
return 0;
@@ -598,6 +677,7 @@ static s32_t spiffs_read_dir_v(
int ix_entry,
u32_t user_data,
void *user_p) {
+ (void)user_data;
s32_t res;
spiffs_page_object_ix_header objix_hdr;
if (obj_id == SPIFFS_OBJ_ID_FREE || obj_id == SPIFFS_OBJ_ID_DELETED ||
@@ -618,6 +698,7 @@ static s32_t spiffs_read_dir_v(
strcpy((char *)e->name, (char *)objix_hdr.name);
e->type = objix_hdr.type;
e->size = objix_hdr.size == SPIFFS_UNDEFINED_LEN ? 0 : objix_hdr.size;
+ e->pix = pix;
return SPIFFS_OK;
}
@@ -670,11 +751,11 @@ s32_t SPIFFS_check(spiffs *fs) {
res = spiffs_lookup_consistency_check(fs, 0);
res = spiffs_object_index_consistency_check(fs);
-// NODE_ERR("before spiffs_object_index_consistency_check\n");
+
res = spiffs_page_consistency_check(fs);
-// NODE_ERR("spiffs_page_consistency_check\n");
+
res = spiffs_obj_lu_scan(fs);
-// NODE_ERR("spiffs_obj_lu_scan\n");
+
SPIFFS_UNLOCK(fs);
return res;
}
@@ -717,13 +798,32 @@ s32_t SPIFFS_tell(spiffs *fs, spiffs_file fh) {
return res;
}
+s32_t SPIFFS_size(spiffs *fs, spiffs_file fh) {
+ SPIFFS_API_CHECK_MOUNT(fs);
+ SPIFFS_LOCK(fs);
+
+ spiffs_fd *fd;
+ s32_t res;
+ res = spiffs_fd_get(fs, fh, &fd);
+ SPIFFS_API_CHECK_RES(fs, res);
+
+#if SPIFFS_CACHE_WR
+ spiffs_fflush_cache(fs, fh);
+#endif
+
+ res = fd->size;
+
+ SPIFFS_UNLOCK(fs);
+ return res;
+}
+
#if SPIFFS_TEST_VISUALISATION
s32_t SPIFFS_vis(spiffs *fs) {
s32_t res = SPIFFS_OK;
SPIFFS_API_CHECK_MOUNT(fs);
SPIFFS_LOCK(fs);
- u32_t entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
+ int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
spiffs_block_ix bix = 0;
@@ -732,13 +832,13 @@ s32_t SPIFFS_vis(spiffs *fs) {
int obj_lookup_page = 0;
int cur_entry = 0;
- while (res == SPIFFS_OK && obj_lookup_page < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
+ while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
int entry_offset = obj_lookup_page * entries_per_page;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
0, bix * SPIFFS_CFG_LOG_BLOCK_SZ(fs) + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
// check each entry
while (res == SPIFFS_OK &&
- cur_entry - entry_offset < entries_per_page && cur_entry < SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
+ cur_entry - entry_offset < entries_per_page && cur_entry < (int)(SPIFFS_PAGES_PER_BLOCK(fs)-SPIFFS_OBJ_LOOKUP_PAGES(fs))) {
spiffs_obj_id obj_id = obj_lu_buf[cur_entry-entry_offset];
if (cur_entry == 0) {
spiffs_printf("%4i ", bix);
diff --git a/app/spiffs/spiffs_nucleus.c b/app/spiffs/spiffs_nucleus.c
index 92ceec05..74217cd0 100644
--- a/app/spiffs/spiffs_nucleus.c
+++ b/app/spiffs/spiffs_nucleus.c
@@ -134,10 +134,10 @@ s32_t spiffs_obj_lu_find_entry_visitor(
spiffs_obj_id *obj_lu_buf = (spiffs_obj_id *)fs->lu_work;
int cur_entry = starting_lu_entry;
- u32_t entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
+ int entries_per_page = (SPIFFS_CFG_LOG_PAGE_SZ(fs) / sizeof(spiffs_obj_id));
// wrap initial
- if (cur_entry >= SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) - 1) {
+ if (cur_entry >= (int)SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs) - 1) {
cur_entry = 0;
cur_block++;
cur_block_addr = cur_block * SPIFFS_CFG_LOG_BLOCK_SZ(fs);
@@ -152,14 +152,14 @@ s32_t spiffs_obj_lu_find_entry_visitor(
while (res == SPIFFS_OK && entry_count > 0) {
int obj_lookup_page = cur_entry / entries_per_page;
// check each object lookup page
- while (res == SPIFFS_OK && obj_lookup_page < SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
+ while (res == SPIFFS_OK && obj_lookup_page < (int)SPIFFS_OBJ_LOOKUP_PAGES(fs)) {
int entry_offset = obj_lookup_page * entries_per_page;
res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU | SPIFFS_OP_C_READ,
0, cur_block_addr + SPIFFS_PAGE_TO_PADDR(fs, obj_lookup_page), SPIFFS_CFG_LOG_PAGE_SZ(fs), fs->lu_work);
// check each entry
while (res == SPIFFS_OK &&
cur_entry - entry_offset < entries_per_page && // for non-last obj lookup pages
- cur_entry < SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs)) // for last obj lookup page
+ cur_entry < (int)SPIFFS_OBJ_LOOKUP_MAX_ENTRIES(fs)) // for last obj lookup page
{
if ((flags & SPIFFS_VIS_CHECK_ID) == 0 || obj_lu_buf[cur_entry-entry_offset] == obj_id) {
if (block_ix) *block_ix = cur_block;
@@ -221,6 +221,9 @@ static s32_t spiffs_obj_lu_scan_v(
int ix_entry,
u32_t user_data,
void *user_p) {
+ (void)bix;
+ (void)user_data;
+ (void)user_p;
if (obj_id == SPIFFS_OBJ_ID_FREE) {
if (ix_entry == 0) {
fs->free_blocks++;
@@ -714,9 +717,10 @@ void spiffs_cb_object_event(
spiffs_span_ix spix,
spiffs_page_ix new_pix,
u32_t new_size) {
+ (void)fd;
// update index caches in all file descriptors
obj_id &= ~SPIFFS_OBJ_ID_IX_FLAG;
- int i;
+ u32_t i;
spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
for (i = 0; i < fs->fd_count; i++) {
spiffs_fd *cur_fd = &fds[i];
@@ -769,6 +773,7 @@ s32_t spiffs_object_open_by_page(
spiffs_fd *fd,
spiffs_flags flags,
spiffs_mode mode) {
+ (void)mode;
s32_t res = SPIFFS_OK;
spiffs_page_object_ix_header oix_hdr;
spiffs_obj_id obj_id;
@@ -1238,6 +1243,7 @@ static s32_t spiffs_object_find_object_index_header_by_name_v(
int ix_entry,
u32_t user_data,
void *user_p) {
+ (void)user_data;
s32_t res;
spiffs_page_object_ix_header objix_hdr;
spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
@@ -1307,7 +1313,7 @@ s32_t spiffs_object_truncate(
spiffs_page_ix objix_pix = fd->objix_hdr_pix;
spiffs_span_ix data_spix = (fd->size > 0 ? fd->size-1 : 0) / SPIFFS_DATA_PAGE_SIZE(fs);
- u32_t cur_size = fd->size == SPIFFS_UNDEFINED_LEN ? 0 : fd->size ;
+ u32_t cur_size = fd->size == (u32_t)SPIFFS_UNDEFINED_LEN ? 0 : fd->size ;
spiffs_span_ix cur_objix_spix = 0;
spiffs_span_ix prev_objix_spix = (spiffs_span_ix)-1;
spiffs_page_object_ix_header *objix_hdr = (spiffs_page_object_ix_header *)fs->work;
@@ -1584,16 +1590,36 @@ typedef struct {
spiffs_obj_id min_obj_id;
spiffs_obj_id max_obj_id;
u32_t compaction;
+ const u8_t *conflicting_name;
} spiffs_free_obj_id_state;
static s32_t spiffs_obj_lu_find_free_obj_id_bitmap_v(spiffs *fs, spiffs_obj_id id, spiffs_block_ix bix, int ix_entry,
u32_t user_data, void *user_p) {
if (id != SPIFFS_OBJ_ID_FREE && id != SPIFFS_OBJ_ID_DELETED) {
spiffs_obj_id min_obj_id = user_data;
+ u8_t *conflicting_name = (u8_t *)user_p;
+
+ // if conflicting name parameter is given, also check if this name is found in object index hdrs
+ if (conflicting_name && (id & SPIFFS_OBJ_ID_IX_FLAG)) {
+ spiffs_page_ix pix = SPIFFS_OBJ_LOOKUP_ENTRY_TO_PIX(fs, bix, ix_entry);
+ int res;
+ spiffs_page_object_ix_header objix_hdr;
+ res = _spiffs_rd(fs, SPIFFS_OP_T_OBJ_LU2 | SPIFFS_OP_C_READ,
+ 0, SPIFFS_PAGE_TO_PADDR(fs, pix), sizeof(spiffs_page_object_ix_header), (u8_t *)&objix_hdr);
+ SPIFFS_CHECK_RES(res);
+ if (objix_hdr.p_hdr.span_ix == 0 &&
+ (objix_hdr.p_hdr.flags & (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_FINAL | SPIFFS_PH_FLAG_IXDELE)) ==
+ (SPIFFS_PH_FLAG_DELET | SPIFFS_PH_FLAG_IXDELE)) {
+ if (strcmp((char *)user_p, (char *)objix_hdr.name) == 0) {
+ return SPIFFS_ERR_CONFLICTING_NAME;
+ }
+ }
+ }
+
id &= ~SPIFFS_OBJ_ID_IX_FLAG;
- int bit_ix = (id-min_obj_id) & 7;
+ u32_t bit_ix = (id-min_obj_id) & 7;
int byte_ix = (id-min_obj_id) >> 3;
- if (byte_ix >= 0 && byte_ix < SPIFFS_CFG_LOG_PAGE_SZ(fs)) {
+ if (byte_ix >= 0 && (u32_t)byte_ix < SPIFFS_CFG_LOG_PAGE_SZ(fs)) {
fs->work[byte_ix] |= (1<conflicting_name && strcmp((const char *)state->conflicting_name, (char *)objix_hdr.name) == 0) {
+ return SPIFFS_ERR_CONFLICTING_NAME;
+ }
+
id &= ~SPIFFS_OBJ_ID_IX_FLAG;
if (id >= state->min_obj_id && id <= state->max_obj_id) {
u8_t *map = (u8_t *)fs->work;
@@ -1629,7 +1660,7 @@ static s32_t spiffs_obj_lu_find_free_obj_id_compact_v(spiffs *fs, spiffs_obj_id
// object ids cannot fit into a work buffer, these are grouped. When a group containing free
// object ids is found, the object lu is again scanned for object ids within group and bitmasked.
// Finally, the bitmasked is searched for a free id
-s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id) {
+s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id, u8_t *conflicting_name) {
s32_t res = SPIFFS_OK;
u32_t max_objects = (SPIFFS_CFG_PHYS_SZ(fs) / (u32_t)SPIFFS_CFG_LOG_PAGE_SZ(fs)) / 2;
spiffs_free_obj_id_state state;
@@ -1640,14 +1671,16 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id) {
state.max_obj_id = ((spiffs_obj_id)-1) & ~SPIFFS_OBJ_ID_IX_FLAG;
}
state.compaction = 0;
+ state.conflicting_name = conflicting_name;
while (res == SPIFFS_OK && free_obj_id == SPIFFS_OBJ_ID_FREE) {
- if (state.max_obj_id - state.min_obj_id <= SPIFFS_CFG_LOG_PAGE_SZ(fs)*8) {
+ if (state.max_obj_id - state.min_obj_id <= (spiffs_obj_id)SPIFFS_CFG_LOG_PAGE_SZ(fs)*8) {
// possible to represent in bitmap
- int i, j;
+ u32_t i, j;
SPIFFS_DBG("free_obj_id: BITM min:%04x max:%04x\n", state.min_obj_id, state.max_obj_id);
c_memset(fs->work, 0, SPIFFS_CFG_LOG_PAGE_SZ(fs));
- res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_bitmap_v, state.min_obj_id, 0, 0, 0);
+ res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_bitmap_v, state.min_obj_id,
+ conflicting_name, 0, 0);
if (res == SPIFFS_VIS_END) res = SPIFFS_OK;
SPIFFS_CHECK_RES(res);
// traverse bitmask until found free obj_id
@@ -1668,7 +1701,7 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id) {
// not possible to represent all ids in range in a bitmap, compact and count
if (state.compaction != 0) {
// select element in compacted table, decrease range and recompact
- int i, min_i = 0;
+ u32_t i, min_i = 0;
u8_t *map = (u8_t *)fs->work;
u8_t min_count = 0xff;
@@ -1700,7 +1733,7 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id) {
state.max_obj_id = state.min_obj_id + state.compaction;
// decrease compaction
}
- if ((state.max_obj_id - state.min_obj_id <= SPIFFS_CFG_LOG_PAGE_SZ(fs)*8)) {
+ if ((state.max_obj_id - state.min_obj_id <= (spiffs_obj_id)SPIFFS_CFG_LOG_PAGE_SZ(fs)*8)) {
// no need for compacting, use bitmap
continue;
}
@@ -1714,6 +1747,7 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id) {
res = spiffs_obj_lu_find_entry_visitor(fs, 0, 0, 0, 0, spiffs_obj_lu_find_free_obj_id_compact_v, 0, &state, 0, 0);
if (res == SPIFFS_VIS_END) res = SPIFFS_OK;
SPIFFS_CHECK_RES(res);
+ state.conflicting_name = 0; // searched for conflicting name once, no need to do it again
}
}
@@ -1721,7 +1755,7 @@ s32_t spiffs_obj_lu_find_free_obj_id(spiffs *fs, spiffs_obj_id *obj_id) {
}
s32_t spiffs_fd_find_new(spiffs *fs, spiffs_fd **fd) {
- int i;
+ u32_t i;
spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
for (i = 0; i < fs->fd_count; i++) {
spiffs_fd *cur_fd = &fds[i];
@@ -1735,7 +1769,7 @@ s32_t spiffs_fd_find_new(spiffs *fs, spiffs_fd **fd) {
}
s32_t spiffs_fd_return(spiffs *fs, spiffs_file f) {
- if (f <= 0 || f > fs->fd_count) {
+ if (f <= 0 || f > (s16_t)fs->fd_count) {
return SPIFFS_ERR_BAD_DESCRIPTOR;
}
spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
@@ -1748,7 +1782,7 @@ s32_t spiffs_fd_return(spiffs *fs, spiffs_file f) {
}
s32_t spiffs_fd_get(spiffs *fs, spiffs_file f, spiffs_fd **fd) {
- if (f <= 0 || f > fs->fd_count) {
+ if (f <= 0 || f > (s16_t)fs->fd_count) {
return SPIFFS_ERR_BAD_DESCRIPTOR;
}
spiffs_fd *fds = (spiffs_fd *)fs->fd_space;
diff --git a/app/spiffs/spiffs_nucleus.h b/app/spiffs/spiffs_nucleus.h
index 49b33053..9b10d918 100644
--- a/app/spiffs/spiffs_nucleus.h
+++ b/app/spiffs/spiffs_nucleus.h
@@ -126,7 +126,7 @@
#define SPIFFS_OBJ_ID_IX_FLAG (1<<(8*sizeof(spiffs_obj_id)-1))
-#define SPIFFS_UNDEFINED_LEN (-1)
+#define SPIFFS_UNDEFINED_LEN (u32_t)(-1)
#define SPIFFS_OBJ_ID_DELETED ((spiffs_obj_id)0)
#define SPIFFS_OBJ_ID_FREE ((spiffs_obj_id)-1)
@@ -487,7 +487,8 @@ s32_t spiffs_obj_lu_scan(
s32_t spiffs_obj_lu_find_free_obj_id(
spiffs *fs,
- spiffs_obj_id *obj_id);
+ spiffs_obj_id *obj_id,
+ u8_t *conflicting_name);
s32_t spiffs_obj_lu_find_free(
spiffs *fs,
diff --git a/examples/fragment.lua b/examples/fragment.lua
index b4fb10dd..bceadaf3 100644
--- a/examples/fragment.lua
+++ b/examples/fragment.lua
@@ -339,3 +339,11 @@ uart.on("data",4, function(data)
end
end, 0)
+file.open("hello.lua","w+")
+file.writeline([[print("hello nodemcu")]])
+file.writeline([[print(node.heap())]])
+file.close()
+
+node.compile("hello.lua")
+dofile("hello.lua")
+dofile("hello.lc")
diff --git a/lua_examples/irsend.lua b/lua_examples/irsend.lua
index 6469a4c0..ed1cb98b 100644
--- a/lua_examples/irsend.lua
+++ b/lua_examples/irsend.lua
@@ -57,7 +57,7 @@ do
pulse(pin, NEC_HDR_MARK)
waitus(NEC_HDR_SPACE)
-- sequence, lsb first
- for i = 0, 31 do
+ for i = 31, 0, -1 do
pulse(pin, NEC_BIT_MARK)
waitus(isset(code, i) and NEC_ONE_SPACE or NEC_ZERO_SPACE)
end
diff --git a/pre_build/0.9.5/nodemcu_20150127.bin b/pre_build/0.9.5/nodemcu_20150127.bin
new file mode 100644
index 00000000..17112015
Binary files /dev/null and b/pre_build/0.9.5/nodemcu_20150127.bin differ
diff --git a/pre_build/0.9.5/nodemcu_20150212.bin b/pre_build/0.9.5/nodemcu_20150212.bin
new file mode 100644
index 00000000..887e4833
Binary files /dev/null and b/pre_build/0.9.5/nodemcu_20150212.bin differ
diff --git a/pre_build/0.9.5/nodemcu_20150213.bin b/pre_build/0.9.5/nodemcu_20150213.bin
new file mode 100644
index 00000000..cb4fa0b1
Binary files /dev/null and b/pre_build/0.9.5/nodemcu_20150213.bin differ
diff --git a/pre_build/latest/nodemcu_latest.bin b/pre_build/latest/nodemcu_latest.bin
index 17112015..acc14e99 100644
Binary files a/pre_build/latest/nodemcu_latest.bin and b/pre_build/latest/nodemcu_latest.bin differ