summaryrefslogtreecommitdiffstats
path: root/apps/plugins
diff options
context:
space:
mode:
authorWilliam Wilgus <me.theuser@yahoo.com>2018-10-29 02:54:35 -0400
committerWilliam Wilgus <me.theuser@yahoo.com>2018-10-29 23:22:35 -0400
commiteab73b3deead4054ba8a1d9165b577ad935b9a05 (patch)
treeadf00c7efe610bb268a26109aa7cd9de3b26ca09 /apps/plugins
parentcc0a4c632aeda82ab4517355b4b4489190da013e (diff)
downloadrockbox-eab73b3deead4054ba8a1d9165b577ad935b9a05.tar.gz
rockbox-eab73b3deead4054ba8a1d9165b577ad935b9a05.tar.bz2
rockbox-eab73b3deead4054ba8a1d9165b577ad935b9a05.zip
Lua replace fscanf
Rocklua was using the full fscanf implementation to simply read %ld for the file:read("*n") function wasting 1k on unneeded/unused functionality Instead, I've implemented a filetol function to duplicate it without the extra overhead using strtol which as an added bonus ERANGE errors now resolve to LONG_MIN and LONGMAX instead of integer overflow filetol() reads long int from an open file, skips preceding whitespaces returns -1 if error, 1 on success. *num set to LONG_MAX or LONG_MIN on overflow. If number of digits is > than LUAI_MAXNUMBER2STR filepointer will continue till the next non digit but buffer will stop being filled with characters. Preceding zero is ignored. Change-Id: Ia42d0f73c63a894625bca4581e9b7e1cc7387fd2
Diffstat (limited to 'apps/plugins')
-rw-r--r--apps/plugins/lua/SOURCES1
-rw-r--r--apps/plugins/lua/fscanf.c291
-rw-r--r--apps/plugins/lua/liolib.c3
-rw-r--r--apps/plugins/lua/rockaux.c63
-rw-r--r--apps/plugins/lua/rocklib.h1
-rw-r--r--apps/plugins/lua/rocklibc.h2
6 files changed, 66 insertions, 295 deletions
diff --git a/apps/plugins/lua/SOURCES b/apps/plugins/lua/SOURCES
index ff40046eb0..8877a4164d 100644
--- a/apps/plugins/lua/SOURCES
+++ b/apps/plugins/lua/SOURCES
@@ -30,7 +30,6 @@ rockaux.c
rocklib.c
rocklib_img.c
tlsf_helper.c
-fscanf.c
strftime.c
strpbrk.c
strtoul.c
diff --git a/apps/plugins/lua/fscanf.c b/apps/plugins/lua/fscanf.c
deleted file mode 100644
index 9f5f129d3c..0000000000
--- a/apps/plugins/lua/fscanf.c
+++ /dev/null
@@ -1,291 +0,0 @@
-/***************************************************************************
- * __________ __ ___.
- * Open \______ \ ____ ____ | | _\_ |__ _______ ___
- * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
- * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
- * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
- * \/ \/ \/ \/ \/
- * $Id$
- *
- * Copied from firmware/common/sscanf.c
- * Original author: Tomasz Malesinski
- *
- * Copyright (C) 2010 Maurus Cuelenaere
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
- * KIND, either express or implied.
- *
- ****************************************************************************/
-
-#include "rocklibc.h"
-
-static int parse_dec(int (*peek)(void *userp),
- void (*pop)(void *userp),
- void *userp,
- long *vp)
-{
- long v = 0;
- int n = 0;
- int minus = 0;
- char ch;
-
- if ((*peek)(userp) == '-')
- {
- (*pop)(userp);
- n++;
- minus = 1;
- }
-
- ch = (*peek)(userp);
- if (!isdigit(ch))
- return -1;
-
- do
- {
- v = v * 10 + ch - '0';
- (*pop)(userp);
- n++;
- ch = (*peek)(userp);
- } while (isdigit(ch));
-
- *vp = minus ? -v : v;
- return n;
-}
-
-static int parse_chars(int (*peek)(void *userp),
- void (*pop)(void *userp),
- void *userp,
- char *vp,
- bool fake)
-{
- int n = 0;
-
- char *pt=vp;
-
- while (!isspace((*peek)(userp)))
- {
- if(fake==false)
- *(pt++) = (*peek)(userp);
-
- n++;
- (*pop)(userp);
- }
-
- if(fake==false)
- (*pt)='\0';
-
- return n;
-}
-
-static int parse_hex(int (*peek)(void *userp),
- void (*pop)(void *userp),
- void *userp,
- unsigned long *vp)
-{
- unsigned long v = 0;
- int n = 0;
- char ch;
-
- ch = (*peek)(userp);
- if (!isxdigit(ch))
- return -1;
-
- do
- {
- if (ch >= 'a')
- ch = ch - 'a' + 10;
- else if (ch >= 'A')
- ch = ch - 'A' + 10;
- else
- ch = ch - '0';
- v = v * 16 + ch;
- (*pop)(userp);
- n++;
- ch = (*peek)(userp);
- } while (isxdigit(ch));
-
- *vp = v;
- return n;
-}
-
-static int skip_spaces(int (*peek)(void *userp),
- void (*pop)(void *userp),
- void *userp)
-{
- int n = 0;
- while (isspace((*peek)(userp))) {
- n++;
- (*pop)(userp);
- }
- return n;
-}
-
-static int scan(int (*peek)(void *userp),
- void (*pop)(void *userp),
- void *userp,
- const char *fmt,
- va_list ap)
-{
- char ch;
- int n = 0;
- int n_chars = 0;
- int r;
- long lval;
- bool skip=false;
- unsigned long ulval;
-
- while ((ch = *fmt++) != '\0')
- {
- bool literal = false;
-
- if (ch == '%')
- {
- ch = *fmt++;
-
- if(ch== '*') /* We should process this, but not store it in an argument */
- {
- ch=*fmt++;
- skip=true;
- }
- else
- {
- skip=false;
- }
-
- switch (ch)
- {
- case 'x':
- n_chars += skip_spaces(peek, pop, userp);
- if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0)
- {
- if(skip==false)
- {
- *(va_arg(ap, unsigned int *)) = ulval;
- n++;
- }
- n_chars += r;
- }
- else
- return n;
- break;
- case 'd':
- n_chars += skip_spaces(peek, pop, userp);
- if ((r = parse_dec(peek, pop, userp, &lval)) >= 0)
- {
- if(skip==false)
- {
- *(va_arg(ap, int *)) = lval;
- n++;
- }
- n_chars += r;
- }
- else
- return n;
- break;
- case 'n':
- if(skip==false)
- {
- *(va_arg(ap, int *)) = n_chars;
- n++;
- }
- break;
- case 'l':
- n_chars += skip_spaces(peek, pop, userp);
- ch = *fmt++;
- switch (ch)
- {
- case 'x':
- if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0)
- {
- if(skip==false)
- {
- *(va_arg(ap, unsigned long *)) = ulval;
- n++;
- }
- n_chars += r;
- }
- else
- return n;
- break;
- case 'd':
- if ((r = parse_dec(peek, pop, userp, &lval)) >= 0)
- {
- if(skip==false)
- {
- *(va_arg(ap, long *)) = lval;
- n++;
- }
- n_chars += r;
- }
- else
- return n;
- break;
- case '\0':
- return n;
- default:
- literal = true;
- break;
- }
- break;
- case 's':
- n_chars += skip_spaces(peek, pop, userp);
- n_chars += parse_chars(peek,pop, userp,skip?0:va_arg(ap, char *), skip );
- if(skip==false)
- {
- n++;
- }
- break;
- case '\0':
- return n;
- default:
- literal = true;
- break;
- }
- } else
- literal = true;
-
- if (literal)
- {
- n_chars += skip_spaces(peek, pop, userp);
- if ((*peek)(userp) != ch)
- continue;
- else
- {
- (*pop)(userp);
- n_chars++;
- }
- }
- }
- return n;
-}
-
-static int fspeek(void *userp)
-{
- int fd = *((int*) userp);
- char buf = 0;
- if(rb->read(fd, &buf, 1) == 1)
- rb->lseek(fd, -1, SEEK_CUR);
- return buf;
-}
-
-static void fspop(void *userp)
-{
- int fd = *((int*) userp);
- rb->lseek(fd, 1, SEEK_CUR);
-}
-
-int PREFIX(fscanf)(int fd, const char *fmt, ...)
-{
- int r;
- va_list ap;
-
- va_start(ap, fmt);
- r = scan(fspeek, fspop, &fd, fmt, ap);
- va_end(ap);
- return r;
-}
diff --git a/apps/plugins/lua/liolib.c b/apps/plugins/lua/liolib.c
index 970543d4d5..6744efedd5 100644
--- a/apps/plugins/lua/liolib.c
+++ b/apps/plugins/lua/liolib.c
@@ -17,6 +17,7 @@
#include "lauxlib.h"
#include "lualib.h"
#include "rocklibc.h"
+#include "rocklib.h"
#include "llimits.h"
@@ -247,7 +248,7 @@ static int io_lines (lua_State *L) {
static int read_number (lua_State *L, int *f) {
lua_Number d;
- if (PREFIX(fscanf)(*f, LUA_NUMBER_SCAN, &d) == 1) {
+ if (filetol(*f, &d) == 1) { /* was fscanf(f, LUA_NUMBER_SCAN, &d)*/
lua_pushnumber(L, d);
return 1;
}
diff --git a/apps/plugins/lua/rockaux.c b/apps/plugins/lua/rockaux.c
index ba3a37343b..562d1654a7 100644
--- a/apps/plugins/lua/rockaux.c
+++ b/apps/plugins/lua/rockaux.c
@@ -8,6 +8,7 @@
* $Id$
*
* Copyright (C) 2008 Dan Everton (safetydan)
+ * Copyright (C) 2018 William Wilgus
* String function implementations taken from dietlibc 0.31 (GPLv2 License)
*
* This program is free software; you can redistribute it and/or
@@ -24,6 +25,8 @@
#define _ROCKCONF_H_ /* Protect against unwanted include */
#include "lua.h"
+extern long strtol(const char *nptr, char **endptr, int base);
+
#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
int errno = 0;
#endif
@@ -101,3 +104,63 @@ int get_current_path(lua_State *L, int level)
lua_pushnil(L);
return 1;
}
+
+/* filetol()
+ reads long int from an open file, skips preceding
+ whitespaces returns -1 if error, 1 on success.
+ *num set to LONG_MAX or LONG_MIN on overflow.
+ If number of digits is > than LUAI_MAXNUMBER2STR
+ filepointer will continue till the next non digit
+ but buffer will stop being filled with characters.
+ Preceding zero is ignored
+*/
+int filetol(int fd, long *num)
+{
+ static char buffer[LUAI_MAXNUMBER2STR];
+ int retn = -1;
+ char chbuf = 0;
+ size_t count = 0;
+ bool neg = false;
+ long val;
+
+ while (rb->read(fd, &chbuf, 1) == 1)
+ {
+ if(!isspace(chbuf) || retn == 1)
+ {
+ if(chbuf == '0') /* strip preceeding zeros */
+ {
+ *num = 0;
+ retn = 1;
+ }
+ else if(chbuf == '-' && retn != 1)
+ neg = true;
+ else
+ {
+ rb->lseek(fd, -1, SEEK_CUR);
+ break;
+ }
+ }
+ }
+
+ while (rb->read(fd, &chbuf, 1) == 1)
+ {
+ if(!isdigit(chbuf))
+ {
+ rb->lseek(fd, -1, SEEK_CUR);
+ break;
+ }
+ else if (count < LUAI_MAXNUMBER2STR - 2)
+ buffer[count++] = chbuf;
+ }
+
+ if(count)
+ {
+ buffer[count] = '\0';
+ val = strtol(buffer, NULL, 10);
+ *num = (neg)? -val:val;
+ retn = 1;
+ }
+
+ return retn;
+}
+
diff --git a/apps/plugins/lua/rocklib.h b/apps/plugins/lua/rocklib.h
index b650207e67..4714dec36d 100644
--- a/apps/plugins/lua/rocklib.h
+++ b/apps/plugins/lua/rocklib.h
@@ -47,6 +47,7 @@ struct lua_str_reg {
LUALIB_API int (luaopen_rock) (lua_State *L);
int get_current_path(lua_State *L, int level);
+int filetol(int fd, long *num);
#endif /* _ROCKLIB_H_ */
diff --git a/apps/plugins/lua/rocklibc.h b/apps/plugins/lua/rocklibc.h
index 44f916fded..fde50ae4f5 100644
--- a/apps/plugins/lua/rocklibc.h
+++ b/apps/plugins/lua/rocklibc.h
@@ -43,7 +43,5 @@ extern int errno;
#define memcmp rb->memcmp
#define strlen rb->strlen
-extern int PREFIX(fscanf)(int fd, const char *fmt, ...);
-
#endif /* _ROCKLIBC_H_ */