Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
ruanhaishen
Nodemcu Firmware
Commits
18886ea6
Commit
18886ea6
authored
Feb 12, 2015
by
zeroday
Browse files
Merge pull request #203 from nodemcu/dev
Fixed floating point bug. add file.rename
parents
370bc88b
22d096ce
Changes
39
Hide whitespace changes
Inline
Side-by-side
README.md
View file @
18886ea6
...
@@ -125,6 +125,7 @@ pre_build/latest/nodemcu_512k_latest.bin is removed. use pre_build/latest/nodemc
...
@@ -125,6 +125,7 @@ pre_build/latest/nodemcu_512k_latest.bin is removed. use pre_build/latest/nodemc
#define LUA_USE_MODULES_UART
#define LUA_USE_MODULES_UART
#define LUA_USE_MODULES_OW
#define LUA_USE_MODULES_OW
#define LUA_USE_MODULES_BIT
#define LUA_USE_MODULES_BIT
#define LUA_USE_MODULES_WS2812
#endif
/* LUA_USE_MODULES */
#endif
/* LUA_USE_MODULES */
...
...
// LUA_NUMBER_INTEGRAL
// LUA_NUMBER_INTEGRAL
...
@@ -330,3 +331,13 @@ cu:send("hello")
...
@@ -330,3 +331,13 @@ cu:send("hello")
ds18b20
=
nil
ds18b20
=
nil
package.loaded
[
"ds18b20"
]
=
nil
package.loaded
[
"ds18b20"
]
=
nil
```
```
####Control a WS2812 based light strip
```
lua
-- set the color of one LED on GPIO 2 to red
ws2812
.
write
(
4
,
string.char
(
0
,
255
,
0
))
-- set the color of 10 LEDs on GPIO 0 to blue
ws2812
.
write
(
3
,
string.char
(
0
,
0
,
255
):
rep
(
10
))
-- first LED green, second LED white
ws2812
.
write
(
4
,
string.char
(
255
,
0
,
0
,
255
,
255
,
255
))
```
app/include/driver/uart.h
View file @
18886ea6
...
@@ -33,18 +33,23 @@ typedef enum {
...
@@ -33,18 +33,23 @@ typedef enum {
}
UartExistParity
;
}
UartExistParity
;
typedef
enum
{
typedef
enum
{
BIT_RATE_1200
=
1200
,
BIT_RATE_300
=
300
,
BIT_RATE_2400
=
2400
,
BIT_RATE_600
=
600
,
BIT_RATE_4800
=
4800
,
BIT_RATE_1200
=
1200
,
BIT_RATE_9600
=
9600
,
BIT_RATE_2400
=
2400
,
BIT_RATE_4800
=
4800
,
BIT_RATE_9600
=
9600
,
BIT_RATE_19200
=
19200
,
BIT_RATE_19200
=
19200
,
BIT_RATE_38400
=
38400
,
BIT_RATE_38400
=
38400
,
BIT_RATE_57600
=
57600
,
BIT_RATE_57600
=
57600
,
BIT_RATE_74880
=
74880
,
BIT_RATE_74880
=
74880
,
BIT_RATE_115200
=
115200
,
BIT_RATE_115200
=
115200
,
BIT_RATE_230400
=
230400
,
BIT_RATE_230400
=
230400
,
BIT_RATE_460800
=
460800
,
BIT_RATE_256000
=
256000
,
BIT_RATE_921600
=
921600
BIT_RATE_460800
=
460800
,
BIT_RATE_921600
=
921600
,
BIT_RATE_1843200
=
1843200
,
BIT_RATE_3686400
=
3686400
,
}
UartBautRate
;
}
UartBautRate
;
typedef
enum
{
typedef
enum
{
...
...
app/include/lwip/app/espconn.h
View file @
18886ea6
...
@@ -394,5 +394,21 @@ extern sint8 espconn_igmp_join(ip_addr_t *host_ip, ip_addr_t *multicast_ip);
...
@@ -394,5 +394,21 @@ extern sint8 espconn_igmp_join(ip_addr_t *host_ip, ip_addr_t *multicast_ip);
*******************************************************************************/
*******************************************************************************/
extern
sint8
espconn_igmp_leave
(
ip_addr_t
*
host_ip
,
ip_addr_t
*
multicast_ip
);
extern
sint8
espconn_igmp_leave
(
ip_addr_t
*
host_ip
,
ip_addr_t
*
multicast_ip
);
/******************************************************************************
* FunctionName : espconn_recv_hold
* Description : hold tcp receive
* Parameters : espconn -- espconn to hold
* Returns : none
*******************************************************************************/
extern
sint8
espconn_recv_hold
(
struct
espconn
*
pespconn
);
/******************************************************************************
* FunctionName : espconn_recv_unhold
* Description : unhold tcp receive
* Parameters : espconn -- espconn to unhold
* Returns : none
*******************************************************************************/
extern
sint8
espconn_recv_unhold
(
struct
espconn
*
pespconn
);
#endif
#endif
app/include/lwip/tcp.h
View file @
18886ea6
...
@@ -277,6 +277,8 @@ struct tcp_pcb {
...
@@ -277,6 +277,8 @@ struct tcp_pcb {
/* KEEPALIVE counter */
/* KEEPALIVE counter */
u8_t
keep_cnt_sent
;
u8_t
keep_cnt_sent
;
u8_t
hold
;
};
};
struct
tcp_pcb_listen
{
struct
tcp_pcb_listen
{
...
...
app/include/user_config.h
View file @
18886ea6
...
@@ -13,6 +13,8 @@
...
@@ -13,6 +13,8 @@
// #define FLASH_1M
// #define FLASH_1M
// #define FLASH_2M
// #define FLASH_2M
// #define FLASH_4M
// #define FLASH_4M
// #define FLASH_8M
// #define FLASH_16M
#define FLASH_AUTOSIZE
#define FLASH_AUTOSIZE
// #define DEVELOP_VERSION
// #define DEVELOP_VERSION
#define FULL_VERSION_FOR_USER
#define FULL_VERSION_FOR_USER
...
@@ -40,7 +42,6 @@
...
@@ -40,7 +42,6 @@
#define ICACHE_STORE_TYPEDEF_ATTR __attribute__((aligned(4),packed))
#define ICACHE_STORE_TYPEDEF_ATTR __attribute__((aligned(4),packed))
#define ICACHE_STORE_ATTR __attribute__((aligned(4)))
#define ICACHE_STORE_ATTR __attribute__((aligned(4)))
#define ICACHE_RAM_ATTR __attribute__((section(".iram0.text")))
#define ICACHE_RAM_ATTR __attribute__((section(".iram0.text")))
// #define ICACHE_RODATA_ATTR __attribute__((section(".rodata2.text")))
#define CLIENT_SSL_ENABLE
#define CLIENT_SSL_ENABLE
#define GPIO_INTERRUPT_ENABLE
#define GPIO_INTERRUPT_ENABLE
...
@@ -64,12 +65,10 @@
...
@@ -64,12 +65,10 @@
#define LUA_USE_MODULES_OW
#define LUA_USE_MODULES_OW
#define LUA_USE_MODULES_BIT
#define LUA_USE_MODULES_BIT
#define LUA_USE_MODULES_MQTT
#define LUA_USE_MODULES_MQTT
#define LUA_USE_MODULES_WS2812
#endif
/* LUA_USE_MODULES */
#endif
/* LUA_USE_MODULES */
// #define LUA_NUMBER_INTEGRAL
// #define LUA_NUMBER_INTEGRAL
#ifndef LUA_NUMBER_INTEGRAL
#define PRINTF_LONG_SUPPORT
#endif
#define LUA_OPTRAM
#define LUA_OPTRAM
#ifdef LUA_OPTRAM
#ifdef LUA_OPTRAM
...
...
app/libc/c_math.c
View file @
18886ea6
#include "c_math.h"
#include "c_math.h"
#include "c_types.h"
#include "c_types.h"
#include "user_config.h"
double
floor
(
double
x
)
double
floor
(
double
x
)
{
{
return
(
double
)
(
x
<
0
.
f
?
(((
int
)
x
)
-
1
)
:
((
int
)
x
));
return
(
double
)
(
x
<
0
.
f
?
(((
int
)
x
)
-
1
)
:
((
int
)
x
));
}
}
double
pow
(
double
x
,
double
y
)
{
#define MAXEXP 2031
/* (MAX_EXP * 16) - 1 */
#define MAXEXP 2031
/* (MAX_EXP * 16) - 1 */
#define MINEXP -2047
/* (MIN_EXP * 16) - 1 */
#define MINEXP -2047
/* (MIN_EXP * 16) - 1 */
#define HUGE MAXFLOAT
#define HUGE MAXFLOAT
double
a1
[]
=
{
1
.
0
,
0
.
95760328069857365
,
0
.
91700404320467123
,
0
.
87812608018664974
,
0
.
84089641525371454
,
0
.
80524516597462716
,
0
.
77110541270397041
,
0
.
73841307296974966
,
0
.
70710678118654752
,
0
.
67712777346844637
,
0
.
64841977732550483
,
0
.
62092890603674203
,
0
.
59460355750136054
,
0
.
56939431737834583
,
0
.
54525386633262883
,
0
.
52213689121370692
,
0
.
50000000000000000
};
double
a2
[]
=
{
0.24114209503420288E-17
,
0.92291566937243079E-18
,
-
0.15241915231122319E-17
,
-
0.35421849765286817E-17
,
-
0.31286215245415074E-17
,
-
0.44654376565694490E-17
,
0.29306999570789681E-17
,
0.11260851040933474E-17
};
double
p1
=
0.833333333333332114e-1
;
double
p2
=
0.125000000005037992e-1
;
double
p3
=
0.223214212859242590e-2
;
double
p4
=
0.434457756721631196e-3
;
double
q1
=
0.693147180559945296e0
;
double
q2
=
0.240226506959095371e0
;
double
q3
=
0.555041086640855953e-1
;
double
q4
=
0.961812905951724170e-2
;
double
q5
=
0.133335413135857847e-2
;
double
q6
=
0.154002904409897646e-3
;
double
q7
=
0.149288526805956082e-4
;
double
k
=
0
.
442695040888963407
;
double
a1
[]
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
{
1
.
0
,
0
.
95760328069857365
,
0
.
91700404320467123
,
0
.
87812608018664974
,
0
.
84089641525371454
,
0
.
80524516597462716
,
0
.
77110541270397041
,
0
.
73841307296974966
,
0
.
70710678118654752
,
0
.
67712777346844637
,
0
.
64841977732550483
,
0
.
62092890603674203
,
0
.
59460355750136054
,
0
.
56939431737834583
,
0
.
54525386633262883
,
0
.
52213689121370692
,
0
.
50000000000000000
};
double
a2
[]
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
{
0.24114209503420288E-17
,
0.92291566937243079E-18
,
-
0.15241915231122319E-17
,
-
0.35421849765286817E-17
,
-
0.31286215245415074E-17
,
-
0.44654376565694490E-17
,
0.29306999570789681E-17
,
0.11260851040933474E-17
};
double
p1
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
0.833333333333332114e-1
;
double
p2
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
0.125000000005037992e-1
;
double
p3
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
0.223214212859242590e-2
;
double
p4
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
0.434457756721631196e-3
;
double
q1
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
0.693147180559945296e0
;
double
q2
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
0.240226506959095371e0
;
double
q3
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
0.555041086640855953e-1
;
double
q4
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
0.961812905951724170e-2
;
double
q5
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
0.133335413135857847e-2
;
double
q6
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
0.154002904409897646e-3
;
double
q7
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
0.149288526805956082e-4
;
double
k
ICACHE_STORE_ATTR
ICACHE_RODATA_ATTR
=
0
.
442695040888963407
;
double
pow
(
double
x
,
double
y
)
{
double
frexp
(),
g
,
ldexp
(),
r
,
u1
,
u2
,
v
,
w
,
w1
,
w2
,
y1
,
y2
,
z
;
double
frexp
(),
g
,
ldexp
(),
r
,
u1
,
u2
,
v
,
w
,
w1
,
w2
,
y1
,
y2
,
z
;
int
iw1
,
m
,
p
;
int
iw1
,
m
,
p
;
...
...
app/libc/c_stdio.c
View file @
18886ea6
...
@@ -58,423 +58,1047 @@ int c_stderr = 1001;
...
@@ -58,423 +58,1047 @@ int c_stderr = 1001;
#else
#else
/*
#define FLOATINGPT 1
File: printf.c
#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
/* $Id: strichr.c,v 1.1.1.1 2006/08/23 17:03:06 pefo Exp $ */
All rights reserved.
/*
* 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 <string.h>
#include "c_string.h"
Redistribution and use in source and binary forms, with or without modification,
char
*
are permitted provided that the following conditions are met:
strichr
(
char
*
p
,
int
c
)
{
char
*
t
;
Redistributions of source code must retain the above copyright notice, this list
if
(
p
!=
NULL
)
{
of conditions and the following disclaimer.
for
(
t
=
p
;
*
t
;
t
++
);
for
(;
t
>=
p
;
t
--
)
{
*
(
t
+
1
)
=
*
t
;
}
*
p
=
c
;
}
return
(
p
);
}
Redistributions in binary form must reproduce the above copyright notice, this
/* $Id: str_fmt.c,v 1.1.1.1 2006/08/23 17:03:06 pefo Exp $ */
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
* Copyright (c) 2000-2002 Opsycon AB (www.opsycon.se)
without specific prior written permission.
*
* 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 <string.h>
#include "c_string.h"
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
#define FMT_RJUST 0
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
#define FMT_LJUST 1
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
#define FMT_RJUST0 2
IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
#define FMT_CENTER 3
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.
----------------------------------------------------------------------
/*
* Format string by inserting blanks.
*/
This library is realy just two files: 'printf.h' and 'printf.c'.
void
str_fmt
(
char
*
p
,
int
size
,
int
fmt
)
{
int
n
,
m
,
len
;
They provide a simple and small (+200 loc) printf functionality to
len
=
strlen
(
p
);
be used in embedded systems.
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
;
}
}
I've found them so usefull in debugging that I do not bother with a
/* $Id: strtoupp.c,v 1.1.1.1 2006/08/23 17:03:06 pefo Exp $ */
debugger at all.
They are distributed in source form, so to use them, just compile them
/*
into your project.
* 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 <string.h>
//#include <ctype.h>
#include "c_string.h"
#include "c_ctype.h"
Two printf variants are provided: printf and sprintf.
void
strtoupper
(
char
*
p
)
{
if
(
!
p
)
return
;
for
(;
*
p
;
p
++
)
*
p
=
toupper
(
*
p
);
}
The formats supported by this implementation are: 'd' 'u' 'c' 's' 'x' 'X'.
/* $Id: atob.c,v 1.1.1.1 2006/08/23 17:03:06 pefo Exp $ */
Zero padding and field width are also supported.
/*
* 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.
*
*/
If the library is compiled with 'PRINTF_SUPPORT_LONG' defined then the
//#include <sys/types.h>
long specifier is also
//#include <string.h>
supported. Note that this will pull in some long math routines (pun intended!)
//#include <pmon.h>
and thus make your executable noticably longer.
#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
;
The memory foot print of course depends on the target cpu, compiler and
#define __P(x) x
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,
static
char
*
_getbase
__P
((
char
*
,
int
*
));
s
omething like :
s
tatic
int
_atob
__P
((
unsigned
long
long
*
,
char
*
p
,
int
));
void putc ( void* p, char c)
static
char
*
{
_getbase
(
char
*
p
,
int
*
basep
)
while (!SERIAL_PORT_EMPTY) ;
{
SERIAL_PORT_TX_REGISTER = c;
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
);
}
}
*
basep
=
10
;
return
(
p
);
}
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
* _atob(vp,p,base)
passed to your 'putc' routine. This allows you to pass some storage space (or
*/
anything realy) to the character output function, if necessary.
static
int
This is not often needed but it was implemented like that because it made
_atob
(
u_quad_t
*
vp
,
char
*
p
,
int
base
)
implementing the sprintf function so neat (look at the source code).
{
u_quad_t
value
,
v1
,
v2
;
char
*
q
,
tmp
[
20
];
int
digit
;
The code is re-entrant, except for the 'init_printf' function, so it
if
(
p
[
0
]
==
'0'
&&
(
p
[
1
]
==
'x'
||
p
[
1
]
==
'X'
))
{
is safe to call it from interupts too, although this may result in mixed output.
base
=
16
;
If you rely on re-entrancy, take care that your 'putc' function is re-entrant!
p
+=
2
;
}
The printf and sprintf functions are actually macros that translate to
if
(
base
==
16
&&
(
q
=
strchr
(
p
,
'.'
))
!=
0
)
{
'tfp_printf' and 'tfp_sprintf'. This makes it possible
if
(
q
-
p
>
sizeof
(
tmp
)
-
1
)
to use them along with 'stdio.h' printf's in a single source file.
return
(
0
);
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.
strncpy
(
tmp
,
p
,
q
-
p
);
tmp
[
q
-
p
]
=
'\0'
;
if
(
!
_atob
(
&
v1
,
tmp
,
16
))
return
(
0
);
regs Kusti, 23.10.2004
q
++
;
*/
if
(
strchr
(
q
,
'.'
))
return
(
0
);
/*
if
(
!
_atob
(
&
v2
,
q
,
16
))
Add lightweight %g support by vowstar, <vowstar@gmail.com>
return
(
0
);
NodeMCU Team, 26.1.2015
*
vp
=
(
v1
<<
16
)
+
v2
;
*/
return
(
1
);
}
typedef
void
(
*
putcf
)
(
void
*
,
char
);
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
);
#ifdef PRINTF_LONG_SUPPORT
if
(
digit
>=
base
)
return
(
0
);
value
*=
base
;
value
+=
digit
;
}
*
vp
=
value
;
return
(
1
);
}
static
int
uli2a
(
unsigned
long
int
num
,
unsigned
int
base
,
int
uc
,
char
*
bf
)
/*
* 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
)
{
{
int
n
=
0
;
u_quad_t
v
;
unsigned
long
int
d
=
1
;
int
len
=
1
;
if
(
base
==
0
)
while
(
num
/
d
>=
base
)
p
=
_getbase
(
p
,
&
base
);
{
if
(
_atob
(
&
v
,
p
,
base
))
{
d
*=
base
;
*
vp
=
v
;
len
++
;
return
(
1
);
}
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
;
}
}
}
*
bf
=
0
;
return
(
0
);
return
len
;
}
}
static
int
li2a
(
long
num
,
char
*
bf
)
/*
* 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
)
{
{
int
len
=
0
;
if
(
base
==
0
)
if
(
num
<
0
)
p
=
_getbase
(
p
,
&
base
);
{
return
_atob
(
vp
,
p
,
base
);
num
=
-
num
;
*
bf
++
=
'-'
;
len
++
;
}
len
+=
uli2a
(
num
,
10
,
0
,
bf
);
return
len
;
}
}
#endif
static
int
ui2a
(
unsigned
int
num
,
unsigned
int
base
,
int
uc
,
char
*
bf
)
/*
* char *btoa(dst,value,base)
* converts value to ascii, result in dst
*/
char
*
btoa
(
char
*
dst
,
u_int
value
,
int
base
)
{
{
int
n
=
0
;
char
buf
[
34
],
digit
;
unsigned
int
d
=
1
;
int
i
,
j
,
rem
,
neg
;
int
len
=
1
;
while
(
num
/
d
>=
base
)
if
(
value
==
0
)
{
{
dst
[
0
]
=
'0'
;
d
*=
base
;
d
st
[
1
]
=
0
;
len
++
;
return
(
dst
)
;
}
}
while
(
d
!=
0
)
{
neg
=
0
;
int
dgt
=
num
/
d
;
if
(
base
==
-
10
)
{
num
%=
d
;
base
=
10
;
d
/=
base
;
if
(
value
&
(
1L
<<
31
))
{
if
(
n
||
dgt
>
0
||
d
==
0
)
value
=
(
~
value
)
+
1
;
{
neg
=
1
;
*
bf
++
=
dgt
+
(
dgt
<
10
?
'0'
:
(
uc
?
'A'
:
'a'
)
-
10
);
++
n
;
}
}
}
}
*
bf
=
0
;
return
len
;
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
);
}
}
static
int
i2a
(
int
num
,
char
*
bf
)
/*
* char *btoa(dst,value,base)
* converts value to ascii, result in dst
*/
char
*
llbtoa
(
char
*
dst
,
u_quad_t
value
,
int
base
)
{
{
int
len
=
0
;
char
buf
[
66
],
digit
;
if
(
num
<
0
)
int
i
,
j
,
rem
,
neg
;
{
num
=
-
num
;
if
(
value
==
0
)
{
*
bf
++
=
'-'
;
dst
[
0
]
=
'0'
;
len
++
;
dst
[
1
]
=
0
;
return
(
dst
);
}
neg
=
0
;
if
(
base
==
-
10
)
{
base
=
10
;
if
(
value
&
(
1LL
<<
63
))
{
value
=
(
~
value
)
+
1
;
neg
=
1
;
}
}
}
len
+=
ui2a
(
num
,
10
,
0
,
bf
);
return
len
;
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
);
}
}
// Converts a floating point number to string.
/*
static
int
d2a
(
double
num
,
char
*
bf
)
* 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
)
{
{
int
len
=
0
;
u_long
v
;
double
ipart
=
0
;
int
digit
;
double
fpart
=
0
;
double
absnum
=
num
;
for
(
v
=
0
;
n
>
0
;
n
--
)
{
if
(
*
p
==
0
)
// Add sign
return
(
0
);
if
(
absnum
<
0
)
if
(
*
p
>=
'0'
&&
*
p
<=
'9'
)
{
digit
=
*
p
-
'0'
;
absnum
=
-
absnum
;
else
if
(
*
p
>=
'a'
&&
*
p
<=
'f'
)
*
bf
++
=
'-'
;
digit
=
*
p
-
'a'
+
10
;
// len must add 1 when return
else
if
(
*
p
>=
'A'
&&
*
p
<=
'F'
)
// but can't add at here
digit
=
*
p
-
'A'
+
10
;
else
return
(
0
);
v
<<=
4
;
v
|=
digit
;
p
++
;
}
}
*
vp
=
v
;
return
(
1
);
}
// Extract integer part
/* $Id: vsprintf.c,v 1.1.1.1 2006/08/23 17:03:06 pefo Exp $ */
ipart
=
(
int
)
absnum
;
// Extract floating part
/*
fpart
=
absnum
-
(
double
)
ipart
;
* 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 <stdio.h>
//#include <stdarg.h>
//#include <string.h>
//#include <ctype.h>
//#include <pmon.h>
#include "c_stdarg.h"
#include "c_string.h"
#include "c_ctype.h"
// convert integer part to string
/*
#ifdef PRINTF_LONG_SUPPORT
* int vsprintf(d,s,ap)
len
+=
li2a
(
ipart
,
bf
);
*/
#else
int
len
+=
i2a
(
ipart
,
bf
);
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
#endif
#ifndef EPSILON
dst
=
d
;
#define EPSILON ((double)(0.00000001))
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
#endif
if
(
fpart
<
EPSILON
)
}
{
if
(
trunc
)
// fpart is zero
d
[
trunc
]
=
0
;
if
(
width
)
str_fmt
(
d
,
width
,
fmt
);
for
(;
*
d
;
d
++
);
s
++
;
}
else
*
d
++
=
*
s
++
;
}
}
else
*
d
=
0
;
{
return
(
d
-
dst
);
bf
+=
len
;
}
// add dot
*
bf
++
=
'.'
;
#ifdef FLOATINGPT
len
+=
1
;
/*
// add zero after dot
* Floating point output, cvt() onward lifted from BSD sources:
while
(
fpart
<
0
.
1
)
*
{
* Copyright (c) 1990 The Regents of the University of California.
fpart
*=
10
;
* All rights reserved.
*
bf
++
=
'0'
;
*
len
+=
1
;
* This code is derived from software contributed to Berkeley by
}
* Chris Torek.
while
((
fpart
<
(
double
)
1
.
0
/
EPSILON
)
&&
((
fpart
-
(
int
)
fpart
)
>
EPSILON
))
*
{
* Redistribution and use in source and binary forms, with or without
fpart
=
fpart
*
10
;
* modification, are permitted provided that the following conditions
}
* are met:
#ifdef PRINTF_LONG_SUPPORT
* 1. Redistributions of source code must retain the above copyright
len
+=
li2a
((
int
)
fpart
,
bf
);
* 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
#else
len
+=
i2a
((
int
)
fpart
,
bf
);
struct
IEEEdp
{
unsigned
sign
:
1
;
unsigned
exp
:
11
;
unsigned
manh
:
20
;
unsigned
manl
:
32
;
}
*
ip
;
#endif
#endif
}
#undef EPSILON
if
(
num
<
0
)
{
len
++
;
}
return
len
;
}
static
int
a2d
(
char
ch
)
ip
=
(
struct
IEEEdp
*
)
&
d
;
{
return
(
ip
->
exp
!=
0x7ff
);
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
)
void
dtoa
(
char
*
dbuf
,
rtype
arg
,
int
fmtch
,
int
width
,
int
prec
)
{
{
char
*
p
=
*
src
;
char
buf
[
MAX_FCONVERSION
+
1
],
*
cp
;
int
num
=
0
;
char
sign
;
int
digit
;
int
size
;
while
((
digit
=
a2d
(
ch
))
>=
0
)
{
if
(
!
_finite
(
arg
)
)
{
if
(
digit
>
base
)
break
;
if
(
_isNan
(
arg
)
)
num
=
num
*
base
+
digit
;
strcpy
(
dbuf
,
"NaN"
);
ch
=
*
p
++
;
else
if
(
arg
<
0
)
strcpy
(
dbuf
,
"-Infinity"
);
else
strcpy
(
dbuf
,
"Infinity"
);
return
;
}
}
*
src
=
p
;
*
nump
=
num
;
return
ch
;
}
static
void
putchw
(
void
*
putp
,
putcf
putf
,
int
n
,
char
z
,
char
*
bf
)
if
(
prec
==
0
)
{
prec
=
6
;
char
fc
=
z
?
'0'
:
' '
;
else
if
(
prec
>
MAX_FRACT
)
char
ch
;
prec
=
MAX_FRACT
;
char
*
p
=
bf
;
while
(
*
p
++
&&
n
>
0
)
/* leave room for sign at start of buffer */
n
--
;
cp
=
buf
+
1
;
while
(
n
--
>
0
)
putf
(
putp
,
fc
);
/*
while
((
ch
=
*
bf
++
))
* cvt may have to round up before the "start" of
putf
(
putp
,
ch
);
* 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
);
}
}
void
c_format
(
void
*
putp
,
putcf
putf
,
char
*
fmt
,
va_list
va
)
static
int
cvt
(
rtype
number
,
int
prec
,
char
*
signp
,
int
fmtch
,
char
*
startp
,
char
*
endp
)
{
{
char
bf
[
12
];
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
;
char
ch
;
fract
=
modf
(
number
,
&
integer
)
;
/* get an extra slot for rounding. */
t
=
++
startp
;
while
((
ch
=
*
(
fmt
++
)))
/*
{
* get integer portion of number; put into the end of the buffer; the
if
(
ch
!=
'%'
)
* .01 is added for modf(356.0 / 10, &integer) returning .59999999...
putf
(
putp
,
ch
);
*/
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
else
{
*
t
++
=
'0'
;
char
lz
=
0
;
/*
#ifdef PRINTF_LONG_SUPPORT
* if precision required or alternate flag set, add in a
char
lng
=
0
;
* decimal point.
#endif
*/
int
w
=
0
;
if
(
prec
||
TESTFLAG
(
ALTERNATE_FORM
))
ch
=
*
(
fmt
++
);
*
t
++
=
'.'
;
if
(
ch
==
'0'
)
/* if requires more precision and some fraction left */
{
if
(
fract
)
{
ch
=
*
(
fmt
++
);
if
(
prec
)
lz
=
1
;
do
{
}
fract
=
modf
(
fract
*
10
,
&
tmp
);
if
(
ch
>=
'0'
&&
ch
<=
'9'
)
*
t
++
=
to_char
((
int
)
tmp
);
{
}
while
(
--
prec
&&
fract
);
ch
=
a2i
(
ch
,
&
fmt
,
10
,
&
w
);
if
(
fract
)
}
startp
=
c_round
(
fract
,
(
int
*
)
NULL
,
startp
,
#ifdef PRINTF_LONG_SUPPORT
t
-
1
,
(
char
)
0
,
signp
);
if
(
ch
==
'l'
)
}
{
for
(;
prec
--
;
*
t
++
=
'0'
);
ch
=
*
(
fmt
++
);
break
;
lng
=
1
;
case
'e'
:
}
case
'E'
:
#endif
eformat:
if
(
expcnt
)
{
switch
(
ch
)
*
t
++
=
*++
p
;
{
if
(
prec
||
TESTFLAG
(
ALTERNATE_FORM
))
case
0
:
*
t
++
=
'.'
;
goto
abort
;
/* if requires more precision and some integer left */
case
'u'
:
for
(;
prec
&&
++
p
<
endp
;
--
prec
)
{
*
t
++
=
*
p
;
#ifdef PRINTF_LONG_SUPPORT
/*
if
(
lng
)
* if done precision and more of the integer component,
uli2a
(
va_arg
(
va
,
unsigned
long
int
),
10
,
0
,
bf
);
* round using it; adjust fract so we don't re-round
else
* later.
#endif
*/
ui2a
(
va_arg
(
va
,
unsigned
int
),
10
,
0
,
bf
);
if
(
!
prec
&&
++
p
<
endp
)
{
putchw
(
putp
,
putf
,
w
,
lz
,
bf
);
fract
=
0
;
break
;
startp
=
c_round
((
double
)
0
,
&
expcnt
,
startp
,
t
-
1
,
*
p
,
signp
);
}
}
case
'o'
:
/* adjust expcnt for digit in front of decimal */
{
--
expcnt
;
#ifdef PRINTF_LONG_SUPPORT
}
if
(
lng
)
/* until first fractional digit, decrement exponent */
uli2a
(
va_arg
(
va
,
unsigned
long
int
),
8
,
0
,
bf
);
else
if
(
fract
)
{
else
/* adjust expcnt for digit in front of decimal */
#endif
for
(
expcnt
=
-
1
;;
--
expcnt
)
{
ui2a
(
va_arg
(
va
,
unsigned
int
),
8
,
0
,
bf
);
fract
=
modf
(
fract
*
10
,
&
tmp
);
putchw
(
putp
,
putf
,
w
,
lz
,
bf
);
if
(
tmp
)
break
;
break
;
}
}
case
'd'
:
case
'i'
:
*
t
++
=
to_char
((
int
)
tmp
);
{
if
(
prec
||
TESTFLAG
(
ALTERNATE_FORM
))
#ifdef PRINTF_LONG_SUPPORT
*
t
++
=
'.'
;
if
(
lng
)
}
li2a
(
va_arg
(
va
,
unsigned
long
int
),
bf
);
else
{
else
*
t
++
=
'0'
;
#endif
if
(
prec
||
TESTFLAG
(
ALTERNATE_FORM
))
i2a
(
va_arg
(
va
,
int
),
bf
);
*
t
++
=
'.'
;
putchw
(
putp
,
putf
,
w
,
lz
,
bf
);
}
break
;
/* 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
);
}
}
}
case
'x'
:
case
'X'
:
if
(
fract
)
#ifdef PRINTF_LONG_SUPPORT
startp
=
c_round
(
fract
,
(
int
*
)
NULL
,
startp
,
if
(
lng
)
t
-
1
,
(
char
)
0
,
signp
);
uli2a
(
va_arg
(
va
,
unsigned
long
int
),
16
,
(
ch
==
'X'
),
bf
);
}
else
/* alternate format, adds 0's for precision, else trim 0's */
#endif
if
(
TESTFLAG
(
ALTERNATE_FORM
))
ui2a
(
va_arg
(
va
,
unsigned
int
),
16
,
(
ch
==
'X'
),
bf
);
for
(;
prec
--
;
*
t
++
=
'0'
);
putchw
(
putp
,
putf
,
w
,
lz
,
bf
);
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
;
break
;
case
'e'
:
case
'E'
:
case
'f'
:
*
end
=
'0'
;
case
'g'
:
case
'G'
:
if
(
end
==
start
)
{
{
if
(
exp
)
{
/* e/E; increment exponent */
d2a
(
va_arg
(
va
,
double
),
bf
);
*
end
=
'1'
;
putchw
(
putp
,
putf
,
w
,
lz
,
bf
);
++*
exp
;
}
else
{
/* f; add extra digit */
*--
end
=
'1'
;
--
start
;
}
break
;
break
;
}
}
case
'c'
:
}
putf
(
putp
,
(
char
)(
va_arg
(
va
,
int
)));
/* ``"%.3f", (double)-0.0004'' gives you a negative 0. */
break
;
else
if
(
*
signp
==
'-'
)
case
's'
:
for
(;;
--
end
)
{
putchw
(
putp
,
putf
,
w
,
0
,
va_arg
(
va
,
char
*
));
if
(
*
end
==
'.'
)
break
;
--
end
;
case
'%'
:
if
(
*
end
!=
'0'
)
putf
(
putp
,
ch
);
default:
break
;
break
;
}
if
(
end
==
start
)
*
signp
=
0
;
}
}
}
return
(
start
);
abort:
;
}
}
static
char
*
static
void
putcp
(
void
*
p
,
char
c
)
exponent
(
char
*
p
,
int
exp
,
int
fmtch
)
{
{
*
(
*
((
char
**
)
p
))
++
=
c
;
char
*
t
;
char
expbuf
[
MAX_FCONVERSION
];
*
p
++
=
fmtch
;
if
(
exp
<
0
)
{
exp
=
-
exp
;
*
p
++
=
'-'
;
}
else
*
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
++
);
}
else
{
*
p
++
=
'0'
;
*
p
++
=
to_char
(
exp
);
}
return
(
p
);
}
}
#endif
/* FLOATINGPT */
void
c_sprintf
(
char
*
s
,
char
*
fmt
,
...)
void
c_sprintf
(
char
*
s
,
char
*
fmt
,
...)
{
{
va_list
va
;
va_list
arg
;
va_start
(
va
,
fmt
);
va_start
(
arg
,
fmt
);
c_format
(
&
s
,
putcp
,
fmt
,
va
);
vsprintf
(
s
,
fmt
,
arg
);
putcp
(
&
s
,
0
);
va_end
(
arg
);
va_end
(
va
);
}
}
#endif
#endif
app/libc/c_stdlib.c
View file @
18886ea6
...
@@ -3,68 +3,65 @@
...
@@ -3,68 +3,65 @@
#include "c_types.h"
#include "c_types.h"
#include "c_string.h"
#include "c_string.h"
#include "user_interface.h"
#include "user_interface.h"
#include "user_config.h"
// const char *lua_init_value = "print(\"Hello world\")";
// const char *lua_init_value = "print(\"Hello world\")";
const
char
*
lua_init_value
=
"@init.lua"
;
const
char
*
lua_init_value
=
"@init.lua"
;
// int c_abs(int x){
// int c_abs(int x){
//
return x>0?x:0-x;
//
return x>0?x:0-x;
// }
// }
// void c_exit(int e){
// void c_exit(int e){
// }
// }
const
char
*
c_getenv
(
const
char
*
__string
){
const
char
*
c_getenv
(
const
char
*
__string
)
if
(
c_strcmp
(
__string
,
"LUA_INIT"
)
==
0
){
{
return
lua_init_value
;
if
(
c_strcmp
(
__string
,
"LUA_INIT"
)
==
0
)
}
{
return
NULL
;
return
lua_init_value
;
}
return
NULL
;
}
}
// make sure there is enough memory before real malloc, otherwise malloc will panic and reset
// make sure there is enough memory before real malloc, otherwise malloc will panic and reset
// void *c_malloc(size_t __size){
// void *c_malloc(size_t __size){
//
if(__size>system_get_free_heap_size()){
//
if(__size>system_get_free_heap_size()){
//
NODE_ERR("malloc: not enough memory\n");
//
NODE_ERR("malloc: not enough memory\n");
//
return NULL;
//
return NULL;
//
}
//
}
//
return (void *)os_malloc(__size);
//
return (void *)os_malloc(__size);
// }
// }
// void *c_zalloc(size_t __size){
// void *c_zalloc(size_t __size){
//
if(__size>system_get_free_heap_size()){
//
if(__size>system_get_free_heap_size()){
//
NODE_ERR("zalloc: not enough memory\n");
//
NODE_ERR("zalloc: not enough memory\n");
//
return NULL;
//
return NULL;
//
}
//
}
//
return (void *)os_zalloc(__size);
//
return (void *)os_zalloc(__size);
// }
// }
// void c_free(void *p){
// void c_free(void *p){
//
// NODE_ERR("free1: %d\n", system_get_free_heap_size());
//
// NODE_ERR("free1: %d\n", system_get_free_heap_size());
//
os_free(p);
//
os_free(p);
//
// NODE_ERR("-free1: %d\n", system_get_free_heap_size());
//
// NODE_ERR("-free1: %d\n", system_get_free_heap_size());
// }
// }
// int
c_rand(void){
// int
c_rand(void){
// }
// }
// void c_srand(unsigned int __seed){
// void c_srand(unsigned int __seed){
// }
// }
// int
c_atoi(const char *__nptr){
// int
c_atoi(const char *__nptr){
// }
// }
#include <_ansi.h>
#include <_ansi.h>
//#include <reent.h>
//#include <reent.h>
#include <string.h>
#include <string.h>
//#include "mprec.h"
//#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
10
.,
/* is 10^2^i. Used to convert decimal */
* exponent larger than this will already
100
.,
/* exponents into floating-point numbers. */
* 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. */
1.0e4
,
1.0e4
,
1.0e8
,
1.0e8
,
1.0e16
,
1.0e16
,
...
@@ -72,43 +69,57 @@ double c_strtod(const char *string, char **endPtr)
...
@@ -72,43 +69,57 @@ double c_strtod(const char *string, char **endPtr)
1.0e64
,
1.0e64
,
1.0e128
,
1.0e128
,
1.0e256
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
;
int
sign
,
expSign
=
FALSE
;
double
fraction
,
dblExp
,
*
d
;
double
fraction
,
dblExp
,
*
d
;
register
const
char
*
p
;
register
const
char
*
p
;
register
int
c
;
register
int
c
;
int
exp
=
0
;
/* Exponent read from "EX" field. */
int
exp
=
0
;
/* Exponent read from "EX" field. */
int
fracExp
=
0
;
/* Exponent that derives from the fractional
int
fracExp
=
0
;
/* Exponent that derives from the fractional
* part. Under normal circumstatnces, it is
* part. Under normal circumstatnces, it is
* the negative of the number of digits in F.
* the negative of the number of digits in F.
* However, if I is very long, the last digits
* However, if I is very long, the last digits
* of I get dropped (otherwise a long I with a
* of I get dropped (otherwise a long I with a
* large negative exponent could cause an
* large negative exponent could cause an
* unnecessary overflow on I alone). In this
* unnecessary overflow on I alone). In this
* case, fracExp is incremented one for each
* case, fracExp is incremented one for each
* dropped digit. */
* dropped digit. */
int
mantSize
;
/* Number of digits in mantissa. */
int
mantSize
;
/* Number of digits in mantissa. */
int
decPt
;
/* Number of mantissa digits BEFORE decimal
int
decPt
;
/* Number of mantissa digits BEFORE decimal
* point. */
* point. */
const
char
*
pExp
;
/* Temporarily holds location of exponent
const
char
*
pExp
;
/* Temporarily holds location of exponent
* in string. */
* in string. */
/*
/*
* Strip off leading blanks and check for a sign.
* Strip off leading blanks and check for a sign.
*/
*/
p
=
string
;
p
=
string
;
while
(
isspace
((
unsigned
char
)(
*
p
)))
{
while
(
isspace
((
unsigned
char
)(
*
p
)))
p
+=
1
;
{
p
+=
1
;
}
if
(
*
p
==
'-'
)
{
sign
=
TRUE
;
p
+=
1
;
}
}
if
(
*
p
==
'-'
)
{
else
sign
=
TRUE
;
{
p
+=
1
;
if
(
*
p
==
'+'
)
}
else
{
{
if
(
*
p
==
'+'
)
{
p
+=
1
;
p
+=
1
;
}
}
sign
=
FALSE
;
sign
=
FALSE
;
}
}
/*
/*
...
@@ -119,14 +130,16 @@ double c_strtod(const char *string, char **endPtr)
...
@@ -119,14 +130,16 @@ double c_strtod(const char *string, char **endPtr)
decPt
=
-
1
;
decPt
=
-
1
;
for
(
mantSize
=
0
;
;
mantSize
+=
1
)
for
(
mantSize
=
0
;
;
mantSize
+=
1
)
{
{
c
=
*
p
;
c
=
*
p
;
if
(
!
isdigit
(
c
))
{
if
(
!
isdigit
(
c
))
if
((
c
!=
'.'
)
||
(
decPt
>=
0
))
{
{
break
;
if
((
c
!=
'.'
)
||
(
decPt
>=
0
))
}
{
decPt
=
mantSize
;
break
;
}
}
p
+=
1
;
decPt
=
mantSize
;
}
p
+=
1
;
}
}
/*
/*
...
@@ -135,49 +148,60 @@ double c_strtod(const char *string, char **endPtr)
...
@@ -135,49 +148,60 @@ double c_strtod(const char *string, char **endPtr)
* If the mantissa has more than 18 digits, ignore the extras, since
* If the mantissa has more than 18 digits, ignore the extras, since
* they can't affect the value anyway.
* they can't affect the value anyway.
*/
*/
pExp
=
p
;
pExp
=
p
;
p
-=
mantSize
;
p
-=
mantSize
;
if
(
decPt
<
0
)
{
if
(
decPt
<
0
)
decPt
=
mantSize
;
{
}
else
{
decPt
=
mantSize
;
mantSize
-=
1
;
/* One of the digits was the point. */
}
}
if
(
mantSize
>
18
)
{
else
fracExp
=
decPt
-
18
;
{
mantSize
=
18
;
mantSize
-=
1
;
/* One of the digits was the point. */
}
else
{
fracExp
=
decPt
-
mantSize
;
}
}
if
(
mantSize
==
0
)
{
if
(
mantSize
>
18
)
fraction
=
0
.
0
;
{
p
=
string
;
fracExp
=
decPt
-
18
;
goto
done
;
mantSize
=
18
;
}
else
{
}
int
frac1
,
frac2
;
else
frac1
=
0
;
{
for
(
;
mantSize
>
9
;
mantSize
-=
1
)
fracExp
=
decPt
-
mantSize
;
{
}
c
=
*
p
;
if
(
mantSize
==
0
)
p
+=
1
;
{
if
(
c
==
'.'
)
{
fraction
=
0
.
0
;
c
=
*
p
;
p
=
string
;
p
+=
1
;
goto
done
;
}
}
frac1
=
10
*
frac1
+
(
c
-
'0'
);
else
}
{
frac2
=
0
;
int
frac1
,
frac2
;
for
(;
mantSize
>
0
;
mantSize
-=
1
)
frac1
=
0
;
{
for
(
;
mantSize
>
9
;
mantSize
-=
1
)
c
=
*
p
;
{
p
+=
1
;
c
=
*
p
;
if
(
c
==
'.'
)
{
p
+=
1
;
c
=
*
p
;
if
(
c
==
'.'
)
p
+=
1
;
{
}
c
=
*
p
;
frac2
=
10
*
frac2
+
(
c
-
'0'
);
p
+=
1
;
}
}
fraction
=
(
1.0e9
*
frac1
)
+
frac2
;
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)
...
@@ -185,30 +209,40 @@ double c_strtod(const char *string, char **endPtr)
*/
*/
p
=
pExp
;
p
=
pExp
;
if
((
*
p
==
'E'
)
||
(
*
p
==
'e'
))
{
if
((
*
p
==
'E'
)
||
(
*
p
==
'e'
))
p
+=
1
;
{
if
(
*
p
==
'-'
)
{
p
+=
1
;
expSign
=
TRUE
;
if
(
*
p
==
'-'
)
p
+=
1
;
{
}
else
{
expSign
=
TRUE
;
if
(
*
p
==
'+'
)
{
p
+=
1
;
p
+=
1
;
}
}
else
expSign
=
FALSE
;
{
}
if
(
*
p
==
'+'
)
if
(
!
isdigit
((
unsigned
char
)(
*
p
)))
{
{
p
=
pExp
;
p
+=
1
;
goto
done
;
}
}
expSign
=
FALSE
;
while
(
isdigit
((
unsigned
char
)(
*
p
)))
{
}
exp
=
exp
*
10
+
(
*
p
-
'0'
);
if
(
!
isdigit
((
unsigned
char
)(
*
p
)))
p
+=
1
;
{
}
p
=
pExp
;
goto
done
;
}
while
(
isdigit
((
unsigned
char
)(
*
p
)))
{
exp
=
exp
*
10
+
(
*
p
-
'0'
);
p
+=
1
;
}
}
}
if
(
expSign
)
{
if
(
expSign
)
exp
=
fracExp
-
exp
;
{
}
else
{
exp
=
fracExp
-
exp
;
exp
=
fracExp
+
exp
;
}
else
{
exp
=
fracExp
+
exp
;
}
}
/*
/*
...
@@ -217,41 +251,52 @@ double c_strtod(const char *string, char **endPtr)
...
@@ -217,41 +251,52 @@ double c_strtod(const char *string, char **endPtr)
* many powers of 2 of 10. Then combine the exponent with the
* many powers of 2 of 10. Then combine the exponent with the
* fraction.
* fraction.
*/
*/
if
(
exp
<
0
)
{
if
(
exp
<
0
)
expSign
=
TRUE
;
{
exp
=
-
exp
;
expSign
=
TRUE
;
}
else
{
exp
=
-
exp
;
expSign
=
FALSE
;
}
}
if
(
exp
>
maxExponent
)
{
else
exp
=
maxExponent
;
{
// errno = ERANGE;
expSign
=
FALSE
;
}
if
(
exp
>
maxExponent
)
{
exp
=
maxExponent
;
// errno = ERANGE;
}
}
dblExp
=
1
.
0
;
dblExp
=
1
.
0
;
for
(
d
=
powersOf10
;
exp
!=
0
;
exp
>>=
1
,
d
+=
1
)
{
for
(
d
=
powersOf10
;
exp
!=
0
;
exp
>>=
1
,
d
+=
1
)
if
(
exp
&
01
)
{
{
dblExp
*=
*
d
;
if
(
exp
&
01
)
}
{
dblExp
*=
*
d
;
}
}
if
(
expSign
)
{
fraction
/=
dblExp
;
}
}
if
(
expSign
)
{
else
fraction
/=
dblExp
;
{
}
else
{
fraction
*=
dblExp
;
fraction
*=
dblExp
;
}
}
done:
done:
if
(
endPtr
!=
NULL
)
{
if
(
endPtr
!=
NULL
)
*
endPtr
=
(
char
*
)
p
;
{
*
endPtr
=
(
char
*
)
p
;
}
}
if
(
sign
)
{
if
(
sign
)
return
-
fraction
;
{
return
-
fraction
;
}
}
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){
// unsigned long c_strtoul(const char *__n, char **__end_PTR, int __base){
// }
// }
...
...
app/lua/luaconf.h
View file @
18886ea6
...
@@ -601,8 +601,7 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
...
@@ -601,8 +601,7 @@ extern int readline4lua(const char *prompt, char *buffer, int length);
#endif // #if !defined LUA_INTEGRAL_LONGLONG
#endif // #if !defined LUA_INTEGRAL_LONGLONG
#else
#else
#define LUA_NUMBER_SCAN "%lf"
#define LUA_NUMBER_SCAN "%lf"
//#define LUA_NUMBER_FMT "%.14g"
#define LUA_NUMBER_FMT "%.14g"
#define LUA_NUMBER_FMT "%g"
#endif // #if defined LUA_NUMBER_INTEGRAL
#endif // #if defined LUA_NUMBER_INTEGRAL
#define lua_number2str(s,n) c_sprintf((s), LUA_NUMBER_FMT, (n))
#define lua_number2str(s,n) c_sprintf((s), LUA_NUMBER_FMT, (n))
#define LUAI_MAXNUMBER2STR 32
/* 16 digits, sign, point, and \0 */
#define LUAI_MAXNUMBER2STR 32
/* 16 digits, sign, point, and \0 */
...
...
app/lwip/app/espconn.c
View file @
18886ea6
...
@@ -718,3 +718,32 @@ espconn_gethostbyname(struct espconn *pespconn, const char *hostname, ip_addr_t
...
@@ -718,3 +718,32 @@ espconn_gethostbyname(struct espconn *pespconn, const char *hostname, ip_addr_t
return
dns_gethostbyname
(
hostname
,
addr
,
found
,
pespconn
);
return
dns_gethostbyname
(
hostname
,
addr
,
found
,
pespconn
);
}
}
sint8
espconn_recv_hold
(
struct
espconn
*
pespconn
)
{
espconn_msg
*
pnode
=
NULL
;
if
(
pespconn
==
NULL
)
{
return
ESPCONN_ARG
;
}
pespconn
->
state
=
ESPCONN_WRITE
;
if
(
!
espconn_find_connection
(
pespconn
,
&
pnode
))
{
return
ESPCONN_ARG
;
}
espconn_tcp_hold
(
pnode
);
return
ESPCONN_OK
;
}
sint8
espconn_recv_unhold
(
struct
espconn
*
pespconn
)
{
espconn_msg
*
pnode
=
NULL
;
if
(
pespconn
==
NULL
)
{
return
ESPCONN_ARG
;
}
pespconn
->
state
=
ESPCONN_WRITE
;
if
(
!
espconn_find_connection
(
pespconn
,
&
pnode
))
{
return
ESPCONN_ARG
;
}
espconn_tcp_unhold
(
pnode
);
return
ESPCONN_OK
;
}
app/lwip/app/espconn_tcp.c
View file @
18886ea6
...
@@ -948,3 +948,19 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_delete(struct espconn *pdeletecon)
...
@@ -948,3 +948,19 @@ sint8 ICACHE_FLASH_ATTR espconn_tcp_delete(struct espconn *pdeletecon)
return
ESPCONN_ARG
;
return
ESPCONN_ARG
;
}
}
}
}
void
espconn_tcp_hold
(
void
*
arg
)
{
espconn_msg
*
ptcp_sent
=
arg
;
struct
tcp_pcb
*
pcb
=
NULL
;
pcb
=
ptcp_sent
->
pcommon
.
pcb
;
pcb
->
hold
=
1
;
}
void
espconn_tcp_unhold
(
void
*
arg
)
{
espconn_msg
*
ptcp_sent
=
arg
;
struct
tcp_pcb
*
pcb
=
NULL
;
pcb
=
ptcp_sent
->
pcommon
.
pcb
;
pcb
->
hold
=
0
;
}
app/lwip/core/tcp.c
View file @
18886ea6
...
@@ -1259,6 +1259,7 @@ tcp_alloc(u8_t prio)
...
@@ -1259,6 +1259,7 @@ tcp_alloc(u8_t prio)
#endif
/* LWIP_TCP_KEEPALIVE */
#endif
/* LWIP_TCP_KEEPALIVE */
pcb
->
keep_cnt_sent
=
0
;
//���ķ��ʹ���
pcb
->
keep_cnt_sent
=
0
;
//���ķ��ʹ���
pcb
->
hold
=
0
;
}
}
return
pcb
;
return
pcb
;
}
}
...
...
app/lwip/core/tcp_in.c
View file @
18886ea6
...
@@ -1137,7 +1137,7 @@ tcp_receive(struct tcp_pcb *pcb)
...
@@ -1137,7 +1137,7 @@ tcp_receive(struct tcp_pcb *pcb)
/* If the incoming segment contains data, we must process it
/* If the incoming segment contains data, we must process it
further. */
further. */
if
(
tcplen
>
0
)
{
if
(
(
tcplen
>
0
)
&&
(
!
pcb
->
hold
))
{
/* This code basically does three things:
/* This code basically does three things:
+) If the incoming segment contains data that is the next
+) If the incoming segment contains data that is the next
...
...
app/modules/file.c
View file @
18886ea6
...
@@ -125,7 +125,7 @@ static int file_remove( lua_State* L )
...
@@ -125,7 +125,7 @@ static int file_remove( lua_State* L )
if
(
len
>
FS_NAME_MAX_LENGTH
)
if
(
len
>
FS_NAME_MAX_LENGTH
)
return
luaL_error
(
L
,
"filename too long"
);
return
luaL_error
(
L
,
"filename too long"
);
file_close
(
L
);
file_close
(
L
);
SPIFFS_remove
(
&
fs
,
fname
);
SPIFFS_remove
(
&
fs
,
(
char
*
)
fname
);
return
0
;
return
0
;
}
}
...
@@ -150,6 +150,31 @@ static int file_check( lua_State* L )
...
@@ -150,6 +150,31 @@ static int file_check( lua_State* L )
}
}
#endif
#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
#endif
// g_read()
// g_read()
...
@@ -282,6 +307,7 @@ const LUA_REG_TYPE file_map[] =
...
@@ -282,6 +307,7 @@ const LUA_REG_TYPE file_map[] =
{
LSTRKEY
(
"seek"
),
LFUNCVAL
(
file_seek
)
},
{
LSTRKEY
(
"seek"
),
LFUNCVAL
(
file_seek
)
},
{
LSTRKEY
(
"flush"
),
LFUNCVAL
(
file_flush
)
},
{
LSTRKEY
(
"flush"
),
LFUNCVAL
(
file_flush
)
},
// { LSTRKEY( "check" ), LFUNCVAL( file_check ) },
// { LSTRKEY( "check" ), LFUNCVAL( file_check ) },
{
LSTRKEY
(
"rename"
),
LFUNCVAL
(
file_rename
)
},
#endif
#endif
#if LUA_OPTIMIZE_MEMORY > 0
#if LUA_OPTIMIZE_MEMORY > 0
...
...
app/modules/modules.h
View file @
18886ea6
...
@@ -117,6 +117,15 @@
...
@@ -117,6 +117,15 @@
#define ROM_MODULES_BIT
#define ROM_MODULES_BIT
#endif
#endif
#if defined(LUA_USE_MODULES_WS2812)
#define MODULES_WS2812 "ws2812"
#define ROM_MODULES_WS2812 \
_ROM(MODULES_WS2812, luaopen_ws2812, ws2812_map)
#else
#define ROM_MODULES_WS2812
#endif
#define LUA_MODULES_ROM \
#define LUA_MODULES_ROM \
ROM_MODULES_GPIO \
ROM_MODULES_GPIO \
ROM_MODULES_PWM \
ROM_MODULES_PWM \
...
@@ -131,7 +140,8 @@
...
@@ -131,7 +140,8 @@
ROM_MODULES_ADC \
ROM_MODULES_ADC \
ROM_MODULES_UART \
ROM_MODULES_UART \
ROM_MODULES_OW \
ROM_MODULES_OW \
ROM_MODULES_BIT
ROM_MODULES_BIT \
ROM_MODULES_WS2812
#endif
#endif
app/modules/net.c
View file @
18886ea6
...
@@ -1193,6 +1193,54 @@ static int net_socket_send( lua_State* L )
...
@@ -1193,6 +1193,54 @@ static int net_socket_send( lua_State* L )
return
net_send
(
L
,
mt
);
return
net_send
(
L
,
mt
);
}
}
static
int
net_socket_hold
(
lua_State
*
L
)
{
const
char
*
mt
=
"net.socket"
;
struct
espconn
*
pesp_conn
=
NULL
;
lnet_userdata
*
nud
;
size_t
l
;
nud
=
(
lnet_userdata
*
)
luaL_checkudata
(
L
,
1
,
mt
);
luaL_argcheck
(
L
,
nud
,
1
,
"Server/Socket expected"
);
if
(
nud
==
NULL
){
NODE_DBG
(
"userdata is nil.
\n
"
);
return
0
;
}
if
(
nud
->
pesp_conn
==
NULL
){
NODE_DBG
(
"nud->pesp_conn is NULL.
\n
"
);
return
0
;
}
pesp_conn
=
nud
->
pesp_conn
;
espconn_recv_hold
(
pesp_conn
);
return
0
;
}
static
int
net_socket_unhold
(
lua_State
*
L
)
{
const
char
*
mt
=
"net.socket"
;
struct
espconn
*
pesp_conn
=
NULL
;
lnet_userdata
*
nud
;
size_t
l
;
nud
=
(
lnet_userdata
*
)
luaL_checkudata
(
L
,
1
,
mt
);
luaL_argcheck
(
L
,
nud
,
1
,
"Server/Socket expected"
);
if
(
nud
==
NULL
){
NODE_DBG
(
"userdata is nil.
\n
"
);
return
0
;
}
if
(
nud
->
pesp_conn
==
NULL
){
NODE_DBG
(
"nud->pesp_conn is NULL.
\n
"
);
return
0
;
}
pesp_conn
=
nud
->
pesp_conn
;
espconn_recv_unhold
(
pesp_conn
);
return
0
;
}
// Lua: socket:dns( string, function(ip) )
// Lua: socket:dns( string, function(ip) )
static
int
net_socket_dns
(
lua_State
*
L
)
static
int
net_socket_dns
(
lua_State
*
L
)
{
{
...
@@ -1251,6 +1299,8 @@ static const LUA_REG_TYPE net_socket_map[] =
...
@@ -1251,6 +1299,8 @@ static const LUA_REG_TYPE net_socket_map[] =
{
LSTRKEY
(
"close"
),
LFUNCVAL
(
net_socket_close
)
},
{
LSTRKEY
(
"close"
),
LFUNCVAL
(
net_socket_close
)
},
{
LSTRKEY
(
"on"
),
LFUNCVAL
(
net_socket_on
)
},
{
LSTRKEY
(
"on"
),
LFUNCVAL
(
net_socket_on
)
},
{
LSTRKEY
(
"send"
),
LFUNCVAL
(
net_socket_send
)
},
{
LSTRKEY
(
"send"
),
LFUNCVAL
(
net_socket_send
)
},
{
LSTRKEY
(
"hold"
),
LFUNCVAL
(
net_socket_hold
)
},
{
LSTRKEY
(
"unhold"
),
LFUNCVAL
(
net_socket_unhold
)
},
{
LSTRKEY
(
"dns"
),
LFUNCVAL
(
net_socket_dns
)
},
{
LSTRKEY
(
"dns"
),
LFUNCVAL
(
net_socket_dns
)
},
// { LSTRKEY( "delete" ), LFUNCVAL ( net_socket_delete ) },
// { LSTRKEY( "delete" ), LFUNCVAL ( net_socket_delete ) },
{
LSTRKEY
(
"__gc"
),
LFUNCVAL
(
net_socket_delete
)
},
{
LSTRKEY
(
"__gc"
),
LFUNCVAL
(
net_socket_delete
)
},
...
...
app/modules/ws2812.c
0 → 100644
View file @
18886ea6
#include "lualib.h"
#include "lauxlib.h"
#include "platform.h"
#include "auxmods.h"
#include "lrotable.h"
/**
* All this code is mostly from http://www.esp8266.com/viewtopic.php?f=21&t=1143&sid=a620a377672cfe9f666d672398415fcb
* from user Markus Gritsch.
* I just put this code into its own module and pushed into a forked repo,
* to easily create a pull request. Thanks to Markus Gritsch for the code.
*
*/
// ----------------------------------------------------------------------------
// -- This WS2812 code must be compiled with -O2 to get the timing right.
// -- http://wp.josh.com/2014/05/13/ws2812-neopixels-are-not-so-finicky-once-you-get-to-know-them/
// The ICACHE_FLASH_ATTR is there to trick the compiler and get the very first pulse width correct.
static
void
ICACHE_FLASH_ATTR
send_ws_0
(
uint8_t
gpio
)
{
uint8_t
i
;
i
=
4
;
while
(
i
--
)
GPIO_REG_WRITE
(
GPIO_OUT_W1TS_ADDRESS
,
1
<<
gpio
);
i
=
9
;
while
(
i
--
)
GPIO_REG_WRITE
(
GPIO_OUT_W1TC_ADDRESS
,
1
<<
gpio
);
}
static
void
ICACHE_FLASH_ATTR
send_ws_1
(
uint8_t
gpio
)
{
uint8_t
i
;
i
=
8
;
while
(
i
--
)
GPIO_REG_WRITE
(
GPIO_OUT_W1TS_ADDRESS
,
1
<<
gpio
);
i
=
6
;
while
(
i
--
)
GPIO_REG_WRITE
(
GPIO_OUT_W1TC_ADDRESS
,
1
<<
gpio
);
}
// Lua: ws2812.write(pin, "string")
// Byte triples in the string are interpreted as G R B values.
// ws2812.write(4, string.char(0, 255, 0)) uses GPIO2 and sets the first LED red.
// ws2812.write(3, string.char(0, 0, 255):rep(10)) uses GPIO0 and sets ten LEDs blue.
// ws2812.write(4, string.char(255, 0, 0, 255, 255, 255)) first LED green, second LED white.
static
int
ICACHE_FLASH_ATTR
ws2812_write
(
lua_State
*
L
)
{
const
uint8_t
pin
=
luaL_checkinteger
(
L
,
1
);
size_t
length
;
const
char
*
buffer
=
luaL_checklstring
(
L
,
2
,
&
length
);
platform_gpio_mode
(
pin
,
PLATFORM_GPIO_OUTPUT
,
PLATFORM_GPIO_FLOAT
);
platform_gpio_write
(
pin
,
0
);
os_delay_us
(
10
);
os_intr_lock
();
const
char
*
const
end
=
buffer
+
length
;
while
(
buffer
!=
end
)
{
uint8_t
mask
=
0x80
;
while
(
mask
)
{
(
*
buffer
&
mask
)
?
send_ws_1
(
pin_num
[
pin
])
:
send_ws_0
(
pin_num
[
pin
]);
mask
>>=
1
;
}
++
buffer
;
}
os_intr_unlock
();
return
0
;
}
#define MIN_OPT_LEVEL 2
#include "lrodefs.h"
const
LUA_REG_TYPE
ws2812_map
[]
=
{
{
LSTRKEY
(
"write"
),
LFUNCVAL
(
ws2812_write
)},
{
LNILKEY
,
LNILVAL
}
};
LUALIB_API
int
luaopen_ws2812
(
lua_State
*
L
)
{
// TODO: Make sure that the GPIO system is initialized
LREGISTER
(
L
,
"ws2812"
,
ws2812_map
);
return
1
;
}
// ----------------------------------------------------------------------------
app/platform/cpu_esp8266.h
View file @
18886ea6
...
@@ -25,6 +25,10 @@
...
@@ -25,6 +25,10 @@
#define FLASH_SEC_NUM 0x200
#define FLASH_SEC_NUM 0x200
#elif defined(FLASH_4M)
#elif defined(FLASH_4M)
#define FLASH_SEC_NUM 0x400
#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)
#elif defined(FLASH_AUTOSIZE)
#define FLASH_SEC_NUM (flash_get_sec_num())
#define FLASH_SEC_NUM (flash_get_sec_num())
#else
#else
...
...
app/platform/flash_api.c
View file @
18886ea6
...
@@ -56,6 +56,12 @@ uint32_t flash_get_size_byte(void)
...
@@ -56,6 +56,12 @@ uint32_t flash_get_size_byte(void)
case
SIZE_32MBIT
:
case
SIZE_32MBIT
:
// 32Mbit, 4MByte
// 32Mbit, 4MByte
flash_size
=
4
*
1024
*
1024
;
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
;
break
;
default:
default:
// Unknown flash size, fall back mode.
// Unknown flash size, fall back mode.
...
...
app/platform/flash_api.h
View file @
18886ea6
...
@@ -52,6 +52,8 @@ typedef struct
...
@@ -52,6 +52,8 @@ typedef struct
SIZE_8MBIT
=
2
,
SIZE_8MBIT
=
2
,
SIZE_16MBIT
=
3
,
SIZE_16MBIT
=
3
,
SIZE_32MBIT
=
4
,
SIZE_32MBIT
=
4
,
SIZE_64MBIT
=
5
,
SIZE_128MBIT
=
6
,
}
size
:
4
;
}
size
:
4
;
}
ICACHE_STORE_TYPEDEF_ATTR
SPIFlashInfo
;
}
ICACHE_STORE_TYPEDEF_ATTR
SPIFlashInfo
;
...
...
Prev
1
2
Next
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment