summaryrefslogtreecommitdiff
path: root/apps
diff options
context:
space:
mode:
Diffstat (limited to 'apps')
-rw-r--r--apps/plugins/lua/SOURCES1
-rw-r--r--apps/plugins/lua/fscanf.c290
-rw-r--r--apps/plugins/lua/liolib.c15
-rw-r--r--apps/plugins/lua/rocklibc.h4
4 files changed, 297 insertions, 13 deletions
diff --git a/apps/plugins/lua/SOURCES b/apps/plugins/lua/SOURCES
index d475783c7a..7354fdc821 100644
--- a/apps/plugins/lua/SOURCES
+++ b/apps/plugins/lua/SOURCES
@@ -29,6 +29,7 @@ lzio.c
29rockaux.c 29rockaux.c
30rocklib.c 30rocklib.c
31rockmalloc.c 31rockmalloc.c
32fscanf.c
32gmtime.c 33gmtime.c
33strcspn.c 34strcspn.c
34strftime.c 35strftime.c
diff --git a/apps/plugins/lua/fscanf.c b/apps/plugins/lua/fscanf.c
new file mode 100644
index 0000000000..25058af7da
--- /dev/null
+++ b/apps/plugins/lua/fscanf.c
@@ -0,0 +1,290 @@
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 rb->lseek((int) userp, 1, SEEK_CUR);
279}
280
281int PREFIX(fscanf)(int fd, const char *fmt, ...)
282{
283 int r;
284 va_list ap;
285
286 va_start(ap, fmt);
287 r = scan(fspeek, fspop, (void*) fd, fmt, ap);
288 va_end(ap);
289 return r;
290}
diff --git a/apps/plugins/lua/liolib.c b/apps/plugins/lua/liolib.c
index eea40c0d02..e50524ae89 100644
--- a/apps/plugins/lua/liolib.c
+++ b/apps/plugins/lua/liolib.c
@@ -245,24 +245,13 @@ static int io_lines (lua_State *L) {
245** ======================================================= 245** =======================================================
246*/ 246*/
247 247
248
249static int read_number (lua_State *L, int *f) { 248static int read_number (lua_State *L, int *f) {
250 char buf[10]; /* Maximum uint32 value is 10 chars long */
251 lua_Number d; 249 lua_Number d;
252 int i = 0; 250 if (PREFIX(fscanf)(*f, LUA_NUMBER_SCAN, &d) == 1) {
253 /* Rather hackish, but we don't have fscanf.
254 Was: fscanf(f, LUA_NUMBER_SCAN, &d); */
255 memset(buf, 0, 10);
256 rb->read(*f, buf, 10);
257 while(isdigit(buf[i]) && i < 10)
258 i++;
259 if(i == 0) return 0;
260 else {
261 rb->lseek(*f, i-10, SEEK_CUR);
262 d = rb->atoi(buf);
263 lua_pushnumber(L, d); 251 lua_pushnumber(L, d);
264 return 1; 252 return 1;
265 } 253 }
254 else return 0; /* read fails */
266} 255}
267 256
268 257
diff --git a/apps/plugins/lua/rocklibc.h b/apps/plugins/lua/rocklibc.h
index 78b83a6c18..9b68f429d2 100644
--- a/apps/plugins/lua/rocklibc.h
+++ b/apps/plugins/lua/rocklibc.h
@@ -28,10 +28,12 @@
28 28
29#ifdef SIMULATOR 29#ifdef SIMULATOR
30#include <errno.h> 30#include <errno.h>
31#define PREFIX(_x_) sim_ ## _x_
31#else 32#else
32extern int errno; 33extern int errno;
33#define EINVAL 22 /* Invalid argument */ 34#define EINVAL 22 /* Invalid argument */
34#define ERANGE 34 /* Math result not representable */ 35#define ERANGE 34 /* Math result not representable */
36#define PREFIX
35#endif 37#endif
36 38
37#define __likely LIKELY 39#define __likely LIKELY
@@ -41,5 +43,7 @@ extern int errno;
41#define memcmp rb->memcmp 43#define memcmp rb->memcmp
42#define strlen rb->strlen 44#define strlen rb->strlen
43 45
46extern int PREFIX(fscanf)(int fd, const char *fmt, ...);
47
44#endif /* _ROCKLIBC_H_ */ 48#endif /* _ROCKLIBC_H_ */
45 49