From eab73b3deead4054ba8a1d9165b577ad935b9a05 Mon Sep 17 00:00:00 2001 From: William Wilgus Date: Mon, 29 Oct 2018 02:54:35 -0400 Subject: 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 --- apps/plugins/lua/SOURCES | 1 - apps/plugins/lua/fscanf.c | 291 -------------------------------------------- apps/plugins/lua/liolib.c | 3 +- apps/plugins/lua/rockaux.c | 63 ++++++++++ apps/plugins/lua/rocklib.h | 1 + apps/plugins/lua/rocklibc.h | 2 - 6 files changed, 66 insertions(+), 295 deletions(-) delete mode 100644 apps/plugins/lua/fscanf.c 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_ */ -- cgit v1.2.3