summaryrefslogtreecommitdiff
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
parentcc0a4c632aeda82ab4517355b4b4489190da013e (diff)
downloadrockbox-eab73b3deead4054ba8a1d9165b577ad935b9a05.tar.gz
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
-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
30rocklib.c 30rocklib.c
31rocklib_img.c 31rocklib_img.c
32tlsf_helper.c 32tlsf_helper.c
33fscanf.c
34strftime.c 33strftime.c
35strpbrk.c 34strpbrk.c
36strtoul.c 35strtoul.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 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copied from firmware/common/sscanf.c
11 * Original author: Tomasz Malesinski
12 *
13 * Copyright (C) 2010 Maurus Cuelenaere
14 *
15 * This program is free software; you can redistribute it and/or
16 * modify it under the terms of the GNU General Public License
17 * as published by the Free Software Foundation; either version 2
18 * of the License, or (at your option) any later version.
19 *
20 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
21 * KIND, either express or implied.
22 *
23 ****************************************************************************/
24
25#include "rocklibc.h"
26
27static int parse_dec(int (*peek)(void *userp),
28 void (*pop)(void *userp),
29 void *userp,
30 long *vp)
31{
32 long v = 0;
33 int n = 0;
34 int minus = 0;
35 char ch;
36
37 if ((*peek)(userp) == '-')
38 {
39 (*pop)(userp);
40 n++;
41 minus = 1;
42 }
43
44 ch = (*peek)(userp);
45 if (!isdigit(ch))
46 return -1;
47
48 do
49 {
50 v = v * 10 + ch - '0';
51 (*pop)(userp);
52 n++;
53 ch = (*peek)(userp);
54 } while (isdigit(ch));
55
56 *vp = minus ? -v : v;
57 return n;
58}
59
60static int parse_chars(int (*peek)(void *userp),
61 void (*pop)(void *userp),
62 void *userp,
63 char *vp,
64 bool fake)
65{
66 int n = 0;
67
68 char *pt=vp;
69
70 while (!isspace((*peek)(userp)))
71 {
72 if(fake==false)
73 *(pt++) = (*peek)(userp);
74
75 n++;
76 (*pop)(userp);
77 }
78
79 if(fake==false)
80 (*pt)='\0';
81
82 return n;
83}
84
85static int parse_hex(int (*peek)(void *userp),
86 void (*pop)(void *userp),
87 void *userp,
88 unsigned long *vp)
89{
90 unsigned long v = 0;
91 int n = 0;
92 char ch;
93
94 ch = (*peek)(userp);
95 if (!isxdigit(ch))
96 return -1;
97
98 do
99 {
100 if (ch >= 'a')
101 ch = ch - 'a' + 10;
102 else if (ch >= 'A')
103 ch = ch - 'A' + 10;
104 else
105 ch = ch - '0';
106 v = v * 16 + ch;
107 (*pop)(userp);
108 n++;
109 ch = (*peek)(userp);
110 } while (isxdigit(ch));
111
112 *vp = v;
113 return n;
114}
115
116static int skip_spaces(int (*peek)(void *userp),
117 void (*pop)(void *userp),
118 void *userp)
119{
120 int n = 0;
121 while (isspace((*peek)(userp))) {
122 n++;
123 (*pop)(userp);
124 }
125 return n;
126}
127
128static int scan(int (*peek)(void *userp),
129 void (*pop)(void *userp),
130 void *userp,
131 const char *fmt,
132 va_list ap)
133{
134 char ch;
135 int n = 0;
136 int n_chars = 0;
137 int r;
138 long lval;
139 bool skip=false;
140 unsigned long ulval;
141
142 while ((ch = *fmt++) != '\0')
143 {
144 bool literal = false;
145
146 if (ch == '%')
147 {
148 ch = *fmt++;
149
150 if(ch== '*') /* We should process this, but not store it in an argument */
151 {
152 ch=*fmt++;
153 skip=true;
154 }
155 else
156 {
157 skip=false;
158 }
159
160 switch (ch)
161 {
162 case 'x':
163 n_chars += skip_spaces(peek, pop, userp);
164 if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0)
165 {
166 if(skip==false)
167 {
168 *(va_arg(ap, unsigned int *)) = ulval;
169 n++;
170 }
171 n_chars += r;
172 }
173 else
174 return n;
175 break;
176 case 'd':
177 n_chars += skip_spaces(peek, pop, userp);
178 if ((r = parse_dec(peek, pop, userp, &lval)) >= 0)
179 {
180 if(skip==false)
181 {
182 *(va_arg(ap, int *)) = lval;
183 n++;
184 }
185 n_chars += r;
186 }
187 else
188 return n;
189 break;
190 case 'n':
191 if(skip==false)
192 {
193 *(va_arg(ap, int *)) = n_chars;
194 n++;
195 }
196 break;
197 case 'l':
198 n_chars += skip_spaces(peek, pop, userp);
199 ch = *fmt++;
200 switch (ch)
201 {
202 case 'x':
203 if ((r = parse_hex(peek, pop, userp, &ulval)) >= 0)
204 {
205 if(skip==false)
206 {
207 *(va_arg(ap, unsigned long *)) = ulval;
208 n++;
209 }
210 n_chars += r;
211 }
212 else
213 return n;
214 break;
215 case 'd':
216 if ((r = parse_dec(peek, pop, userp, &lval)) >= 0)
217 {
218 if(skip==false)
219 {
220 *(va_arg(ap, long *)) = lval;
221 n++;
222 }
223 n_chars += r;
224 }
225 else
226 return n;
227 break;
228 case '\0':
229 return n;
230 default:
231 literal = true;
232 break;
233 }
234 break;
235 case 's':
236 n_chars += skip_spaces(peek, pop, userp);
237 n_chars += parse_chars(peek,pop, userp,skip?0:va_arg(ap, char *), skip );
238 if(skip==false)
239 {
240 n++;
241 }
242 break;
243 case '\0':
244 return n;
245 default:
246 literal = true;
247 break;
248 }
249 } else
250 literal = true;
251
252 if (literal)
253 {
254 n_chars += skip_spaces(peek, pop, userp);
255 if ((*peek)(userp) != ch)
256 continue;
257 else
258 {
259 (*pop)(userp);
260 n_chars++;
261 }
262 }
263 }
264 return n;
265}
266
267static int fspeek(void *userp)
268{
269 int fd = *((int*) userp);
270 char buf = 0;
271 if(rb->read(fd, &buf, 1) == 1)
272 rb->lseek(fd, -1, SEEK_CUR);
273 return buf;
274}
275
276static void fspop(void *userp)
277{
278 int fd = *((int*) userp);
279 rb->lseek(fd, 1, SEEK_CUR);
280}
281
282int PREFIX(fscanf)(int fd, const char *fmt, ...)
283{
284 int r;
285 va_list ap;
286
287 va_start(ap, fmt);
288 r = scan(fspeek, fspop, &fd, fmt, ap);
289 va_end(ap);
290 return r;
291}
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 @@
17#include "lauxlib.h" 17#include "lauxlib.h"
18#include "lualib.h" 18#include "lualib.h"
19#include "rocklibc.h" 19#include "rocklibc.h"
20#include "rocklib.h"
20 21
21#include "llimits.h" 22#include "llimits.h"
22 23
@@ -247,7 +248,7 @@ static int io_lines (lua_State *L) {
247 248
248static int read_number (lua_State *L, int *f) { 249static int read_number (lua_State *L, int *f) {
249 lua_Number d; 250 lua_Number d;
250 if (PREFIX(fscanf)(*f, LUA_NUMBER_SCAN, &d) == 1) { 251 if (filetol(*f, &d) == 1) { /* was fscanf(f, LUA_NUMBER_SCAN, &d)*/
251 lua_pushnumber(L, d); 252 lua_pushnumber(L, d);
252 return 1; 253 return 1;
253 } 254 }
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 @@
8 * $Id$ 8 * $Id$
9 * 9 *
10 * Copyright (C) 2008 Dan Everton (safetydan) 10 * Copyright (C) 2008 Dan Everton (safetydan)
11 * Copyright (C) 2018 William Wilgus
11 * String function implementations taken from dietlibc 0.31 (GPLv2 License) 12 * String function implementations taken from dietlibc 0.31 (GPLv2 License)
12 * 13 *
13 * This program is free software; you can redistribute it and/or 14 * This program is free software; you can redistribute it and/or
@@ -24,6 +25,8 @@
24#define _ROCKCONF_H_ /* Protect against unwanted include */ 25#define _ROCKCONF_H_ /* Protect against unwanted include */
25#include "lua.h" 26#include "lua.h"
26 27
28extern long strtol(const char *nptr, char **endptr, int base);
29
27#if (CONFIG_PLATFORM & PLATFORM_NATIVE) 30#if (CONFIG_PLATFORM & PLATFORM_NATIVE)
28int errno = 0; 31int errno = 0;
29#endif 32#endif
@@ -101,3 +104,63 @@ int get_current_path(lua_State *L, int level)
101 lua_pushnil(L); 104 lua_pushnil(L);
102 return 1; 105 return 1;
103} 106}
107
108/* filetol()
109 reads long int from an open file, skips preceding
110 whitespaces returns -1 if error, 1 on success.
111 *num set to LONG_MAX or LONG_MIN on overflow.
112 If number of digits is > than LUAI_MAXNUMBER2STR
113 filepointer will continue till the next non digit
114 but buffer will stop being filled with characters.
115 Preceding zero is ignored
116*/
117int filetol(int fd, long *num)
118{
119 static char buffer[LUAI_MAXNUMBER2STR];
120 int retn = -1;
121 char chbuf = 0;
122 size_t count = 0;
123 bool neg = false;
124 long val;
125
126 while (rb->read(fd, &chbuf, 1) == 1)
127 {
128 if(!isspace(chbuf) || retn == 1)
129 {
130 if(chbuf == '0') /* strip preceeding zeros */
131 {
132 *num = 0;
133 retn = 1;
134 }
135 else if(chbuf == '-' && retn != 1)
136 neg = true;
137 else
138 {
139 rb->lseek(fd, -1, SEEK_CUR);
140 break;
141 }
142 }
143 }
144
145 while (rb->read(fd, &chbuf, 1) == 1)
146 {
147 if(!isdigit(chbuf))
148 {
149 rb->lseek(fd, -1, SEEK_CUR);
150 break;
151 }
152 else if (count < LUAI_MAXNUMBER2STR - 2)
153 buffer[count++] = chbuf;
154 }
155
156 if(count)
157 {
158 buffer[count] = '\0';
159 val = strtol(buffer, NULL, 10);
160 *num = (neg)? -val:val;
161 retn = 1;
162 }
163
164 return retn;
165}
166
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 {
47 47
48LUALIB_API int (luaopen_rock) (lua_State *L); 48LUALIB_API int (luaopen_rock) (lua_State *L);
49int get_current_path(lua_State *L, int level); 49int get_current_path(lua_State *L, int level);
50int filetol(int fd, long *num);
50 51
51#endif /* _ROCKLIB_H_ */ 52#endif /* _ROCKLIB_H_ */
52 53
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;
43#define memcmp rb->memcmp 43#define memcmp rb->memcmp
44#define strlen rb->strlen 44#define strlen rb->strlen
45 45
46extern int PREFIX(fscanf)(int fd, const char *fmt, ...);
47
48#endif /* _ROCKLIBC_H_ */ 46#endif /* _ROCKLIBC_H_ */
49 47