rel_1.6.0 init

This commit is contained in:
guocheng.kgc 2020-06-18 20:06:52 +08:00 committed by shengdong.dsd
commit 27b3e2883d
19359 changed files with 8093121 additions and 0 deletions

View file

@ -0,0 +1,74 @@
# BoneEngine @lite for AliOS Things #
BoneEngine for AOS, 是一套为AliOS Things优化定制的JavaScript引擎, 集成了各IoT模块为AliOS Things及运行AliOS的设备提供一套JavaScript的编程及运行环境。
采用 BoneEngine for AOS来构建物联网应用极大的降低开发门槛让更多开发者得以进入到硬件开发领域中。
## 使用方法
详情请参考[BoneEngine@lite for aos 使用说明.md](/doc/BoneEngine@lite%20for%20aos%20%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E.md)
```
代码放置路径: aos.git/framework/bone_engine
BoneEngine例程编译方法
在example目录中创建参考例程目的符号链接
cd aos.git
ln -s ../framework/bone_engine/examples example/boneengine_demo
编译方法
aos make boneengine_demo@linuxhost
aos make boneengine_demo@mk3060
aos make boneengine_demo@mk3060 VERBOSE=1
aos make boneengine_demo@mk3060 BUILD_TYPE=release
aos make boneengine_demo@mk3060 JTAG=jlink download
```
## 说明文档
请参考doc目录下相关文档
* [BoneEngine@lite for aos 使用说明.md](/doc/BoneEngine@lite%20for%20aos%20%E4%BD%BF%E7%94%A8%E8%AF%B4%E6%98%8E.md)
* [javascript能力集介绍.md](/doc/javascript%E8%83%BD%E5%8A%9B%E9%9B%86%E4%BB%8B%E7%BB%8D.md)
* [javascript支持范围.xlsx](/doc/javascript%E6%94%AF%E6%8C%81%E8%8C%83%E5%9B%B4.xlsx)
* [alink对象说明.md](/doc/alink%E5%AF%B9%E8%B1%A1%E8%AF%B4%E6%98%8E.md)
* [gpio对象说明.md](/doc/gpio%E5%AF%B9%E8%B1%A1%E8%AF%B4%E6%98%8E.md)
* [process对象说明.md](/doc/process%E5%AF%B9%E8%B1%A1%E8%AF%B4%E6%98%8E.md)
* [timers说明.md](/doc/timers%E8%AF%B4%E6%98%8E.md)
* [uart对象说明.md](/doc/uart%E5%AF%B9%E8%B1%A1%E8%AF%B4%E6%98%8E.md)
## 重要参考资料
* [tiny-js](https://github.com/gfwilliams/tiny-js "tiny-js")
* [ECMAScript® Language Specification](https://www.ecma-international.org/ecma-262/5.1/)
* [ECMAScript5.1中文版](http://yanhaijing.com/es5/#0)
* 《Compilers: Principles, Techniques, and Tools (2nd Edition)》 ISBN-13: 978-0321486813
## 后续计划
**将重构JSE代码并持续优化BoneBngine。 **
# License
BoneEngine @lite for AliOS Things is released under the Apache 2.0 license.
Copyright 2015-2017 Alibaba Group Holding Ltd.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at following link.
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View file

@ -0,0 +1,77 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef BOARD_H_
#define BOARD_H_
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "aos/aos.h"
//#define USE_MK3060
#define USE_AOS
//#define OPTIMIZE_SIZE
#define USE_GLOBAL
#define USE_INTEGER
#define USE_MATH
#define USE_JSON
#define USE_STRING
#define USE_ARRAY
//#define USE_ALINK
#define USE_PROCESS
//#define USE_GPIO
#define USE_TIMERS
#define USE_UART
#define TRACE_JSE_INFO
#define DUMP_SYMBL_USAGE
// 根据实现情况配置GPIO或与HAL对应
/*
platform\mcu\beken\hal\gpio.c
static const uint8_t gpio_map[] =
{
[1] = 30,
[2] = 29,
[3] = 17,
[4] = 16,
[5] = 14,
[6] = 15,
[7] = 0,
[8] = 1,
[11] = 20,
[12] = 4,
[17] = 23,
[18] = 22,
[19] = 11,
[20] = 10,
[21] = 21,
};
GPIO20 GPIO4
*/
#define GPIO_COUNT 22
// GPIO id号, 与硬件对应
static const int gpio_id[GPIO_COUNT]= {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21};
//#define USE_ADC
#undef USE_ADC
#endif /* BOARD_H_ */

View file

@ -0,0 +1,59 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef BOARD_H_
#define BOARD_H_
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "aos/aos.h"
#define USE_AOS
#define USE_GLOBAL
#define USE_INTEGER
#define USE_MATH
#define USE_JSON
#define USE_STRING
#define USE_ARRAY
#define USE_ALINK
#define USE_PROCESS
#define USE_GPIO
#define USE_TIMERS
#define USE_UART
#define TRACE_JSE_INFO
#define DUMP_SYMBL_USAGE
// 根据实现情况配置GPIO
#define GPIO_COUNT 5
// GPIO id号, 与硬件对应
static const int gpio_id[GPIO_COUNT]= {1,2,3,4,5};
/*
aos make xxx@linuxhost
linuxhost gpio
undefined reference to `hal_gpio_init'
undefined reference to `hal_gpio_output_high'
undefined reference to `hal_gpio_output_low'
undefined reference to `hal_gpio_input_get'
*/
#undef USE_GPIO
#endif /* BOARD_H_ */

View file

@ -0,0 +1,77 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef BOARD_H_
#define BOARD_H_
#include <string.h>
#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "aos/aos.h"
#define USE_MK3060
#define USE_AOS
//#define OPTIMIZE_SIZE
#define USE_GLOBAL
#define USE_INTEGER
#define USE_MATH
#define USE_JSON
#define USE_STRING
#define USE_ARRAY
#define USE_ALINK
#define USE_PROCESS
#define USE_GPIO
#define USE_TIMERS
#define USE_UART
#define TRACE_JSE_INFO
#define DUMP_SYMBL_USAGE
// 根据实现情况配置GPIO或与HAL对应
/*
platform\mcu\beken\hal\gpio.c
static const uint8_t gpio_map[] =
{
[1] = 30,
[2] = 29,
[3] = 17,
[4] = 16,
[5] = 14,
[6] = 15,
[7] = 0,
[8] = 1,
[11] = 20,
[12] = 4,
[17] = 23,
[18] = 22,
[19] = 11,
[20] = 10,
[21] = 21,
};
GPIO20 GPIO4
*/
#define GPIO_COUNT 22
// GPIO id号, 与硬件对应
static const int gpio_id[GPIO_COUNT]= {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21};
//#define USE_ADC
#undef USE_ADC
#endif /* BOARD_H_ */

View file

@ -0,0 +1,29 @@
NAME := bone_engine
$(NAME)_SOURCES += jse/be_jse_executor.c \
jse/be_jse_lex.c \
jse/be_jse_utils.c \
jse/be_jse_symbol.c \
src/bone_engine.c \
modules/be_bi_module.c \
modules/be_iot_module.c \
modules/aos_alink_impl.c \
modules/module_alink.c \
modules/module_process.c \
modules/module_gpio.c \
modules/module_timers.c \
modules/module_uart.c
GLOBAL_INCLUDES += include
# 根据board类型区别编译
$(warning BUILD_TYPE=$(BUILD_TYPE) )
$(warning $(NAME)_BUILD_TYPE=$(bone_engine_BUILD_TYPE) )
$(warning HOST_ARCH=$(HOST_ARCH) )
$(warning CONFIG_SYSINFO_PRODUCT_MODEL=$(CONFIG_SYSINFO_PRODUCT_MODEL) )
GLOBAL_INCLUDES += boards/$(CONFIG_SYSINFO_PRODUCT_MODEL)

View file

@ -0,0 +1,296 @@
# BoneEngine@lite for aos 介绍
AliOS Things是阿里巴巴旗下物联网操作系统。阿里巴巴发布物联网操作系统AliOS Things主要目的是让阿里巴巴的物联网技术普惠更多的开发者和用户助力实现更加美好的物联网时代。
`BoneEngine@lite for aos` 是一个专门为AOS系统设计的JavaScript引擎为模组使用做了专门优化。
## aos编译说明
* **编译命令**
bone_engine 是模块名称
linuxhost 是指board类型
参数VERBOSE=1
参数BUILD_TYPE 默认release_log可选有debug,release,release_log
```
代码放置路径: aos.git/framework/bone_engine
cd aos.git
ln -s ../framework/bone_engine/examples example/boneengine_demo
aos make boneengine_demo@linuxhost
aos make boneengine_demo@mk3060
aos make boneengine_demo@mk3060 VERBOSE=1
aos make boneengine_demo@mk3060 BUILD_TYPE=release
aos make boneengine_demo@mk3060 JTAG=jlink download
```
* 查看CFLAG
重要flag: SYSINFO_PRODUCT_MODEL 用于区别产品类型
```
cat out/boneengine_demo@mk3060/libraries/bone_engine.c_opts
-c -MD -DSYSINFO_KERNEL_VERSION=\"AOS-R-1.3.4\" -DMESH_GATEWAY_SERVICE -DGATEWAY_SDK -mcpu=arm968e-s -march=armv5te -mthumb -mthumb-interwork -mlittle-endian -w -DSYSINFO_PRODUCT_MODEL=\"ALI_AOS_MK3060\" -DSYSINFO_DEVICE_NAME=\"MK3060\" -DSYSINFO_APP_VERSION=\"APP-1.0.0-20171117.0857\" -ggdb -Os -Wall -Wfatal-errors -fsigned-char -ffunction-sections -fdata-sections -fno-common -std=gnu11 -DAOS_SDK_VERSION_MAJOR=3 -DAOS_SDK_VERSION_MINOR=2 -DAOS_SDK_VERSION_REVISION=3 -Iout/boneengine_demo@mk3060/resources/ -DPLATFORM=\"mk3060\" -I./security/alicrypto/inc -I./security/alicrypto/test -I./framework/gateway/msdp/. -I./framework/gateway/devmgr/. -I./kernel/protocols/mesh/include -I./framework/fota/socket/./ -I./framework/fota/platform/./ -I./kernel/modules/fs/kv/include -I./utility/hashtable/. -I./utility/base64/. -I./framework/connectivity/wsf/. -I./kernel/protocols/net/include -I./kernel/protocols/net/port/include -I././platform/mcu/beken/beken7231/beken378/driver/entry/. -I./utility/digest_algorithm/. -I./utility/cjson/include -I./security/mbedtls/include -I./kernel/rhino/core/include -I././platform/arch/arm/armv5/. -I./framework/gateway/./ -I./framework/ywss/. -I./framework/bone_engine/include -I./framework/bone_engine/boards/ALI_AOS_MK3060 -I./framework/netmgr/include -I./framework/netmgr/../protocol/alink/os/platform/ -I./framework/fota/. -I./tools/cli/include -I./framework/protocol/alink/. -I./framework/protocol/alink/accs -I./framework/protocol/alink/json -I./framework/protocol/alink/system -I./framework/protocol/alink/os -I./kernel/vfs/include -I./kernel/vcall/./mico/include -I././platform/mcu/beken/beken7231/beken378/func/mxchip/lwip-2.0.2/port -I././platform/mcu/beken/beken7231/beken378/common -I././platform/mcu/beken/beken7231/beken378/app/config -I././platform/mcu/beken/beken7231/beken378/func/include -I././platform/mcu/beken/beken7231/beken378/os/include -I././platform/mcu/beken/beken7231/beken378/driver/include -I././platform/mcu/beken/beken7231/beken378/driver/common -I././platform/mcu/beken/beken7231/beken378/ip/common -I././platform/mcu/beken/beken7231/beken378/os/FreeRTOSv9.0.0/FreeRTOS/Source/portable/Keil/ARM968es -I./board/mk3060/. -I./include -I./example/boneengine_demo -DBUILD_BIN -DCONFIG_ALICRYPTO -DCONFIG_AOS_MESH -DAOS_KV -DAOS_LOOP -DWITH_LWIP -DCONFIG_NET_LWIP -DAOS_HAL -DCONFIG_YWSS -DAOS_FRAMEWORK_COMMON -DAOS_NETMGR -DAOS_FOTA -DHAVE_NOT_ADVANCED_FORMATE -DCONFIG_AOS_CLI -DAOS_VFS -DVCALL_RHINO -DCONFIG_MX108 -DCONFIG_AOS_KV_MULTIPTN_MODE -DCONFIG_AOS_KV_PTN=6 -DCONFIG_AOS_KV_SECOND_PTN=7 -DCONFIG_AOS_KV_PTN_SIZE=4096 -DCONFIG_AOS_KV_BUFFER_SIZE=8192 -DSTDIO_UART=0
```
* **查看board类型**
```
ls board
armhflinux b_l475e esp32devkitc linuxhost mk108 mk3060
```
* **烧录说明**
[庆科 MK3060 烧录说明](https://github.com/alibaba/AliOS-Things/wiki/AliOS-Things-Environment-Setup)
## 目录介绍
```
├── boards
│   ├── ALI_AOS_LINUXHOST
│   │   └── be_board.h
│   └── ALI_AOS_MK3060
│   └── be_board.h
├── bone_engine.mk
├── doc
│   ├── alink对象说明.md
│   ├── BoneEngine@lite for aos 使用说明.md
│   ├── gpio对象说明.md
│   ├── javascript支持范围.xlsx
│   ├── javascript能力集介绍.md
│   ├── process对象说明.md
│   ├── timers说明.md
│   └── uart对象说明.md
├── include
│   ├── aos_alink_impl.h
│   ├── be_bi_module.h
│   ├── be_iot_module.h
│   ├── be_jse_api.h
│   ├── be_jse_executor.h
│   ├── be_jse_feature.h
│   ├── be_jse_global.h
│   ├── be_jse.h
│   ├── be_jse_lex.h
│   ├── be_jse_symbol.h
│   ├── be_jse_types.h
│   ├── be_jse_utils.h
│   ├── module_alink.h
│   ├── module_gpio.h
│   ├── module_process.h
│   ├── module_timers.h
│   └── module_uart.h
├── jse
│   ├── be_jse_executor.c
│   ├── be_jse_lex.c
│   ├── be_jse_symbol.c
│   └── be_jse_utils.c
├── modules
│   ├── aos_alink_impl.c
│   ├── be_bi_module.c
│   ├── be_iot_module.c
│   ├── module_alink.c
│   ├── module_gpio.c
│   ├── module_process.c
│   ├── module_timers.c
│   └── module_uart.c
├── README.md
├── examples
│   ├── boneengine_demo.mk
│   └── demo.c
└── src
└── bone_engine.c
```
* boards目录
板型配置
对于不同的产品JS的扩展可以定制
可以配置JS扩展类可以配置外设如GPIO端口映射等
配置文件:`board/$(CONFIG_SYSINFO_PRODUCT_MODEL)/be_board.h`
* doc目录
相关文档资料
* include目录
头文件
* jse
JS引擎源文件
* modules
扩展模块文件
* src
AOS系统中对于JSE的调用封装
* boneengine_demo
AOS系统上应用参考例程
## API介绍
1. **void bone_engine_init();**
BoneEngine初始化
2. **void bone_engine_native_function_register(BE_JSE_FUNCTION_EXECUTE_CB extension);**
注册自定义JS对象Native扩展方法及属性的实现函数
3. **be_jse_node_t bone_engine_native_object_register(const char* objectName);**
用户注册自定义的JS对象,返回该对象的引用值
<font color=#DC143C><b>必须在bone_engine_init之后调用</b></font>
4. **void bone_engine_start(const char\* js); **
运行JS程序
5. **void bone_engine_restart(const char\* js);**
重新运行JS程序
6. **void bone_engine_exit();**
退出BoneEngine
7. **be_jse_executor_ctx_t* bone_engine_get_executor();**
获取当前BoneEngine引擎的executor对象
## natvie扩展
&emsp;&emsp;**用户可以根据需要扩展JS对象的方法及全局函数**
* 使用API: **bone_engine_native_object_register**
在使用BoneEngine时用户可以调用`bone_engine_native_object_register`注册一个自定义的命名对象
参考代码: demo.c 中注册了一个自定义的`custom`对象
```
customObj = bone_engine_register_object("custom");
```
* 使用API: **`bone_engine_native_function_register`**
在使用BoneEngine时用户可以调用`bone_engine_native_function_register`注册JS对象Native扩展方法及属性的实现函数在这个注册的函数中用户可以实现全局函数扩展和自定义对象的方法及属性的扩展
参考代码: `be_bi_module.c`文件中`handle_function_call`这个函数中有对内部对象(`Integer``Math``JSON``String``Array`)方法及全局函数扩展的实现
参考代码: demo.c 中`BeJseNativeFunctions`函数
```
全局函数:
print(x);
now();
exit();
getip();
trace();
custom对象
custom.add(a,b) Native函数扩展
custom.version 该对象属性扩展
be_jse_symbol_t *BeJseNativeFunctions(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *var, const char *name)
{
be_jse_symbol_t* arg0;
be_jse_symbol_t* arg1;
int val;
NOT_USED(execInfo);
char str[32];
if( var == NULL ) {
// 全局函数
if (strcmp(name,"print")==0) {
// JS function print(text)
be_jse_symbol_t *text = str_to_symbol(be_jse_handle_single_arg_function(), true);
bevPrintStringVar(text);
symbol_unlock(text);
//printf("\n");
return new_symbol(BE_SYM_NULL);
}
if( strcmp(name, "now")==0) {
// 必须加上,函数参数完成语法分析
be_jse_handle_function(0, 0, 0, 0, 0);
// framework/protocol/alink/os/platform/platform.h platform_get_utc_time
extern uint64_t platform_get_utc_time(uint64_t *p_utc);
be_jse_symbol_t *newValue = new_int_symbol( (be_jse_int_t)platform_get_utc_time(NULL));
return newValue;
}
if( strcmp(name, "exit")==0) {
be_jse_handle_function(0, 0, 0, 0, 0);
LOGW("BoneEngine", "aos_loop_exit ...");
aos_loop_exit();
return new_symbol(BE_SYM_NULL);
}
if( strcmp(name, "getip")==0) {
be_jse_handle_function(0, 0, 0, 0, 0);
LOGW("BoneEngine", "getip ...");
LOGW("BoneEngine","netmgr_get_ip_state=%d \r\n", netmgr_get_ip_state());
memset(str, 0, sizeof(str));
wifi_get_ip(str);
LOGW("BoneEngine","wifi_get_ip=%s \r\n", str);
if( strcmp(str,"0.0.0.0")==0 )
return new_symbol(BE_SYM_NULL);
return new_str_symbol(str);
}
if(strcmp(name, "trace")==0) {
be_jse_handle_function(0, 0, 0, 0, 0);
#ifdef TRACE_JSE_INFO
trace_symbol_info(bone_engine_get_executor()->root, 0);
#endif
return new_symbol(BE_SYM_NULL);
}
}
// 自定义对象的Native函数扩展实现 custom.add(a,b)
if( customObj > 0 && customObj == get_symbol_node_id(var) ) {
if( strcmp(name, "add")==0) {
be_jse_handle_function(0, &arg0, &arg1, 0, 0);
val = get_symbol_value_int(arg0) + get_symbol_value_int(arg1);
symbol_unlock(arg0);
symbol_unlock(arg1);
return new_int_symbol(val);
}
if (strcmp(name,"version")==0) {
lexer_token_cmp(execInfo->lex, BE_TOKEN_ID);
return new_str_symbol("0.0.1");
}
}
return BE_JSE_FUNC_UNHANDLED;
}
```
## ROM/RAM优化
* **编译成release版本, BUILD_TYPE = release**
* **根据实际需要配置合适的BE_JSE_VAR_CACHE_SIZE**
**`#define BE_JSE_VAR_CACHE_SIZE 500`**
**BE_JSE_VAR_CACHE_SIZE每增加100, RAM增加2100Byte**
编译成release_log或debug版本 boneengine_demo中有一个`meminfo`可以查看当前系统js symbol运行中最大使用值可以根据该值调整BE_JSE_VAR_CACHE_SIZE
* **定制be_board.h,删除无用的功能模块**
TRACE_JSE_INFO、DUMP_SYMBL_USAGE

View file

@ -0,0 +1,141 @@
# alink对象说明
alink对象是一个全局对象能够在任意位置访问。
## alink 介绍
alink是指阿里巴巴使用物联网连接协议。
## 属性
## 方法
### **1. alink.getloglevel()**
获取log输出level等级返回数字
log level等级说明:
* 0 : AOS_LL_NONE, disable log
* 1 : AOS_LL_FATAL, fatal log will output
* 2 : AOS_LL_ERROR, fatal + error log will output
* 3 : AOS_LL_WARN, fatal + warn + error log will output(default level)
* 4 : AOS_LL_INFO, info + warn + error log will output
* 5 : AOS_LL_DEBUG, debug + info + warn + error + fatal log will output
```
print('alink.getloglevel()=' + alink.getloglevel());
```
输出
```
BoneEngine > alink.getloglevel()=3
```
### **2. alink.setloglevel(level)**
设置log输出level等级
### **3. alink.getuuid()**
获取当前设备的UUID返回一个String
```
print('alink.getuuid()=' + alink.getuuid());
```
输出
```
BoneEngine > uuid=851174F61FE684496564C6CF4EEC13FB
```
### **4. alink.getstatus()**
获取当前alink模块的状态,返回数字
status说明:
* 0 : stop
* 1 : start
* 2 : connected
### **5. alink.isrunning()**
获取当前alink模块是否已经运行返回数字
### **6. alink.start()**
启动alink模块, 返回数字
* 0 : 成功
### **7. alink.postdata(method, jsonCmd)**
发送属性上云
输入参数:
* method : string类型, alink method
* jsonCmd : string类型, json字符串
返回值:数字
* 0 成功
```
var cmd = {};
cmd.attrSet = [\"BodyWeight\", \"DateTime\"];
cmd.BodyWeight = {value:57.9};
cmd.DateTime = {value: now() };
alink.postdata('postDeviceData', JSON.stringify(cmd));
```
输出LOG
```
[ 0.000]<W> aos_alink_impl [alink_post_data#131] : method=postDeviceData jsonBuf = {"attrSet":["BodyWeight","DateTime"],"BodyWeight":{"value":"91.251451"},"DateTime":{"value":"1508407685"}}
[ 0.000]<D> accs [get_protocol_buff#87] : ------->>> lock <<<-------
[ 0.000]<D> wsf [wsf_send_async#108] : wsf_send: {"system":{"alink":"1.0","jsonrpc":"2.0","lang":"en","sign":"2cb86d1dd34f8fa3524df8af55a3ee0d","key":"noZXLHemHlRDD4TdIcda","time":""},"request":{"cid":"rtl8188eu 12345678","rspID":-1,"target":"","token":"","uuid":"851174F61FE684496564C6CF4EEC13FB"},"method":"postDeviceData","params":{"attrSet":["BodyWeight","DateTime"],"BodyWeight":{"value":"91.251451"},"DateTime":{"value":"1508407685"}},"id":101}
[ 0.000]<D> wsf [wsf_send_msg#176] : wsf send succeed-> 505
[ 0.000]<D> wsf [__send_msg#605] : wsf msg send succeed.id=2
[ 0.000]<D> accs [put_protocol_buff#94] : ------->>> unlock <<<--------
```
### **8. alink.stop()**
停止alink模块, 返回数字
* 0 : 成功
## 事件
### **1. onStatusChange**
alink状态变化通知
alink.on(“onStatusChange”, function(status, uuid){
});
回调函数参数:
* status : alink状态 与alink.getstatus()一致
* uuid : 设备UUID 与alink.getuuid()一致
```
function onStatusChange(status, uuid){
print('call js func onStatusChange');
print('status =' + status);
print('uuid=' + uuid);
}
alink.on(\"onStatusChange\", onStatusChange);
```
### **2. onSetAttrs**
alink云端下发`ALINK_SET_DEVICE_STATUS`事件通知
alink.on(“onSetAttrs”, function(jsonBuf){
});
回调函数参数:
* jsonBuf : alink云端下发`ALINK_SET_DEVICE_STATUS`事件, json字符串
### **3. onGetAttrs**
alink云端下发`ALINK_GET_DEVICE_RAWDATA`事件通知
alink.on(“onGetAttrs”, function(jsonBuf){
});
回调函数参数:
* jsonBuf : alink云端下发`ALINK_GET_DEVICE_RAWDATA`事件, json字符串

View file

@ -0,0 +1,61 @@
# gpio对象说明
gpio对象是一个全局对象能够在任意位置访问。
## gpio 介绍
## 属性
## 方法
### **1. gpio.open(id,config)**
配置gpio端口返回值数字
- 0 成功
输入参数:
- id : GPIO端口序号类型为数字从0开始
GPIO id序号, 与实际板型硬件有映射, board.h中有配置
- config : GPIO端口属性配置, 类型为数字
配置属性如下:
- 0 INPUT_PULL_UP
- 1 INPUT_PULL_DOWN
- 2 INPUT_HIGH_IMPEDANCE
- 3 OUTPUT_PUSH_PULL
- 4 OUTPUT_OPEN_DRAIN_NO_PULL
- 5 OUTPUT_OPEN_DRAIN_PULL_UP
### **2. gpio.write(id,value)**
配置GPIO id号对应的端口状态, 返回值数字
- 0 成功
输入参数:
- id : GPIO端口序号类型为数字从0开始
- value : GHIO端口状态
- \>0 : high
- \<0 : low
### **3. gpio.read(id)**
获取GPIO指定端口的状态返回值数字
- 1 : high
- 0 : low
**如果gpio pin配置成output mode返回无效**
### **4. gpio.close(id)**
结束操作GPIO操作,返回值数字
- 0 成功
输入参数:
- id : GPIO端口序号类型为数字从0开始
## 事件

View file

@ -0,0 +1,286 @@
# 介绍
**`BoneEngine@lite` 是一个为模组设计的JavaScript引擎由于模组对于`ROM、RAM`的使用限制要求比较严格,所以`BoneEngine@lite`对于JS的标准有裁剪,对JavaScript语法支持范围有限。**
---
## 支持能力集
### 1. 请见《javascript支持范围.xlsx》
### 2. javascript测试集目录testcases
```
编译master分支运行自测程序
./BoneEngine testcases
```
### 3. 标准JS对象说明
* Object对象
不支持constructor、prototype属性
* Integer对象
- Integer.parseInt(value)
测试代码:
```
var a = Integer.parseInt('0b011');
var b = Integer.parseInt('0B1000');
var c = Integer.parseInt('10.33');
var d = Integer.parseInt('34 45 66');
var e = Integer.parseInt(' 60 ');
var f = Integer.parseInt('40 years');
var h = Integer.parseInt('10');
var i = Integer.parseInt('010');
var j = Integer.parseInt('10');
var k = Integer.parseInt('0x10');
print('a=' + a);
print('b=' + b);
print('c=' + c);
print('d=' + d);
print('e=' + e);
print('f=' + f);
print('h=' + h);
print('i=' + i);
print('j=' + j);
print('k=' + k);
```
运行结果:
```
BoneEngine > a=3
BoneEngine > b=8
BoneEngine > c=10
BoneEngine > d=34
BoneEngine > e=60
BoneEngine > f=40
BoneEngine > h=10
BoneEngine > i=8
BoneEngine > j=10
BoneEngine > k=16
```
* Math对象
- Math.random()
* Array对象
- 不支持 new 操作
- 支持 []初始化
- length
- push(newelement)
- pop()
- indexOf(element)
- contains(element)
测试代码:
```
var arr = [1,2];
arr.push(3);
arr.push(4);
arr.push('ok5');
arr.push(6);
print('arr.length = ' + arr.length);
arr.pop();
print('arr.length = ' + arr.length);
print('arr.indeOf(2) = ' + arr.indexOf(2));
print('arr.contains(2) = ' + arr.contains(2));
print('arr.contains(9) = ' + arr.contains(9));
```
运行结果:
```
BoneEngine > arr.length = 6
BoneEngine > arr.length = 5
BoneEngine > arr.indeOf(2) = 1
BoneEngine > arr.contains(2) = 1
BoneEngine > arr.contains(9) = 0
```
* String对象
- 不支持 new 操作
- length
- charAt(index)
- substring(start,[stop])
- substr(start,[length])
- clone()
测试代码:
```
var str="Hello world!"
print('str.charAt(2)=' + str.charAt(2));
print('str.substr(3,7)=' + str.substr(3,7));
print('str.substring(3)=' + str.substring(3));
print('str.length=' + str.length);
str = str + 'ok';
print('str.length=' + str.length);
print('str=' + str);
var str2 = str.clone();
print('str2=' + str2);
```
运行结果
```
BoneEngine > str.charAt(2)=l
BoneEngine > str.substr(3,7)=lo worl
BoneEngine > str.substring(3)=lo world!
BoneEngine > str.length=12
BoneEngine > str.length=14
BoneEngine > str=Hello world!ok
BoneEngine > str2=Hello world!ok
```
* JSON对象
- stringify(value)
- parse(text)
测试代码:
```
var cmd = {};
cmd.attrSet = ['BodyWeight', "DateTime"];
cmd.BodyWeight = {value:57.9};
cmd.DateTime = {value: '2017/10/20 14:00' };
print('JSON.stringify(cmd)=' + JSON.stringify(cmd));
print('JSON.stringify(cmd.attrSet)=' + JSON.stringify(cmd.attrSet));
var jsontext = '{"firstname":"Jesper",' + '"surname":"Aaberg","phone":["555-0100","555-0120"]}';
var contact = JSON.parse(jsontext);
print('contact.firstname=' + contact.firstname);
print('contact.surname=' + contact.surname);
var arr = ["a", "b", "c"];
var str = JSON.stringify(arr);
print('str=' + str);
var newArr = JSON.parse(str);
print('newArr.pop()='+newArr.pop());
```
运行结果:
```
BoneEngine > JSON.stringify(cmd)={"attrSet":["BodyWeight","DateTime"],"BodyWeight":{"value":"57.900000"},"DateTime":{"value":"2017/10/20 14:00"}}
BoneEngine > JSON.stringify(cmd.attrSet)=["BodyWeight","DateTime"]
BoneEngine > contact.firstname=Jesper
BoneEngine > contact.surname=Aaberg
BoneEngine > str=["a","b","c"]
BoneEngine > newArr.pop()=c
```
* 全局函数
- eval(string)
测试代码:
```
var x = 10;
var y = 20;
var a = eval("x * y");
var b = eval("2 + 2");
var c = eval("x + 17");
print('a='+a);
print('b='+b);
print('c='+c);
```
运行结果:
```
BoneEngine > a=200
BoneEngine > b=4
BoneEngine > c=27
```
* 支持的语法
- 常用语法
```
12.5 if语句
12.6.2 while 语句
12.6.3 for语句
12.6.4 for-in 语句
12.7 continue 语句
12.8 break 语句
12.11 switch 语句
default语句在switch块的最后且不需要break结束
```
## 不支持范围及限制条件
* 声明变量时表达式命名最长为63个字符
> 但是`String`类型的值的长度并没有限制
```
var name="123456789012345678901234567890123456789012345678901234567890123";
在js语法中, name最大可以等于63个字符的常量
若name值超过63运行出会出现"Token name is too long"
var str = "1234567890";
int i;
for(i=0; i<31; i++)
str = str + "1234567890"
print(str.length);
print(str);
//str 计算正常
//320
//12345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890
```
* 内置对象不支持`new`操作
不支持Object的`prototype`属性
不支持Object的`constructor`属性
```
下例不支持
var arr = new Array(2);
var str = new String(2);
```
* String不支持`UTF-8`
只支持普通字符串`char*`,为0为结束符
* 不支持类型转换函数
```
下例不支持
9.1 ToPrimitive
9.2 ToBoolean
9.3 ToNumber
9.4 ToInteger
9.5 ToInt32
9.6 ToUint32
9.7 ToUint16
9.8 ToString
9.9 ToObject
```
* 部分运算符不支持
```
下例不支持
11.4.1 delete 运算符
11.4.2 void 运算符
11.4.3 typeof 运算符
11.8.6 instanceof 运算符
11.8.7 in 运算符
11.9.4 严格等于运算符 ( === )
11.9.5 严格不等于运算符 ( !== )
```
* 部份语法不支持
```
下例不支持
12.6.1 do-while 语句
12.10 with 语句
12.12 标签语句
12.13 throw 语句
12.14 try 语句
```
* 不支持`NaN`
* 不支持`Infinity`
* 不支持`Date 对象`
* 不支持`RegExp 对象`
* 不支持`Error 对象`

View file

@ -0,0 +1,57 @@
# process对象说明
process对象是一个全局对象能够在任意位置访问。
## process 介绍
## 属性
### **1. process.version**
获取BoneEngine版本信息
### **2. process.platform**
获取BoneEngine的运行平台信息
## 方法
### **1. process.nextTick(callback)**
在下一个事件循环中调用callback函数
```
process.nextTick(function(){
print('process.uptime()=' + process.uptime());
print(process.memoryUsage());
});
```
输出
```
BoneEngine > process.uptime()=0
BoneEngine > { heapTotal: 500,
heapUsed: 138 }
```
### **2. process.uptime()**
返回`AOS`系统已经运行的秒数
### **3. process.memoryUsage()**
返回一个String对象描述当前JS内存使用情况
```
process.nextTick(function(){
print('process.uptime()=' + process.uptime());
print(process.memoryUsage());
});
```
输出
```
BoneEngine > { heapTotal: 500,
heapUsed: 138 }
```
## 事件

View file

@ -0,0 +1,79 @@
# timers说明
所有timer相关函数都是全局函数能够在任意位置访问。
## timer 介绍
## 方法
### **1. setTimeout(callback, delay**
设定定时器在delay毫秒之后执行callback函数返回类型整数定时器句柄
- null : 失败
- number : 成功
输入参数:
- callback : 回调函数
- delay : 类型为整数,单位毫秒
```
var t1 = setTimeout(function() {"
print('timer t1 callback run');
clearTimeout(t1);
}, 500);
```
输出
```
BoneEngine > timer t1 callback run
```
### **2. clearTimeout(timeoutObject)**
取消定时器, 返回值null
输入参数:
- timeoutObject : 调用setTimeout函数返回的整数
> **setTimeout设定定时器之后 在时间未到达时可以调用clearTimeout取消定时器**
> **setTimeout设定的定时器执行完之后会自动释放资源clearTimeout函数可以不调用**
### **3. setInterval(callback, delay**
设定定时器每次间隔delay毫秒之后执行callback函数返回类型整数定时器句柄
- 0 成功
输入参数:
- callback : 回调函数
- delay : 类型为整数,单位毫秒
### **2. clearInterval(timeoutObject)**
取消setInterval设定的定时器, 返回值null
输入参数:
- timeoutObject : 调用setInterval函数返回的整数
> **setInterval设定定时器之后 需要调用clearInterval取消定时器**
> **setInterval函数的callback中可以调用clearInterval取消定时器**
```
var count = 0;
var t3 = setInterval(function() {
count++;
print('js t3 callback run count: ' + count);
if (count == 3)
clearInterval(t3);
}, 500);
```
运行结果:
```
BoneEngine > js t3 callback run count: 1
BoneEngine > js t3 callback run count: 2
BoneEngine > js t3 callback run count: 3
```

View file

@ -0,0 +1,71 @@
# uart对象说明
uart对象是一个全局对象能够在任意位置访问。
## uart 介绍
## 属性
## 方法
### **1. uart.open(config)**
打开指定串口,返回值数字
- 0 成功
输入参数:
- config : 串口配置类型为Object
对象属性如下:
- port 串口号,必选
- baudRate 波特率可选默认115200
- dataBits data bits, 可选, 默认8
```
var config={};
config.port=1;
config.baudRate=115200;
config.dataBits=8;
var serial=uart.open(config);
print('uart.open = ' + serial);
```
输出
```
BoneEngine > uart.open = 1
```
### **2. uart.close(port)**
关闭指定串口, 返回值数字
- 0 成功
输入参数:
- port : 串口号
### **3. uart.write(port, data)**
写指定串口,返回值数字
- 0 成功
输入参数:
- port : 串口号
- data : 类型为String**长度限制为127Byte**
### **4. uart.read(port, [timeout])**
读指定串口,返回值读到的字符串
输入参数:
- port : 串口号
- timeout : 读取串口超时值,单位是毫秒, 可选
**若无timeout参数则超时值为0**
**读取字符串长度最大127Byte**
## 事件

View file

@ -0,0 +1,596 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/time.h>
//#include "alink_export.h"
//#include "json_parser.h"
#include "aos/aos.h"
#include "aos/network.h"
#include "kvmgr.h"
#ifndef STM32L475xx
#include <netmgr.h>
#endif
//#include <accs.h>
#include "aos/log.h"
#include "be_jse_api.h"
static bool auto_netmgr = false;
/*
timeralinkprocess等对象演示
*/
#define JS_TXT_1 " \
print('process.platform=' + process.platform);\
print('process.version=' + process.version);\
function randomNum(minNum,maxNum){\
var ret = Math.random()*(maxNum-minNum+1)+minNum;\
return ret;\
}\
var cmd = {}; \
cmd.attrSet = [\"ErrorCode\", \"Hue\", \"Luminance\", \"Switch\", \"WorkMode\"];\
cmd.ErrorCode = {value:0};\
cmd.Hue = {value:10};\
cmd.Luminance = {value:50};\
cmd.Switch = {value:1};\
cmd.WorkMode = {value:2};\
function onStatusChange(status, uuid){\
print('call js func onStatusChange');\
print('status =' + status);\
print('uuid=' + uuid); \
if( status == 2 ) {\
cmd.Luminance = {value: randomNum(40, 100) };\
print('json str='+JSON.stringify(cmd));\
alink.postdata('postDeviceData', JSON.stringify(cmd));\
process.nextTick(function(){\
print('nextTick alink.getuuid()=' + alink.getuuid());\
print('process.uptime()=' + process.uptime());\
print(process.memoryUsage());\
});\
}\
}\
alink.on(\"onStatusChange\", onStatusChange); \
var jsonstr = JSON.stringify(cmd);\
print('jsonstr=' + jsonstr); \
print('------------------------\r\n');\
print('BoneEngine @ lite version =' + process.version);\
print('alink.isrunning()=' + alink.isrunning());\
print('alink.getuuid()=' + alink.getuuid());\
print('process.uptime()=' + process.uptime());\
print(process.memoryUsage());\
print('alink.getloglevel()=' + alink.getloglevel());\
print('------------------------\r\n');\
var timeout = 2000;\
var t1 = setInterval(function() {\
var ip = getip(); \
print('js get ip=' + ip);\
if(ip != null ){\
alink.start();\
clearInterval(t1);}\
}, timeout);\
print('custom对象演示');\
print('custom.add(1,2)='+custom.add(1,2));\
print('custom.version=' + custom.version);\
print('custom.versionRW='+custom.versionRW);\
custom.versionRW='2.1';\
print('custom.versionRW='+custom.versionRW);\
print('');\
"
#ifdef USE_MK3060
/*
id 2, GPIO29 -> write led, LED灯的负极
id 12, GPIO4 -> read D0, 1, (LM393)DO管脚
200ms读取一次D0, LED灯显示
*/
#define JS_TXT_2 " \
var gpioId=2;\
var night=0;\
gpio.open(gpioId,3);\
gpio.open(12,0);\
night=gpio.read(12);\
gpio.write(gpioId,!night);\
var val = night;\
var t2 = setInterval(function() {\
val=gpio.read(12);\
if(val != night){\
night=val;\
print('night='+night);\
gpio.write(gpioId,!night);\
}\
}, 200);\
"
/*
*/
#define JS_TXT_3 " \
var config={};\
config.port=1;\
config.baudRate=921600;\
config.dataBits=8;\
var serial=uart.open(config);\
print('uart.open = ' + serial);\
uart.write(config.port, 'uart0 write test\r\n');\
var str; \
var t3 = setInterval(function() {\
str=uart.read(config.port, 0);\
if(str!=null && str.length>0){ \
print('uart read=' + str);\
}\
}, 1000);\
"
#endif
/*
JS symbol为string类型值并打印输出
*/
void bevPrintStringVar(be_jse_symbol_t *v)
{
char buf[256];
symbol_to_str(v, buf, 255);
//LOGW("BoneEngine >","%s", buf);
#define GLOBAL_LOG_TAG "\e[65m"
#define MAG "\x1B[35m"
#define CYN "\x1B[36m"
#define RESET "\x1B[0m"
csp_printf(GLOBAL_LOG_TAG MAG "BoneEngine > %s \r\n" RESET, buf);
}
#ifdef USE_ADC
#include "hal/soc/soc.h"
adc_dev_t adc_config;
#endif
static be_jse_node_t customObjRef = 0;
be_jse_symbol_t *BeJseNativeFunctions(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *var, const char *name)
{
be_jse_symbol_t* arg0;
be_jse_symbol_t* arg1;
int val;
NOT_USED(execInfo);
char str[32];
//LOGW("BoneEngine","var = %p name = %var \n", var, name);
if( var == NULL ) {
// 全局函数
if (strcmp(name,"print")==0) {
// JS function print(text)
be_jse_symbol_t *text = str_to_symbol(be_jse_handle_single_arg_function(), true);
bevPrintStringVar(text);
symbol_unlock(text);
//printf("\n");
return new_symbol(BE_SYM_NULL);
}
if( strcmp(name, "now")==0) {
// 必须加上,获取函数参数
be_jse_handle_function(0, 0, 0, 0, 0);
#ifndef STM32L475xx
// framework/protocol/alink/os/platform/platform.h platform_get_utc_time
extern uint64_t platform_get_utc_time(uint64_t *p_utc);
be_jse_symbol_t *newValue = new_int_symbol( (be_jse_int_t)platform_get_utc_time(NULL));
#else
be_jse_symbol_t *newValue = new_int_symbol(0);
#endif
return newValue;
}
if( strcmp(name, "exit")==0) {
be_jse_handle_function(0, 0, 0, 0, 0);
LOGW("BoneEngine", "aos_loop_exit ...");
aos_loop_exit();
return new_symbol(BE_SYM_NULL);
}
if( strcmp(name, "getip")==0) {
be_jse_handle_function(0, 0, 0, 0, 0);
LOGW("BoneEngine", "getip ...");
LOGW("BoneEngine","netmgr_get_ip_state=%d \r\n", netmgr_get_ip_state());
memset(str, 0, sizeof(str));
wifi_get_ip(str);
LOGW("BoneEngine","wifi_get_ip=%s \r\n", str);
if( strcmp(str,"0.0.0.0")==0 )
return new_symbol(BE_SYM_NULL);
return new_str_symbol(str);
}
if(strcmp(name, "trace")==0) {
be_jse_handle_function(0, 0, 0, 0, 0);
#ifdef TRACE_JSE_INFO
trace_symbol_info(bone_engine_get_executor()->root, 0);
#endif
return new_symbol(BE_SYM_NULL);
}
}
// 自定义对象的Native函数扩展实现 custom.add(a,b)
if( customObjRef > 0 && customObjRef == get_symbol_node_id(var) ) {
if( strcmp(name, "add")==0) {
be_jse_handle_function(0, &arg0, &arg1, 0, 0);
val = get_symbol_value_int(arg0) + get_symbol_value_int(arg1);
symbol_unlock(arg0);
symbol_unlock(arg1);
return new_int_symbol(val);
}
if (strcmp(name,"version")==0) {
// 特殊用法, 该属性只读, 并未加入到JSE符号表中, 使用返回值替换custom.version
// 使用lexer_token_cmp完成该属性的词法分析并获取一下个token
lexer_token_cmp(execInfo->lex, BE_TOKEN_ID);
return new_str_symbol("1.0");
}
}
return BE_JSE_FUNC_UNHANDLED;
}
static void clear_kv_and_reboot()
{
#ifndef STM32L475xx
aos_kv_del(NETMGR_WIFI_KEY);
LOGW("BoneEngine","KV cleared, will reboot now.");
aos_reboot();
#endif
}
#define AUTO_HOTSPOT_TIMEOUT_S (2*60) // 2 min
#define HOTSPOT_TIMEOUT_KV_NAME "hotspot_timeout"
static int get_hotspot_timeout()
{
char timeout_s[10];
int len = sizeof(timeout_s);
int timeout;
if (aos_kv_get(HOTSPOT_TIMEOUT_KV_NAME, (void *)timeout_s, &len) == 0) {
LOGW("BoneEngine","hotspot_timeout KV value will be used: %s seconds", timeout_s);
timeout = atoi(timeout_s);
} else {
timeout = AUTO_HOTSPOT_TIMEOUT_S;
LOGW("BoneEngine","Default hotspot timeout (%s) will be used.", timeout);
}
return timeout * 1000; // s -> ms
}
static void auto_netmgr_timer_fn(void *arg1, void *arg2)
{
LOGW("BoneEngine","Info: Auto netmgr timeout hit.");
clear_kv_and_reboot();
}
#define AUTO_NETMGR_TIMEOUT (10*60*1000) // 10 mins
static aos_timer_t auto_netmgr_timer = {NULL};
static aos_timer_t hotspot_timer = {NULL};
static void start_auto_netmgr_timer()
{
int ms = AUTO_NETMGR_TIMEOUT;
LOGW("BoneEngine","%s", __func__);
if (auto_netmgr == false) return;
if (aos_timer_new(&auto_netmgr_timer, auto_netmgr_timer_fn, NULL, ms, 0) != 0) {
LOGW("BoneEngine","Error: aos_timer_new failed in %s", __func__);
return;
}
if (aos_timer_start(&hotspot_timer) != 0) {
LOGW("BoneEngine","Error: aos_timer_start failed in %s", __func__);
return;
}
}
static void stop_timer(aos_timer_t *timer)
{
LOGW("BoneEngine","%s", __func__);
if (!timer) {
LOGW("BoneEngine","Timer is not set");
return;
}
if (aos_timer_stop(timer) != 0) {
LOGW("BoneEngine","Error: aos_timer_stop failed in ");
return;
}
}
static void hotspot_timer_fn(void *arg1, void *arg2)
{
LOGW("BoneEngine","Info: Hotspot timeout hit.");
clear_kv_and_reboot();
}
static void awss_hotspot_connected_handler()
{
int ms;
LOGW("BoneEngine","%s", __func__);
if (auto_netmgr == false) return;
ms = get_hotspot_timeout();
stop_timer(&auto_netmgr_timer);
if (aos_timer_new(&hotspot_timer, hotspot_timer_fn, NULL, ms, 0) != 0) {
LOGW("BoneEngine","Error: aos_timer_new failed");
return;
}
if (aos_timer_start(&hotspot_timer) != 0) {
LOGW("BoneEngine","Error: aos_timer_start failed");
return;
}
}
static void awss_hotspot_switch_ap_done_handler()
{
LOGW("BoneEngine","%s", __func__);
if (auto_netmgr == false) return;
stop_timer(&hotspot_timer);
}
#define ACTIVE_DELAY (5*1000)
static void do_auto_active()
{
//alink_activate(NULL);
LOGW("BoneEngine","--------auto active done------");
aos_msleep(ACTIVE_DELAY);
//clear_kv_and_reboot();
}
static void auto_active_handler(input_event_t *event, void *priv_data)
{
if (auto_netmgr == false) return;
if (event->type != EV_YUNIO) return;
if (event->code != CODE_YUNIO_ON_CONNECTED) return;
aos_post_delayed_action(ACTIVE_DELAY, do_auto_active, NULL);
}
#define AUTO_NETMGR_KEY "auto_netmgr"
static bool get_auto_netmgr_config()
{
char c[5];
int len = sizeof(c);
bool ret;
if (aos_kv_get(AUTO_NETMGR_KEY, (void *)c, &len) != 0) {
ret = false;
LOGE("alink", "kv(%s) not set, auto_netmgr will be disabled",
AUTO_NETMGR_KEY);
} else {
ret = true;
LOGD("alink", "kv(%s) found, auto_netmgr will be enabled",
AUTO_NETMGR_KEY);
}
return ret;
}
static void handle_quit_cmd(char *pwbuf, int blen, int argc, char **argv)
{
LOGW("main", "call %s ...", __FUNCTION__);
aos_loop_exit();
}
static struct cli_command quitcmd = {
.name = "quit",
.help = "quit example",
.function = handle_quit_cmd
};
static void handle_meminfo_cmd(char *pwbuf, int blen, int argc, char **argv)
{
LOGW("main", "call %s ...", __FUNCTION__);
LOGW("BoneEngine", "memory usage= %d max=%d", be_jse_get_memory_usage(), be_jse_get_memory_max_usage());
}
static struct cli_command meminfocmd = {
.name = "meminfo",
.help = "show BoneEngine meminfo",
.function = handle_meminfo_cmd
};
void nextTick_run_js(void *arg)
{
LOGW("BoneEngine","aos_task_name=%s \r\n", aos_task_name());
LOGW("BoneEngine", "js=%s", arg);
bone_engine_start(arg);
}
static void handle_eval_cmd(char *pwbuf, int blen, int argc, char **argv)
{
LOGW("BoneEngine","aos_task_name=%s \r\n", aos_task_name());
LOGW("BoneEngine", "pwbuf=%s blen=%d", pwbuf, blen);
LOGW("BoneEngine", "argc=%d", argc);
if( argc > 1) {
LOGW("BoneEngine", "js=%s", argv[1]);
aos_schedule_call(nextTick_run_js, argv[1]);
}
}
static struct cli_command evalcmd = {
.name = "eval",
.help = "BoneEngine eval javascript",
.function = handle_eval_cmd
};
void main_idle(void *arg)
{
NOT_USED(arg);
// aos_task_name= app
LOGD("BoneEngine","aos_task_name= %s\r\n", aos_task_name());
}
static void wifi_process(input_event_t *event, void *priv_data)
{
LOGW("BoneEngine","wifi_process, event->type=%d ", event->type);
LOGW("BoneEngine","wifi_process, event->code=%d ", event->code);
if (event->type != EV_WIFI) {
return;
}
if (event->code != CODE_WIFI_ON_GOT_IP) {
return;
}
}
void key_process(input_event_t *event, void *priv_data)
{
if (event->type != EV_KEY) {
return;
}
LOGW("BoneEngine","event->code = %d , event->value=%d ", event->code, event->value);
if (event->code == CODE_BOOT) {
if (event->value == VALUE_KEY_CLICK) {
/*
if (cloud_is_connected() == false) {
}
*/
} else if(event->value == VALUE_KEY_LTCLICK) {
} else if(event->value == VALUE_KEY_LLTCLICK) {
}
}
}
int application_start(int argc, char *argv[])
{
aos_set_log_level(AOS_LL_WARN);
//aos_set_log_level(AOS_LL_DEBUG);
LOGW("BoneEngine", "aos_get_product_model=%s", aos_get_product_model());
LOGW("BoneEngine", "aos_get_os_version=%s", aos_get_os_version());
LOGW("BoneEngine", "aos_get_kernel_version=%s", aos_get_kernel_version());
LOGW("BoneEngine", "aos_get_app_version=%s", aos_get_app_version());
LOGW("BoneEngine", "aos_get_device_name=%s", aos_get_device_name());
// mk3060平台: aos_task_name=aos-init
LOGW("BoneEngine","aos_task_name=%s \r\n", aos_task_name());
// 网络事件
aos_register_event_filter(EV_WIFI, wifi_process, NULL);
// KEY事件
aos_register_event_filter(EV_KEY, key_process, NULL);
#if 0
// zhengxiang.zzx ???
aos_register_event_filter(EV_YUNIO, auto_active_handler, NULL);
auto_netmgr = get_auto_netmgr_config();
awss_register_callback(AWSS_HOTSPOT_CONNECTED, &awss_hotspot_connected_handler);
awss_register_callback(AWSS_HOTSPOT_SWITCH_AP_DONE, &awss_hotspot_switch_ap_done_handler);
if (auto_netmgr)
start_auto_netmgr_timer();
#endif
netmgr_init();
#ifndef STM32L475xx
// only test, connect my router
#if 1
auto_netmgr = false;
netmgr_ap_config_t apconfig;
memset(&apconfig, 0, sizeof(apconfig));
strcpy(apconfig.ssid,"xxxxxxxx");
strcpy(apconfig.pwd, "xxxxxxxx");
netmgr_set_ap_config(&apconfig);
#endif
LOGW("BoneEngine","netmgr_start%d) \r\n", auto_netmgr);
netmgr_start(auto_netmgr);
LOGW("BoneEngine","netmgr_get_ip_state=%d \r\n", netmgr_get_ip_state());
#endif
aos_cli_register_command(&quitcmd);
aos_cli_register_command(&meminfocmd);
aos_cli_register_command(&evalcmd);
// BoneEngine初始化
bone_engine_init();
bone_engine_native_function_register(BeJseNativeFunctions);
// 注册自定义对象,必须在bone_engine_register之后调用!
customObjRef = bone_engine_native_object_register("custom");
/*
custom增加一个可读写的属性versionRW,JSE符号表中
*/
be_jse_symbol_t* value = new_str_symbol("2.0");
be_jse_symbol_t* customObj = symbol_lock(customObjRef);
symbol_unlock(add_symbol_node_name(customObj, value, "versionRW"));
symbol_unlock(value);
symbol_unlock(customObj);
#ifdef USE_ADC
int ret;
adc_config.adc = 0;
adc_config.config.sampling_cycle = 3;
adc_config.priv = NULL;
ret = hal_adc_init(&adc_config); //undefined reference to `hal_adc_init'
LOGW("BoneEngine","hal_adc_init ret=%d ", ret);
ret = MicoAdcInitialize(0, 3); //undefined reference to `MicoAdcInitialize'
LOGW("BoneEngine","MicoAdcInitialize ret=%d ", ret);
#endif
bone_engine_start(JS_TXT_1);
#ifdef USE_MK3060
// JS_TXT_2、JS_TXT_3 顺序执行
bone_engine_start(JS_TXT_2);
bone_engine_start(JS_TXT_3);
#endif
LOGW("BoneEngine","jse memory usage=%d max=%d ", be_jse_get_memory_usage(), be_jse_get_memory_max_usage() );
// test
//aos_schedule_call(main_idle, NULL);
//aos_loop_schedule_call(NULL, main_idle, NULL); //作用同上
aos_loop_run();
LOGE("BoneEngine","after aos_loop_run\n");
bone_engine_exit();
LOGE("BoneEngine","bone_engine_exit Done!\n");
return 0;
}

View file

@ -0,0 +1,96 @@
NAME := javascript_demo
$(NAME)_SOURCES := demo.c
$(NAME)_INCLUDES += ./include ./
#$(NAME)_COMPONENTS := log protocol.alink cli fota netmgr framework.common bone_engine
ifneq (,$(filter linuxhost,$(COMPONENTS)))
gateway ?= 0
else
gateway ?= 1
endif
ifeq ($(findstring ALI_AOS_B-L475E, $(CONFIG_SYSINFO_PRODUCT_MODEL)), ALI_AOS_B-L475E)
$(NAME)_COMPONENTS := log cli fota netmgr framework.common bone_engine
#GLOBAL_DEFINES += AOS_NO_WIFI
LWIP := 0
ywss := 0
DDA := 0
sds := 0
gateway := 0
else
$(NAME)_COMPONENTS := log protocol.alink cli fota netmgr framework.common bone_engine
endif
#default release_log
#可选 debug release_log release
#BUILD_TYPE = release_log
#编译时可以传入该参数,如: aos make jsdemo@mk3060 BUILD_TYPE=release
ifeq ($(findstring ALI_AOS_LINUXHOST, $(CONFIG_SYSINFO_PRODUCT_MODEL)), ALI_AOS_LINUXHOST)
GLOBAL_DEFINES += AOS_NO_WIFI
else
endif
ifneq (,${BINS})
GLOBAL_CFLAGS += -DSYSINFO_OS_BINS
endif
ifneq ($(ywss),0)
$(NAME)_COMPONENTS += ywss
endif
ifeq ($(gateway),1)
$(NAME)_COMPONENTS += gateway
ifneq (,$(filter linuxhost,$(COMPONENTS)))
DDA ?= 1
endif
ifneq (,$(filter armhflinux,$(COMPONENTS)))
DDA ?= 1
endif
endif
ifeq ($(LWIP),1)
$(NAME)_COMPONENTS += protocols.net
no_with_lwip := 0
endif
MESHDEBUG = 0
ifeq ($(meshdebug), 1)
MESHDEBUG = 1
endif
MESHSUPER = 0
ifeq ($(meshsuper), 1)
MESHSUPER = 1
endif
ifeq ($(DDA),1)
GLOBAL_LDFLAGS += -lreadline -lncurses
$(NAME)_COMPONENTS += dda
endif
ifeq ($(sds),1)
GLOBAL_DEFINES += CONFIG_SDS
endif
ifeq ($(BENCHMARKS),1)
$(NAME)_COMPONENTS += benchmarks
GLOBAL_DEFINES += CONFIG_CMD_BENCHMARKS
endif

View file

@ -0,0 +1,32 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
/*
* aos_alink.h
*
*
*/
#ifndef AOS_ALINK_H_
#define AOS_ALINK_H_
#include "module_alink.h"
void aos_alink_init();
void aos_alink_exit();
int aos_alink_get_time(unsigned int *utc_time);
#ifdef __cplusplus
}
#endif
#endif /* AOS_ALINK_H_ */

View file

@ -0,0 +1,33 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
/*
* be_bi_module.h
*
* builtin对象方法实现
* native扩展方法实现
*
*
*/
#ifndef _BE_BI_MODULE_H_
#define _BE_BI_MODULE_H_
#include "be_jse.h"
#include "be_jse_executor.h"
typedef be_jse_symbol_t *(*BE_JSE_FUNCTION_EXECUTE_CB)(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *a, const char *name);
/*
JS native
*/
void be_jse_register_function_cb(BE_JSE_FUNCTION_EXECUTE_CB func_cb);
be_jse_symbol_t *handle_function_call(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *a, const char *name);
#endif /* _BE_BI_MODULE_H_ */

View file

@ -0,0 +1,18 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef __BE_IOT_MODULE_H__
#define __BE_IOT_MODULE_H__
#include "be_jse.h"
#include "be_jse_api.h"
be_jse_symbol_t *be_iot_module_handle_cb(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *var, const char *name);
void be_module_init(be_jse_executor_ctx_t *parse);
void be_module_exit();
#endif /* __BE_IOT_MODULE_H__ */

View file

@ -0,0 +1,14 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef BE_JSE_H_
#define BE_JSE_H_
#include "be_jse_types.h"
#include "be_jse_utils.h"
#include "be_jse_symbol.h"
#include "be_jse_executor.h"
#include "be_bi_module.h"
#endif /* BE_JSE_H_ */

View file

@ -0,0 +1,56 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef BE_JSE_API_H_
#define BE_JSE_API_H_
#include "be_jse.h"
/*
BoneEngine引擎的executor对象
*/
be_jse_executor_ctx_t* bone_engine_get_executor();
/*
BoneEngine初始化
*/
void bone_engine_init();
/*
JS对象,
bone_engine_init之后调用
*/
be_jse_node_t bone_engine_native_object_register(const char* objectName);
/*
JS对象Native扩展方法及属性,JS全局函数的实现函数
*/
void bone_engine_native_function_register(BE_JSE_FUNCTION_EXECUTE_CB extension);
/*
JS程序
, BoneEngine符号表共享
*/
void bone_engine_start(const char* js);
/*
BoneEngine复位之后重新运行JS程序
*/
void bone_engine_restart(const char* js);
/*
退BoneEngine
*/
void bone_engine_exit();
#ifdef __cplusplus
}
#endif
#endif /* BE_JSE_API_H_ */

View file

@ -0,0 +1,78 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
/*
* be_jse_executor.h
*
* Ecmascript bytecode executor.
*
*
*/
#ifndef BE_JSE_EXECUTOR_H_
#define BE_JSE_EXECUTOR_H_
#include "be_jse_types.h"
#include "be_jse_symbol.h"
#include "be_jse_lex.h"
#ifdef __cplusplus
extern "C" {
#endif
/*关系操作表达式*/
#define MEET_RELATIONAL_OP (vm.lex->tk==BE_TOKEN_OP_EQUAL ||\
vm.lex->tk==BE_TOKEN_OP_NEQUAL || \
vm.lex->tk==BE_TOKEN_OP_TYPE_EQUAL|| \
vm.lex->tk==BE_TOKEN_OP_TYPE_NEQUAL ||\
vm.lex->tk==BE_TOKEN_OP_LESS_EQUAL || \
vm.lex->tk==BE_TOKEN_OP_MORE_EQUAL ||\
vm.lex->tk=='<' || vm.lex->tk=='>')
/**/
#define MEET_POSTFIX_OP (vm.lex->tk==BE_TOKEN_OP_PLUS_PLUS || vm.lex->tk==BE_TOKEN_OP_MINUS_MINUS)
#define MEET_SHIFT_OP (vm.lex->tk==BE_TOKEN_OP_LEFT_SHIFT || vm.lex->tk==BE_TOKEN_OP_RIGHT_SHIFT || vm.lex->tk==BE_TOKEN_OP_RIGHT_SHIFT_UNSIGN)
#define MEET_BIT_ARITHMATICAL_OP (vm.lex->tk=='&' || vm.lex->tk=='|' || vm.lex->tk=='^')
#define MEET_LOGICAL_OP (vm.lex->tk==BE_TOKEN_OP_LOGIC_AND || vm.lex->tk==BE_TOKEN_OP_LOGIC_OR)
#define MEET_ASSIGNMENT_OP (vm.lex->tk=='=' || vm.lex->tk==BE_TOKEN_OP_PLUS_EQUAL || vm.lex->tk==BE_TOKEN_OP_MINUS_EQUAL)
/* 宏定义可以减少重复编码,相对于函数,可以减少函数调用和返回的堆栈压栈和出栈*/
//匹配需要的词法并搜索下一个char,该宏带返回值,并带异常处理
#define LEXER_MATCH_WITH_CLEAN_AND_RETURN(EXPECTED_TOKEN, CLEANUP_CODE, RETURN_VAL) { if (!lexer_token_cmp(vm.lex,(EXPECTED_TOKEN))) { be_jse_execute_error(); CLEANUP_CODE; return RETURN_VAL; } }
//匹配需要的词法并搜索下一个char,该宏带返回值
#define LEXER_MATCH_WITH_RETURN(EXPECTED_TOKEN, RETURN_VAL) LEXER_MATCH_WITH_CLEAN_AND_RETURN(EXPECTED_TOKEN, , RETURN_VAL)
//匹配需要的词法并搜索下一个char
#define LEXER_MATCH(EXPECTED_TOKEN) LEXER_MATCH_WITH_CLEAN_AND_RETURN(EXPECTED_TOKEN, , 0)
#define BE_VM_PARSE_SHOULD_EXECUTE (((vm.execute)&EXEC_RUN_MASK)==EXEC_NORMAL)
#define BE_SAVE_VM_EXE_STATE() be_execflag_e oldExecute = vm.execute
#define BE_RESTORE_VM_EXE_STATE() vm.execute = (vm.execute&(be_execflag_e)(~EXEC_NORMAL)) | (oldExecute&EXEC_NORMAL);
void be_jse_executor_init(be_jse_executor_ctx_t *executor);
void be_jse_executor_deinit(be_jse_executor_ctx_t *executor);
//添加Native函数和本地对象
bool be_jse_add_native_func(be_jse_executor_ctx_t *executor, const char *funcDesc, be_jse_callback callbackPtr);
// 运行JS代码
be_jse_symbol_t *be_jse_eval_string(be_jse_executor_ctx_t *executor, const char *str);
bool be_jse_execute_func(be_jse_executor_ctx_t *executor, be_jse_symbol_t *func, int argCount, be_jse_symbol_t **argPtr);
bool be_jse_handle_function(be_jse_parse_skip_flag_e skipName, be_jse_symbol_t **a, be_jse_symbol_t **b, be_jse_symbol_t **c, be_jse_symbol_t **d);
bool be_jse_is_none_arg_function();
be_jse_symbol_t *be_jse_handle_single_arg_function();
void be_jse_execute_error();
#ifdef __cplusplus
}
#endif
#endif /* BE_JSE_EXECUTOR_H_ */

View file

@ -0,0 +1,20 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
/*
* be_jse_feature.h
*
* JavaScript feature
* board相关
*
*/
#ifndef BE_JSE_FEATURE_H_
#define BE_JSE_FEATURE_H_
#include "be_board.h"
#endif /* BE_JSE_FEATURE_H_ */

View file

@ -0,0 +1,46 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef BE_JSE_GLOBAL_H_
#define BE_JSE_GLOBAL_H_
#include "be_jse_feature.h"
#define BE_JSE_SYMBOL_DATA_STRING_LEN 8
#define BE_JSE_SYMBOL_DATA_STRING_MAX_LEN (BE_JSE_SYMBOL_DATA_STRING_LEN + sizeof(be_jse_node_t)*3)
#define BE_JSE_SYMBOL_STRING_OP_BUFFER_SIZE 256
#define MAX_TOKEN_LENGTH 64
#define BE_JSE_ERROR_BUF_SIZE 64
#define BE_JSE_ERROR_TOKEN_BUF_SIZE 16
#define BE_JSE_PARSE_MAX_SCOPES 32
#define BE_JSE_PARSE_MAX_LOOPS 8192
#define BE_JSE_PARSE_RETURN_VAR "return"
#define BE_JSE_PARSE_THIS_OBJ "this"
#define BE_JSE_PARSE_PROTOTYPE_CLASS "prototype"
#define BE_JSE_PARSE_FUNCTION_CODE_NAME "#code#"
#define BE_JSE_PARSE_FUNCTION_SCOPE_NAME "#scope#"
#define BE_JSE_SYMBOL_TABLE_SIZE 500
#define BE_JSE_SYMBOL_APPEND_STR_MAX_LEN (0x7FFFFFFF)
#define BE_JSE_FUNC_UNHANDLED ((be_jse_symbol_t*)-1)
#define BE_JSE_LOCK_SHIFT 8
#define BE_JSE_LOCK_MAX 15
#define BE_JSE_STRING_LEN_SHIFT 12
#define BE_JSE_STRING_LEN_MAX 15
#define PACKED_FLAGS __attribute__ ((__packed__))
#define NO_INLINE __attribute__ ((noinline))
//#define BE_JSE_SILENT
#ifdef __cplusplus
}
#endif
#endif /* BE_JSE_GLOBAL_H_ */

View file

@ -0,0 +1,44 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
/*
* be_jse_lex.h
*
* JS词法分析器
* be_token_type_e
*
*
*/
#ifndef BE_JSE_LEX_H_
#define BE_JSE_LEX_H_
#include "be_jse.h"
#ifdef __cplusplus
extern "C" {
#endif
/* lexer 操作*/
void be_jse_lexer_init(be_jse_lex_ctx_t *lex, const char *src, int startPos, int endPos);
void be_jse_lexer_init2(be_jse_lex_ctx_t *lex, be_jse_lex_ctx_t *initFrom, int startPos);
void be_jse_lexer_deinit(be_jse_lex_ctx_t *lex);
void be_jse_lexer_reset(be_jse_lex_ctx_t *lex);
/*Lexer对token/字符元素操作*/
bool lexer_token_cmp(be_jse_lex_ctx_t *lex, int expected_token);
char *lexer_get_token(be_jse_lex_ctx_t *lex);
void lexer_seekto_char(be_jse_lex_ctx_t *lex, int seekToChar);
void lexer_get_next_char(be_jse_lex_ctx_t *lex);
// 调试使用
// 把token转成string, 方便调试
void lexer_token_to_str(int token, char *str, size_t len);
void lexer_dump_line_and_col(be_jse_lex_ctx_t *lex, int charPos, int *line, int *col);
#ifdef __cplusplus
}
#endif
#endif /* BE_JSE_LEX_H_ */

View file

@ -0,0 +1,234 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef be_jse_symbol_H_
#define be_jse_symbol_H_
#include "be_jse_types.h"
#include "be_jse_utils.h"
#ifdef __cplusplus
extern "C" {
#endif
#define SYM_TABLE_UNUSED_REF 0xFFFF
void be_jse_symbol_table_init();
//symbol node ops
void free_symbol_node(be_jse_symbol_t *node);
void add_symbol_node(be_jse_symbol_t* parent, be_jse_symbol_t* namedChild);
be_jse_symbol_t *get_root_node();
//symbol new ops
be_jse_symbol_t *new_symbol(be_jse_symbol_type_e type);
be_jse_symbol_t *new_str_symbol(const char *str);
be_jse_symbol_t *new_int_symbol(be_jse_int_t value);
be_jse_symbol_t *new_bool_symbol(bool value);
be_jse_symbol_t *new_float_symbol(be_jse_float_t value);
be_jse_symbol_t *new_lexer_symbol(be_jse_lex_ctx_t *lex, int charFrom, int charTo);
be_jse_symbol_t *new_named_symbol(be_jse_symbol_t *var, be_jse_symbol_t* valueOrZero);
/*symbol lock ops*/
be_jse_symbol_t *symbol_lock(be_jse_node_t id);
be_jse_symbol_t *symbol_relock(be_jse_symbol_t *s);
be_jse_node_t symbol_unlock(be_jse_symbol_t *s);
be_jse_symbol_t *unlock_symbol_value(be_jse_symbol_t *v);
//symbol value ops
void * get_symbol_first_ptr();
be_jse_int_t get_symbol_int(be_jse_symbol_t *s);
be_jse_bool_t get_symbol_bool(be_jse_symbol_t *s);
be_jse_symbol_t *get_symbol_value(be_jse_symbol_t *s);
be_jse_bool_t get_symbol_value_bool(be_jse_symbol_t *s);
be_jse_float_t get_symbol_double(be_jse_symbol_t *s);
//取符号的值项key/value并强制类型转换成int
be_jse_int_t get_symbol_value_int(be_jse_symbol_t *s);
/*symbol string ops*/
void symbol_to_str(be_jse_symbol_t *v, char *str, size_t len);
int symbol_str_len(be_jse_symbol_t *v);
bool symbol_str_equal(be_jse_symbol_t *var, const char *str);
int symbol_str_cmp(be_jse_symbol_t *va, be_jse_symbol_t *vb, int starta, int startb, bool equalAtEndOfString); ///< Compare 2 strings, starting from the given character positions
void symbol_str_append(be_jse_symbol_t *var, const char *str);
void symbol_str_value_append(be_jse_symbol_t *var, be_jse_symbol_t *str, int stridx, int maxLength);
be_jse_symbol_t *symbol_maths_op(be_jse_symbol_t *a, be_jse_symbol_t *b, int op);
be_jse_symbol_t *symbol_value_maths_op(be_jse_symbol_t *a, be_jse_symbol_t *b, int op);
be_jse_symbol_t *symbol_maths_op_error(int op, const char *datatype);
//Symbol ops
be_jse_symbol_t *symbol_cp(be_jse_symbol_t *src);
be_jse_symbol_t *symbol_name_cp(be_jse_symbol_t *src, bool linkChildren, bool keepAsName);
be_jse_symbol_t *add_symbol_node_name(be_jse_symbol_t* parent, be_jse_symbol_t* child, const char *name);
be_jse_symbol_t *set_symbol_node_name(be_jse_symbol_t *name, be_jse_symbol_t *src);
be_jse_symbol_t *lookup_named_child_symbol(be_jse_node_t parentref, const char *name, bool createIfNotFound);
be_jse_symbol_t *lookup_child_symbol(be_jse_node_t parentref, be_jse_symbol_t *childName, bool addIfNotFound);
void remove_child_symbol(be_jse_symbol_t *parent, be_jse_symbol_t *child);
//Array ops
be_jse_int_t get_symbol_array_length(be_jse_symbol_t *v);
be_jse_symbol_t *get_symbol_array_item(be_jse_symbol_t *arr, int index); ///< Get an item at the specified index in the array (and lock it)
be_jse_symbol_t *get_symbol_array_index(be_jse_symbol_t *arr, be_jse_symbol_t *value); ///< Get the index of the value in the array
be_jse_int_t symbol_array_push(be_jse_symbol_t *arr, be_jse_symbol_t *value);
be_jse_symbol_t *symbol_array_pop(be_jse_symbol_t *arr);
be_jse_symbol_t *str_to_symbol(be_jse_symbol_t *var, bool unlockVar);
int get_symbol_ref_count(be_jse_symbol_t *toCount, be_jse_symbol_t *var);
#ifdef USE_JSON
void symbol_to_json(be_jse_symbol_t *var, be_jse_symbol_t *result);
#endif
// ALWAYS_INLINE 减少调用开销
// ALWAYS_INLINE 定义的函数代码小但调用频繁
//符号表引用计数
static ALWAYS_INLINE be_jse_symbol_t *INC_SYMBL_REF(be_jse_symbol_t *s)
{
be_assert(s);
s->refs++;
return s;
}
static ALWAYS_INLINE void DEC_SYMBL_REF(be_jse_symbol_t *s)
{
be_assert(s && s->refs>0);
s->refs--;
if (s->locks == 0 && s->refs==0)
free_symbol_node(s);
}
static ALWAYS_INLINE be_jse_node_t INC_SYMBL_REF_BY_ID(be_jse_node_t id)
{
be_jse_symbol_t *s;
be_assert(id);
s = symbol_lock(id);
INC_SYMBL_REF(s);
symbol_unlock(s);
return id;
}
static ALWAYS_INLINE be_jse_node_t DEC_SYMBL_REF_BY_ID(be_jse_node_t ref)
{
be_jse_symbol_t *s;
be_assert(ref);
s = symbol_lock(ref);
DEC_SYMBL_REF(s);
symbol_unlock(s);
return 0;
}
static ALWAYS_INLINE be_jse_node_t get_symbol_node_id(be_jse_symbol_t *s)
{
if (!s) return 0;
#ifdef LINUXHOST
return s->node_id;
#else
return (be_jse_node_t)(1 + (s - (be_jse_symbol_t*)get_symbol_first_ptr()));
#endif
}
static ALWAYS_INLINE bool symbol_is_int(const be_jse_symbol_t *s)
{
return s && (s->flags&BE_SYM_TYPE_MASK)==BE_SYM_INTEGER;
}
static ALWAYS_INLINE bool symbol_is_float(const be_jse_symbol_t *s)
{
return s && (s->flags&BE_SYM_TYPE_MASK)==BE_SYM_FLOAT;
}
static ALWAYS_INLINE bool symbol_is_string(const be_jse_symbol_t *s)
{
return s && (s->flags&BE_SYM_TYPE_MASK)==BE_SYM_STRING;
}
static ALWAYS_INLINE bool symbol_is_string_ext(const be_jse_symbol_t *s)
{
return s && (s->flags&BE_SYM_TYPE_MASK)==BE_SYM_STRING_EXT;
}
static ALWAYS_INLINE bool symbol_is_number(const be_jse_symbol_t *s)
{
return s && (s->flags&BE_SYM_NUM_MASK)!=0;
}
static ALWAYS_INLINE bool symbol_is_function(const be_jse_symbol_t *s)
{
return s && (s->flags&BE_SYM_TYPE_MASK)==BE_SYM_FUNCTION;
}
static ALWAYS_INLINE bool symbol_is_function_argv(const be_jse_symbol_t *s)
{
return s && (s->flags&BE_SYM_FUNCTION_ARGVS) == BE_SYM_FUNCTION_ARGVS;
}
static ALWAYS_INLINE bool symbol_is_object(const be_jse_symbol_t *s)
{
return s && (s->flags&BE_SYM_TYPE_MASK)==BE_SYM_OBJECT;
}
static ALWAYS_INLINE bool symbol_is_array(const be_jse_symbol_t *s)
{
return s && (s->flags&BE_SYM_TYPE_MASK)==BE_SYM_ARRAY;
}
static ALWAYS_INLINE bool symbol_is_native(const be_jse_symbol_t *s)
{
return s && (s->flags&BE_SYM_NATIVE)!=0;
}
static ALWAYS_INLINE bool symbol_is_undefined(const be_jse_symbol_t *s)
{
return !s;
}
static ALWAYS_INLINE bool symbol_is_null(const be_jse_symbol_t *s)
{
return s && (s->flags&BE_SYM_TYPE_MASK)==BE_SYM_NULL;
}
static ALWAYS_INLINE bool symbol_is_basic(const be_jse_symbol_t *s)
{
return symbol_is_number(s) || symbol_is_string(s); ///< Is this *not* an array/object/etc
}
static ALWAYS_INLINE bool symbol_is_name(const be_jse_symbol_t *s)
{
return s && (s->flags & BE_SYM_NAME)!=0;
}
static ALWAYS_INLINE bool symbol_has_characterdata(const be_jse_symbol_t *s)
{
return symbol_is_string(s) || symbol_is_string_ext(s) || symbol_is_function_argv(s);
}
static ALWAYS_INLINE bool symbol_has_child(const be_jse_symbol_t *s)
{
return symbol_is_function(s) || symbol_is_object(s) || symbol_is_array(s);
}
/// This is the number of characters a be_jse_symbol_t can contain, NOT string length
static ALWAYS_INLINE int symbol_get_max_char_len(const be_jse_symbol_t *s)
{
if (symbol_is_string_ext(s)) return BE_JSE_SYMBOL_DATA_STRING_MAX_LEN;
be_assert(symbol_has_characterdata(s));
return BE_JSE_SYMBOL_DATA_STRING_LEN;
}
static ALWAYS_INLINE bool get_bool_symbol_and_unlock(be_jse_symbol_t *v)
{
bool b = get_symbol_bool(v);
symbol_unlock(v);
return b;
}
#ifdef DUMP_SYMBL_USAGE
// 获取当前使用了多少symbol table
int be_jse_get_memory_usage();
// 获取当前使用symbol table的最大值
int be_jse_get_memory_max_usage();
// 查看当前正在使用的BeVars, 用于debug分析内存相关问题
void be_jse_show_symbol_table_used();
#endif
#ifdef TRACE_JSE_INFO
void trace_symbol_info(be_jse_node_t node, int indent);
#endif
#ifdef __cplusplus
}
#endif
#endif /* be_jse_symbol_H_ */

View file

@ -0,0 +1,247 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef BE_JSE_TYPES_H_
#define BE_JSE_TYPES_H_
#include "be_jse_global.h"
typedef enum {
BE_SYM_NUM_MASK = 8, //01000 ~ 01111 之间的都是数字, bit3==1
BE_SYM_TYPE_MASK = 15,
BE_SYM_NULL = 1, //NULL
BE_SYM_STRING = 2, //字符串
BE_SYM_STRING_EXT = 3, //字符串扩展
BE_SYM_ARRAY = 4, //数组
BE_SYM_OBJECT = 5, //对象
BE_SYM_FUNCTION = 6, //函数
BE_SYM_INTEGER = 8, //整型
BE_SYM_FLOAT = 9, //浮点型
BE_SYM_NAME = 16, //名称
BE_SYM_NATIVE = 32, //本地扩展
BE_SYM_RECURSING = 128,//
BE_SYM_FUNCTION_ARGVS = BE_SYM_FUNCTION | BE_SYM_NAME,
BE_SYM_ROOT = BE_SYM_OBJECT | BE_SYM_NATIVE,
} be_jse_symbol_type_e;
typedef enum {
/* 变量类型 */
BE_TOKEN_ID = 256,
BE_TOKEN_INT,
BE_TOKEN_FLOAT,
BE_TOKEN_STR,
/* 运算操作符 */
// 逻辑判断
BE_TOKEN_OP_EQUAL, // ==
BE_TOKEN_OP_TYPE_EQUAL, // ===
BE_TOKEN_OP_NEQUAL, // !=
BE_TOKEN_OP_TYPE_NEQUAL, //!===
BE_TOKEN_OP_LESS_EQUAL, // <=
// 移位操作
BE_TOKEN_OP_LEFT_SHIFT,
BE_TOKEN_OP_LEFT_SHIFT_EQL, //
BE_TOKEN_OP_MORE_EQUAL,
BE_TOKEN_OP_RIGHT_SHIFT,
BE_TOKEN_OP_RIGHT_SHIFT_UNSIGN,
BE_TOKEN_OP_RIGHT_SHIFT_EQUAL,
// += 或者 -=
BE_TOKEN_OP_PLUS_EQUAL,
BE_TOKEN_OP_MINUS_EQUAL,
// ++ 或者 --
BE_TOKEN_OP_PLUS_PLUS,
BE_TOKEN_OP_MINUS_MINUS,
// 逻辑运算
BE_TOKEN_OP_AND_EQUAL,
BE_TOKEN_OP_LOGIC_AND,
BE_TOKEN_OP_OR_EQUAL,
BE_TOKEN_OP_LOGIC_OR,
BE_TOKEN_OP_XOR_EQUAL,
//关键字
BE_TOKEN_KW_IF,
BE_TOKEN_KW_ELSE,
BE_TOKEN_KW_DO,
BE_TOKEN_KW_WHILE,
BE_TOKEN_KW_FOR,
BE_TOKEN_KW_IN,
BE_TOKEN_KW_BREAK,
BE_TOKEN_KW_CONTINUE,
BE_TOKEN_KW_SWITCH,
BE_TOKEN_KW_CASE,
BE_TOKEN_KW_DEFAULT,
BE_TOKEN_KW_NEW,
BE_TOKEN_KW_VAR,
BE_TOKEN_KW_FUNCTION,
BE_TOKEN_KW_RETURN,
BE_TOKEN_KW_TRUE,
BE_TOKEN_KW_FALSE,
BE_TOKEN_KW_NULL,
BE_TOKEN_KW_UNDEFINED,
BE_TOKEN_END=0,
} be_token_type_e;
typedef enum {
EXEC_IDLE = 0,
EXEC_NORMAL = 1,
EXEC_BREAK = 2,
EXEC_CONTINUE = 4,
EXEC_INTERRUPTED = 8,
EXEC_ERROR = 16,
EXEC_FOR_INIT = 32,
EXEC_IN_LOOP = 64,
EXEC_IN_SWITCH = 128,
EXEC_RUN_MASK = EXEC_NORMAL|EXEC_BREAK|EXEC_CONTINUE,
EXEC_ERROR_MASK = EXEC_INTERRUPTED|EXEC_ERROR,
EXEC_SAVE_RESTORE_MASK = EXEC_NORMAL|EXEC_IN_LOOP|EXEC_IN_SWITCH, // the things JSP_SAVE/RESTORE_EXECUTE should keep track of
} be_execflag_e;
typedef unsigned short be_jse_node_t;
typedef long be_jse_int_t;
typedef bool be_jse_bool_t;
typedef unsigned long be_jse_uint_t;
#ifdef USE_FLOATS
typedef float be_jse_float_t;
#else
typedef double be_jse_float_t;
#endif
typedef void (*be_jse_callback)(be_jse_node_t id);
typedef union {
char str[BE_JSE_SYMBOL_DATA_STRING_LEN];
be_jse_int_t integer;
be_jse_float_t floating;
be_jse_callback callback; // native扩展函数
} PACKED_FLAGS be_symbol_data_t;
/*
BoneEngine lite中编译时指定一个固定大小的be_jse_symbol_t类型数组存所javascript运行中所有的js对象
be_jse_entry_id_t类型数据: var在数组中的位置, 1+1
*/
/*
TBD: , locks flags变量的高8位去(4bits), string length flags 12(4bits)
*/
typedef struct {
#ifdef LINUXHOST
be_jse_node_t node_id;
#endif
unsigned char locks;
unsigned short refs; // 引用计数,用于垃圾回收
be_jse_symbol_type_e flags; // 变量类型
// data若是存放字符串, next_sibling/prev_sibling/first_child都在使用, 长度增加sizeof(be_jse_entry_id_t)*3
be_symbol_data_t data;
// 平行节点
be_jse_node_t next_sibling;
be_jse_node_t prev_sibling;
// 子节点
be_jse_node_t first_child;
be_jse_node_t last_child;
} PACKED_FLAGS be_jse_symbol_t;
typedef struct _be_jse_lex_ctx_t {
int tk; // token类型 == be_lex_type_e
int token_start;
int token_end;
int token_last_end;
char token[MAX_TOKEN_LENGTH];
int token_len; // 当前token长度
char curr_char;
char next_char;
// 从字符串中分析
const char *src;
int start_pos;
int end_pos;
int curr_pos;
} be_jse_lex_ctx_t;
typedef enum {
PARSE_NOSKIP_ALL=0,
PARSE_NOSKIP_A = 1,
PARSE_NOSKIP_B = 2,
PARSE_NOSKIP_C = 4,
PARSE_NOSKIP_D = 8,
} be_jse_parse_skip_flag_e;
typedef struct {
be_jse_node_t root; // 所有符号表的根起点
be_jse_node_t zeroInt;
be_jse_node_t oneInt;
// 内嵌的string/object/array/int/math/json对象
be_jse_node_t stringClass;
be_jse_node_t objectClass;
be_jse_node_t arrayClass;
be_jse_node_t intClass;
be_jse_node_t mathClass;
be_jse_node_t jsonClass;
#ifdef USE_ALINK
// alink协议扩展
be_jse_node_t alinkClass;
#endif
#ifdef USE_PROCESS
// process扩展
be_jse_node_t processClass;
#endif
#ifdef USE_GPIO
// gpio扩展
be_jse_node_t gpioClass;
#endif
#ifdef USE_UART
// uart扩展
be_jse_node_t uartClass;
#endif
} be_jse_executor_ctx_t;
typedef struct {
be_jse_executor_ctx_t *executor;
be_jse_lex_ctx_t *lex;
be_jse_node_t scopes[BE_JSE_PARSE_MAX_SCOPES];
int scopeCount;
be_execflag_e execute;
} be_jse_vm_ctx_t;
#endif /* BE_JSE_TYPES_H_ */

View file

@ -0,0 +1,103 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
/*
* be_jse_utils.h
*
* utils函数
*
*/
#ifndef BE_JSE_UTILS_H_
#define BE_JSE_UTILS_H_
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "be_jse_types.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef alloca
#define alloca(x) __builtin_alloca(x)
#endif
#if defined(ESP8266)
#define USE_FLASH_MEMORY
#define IN_FLASH_MEMORY __attribute__((section(".irom.literal"))) __attribute__((aligned(4)))
#define READ_FLASH_UINT8(ptr) ({ uint32_t __p = (uint32_t)(char*)(ptr); volatile uint32_t __d = *(uint32_t*)(__p & (uint32_t)~3); ((uint8_t*)&__d)[__p & 3]; })
#define READ_FLASH_UINT16(ptr) (READ_FLASH_UINT8(ptr) | (READ_FLASH_UINT8(((char*)ptr)+1)<<8) )
#define CALLED_FROM_INTERRUPT __attribute__((section(".iram1.text")))
#define itoa(val,str,base) os_sprintf(str,"%d",val)
#define ftoa(val,str) os_sprintf(str,"%f",val)
#define printf os_printf
#else
#define CALLED_FROM_INTERRUPT
#define itoa(val,str,base) sprintf(str,"%d",val)
#define ftoa(val,str) sprintf(str,"%g",val)
#endif
#if defined(__GNUC__) && !defined(__clang__)
#if defined(LINK_TIME_OPTIMISATION) && !defined(SAVE_ON_FLASH) && !defined(DEBUG)
#define ALWAYS_INLINE __attribute__ ((gnu_inline)) __attribute__((always_inline)) inline
#else
#define ALWAYS_INLINE __attribute__ ((gnu_inline)) inline
#endif
#else
#define ALWAYS_INLINE
#endif
#if 1
//#ifdef DEBUG
#define be_assert(X) if (!(X)) be_jse_assert_fail(__FILE__,__LINE__);
#else
#define be_assert(X) do { } while(0)
#endif
#define NOT_USED(x) ( (void)(x) )
bool is_whitespace(char ch);
bool is_numeric(char ch);
bool is_hex_decimal(char ch);
bool is_alpha(char ch);
// ------------
void be_jse_error(const char *message);
void be_jse_error_at(const char *message, be_jse_lex_ctx_t *lex, int tokenPos);
void be_jse_warn(const char *message);
void be_jse_warn_at(const char *message, be_jse_lex_ctx_t *lex, int tokenPos);
void be_jse_assert_fail(const char *file, int line);
// C99中函数的实现,如 strtol、snprintf、atol、atof、itoa、ftoa
// ESP8266中的libc部份支持C99
void itostr(be_jse_int_t val,char *str,unsigned int base);
void ftoa_bounded(be_jse_float_t val,char *str, size_t len);
int chtod(char ch);
be_jse_float_t string_to_float(const char *str);
long long string_to_int(const char *s);
#ifndef BE_JSE_SILENT
// 仅仅用于调试
void be_jse_save_tmp_token(const char* token);
const char* be_jse_get_tmp_token();
#endif
#ifdef __cplusplus
}
#endif
#endif /* BE_JSE_UTILS_H_ */

View file

@ -0,0 +1,86 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
/*
* module_alink.h
* Alink协议JS扩展对象
*
*/
/*
JS alink Class
API:
alink.getloglevel()
alink.setloglevel(level)
alink.getuuid()
alink.getstatus() 0: stop 1: start 2: connected
alink.isrunning()
alink.start()
alink.postdata(method, jsonCmd)
alink.stop()
Event:
onStatusChange
JS example:
alink.on("onStatusChange", function(status, uuid){
});
onSetAttrs
alink.on("onSetAttrs", function(jsonBuf){
});
onGetAttrs
alink.on("onGetAttrs", function(jsonBuf){
});
*/
#ifndef MODULE_ALINK_H_
#define MODULE_ALINK_H_
#include "be_jse.h"
typedef enum {
ALINK_GETLOGLEVEL = 0,
ALINK_SETLOGLEVEL,
ALINK_GETUUID,
ALINK_GETSTATUS,
ALINK_ISRUNNING,
ALINK_START,
ALINK_STOP,
ALINK_POSTDATA,
} ALINK_CMD_e;
typedef int (*ALINK_CMD_CB)(ALINK_CMD_e cmd, int arg0, void* arg1, void* arg2);
// JavaScript调用C层接口
void alink_module_register_cmd_callback(ALINK_CMD_CB cb);
// event
// 通知JavaScript层
void alink_module_onStatusChange(int status, const char* uuid);
void alink_module_onSetAttrs(const char* jsonBuf);
void alink_module_onGetAttrs(const char* jsonBuf);
// 注册Alink类Native函数扩展
be_jse_symbol_t *alink_module_handle_cb(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *var, const char *name);
// only debug, 释放异步函数句柄
void alink_module_release();
#ifdef __cplusplus
}
#endif
#endif /* MODULE_ALINK_H_ */

View file

@ -0,0 +1,55 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
/*
* module_gpio.h
* gpio JS扩展对象
*
*/
/*
JS gpio Class
API:
gpio.open(id,config)
gpio.write(id,value)
gpio.read(id)
gpio.close(id)
Event:
*/
#ifndef MODULE_GPIO_H_
#define MODULE_GPIO_H_
#include "be_jse.h"
// 注册gpio类Native函数扩展
be_jse_symbol_t* gpio_module_handle_cb(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *var, const char *name);
// 内部函数,内部调用(be_jse_executor_init)
// gpio_dev_t初始化, index id与硬件port映射
void gpio_module_init();
#ifdef __cplusplus
}
#endif
#endif /* MODULE_GPIO_H_ */

View file

@ -0,0 +1,51 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
/*
* module_process.h
* process JS扩展对象
*
*/
/*
JS process Class
API:
process.uptime()
process.memoryUsage()
process.nextTick(callback)
process.version
process.platform
Event:
*/
#ifndef MODULE_PROCESS_H_
#define MODULE_PROCESS_H_
#include "be_jse.h"
// 注册process类Native函数扩展
be_jse_symbol_t* process_module_handle_cb(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *var, const char *name);
#ifdef __cplusplus
}
#endif
#endif /* MODULE_PROCESS_H_ */

View file

@ -0,0 +1,22 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#ifndef BE_JSE_TIMERS_H_
#define BE_JSE_TIMERS_H_
/*
timers全局函数
setTimeout(callback, delay)
clearTimeout(timeoutObject)
setInterval(callback, delay)
clearInterval(intervalObject)
*/
be_jse_symbol_t* timers_module_handle_cb(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *var, const char *name);
#endif

View file

@ -0,0 +1,59 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
/*
* be_jse_uart.h
* gpio JS扩展对象
*
*/
/*
JS uart Class
API:
return 0 : on success
uart.open(config);
example:
config.port=1;
config.baudRate=115200;
config.dataBits=8;
var serial=uart.open(config);
uart.close(port);
uart.write(port, data);
uart.read(port, timeout);
Event:
*/
#ifndef BE_JSE_UART_H_
#define BE_JSE_UART_H_
#include "be_jse.h"
// 注册uart类Native函数扩展
be_jse_symbol_t* uart_module_handle_cb(be_jse_vm_ctx_t *vm, be_jse_symbol_t *var, const char *name);
#ifdef __cplusplus
}
#endif
#endif /* BE_JSE_UART_H_ */

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,598 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
/*
* BoneEngine Javascript
* Javascript JS关键语法成分的token
* token放到本地symbol表中缓存使
* ---
*
*/
#include "be_jse_lex.h"
static void append_char(be_jse_lex_ctx_t *lex, char ch)
{
if (lex->token_len < MAX_TOKEN_LENGTH-1) {
lex->token[lex->token_len++] = ch;
} else {
be_jse_warn_at("Token name is too long! skipping character", lex, lex->token_start);
}
}
static bool is_token(be_jse_lex_ctx_t *lex, const char *token)
{
int i;
for (i=0; i<lex->token_len; i++) {
if (lex->token[i]!=token[i])
return false;
}
return token[lex->token_len] == 0;
}
/*直接跳到指定的字符 */
void lexer_seekto_char(be_jse_lex_ctx_t *lex, int seek_to_char)
{
if( lex->src) {
lex->curr_pos = seek_to_char;
return;
}
}
/*取下一个字符 */
void lexer_get_next_char(be_jse_lex_ctx_t *lex)
{
if(lex->src) {
lex->curr_char = lex->next_char;
if (lex->curr_pos < lex->end_pos) {
lex->next_char = lex->src[lex->curr_pos];
} else {
lex->next_char = 0;
}
lex->curr_pos++;
return ;
}
}
/* 根据词法分析提取JS 语法基本单元(token) */
static void next_token(be_jse_lex_ctx_t *lex)
{
lex->tk = BE_TOKEN_END;
lex->token_len = 0;
// Javascript 中的空白和注释需要先剔除掉
while (lex->curr_char && is_whitespace(lex->curr_char)) { //去除掉空格或者空行
lexer_get_next_char(lex);
}
if (lex->curr_char=='/' && lex->next_char=='/') { //去除掉注释 "//"
while (lex->curr_char && lex->curr_char!='\n') lexer_get_next_char(lex);
lexer_get_next_char(lex);
next_token(lex);
return;
}
if (lex->curr_char=='/' && lex->next_char=='*') { //去除掉注释 "/*"
while (lex->curr_char && (lex->curr_char!='*' || lex->next_char!='/')) {
lexer_get_next_char(lex);
}
lexer_get_next_char(lex);
lexer_get_next_char(lex);
next_token(lex);
return;
}
lex->token_start = lex->curr_pos-2;
//是否为一个字符,基本语句单元
if (is_alpha(lex->curr_char)) {
while (is_alpha(lex->curr_char) || is_numeric(lex->curr_char)) {
// IDs
append_char(lex, lex->curr_char);
lexer_get_next_char(lex);
}
lex->tk = BE_TOKEN_ID;
if (is_token(lex,"if")) lex->tk = BE_TOKEN_KW_IF;
else if (is_token(lex,"else")) lex->tk = BE_TOKEN_KW_ELSE;
else if (is_token(lex,"do")) lex->tk = BE_TOKEN_KW_DO;
else if (is_token(lex,"while")) lex->tk = BE_TOKEN_KW_WHILE;
else if (is_token(lex,"for")) lex->tk = BE_TOKEN_KW_FOR;
else if (is_token(lex,"break")) lex->tk = BE_TOKEN_KW_BREAK;
else if (is_token(lex,"continue")) lex->tk = BE_TOKEN_KW_CONTINUE;
else if (is_token(lex,"function")) lex->tk = BE_TOKEN_KW_FUNCTION;
else if (is_token(lex,"return")) lex->tk = BE_TOKEN_KW_RETURN;
else if (is_token(lex,"var")) lex->tk = BE_TOKEN_KW_VAR;
else if (is_token(lex,"true")) lex->tk = BE_TOKEN_KW_TRUE;
else if (is_token(lex,"false")) lex->tk = BE_TOKEN_KW_FALSE;
else if (is_token(lex,"null")) lex->tk = BE_TOKEN_KW_NULL;
else if (is_token(lex,"undefined")) lex->tk = BE_TOKEN_KW_UNDEFINED;
else if (is_token(lex,"new")) lex->tk = BE_TOKEN_KW_NEW;
else if (is_token(lex,"in")) lex->tk = BE_TOKEN_KW_IN;
else if (is_token(lex,"switch")) lex->tk = BE_TOKEN_KW_SWITCH;
else if (is_token(lex,"case")) lex->tk = BE_TOKEN_KW_CASE;
else if (is_token(lex,"default")) lex->tk = BE_TOKEN_KW_DEFAULT;
}
else if (is_numeric(lex->curr_char)) { //操作数处理
bool canBeFloating = true;
if (lex->curr_char=='0') {
append_char(lex, lex->curr_char);
lexer_get_next_char(lex);
}
if (lex->curr_char=='x' || lex->curr_char=='b') { //0xXX or 0bxx 十六进制或者二进制
canBeFloating = false; //整数
append_char(lex, lex->curr_char);
lexer_get_next_char(lex);
}
lex->tk = BE_TOKEN_INT;
while (is_numeric(lex->curr_char) || (!canBeFloating && is_hex_decimal(lex->curr_char))) { //整数
append_char(lex, lex->curr_char);
lexer_get_next_char(lex);
}
if (canBeFloating && lex->curr_char=='.') { //浮点小数
lex->tk = BE_TOKEN_FLOAT;
append_char(lex, '.');
lexer_get_next_char(lex);
while (is_numeric(lex->curr_char)) {
append_char(lex, lex->curr_char);
lexer_get_next_char(lex);
}
}
// 类似 3.45e2
if (canBeFloating && (lex->curr_char=='e'||lex->curr_char=='E')) {
lex->tk = BE_TOKEN_FLOAT;
append_char(lex, lex->curr_char);
lexer_get_next_char(lex);
if (lex->curr_char=='-') {
append_char(lex, lex->curr_char);
lexer_get_next_char(lex);
}
while (is_numeric(lex->curr_char)) {
append_char(lex, lex->curr_char);
lexer_get_next_char(lex);
}
}
} else if (lex->curr_char=='"') { //字符串
lexer_get_next_char(lex);
while (lex->curr_char && lex->curr_char!='"') {
if (lex->curr_char == '\\') {
lexer_get_next_char(lex);
switch (lex->curr_char) {
case 'n' :
append_char(lex, '\n');
break;
case '"' :
append_char(lex, '"');
break;
case '\\' :
append_char(lex, '\\');
break;
default:
append_char(lex, lex->curr_char);
break;
}
} else {
append_char(lex, lex->curr_char);
}
lexer_get_next_char(lex);
}
lexer_get_next_char(lex);
lex->tk = BE_TOKEN_STR;
} else if (lex->curr_char=='\'') { //特殊的转义字符
lexer_get_next_char(lex);
while (lex->curr_char && lex->curr_char!='\'') {
if (lex->curr_char == '\\') {
lexer_get_next_char(lex);
switch (lex->curr_char) {
case 'n' :
append_char(lex, '\n');
break;
case 'a' :
append_char(lex, '\a');
break;
case 'r' :
append_char(lex, '\r');
break;
case 't' :
append_char(lex, '\t');
break;
case '\'' :
append_char(lex, '\'');
break;
case '\\' :
append_char(lex, '\\');
break;
case 'x' : {
// 16进制数字
char buf[5] = "0x??";
lexer_get_next_char(lex);
buf[2] = lex->curr_char;
lexer_get_next_char(lex);
buf[3] = lex->curr_char;
append_char(lex, (char)string_to_int(buf));
}
break;
default:
if (lex->curr_char>='0' && lex->curr_char<='7') {
// 八进制数字
char buf[5] = "0???";
buf[1] = lex->curr_char;
lexer_get_next_char(lex);
buf[2] = lex->curr_char;
lexer_get_next_char(lex);
buf[3] = lex->curr_char;
append_char(lex, (char)string_to_int(buf));
} else {
append_char(lex, lex->curr_char);
}
break;
}
} else {
append_char(lex, lex->curr_char);
}
lexer_get_next_char(lex);
}
lexer_get_next_char(lex);
lex->tk = BE_TOKEN_STR;
} else { //运算符处理
// single chars
lex->tk = lex->curr_char;
if (lex->curr_char) lexer_get_next_char(lex);
if (lex->tk=='=' && lex->curr_char=='=') {
lex->tk = BE_TOKEN_OP_EQUAL;
lexer_get_next_char(lex);
if (lex->curr_char=='=') {
lex->tk = BE_TOKEN_OP_TYPE_EQUAL;
lexer_get_next_char(lex);
}
} else if (lex->tk=='!' && lex->curr_char=='=') {
lex->tk = BE_TOKEN_OP_NEQUAL;
lexer_get_next_char(lex);
if (lex->curr_char=='=') {
lex->tk = BE_TOKEN_OP_TYPE_NEQUAL;
lexer_get_next_char(lex);
}
} else if (lex->tk=='<' && lex->curr_char=='=') {
lex->tk = BE_TOKEN_OP_LESS_EQUAL;
lexer_get_next_char(lex);
} else if (lex->tk=='<' && lex->curr_char=='<') {
lex->tk = BE_TOKEN_OP_LEFT_SHIFT;
lexer_get_next_char(lex);
if (lex->curr_char=='=') {
lex->tk = BE_TOKEN_OP_LEFT_SHIFT_EQL;
lexer_get_next_char(lex);
}
} else if (lex->tk=='>' && lex->curr_char=='=') {
lex->tk = BE_TOKEN_OP_MORE_EQUAL;
lexer_get_next_char(lex);
} else if (lex->tk=='>' && lex->curr_char=='>') {
lex->tk = BE_TOKEN_OP_RIGHT_SHIFT;
lexer_get_next_char(lex);
if (lex->curr_char=='=') {
lex->tk = BE_TOKEN_OP_RIGHT_SHIFT_EQUAL;
lexer_get_next_char(lex);
} else if (lex->curr_char=='>') {
lex->tk = BE_TOKEN_OP_RIGHT_SHIFT_UNSIGN;
lexer_get_next_char(lex);
}
} else if (lex->tk=='+' && lex->curr_char=='=') {
lex->tk = BE_TOKEN_OP_PLUS_EQUAL;
lexer_get_next_char(lex);
} else if (lex->tk=='-' && lex->curr_char=='=') {
lex->tk = BE_TOKEN_OP_MINUS_EQUAL;
lexer_get_next_char(lex);
} else if (lex->tk=='+' && lex->curr_char=='+') {
lex->tk = BE_TOKEN_OP_PLUS_PLUS;
lexer_get_next_char(lex);
} else if (lex->tk=='-' && lex->curr_char=='-') {
lex->tk = BE_TOKEN_OP_MINUS_MINUS;
lexer_get_next_char(lex);
} else if (lex->tk=='&' && lex->curr_char=='=') {
lex->tk = BE_TOKEN_OP_AND_EQUAL;
lexer_get_next_char(lex);
} else if (lex->tk=='&' && lex->curr_char=='&') {
lex->tk = BE_TOKEN_OP_LOGIC_AND;
lexer_get_next_char(lex);
} else if (lex->tk=='|' && lex->curr_char=='=') {
lex->tk = BE_TOKEN_OP_OR_EQUAL;
lexer_get_next_char(lex);
} else if (lex->tk=='|' && lex->curr_char=='|') {
lex->tk = BE_TOKEN_OP_LOGIC_OR;
lexer_get_next_char(lex);
} else if (lex->tk=='^' && lex->curr_char=='=') {
lex->tk = BE_TOKEN_OP_XOR_EQUAL;
lexer_get_next_char(lex);
}
}
lex->token_last_end = lex->token_end;
lex->token_end = lex->curr_pos-3;
}
//初始化词法分析器
void be_jse_lexer_init(be_jse_lex_ctx_t *lex, const char *src, int start, int end)
{
if (end<0) {
end = (int)strlen(src);
}
lex->src = src;
lex->start_pos = start;
lex->end_pos = end;
lex->curr_pos = 0;
lex->tk = 0;
lex->token_start = 0;
lex->token_end = 0;
lex->token_last_end = 0;
lex->token_len = 0;
be_jse_lexer_reset(lex);
}
//从如入的JS文本字符串的指定位置开始初始化词法分析器
void be_jse_lexer_init2(be_jse_lex_ctx_t *lex, be_jse_lex_ctx_t *from, int start)
{
int idx = from->token_last_end+1;
if (idx >= from->end_pos) idx = from->end_pos;
if( from->src ) {
be_jse_lexer_init(lex, from->src, start, idx);
return;
}
}
//复位词法分析器复位状态机buffer
void be_jse_lexer_reset(be_jse_lex_ctx_t *lex)
{
lexer_seekto_char(lex, lex->start_pos);
lexer_get_next_char(lex);
lexer_get_next_char(lex);
next_token(lex);
}
void be_jse_lexer_deinit(be_jse_lex_ctx_t *lex)
{
lex->tk = BE_TOKEN_END;
if(lex->src) {
lex->src = NULL;
return ;
}
}
/* 把token 转化成字符串 */
#ifndef BE_JSE_SILENT
void lexer_token_to_str(int token, char *str, size_t len)
{
if (token>32 && token<128) {
be_assert(len>=4);
str[0] = '\'';
str[1] = (char)token;
str[2] = '\'';
str[3] = 0;
return;
}
switch (token) {
case BE_TOKEN_END :
strncpy(str, "EOF", len);
return;
case BE_TOKEN_ID :
strncpy(str, "ID", len);
return;
case BE_TOKEN_INT :
strncpy(str, "INT", len);
return;
case BE_TOKEN_FLOAT :
strncpy(str, "FLOAT", len);
return;
case BE_TOKEN_STR :
strncpy(str, "STRING", len);
return;
case BE_TOKEN_OP_EQUAL :
strncpy(str, "==", len);
return;
case BE_TOKEN_OP_TYPE_EQUAL :
strncpy(str, "===", len);
return;
case BE_TOKEN_OP_NEQUAL :
strncpy(str, "!=", len);
return;
case BE_TOKEN_OP_TYPE_NEQUAL :
strncpy(str, "!==", len);
return;
case BE_TOKEN_OP_LESS_EQUAL :
strncpy(str, "<=", len);
return;
case BE_TOKEN_OP_LEFT_SHIFT :
strncpy(str, "<<", len);
return;
case BE_TOKEN_OP_LEFT_SHIFT_EQL :
strncpy(str, "<<=", len);
return;
case BE_TOKEN_OP_MORE_EQUAL :
strncpy(str, ">=", len);
return;
case BE_TOKEN_OP_RIGHT_SHIFT :
strncpy(str, ">>", len);
return;
case BE_TOKEN_OP_RIGHT_SHIFT_UNSIGN :
strncpy(str, ">>", len);
return;
case BE_TOKEN_OP_RIGHT_SHIFT_EQUAL :
strncpy(str, ">>=", len);
return;
case BE_TOKEN_OP_PLUS_EQUAL :
strncpy(str, "+=", len);
return;
case BE_TOKEN_OP_MINUS_EQUAL :
strncpy(str, "-=", len);
return;
case BE_TOKEN_OP_PLUS_PLUS :
strncpy(str, "++", len);
return;
case BE_TOKEN_OP_MINUS_MINUS :
strncpy(str, "--", len);
return;
case BE_TOKEN_OP_AND_EQUAL :
strncpy(str, "&=", len);
return;
case BE_TOKEN_OP_LOGIC_AND :
strncpy(str, "&&", len);
return;
case BE_TOKEN_OP_OR_EQUAL :
strncpy(str, "|=", len);
return;
case BE_TOKEN_OP_LOGIC_OR :
strncpy(str, "||", len);
return;
case BE_TOKEN_OP_XOR_EQUAL :
strncpy(str, "^=", len);
return;
case BE_TOKEN_KW_IF :
strncpy(str, "if", len);
return;
case BE_TOKEN_KW_ELSE :
strncpy(str, "else", len);
return;
case BE_TOKEN_KW_DO :
strncpy(str, "do", len);
return;
case BE_TOKEN_KW_WHILE :
strncpy(str, "while", len);
return;
case BE_TOKEN_KW_FOR :
strncpy(str, "for", len);
return;
case BE_TOKEN_KW_BREAK :
strncpy(str, "return", len);
return;
case BE_TOKEN_KW_CONTINUE :
strncpy(str, "continue", len);
return;
case BE_TOKEN_KW_FUNCTION :
strncpy(str, "function", len);
return;
case BE_TOKEN_KW_RETURN :
strncpy(str, "return", len);
return;
case BE_TOKEN_KW_VAR :
strncpy(str, "var", len);
return;
case BE_TOKEN_KW_TRUE :
strncpy(str, "true", len);
return;
case BE_TOKEN_KW_FALSE :
strncpy(str, "false", len);
return;
case BE_TOKEN_KW_NULL :
strncpy(str, "null", len);
return;
case BE_TOKEN_KW_UNDEFINED :
strncpy(str, "undefined", len);
return;
case BE_TOKEN_KW_NEW :
strncpy(str, "new", len);
return;
case BE_TOKEN_KW_IN :
strncpy(str, "in", len);
return;
}
be_assert(len>=10);
strncpy(str, "?[",len);
//itostr(token, &str[2], 10);
itoa(token, &str[2], 10);
strncat(str, "]",len);
}
void lexer_get_token_str(be_jse_lex_ctx_t *lex, char *str, size_t len)
{
if (lex->tk == BE_TOKEN_ID) {
strncpy(str, "ID:",len);
strncat(str, lexer_get_token(lex),len);
} else if (lex->tk == BE_TOKEN_STR) {
strncpy(str, "String:'",len);
strncat(str, lexer_get_token(lex),len);
strncat(str, "'",len);
} else {
lexer_token_to_str(lex->tk, str, len);
}
}
#endif
char *lexer_get_token(be_jse_lex_ctx_t *lex)
{
be_assert(lex->token_len < MAX_TOKEN_LENGTH);
lex->token[lex->token_len] = 0; // add final null
return lex->token;
}
bool lexer_token_cmp(be_jse_lex_ctx_t *lex, int expected_tk)
{
if (lex->tk!=expected_tk) {
#ifndef BE_JSE_SILENT
char buf[BE_JSE_ERROR_BUF_SIZE];
size_t bufpos = 0;
strncpy(&buf[bufpos], "Got ", BE_JSE_ERROR_BUF_SIZE-bufpos);
bufpos = strlen(buf);
lexer_get_token_str(lex, &buf[bufpos], BE_JSE_ERROR_BUF_SIZE-bufpos);
bufpos = strlen(buf);
strncpy(&buf[bufpos], " expected ", BE_JSE_ERROR_BUF_SIZE-bufpos);
bufpos = strlen(buf);
lexer_token_to_str(expected_tk, &buf[bufpos], BE_JSE_ERROR_BUF_SIZE-bufpos);
be_jse_error_at(buf, lex, lex->token_start);
#else
be_jse_error_at("be_jse_lex_match error", lex, lex->token_start);
#endif
next_token(lex);
return false;
}
next_token(lex);
return true;
}
// 获取行与列信息便于查看出错位置
void lexer_dump_line_and_col(be_jse_lex_ctx_t *lex, int charPos, int *line, int *col)
{
#ifdef BE_JSE_SILENT
NOT_USED(lex);
NOT_USED(charPos);
*line = 0;
*col = 0;
#else
int currentPos = lex->curr_pos;
// reset us completely
*line = 1;
*col = 1;
lexer_seekto_char(lex, 0);
lexer_get_next_char(lex);
while (lex->curr_char && lex->curr_pos<charPos-1) {
if (lex->curr_char == '\n') {
*col=0;
(*line)++;
} else {
(*col)++;
}
lexer_get_next_char(lex);
}
// Go back to where we were
be_assert(currentPos>1); // must be, as lex should already have been loaded
lexer_seekto_char(lex, currentPos-2);
lexer_get_next_char(lex);
lexer_get_next_char(lex);
#endif
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,362 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <math.h>
#include <sys/time.h>
#include <stdarg.h>
#include "be_jse.h"
#include "be_jse_utils.h"
#ifndef BE_JSE_SILENT
static char tmp_token[MAX_TOKEN_LENGTH];
void be_jse_save_tmp_token(const char* token)
{
strcpy(tmp_token, token);
}
const char* be_jse_get_tmp_token()
{
return tmp_token;
}
#endif
ALWAYS_INLINE bool is_whitespace(char ch)
{
return (ch==' ') || (ch=='\t') || (ch=='\n') || (ch=='\r');
}
ALWAYS_INLINE bool is_numeric(char ch)
{
return (ch>='0') && (ch<='9');
}
ALWAYS_INLINE bool is_hex_decimal(char ch)
{
return ((ch>='0') && (ch<='9')) ||
((ch>='a') && (ch<='f')) ||
((ch>='A') && (ch<='F'));
}
ALWAYS_INLINE bool is_alpha(char ch)
{
return ((ch>='a') && (ch<='z')) || ((ch>='A') && (ch<='Z')) || ch=='_';
}
NO_INLINE void be_jse_error(const char *message)
{
printf("ERROR: %s\n", message);
}
NO_INLINE void be_jse_error_at(const char *message, be_jse_lex_ctx_t *lex, int tokenPos)
{
int line,col;
lexer_dump_line_and_col(lex, tokenPos, &line, &col);
be_jse_execute_error();
printf("ERROR: %s at %d:%d current tolken=%s \n", message, line, col, lex->token);
}
NO_INLINE void be_jse_warn(const char *message)
{
printf("WARNING: %s\n", message);
}
NO_INLINE void be_jse_warn_at(const char *message, be_jse_lex_ctx_t *lex, int tokenPos)
{
int line,col;
lexer_dump_line_and_col(lex, tokenPos, &line, &col);
be_jse_execute_error();
printf("WARNING: %s at %d:%d current tolken=%s \n", message, line, col, lex->token);
}
NO_INLINE void be_jse_assert_fail(const char *file, int line)
{
be_jse_execute_error();
printf("ASSERT FAIL AT %s:%d\n", file, line);
#if defined(ESP8266)
#else
//exit(1);
abort();
#endif
}
static char itoch(int val)
{
if (val<10) return (char)('0'+val);
return (char)('a'+val-10);
}
static void itostr_extra(be_jse_int_t vals,char *str,bool signedVal, unsigned int base)
{
be_jse_uint_t val;
if (signedVal && vals<0) {
*(str++)='-';
val = (be_jse_uint_t)(-vals);
} else {
val = (be_jse_uint_t)vals;
}
be_jse_uint_t tmp = val;
int digits = 1;
while (tmp>=base) {
digits++;
tmp /= base;
}
int i;
for (i=digits-1; i>=0; i--) {
str[i] = itoch((int)(val % base));
val /= base;
}
str[digits] = 0;
}
static void ftoa_bounded_extra(be_jse_float_t val,char *str, size_t len, int radix, int fractionalDigits)
{
const be_jse_float_t stopAtError = 0.0000001;
if (isnan(val)) strncpy(str,"NaN",len);
else if (!isfinite(val)) {
if (val<0) strncpy(str,"-Infinity",len);
else strncpy(str,"Infinity",len);
} else {
if (val<0) {
if (--len <= 0) {
*str=0;
return;
}
*(str++) = '-';
val = -val;
}
if (((be_jse_int_t)(val+stopAtError)) == (1+(be_jse_int_t)val))
val = (be_jse_float_t)(1+(be_jse_int_t)val);
be_jse_float_t d = 1;
while (d*radix <= val) d*=radix;
while (d >= 1) {
int v = (int)(val / d);
val -= v*d;
if (--len <= 0) {
*str=0;
return;
}
*(str++) = itoch(v);
d /= radix;
}
#ifndef USE_NO_FLOATS
if (((fractionalDigits<0) && val>0) || fractionalDigits>0) {
if (--len <= 0) {
*str=0;
return;
}
*(str++)='.';
val*=radix;
while (((fractionalDigits<0) && (fractionalDigits>-12) && (val > stopAtError)) || (fractionalDigits > 0)) {
int v = (int)(val+((fractionalDigits==1) ? 0.4 : 0.00000001) );
val = (val-v)*radix;
if (--len <= 0) {
*str=0;
return;
}
if (v==radix) v=radix-1;
*(str++)=itoch(v);
fractionalDigits--;
}
}
#endif
*(str++)=0;
}
}
ALWAYS_INLINE void itostr(be_jse_int_t val,char *str,unsigned int base)
{
itostr_extra(val, str, true, base);
}
void ftoa_bounded(be_jse_float_t val,char *str, size_t len)
{
ftoa_bounded_extra(val, str, len, 10, -1);
}
static NO_INLINE int get_radix(const char **s, int forceRadix, bool *hasError)
{
int radix = 10;
if (forceRadix > 36) {
if (hasError) *hasError = true;
return 0;
}
if (**s == '0') {
radix = 8;
(*s)++;
if (**s == 'o' || **s == 'O') {
radix = 8;
if (forceRadix && forceRadix!=8 && forceRadix<25) return 0;
(*s)++;
} else if (**s == 'x' || **s == 'X') {
radix = 16;
if (forceRadix && forceRadix!=16 && forceRadix<34) return 0;
(*s)++;
} else if (**s == 'b' || **s == 'B') {
radix = 2;
if (forceRadix && forceRadix!=2 && forceRadix<12)
return 0;
else
(*s)++;
} else if (!forceRadix) {
const char *p;
for (p=*s; *p; p++)
if (*p=='.' || *p=='8' || *p=='9')
radix = 10;
else if (*p<'0' || *p>'9') break;
}
}
if (forceRadix>0 && forceRadix<=36)
radix = forceRadix;
return radix;
}
int chtod(char ch)
{
if (ch >= '0' && ch <= '9')
return ch - '0';
else if (ch >= 'a' && ch <= 'z')
return 10 + ch - 'a';
else if (ch >= 'A' && ch <= 'Z')
return 10 + ch - 'A';
else return -1;
}
static be_jse_float_t string_to_floatr(const char *s,int forceRadix)
{
while (is_whitespace(*s)) s++;
bool isNegated = false;
if (*s == '-') {
isNegated = true;
s++;
} else if (*s == '+') {
s++;
}
const char *numberStart = s;
int radix = get_radix(&s, forceRadix, 0);
if (!radix) return NAN;
be_jse_float_t v = 0;
be_jse_float_t mul = 0.1;
while (*s) {
int digit = chtod(*s);
if (digit<0 || digit>=radix)
break;
v = (v*radix) + digit;
s++;
}
if (radix == 10) {
if (*s == '.') {
s++;
while (*s) {
if (*s >= '0' && *s <= '9')
v += mul*(*s - '0');
else break;
mul /= 10;
s++;
}
}
if (*s == 'e' || *s == 'E') {
s++;
bool isENegated = false;
if (*s == '-' || *s == '+') {
isENegated = *s=='-';
s++;
}
int e = 0;
while (*s) {
if (*s >= '0' && *s <= '9')
e = (e*10) + (*s - '0');
else break;
s++;
}
if (isENegated) e=-e;
while (e>0) {
v*=10;
e--;
}
while (e<0) {
v/=10;
e++;
}
}
}
if (numberStart==s || (numberStart[0]=='.' && numberStart[1]==0)) return NAN;
if (isNegated) return -v;
return v;
}
static long long string_to_intr(const char *s, int forceRadix, bool *hasError)
{
while (is_whitespace(*s)) s++;
bool isNegated = false;
long long v = 0;
if (*s == '-') {
isNegated = true;
s++;
} else if (*s == '+') {
s++;
}
const char *numberStart = s;
int radix = get_radix(&s, forceRadix, hasError);
if (!radix) return 0;
while (*s) {
int digit = chtod(*s);
if (digit<0 || digit>=radix)
break;
v = v*radix + digit;
s++;
}
if (hasError)
*hasError = s==numberStart;
if (isNegated) return -v;
return v;
}
be_jse_float_t string_to_float(const char *s)
{
return string_to_floatr(s,0);
}
long long string_to_int(const char *s)
{
return string_to_intr(s,0,0);
}

View file

@ -0,0 +1,386 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <sys/time.h>
#include <aos/aos.h>
#include "aos_alink_impl.h"
#ifdef USE_ALINK
#include "aos/network.h"
#include "alink_export.h"
#include "json_parser.h"
#include "kvmgr.h"
#include <netmgr.h>
#include <accs.h>
#define AOS_ALINK_LOG LOGW
static aos_log_level_t log_level = AOS_LL_WARN;
static int is_alink_started = 0;
extern int cloud_is_connected(void);
extern const char *config_get_main_uuid(void);
/*
Alink收到的云端数据转发到yloop
aos_task_name: DEFAULT-WORKQUEUE ----> aos_task_name=app
*/
static dlist_t gAlinkMsgList;
typedef struct _alink_msg {
dlist_t list_head;
int type;
char* msg;
} alink_msg_t;
static aos_mutex_t gMutex;
static int alink_get_status()
{
if( is_alink_started ) {
if( cloud_is_connected() ) {
return 2;
} else {
// 正在连接
return 1;
}
}
return 0;
}
static void aos_alink_loop(void *arg)
{
alink_msg_t *pos;
dlist_t *tmp = NULL;
aos_mutex_lock(&gMutex, AOS_WAIT_FOREVER);
// if( dlist_empty(&gAlinkMsgList) ){
// AOS_ALINK_LOG("aos_alink_impl","dlist_empty aos_task_name=%s \r\n", aos_task_name());
// }
dlist_for_each_entry_safe(&gAlinkMsgList, tmp, pos, alink_msg_t,
list_head) {
if (pos->type == 0) {
AOS_ALINK_LOG("aos_alink_impl","aos_task_name=%s \r\n", aos_task_name());
AOS_ALINK_LOG("aos_alink_impl","---> ALINK_GET_DEVICE_STATUS : %s",pos->msg);
alink_module_onGetAttrs(pos->msg);
} else {
AOS_ALINK_LOG("aos_alink_impl","aos_task_name=%s \r\n", aos_task_name());
AOS_ALINK_LOG("aos_alink_impl","---> ALINK_SET_DEVICE_STATUS : %s",pos->msg);
alink_module_onSetAttrs(pos->msg);
}
dlist_del(&pos->list_head);
aos_free(pos->msg);
aos_free(pos);
}
aos_schedule_call(aos_alink_loop, NULL);
aos_mutex_unlock(&gMutex);
}
static int alink_cloud_report(const char *method, const char *json_buffer)
{
return alink_report_async(method, json_buffer, NULL, NULL);
}
static void alink_cloud_connected(void)
{
aos_post_event(EV_YUNIO, CODE_YUNIO_ON_CONNECTED, 0);
AOS_ALINK_LOG("aos_alink_impl","alink cloud connected!");
aos_cloud_register_backend(&alink_cloud_report);
aos_cloud_trigger(CLOUD_CONNECTED, NULL);
}
static void alink_cloud_disconnected(void)
{
aos_post_event(EV_YUNIO, CODE_YUNIO_ON_DISCONNECTED, 0);
aos_cloud_trigger(CLOUD_DISCONNECTED, NULL);
}
static void alink_cloud_get_device_status(char *json_buffer)
{
aos_cloud_trigger(GET_DEVICE_STATUS, json_buffer);
}
static void alink_cloud_set_device_status(char *json_buffer)
{
aos_cloud_trigger(SET_DEVICE_STATUS, json_buffer);
}
// method "postDeviceData"
static int alink_post_data(const char* method, const char* jsonBuf)
{
int ret;
AOS_ALINK_LOG("aos_alink_impl","method=%s jsonBuf = %s \n", method, jsonBuf);
// 等同调用 alink_cloud_report
ret = aos_cloud_report(method, jsonBuf, NULL, NULL);
return ret;
}
/*
static void do_report(void)
{
snprintf(post_data_buffer, post_data_buffer_size, PostDataFormat,
device_state[ATTR_ERRORCODE_INDEX],
device_state[ATTR_HUE_INDEX],
device_state[ATTR_LUMINANCE_INDEX],
device_state[ATTR_SWITCH_INDEX],
device_state[ATTR_WORKMODE_INDEX]);
AOS_ALINK_LOG("aos_alink_impl","start report async");
aos_cloud_report(Method_PostData, post_data_buffer, NULL, NULL);
}
*/
static void cloud_get_device_status(int cb_type, const char *json_buffer)
{
/*
aos_task_name: DEFAULT-WORKQUEUE
aos_task_name=app
*/
AOS_ALINK_LOG("aos_alink_impl","---> get device status : %s",json_buffer);
alink_msg_t *pMsg;
if( json_buffer ) {
pMsg = (alink_msg_t*)aos_malloc(sizeof(pMsg));
pMsg->type = 0;
pMsg->msg = aos_malloc(strlen(json_buffer)+1);
strcpy(pMsg->msg, json_buffer);
aos_mutex_lock(&gMutex, AOS_WAIT_FOREVER);
dlist_add(&pMsg->list_head, &gAlinkMsgList);
aos_mutex_unlock(&gMutex);
aos_schedule_call(aos_alink_loop, NULL);
}
}
static void cloud_set_device_status(int cb_type, const char *json_buffer)
{
AOS_ALINK_LOG("aos_alink_impl","---> set device status : cb_type=%d , status= %s",cb_type, json_buffer);
alink_msg_t *pMsg;
if( json_buffer ) {
pMsg = (alink_msg_t*)aos_malloc(sizeof(pMsg));
pMsg->type = 1;
pMsg->msg = aos_malloc(strlen(json_buffer)+1);
strcpy(pMsg->msg, json_buffer);
aos_mutex_lock(&gMutex, AOS_WAIT_FOREVER);
dlist_add(&pMsg->list_head, &gAlinkMsgList);
aos_mutex_unlock(&gMutex);
aos_schedule_call(aos_alink_loop, NULL);
}
}
static void cloud_connected(int cb_type, const char *json_buffer)
{
// [cloud_connected#272] : taskname: DEFAULT-WORKQUEUE
AOS_ALINK_LOG("aos_alink_impl","aos_task_name: %s", aos_task_name());
//do_report();
}
static void cloud_disconnected(int cb_type, const char *json_buffer)
{
AOS_ALINK_LOG("aos_alink_impl","alink cloud disconnected!");
}
static void alink_cloud_init(void)
{
alink_register_callback(ALINK_CLOUD_CONNECTED, &alink_cloud_connected);
alink_register_callback(ALINK_CLOUD_DISCONNECTED, &alink_cloud_disconnected);
//alink_register_callback(ALINK_GET_DEVICE_RAWDATA, &alink_cloud_get_device_raw_data);
//alink_register_callback(ALINK_SET_DEVICE_RAWDATA, &alink_cloud_set_device_raw_data);
// 直连设备
alink_register_callback(ALINK_GET_DEVICE_STATUS, &alink_cloud_get_device_status);
alink_register_callback(ALINK_SET_DEVICE_STATUS, &alink_cloud_set_device_status);
aos_cloud_register_callback(CLOUD_CONNECTED, &cloud_connected);
aos_cloud_register_callback(CLOUD_DISCONNECTED, &cloud_disconnected);
aos_cloud_register_callback(GET_DEVICE_STATUS, &cloud_get_device_status);
aos_cloud_register_callback(SET_DEVICE_STATUS, &cloud_set_device_status);
}
int alink_cmd_cb(ALINK_CMD_e cmd, int arg0, void* arg1, void* arg2)
{
int ret = 0;
switch(cmd) {
case ALINK_GETLOGLEVEL:
ret = log_level;
break;
case ALINK_SETLOGLEVEL:
//alink_set_loglevel(arg0); 未实现
log_level = arg0;
aos_set_log_level(log_level);
break;
case ALINK_GETUUID:
if(config_get_main_uuid() && arg1)
strcpy(arg1, config_get_main_uuid());
break;
case ALINK_GETSTATUS:
ret = alink_get_status();
break;
case ALINK_ISRUNNING:
if( alink_get_status() )
ret = 1;
break;
case ALINK_START:
if(is_alink_started == 0) {
is_alink_started = 1;
ret = alink_start();
}
break;
case ALINK_STOP:
if(is_alink_started) {
is_alink_started = 0;
ret = alink_end();
}
break;
case ALINK_POSTDATA:
ret = alink_post_data(arg1, arg2);
break;
default:
break;
}
return ret;
}
static void alink_service_event(input_event_t *event, void *priv_data)
{
AOS_ALINK_LOG("aos_alink_impl","aos_task_name=%s \r\n", aos_task_name());
if (event->type != EV_WIFI) {
return;
}
if (event->code != CODE_WIFI_ON_GOT_IP) {
return;
}
if(is_alink_started == 0) {
is_alink_started = 1;
alink_start();
alink_module_onStatusChange(alink_get_status(), config_get_main_uuid());
}
}
static void alink_connect_event(input_event_t *event, void *priv_data)
{
AOS_ALINK_LOG("aos_alink_impl","aos_task_name=%s \r\n", aos_task_name());
if (event->type != EV_SYS) {
return;
}
if (event->code == CODE_SYS_ON_ALINK_ONLINE ) {
aos_post_event(EV_SYS, CODE_SYS_ON_START_FOTA, 0);
//do_report();
// zhengxiang.zzx
// 设备上线了
alink_module_onStatusChange(alink_get_status(), config_get_main_uuid());
//unsigned int time;
//int ret = alink_get_time(&time);
//AOS_ALINK_LOG("aos_alink_impl","get alink utc time: %d", time);
return;
}
}
void aos_alink_init()
{
// 使用 健康-体重秤
//extern void alink_use_scales();
//alink_use_scales();
AOS_ALINK_LOG("aos_alink_impl","aos_task_name=%s \r\n", aos_task_name());
if (aos_mutex_new(&gMutex) != 0) {
LOGE("aos_alink_impl", "aos_mutex_new failed !");
}
dlist_init(&gAlinkMsgList);
//aos_set_log_level(log_level);
// alink初始化
alink_cloud_init();
// alink jse扩展注册
alink_module_register_cmd_callback(alink_cmd_cb);
// 网络联通之后自动启动alink连接
// aos_register_event_filter(EV_WIFI, alink_service_event, NULL);
aos_register_event_filter(EV_SYS, alink_connect_event, NULL);
alink_module_onStatusChange(alink_get_status(), config_get_main_uuid());
}
void aos_alink_exit()
{
if(is_alink_started) {
is_alink_started = 0;
alink_end();
}
}
int aos_alink_get_time(unsigned int *utc_time)
{
#define TIME_STR_LEN (32)
char buf[TIME_STR_LEN] = { 0 }, *attr_str;
int size = TIME_STR_LEN, attr_len = 0;
int ret;
ret = alink_query("getAlinkTime", "{}", buf, &size);
if (!ret) {
attr_str = json_get_value_by_name(buf, size, "time", &attr_len, NULL);
if (attr_str && utc_time) {
sscanf(attr_str, "%u", utc_time);
}
}
return ret;
}
#endif

View file

@ -0,0 +1,301 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include "be_jse.h"
#include "be_bi_module.h"
//#define RAND_MAX (0x7FFFFFFF)
ALWAYS_INLINE be_jse_symbol_t* new_undefined_symbol()
{
return new_symbol(BE_SYM_NULL); // TODO see about above - should really be 'undefined'
}
static BE_JSE_FUNCTION_EXECUTE_CB beJseHandleFunctionCallExt = 0;
void be_jse_register_function_cb(BE_JSE_FUNCTION_EXECUTE_CB func_cb)
{
beJseHandleFunctionCallExt = func_cb;
}
#ifdef USE_STRING
static char get_char_in_str_symbol(be_jse_symbol_t *s, int idx)
{
if (!symbol_is_string(s)) return 0;
if (idx<0) idx += symbol_str_len(s); // <0 goes from end of string
if (idx<0) return 0;
s = symbol_relock(s);
while (s && idx >= symbol_get_max_char_len(s)) {
be_jse_node_t next;
idx -= symbol_get_max_char_len(s);
next = s->last_child;
symbol_unlock(s);
s = symbol_lock(next);
}
char c = 0;
if (s) {
c = s->data.str[idx];
symbol_unlock(s);
}
return c;
}
#endif
be_jse_symbol_t *handle_function_call(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *a, const char *name)
{
// 外部扩展
if (beJseHandleFunctionCallExt) {
be_jse_symbol_t *v = beJseHandleFunctionCallExt(execInfo, a, name);
if (v!=BE_JSE_FUNC_UNHANDLED)
return v;
}
#ifdef USE_GLOBAL
if (a==0) { // Special cases for where we're just a basic function
if (strcmp(name,"eval")==0) {
be_jse_symbol_t *v = be_jse_handle_single_arg_function();
be_jse_symbol_t *result = 0;
if (v) {
int len = symbol_str_len(v);
if(len) {
char *sourcePtr = aos_malloc(len+1);
symbol_to_str(v, sourcePtr, len);
result = be_jse_eval_string(execInfo->executor, sourcePtr);
aos_free(sourcePtr);
}
symbol_unlock(v);
}
//if (!result) result = new_undefined_symbol();
return result;
}
#ifdef TRACE_JSE_INFO
if(strcmp(name, "trace")==0) {
be_jse_handle_function(0, 0, 0, 0, 0);
trace_symbol_info(execInfo->executor->root, 0);
return new_symbol(BE_SYM_NULL);
}
#endif
// unhandled
return BE_JSE_FUNC_UNHANDLED;
}
#endif
// Is actually a method on some variable
if (strcmp(name,"length")==0) {
if (symbol_is_array(a)) {
lexer_token_cmp(execInfo->lex, BE_TOKEN_ID);
return new_int_symbol(get_symbol_array_length(a));
}
if (symbol_is_string(a)) {
lexer_token_cmp(execInfo->lex, BE_TOKEN_ID);
return new_int_symbol((be_jse_int_t)symbol_str_len(a));
}
}
#ifdef USE_PROCESS
// process 扩展
if (get_symbol_node_id(a) == execInfo->executor->processClass) {
#ifdef USE_AOS
if (strcmp(name,"version")==0) {
lexer_token_cmp(execInfo->lex, BE_TOKEN_ID);
return new_str_symbol("0.0.1");
}
if (strcmp(name,"platform")==0) {
lexer_token_cmp(execInfo->lex, BE_TOKEN_ID);
return new_str_symbol(aos_get_product_model());
}
#endif
}
#endif
#ifdef USE_INTEGER
// --------------------------------- built-in Integer
if (get_symbol_node_id(a) == execInfo->executor->intClass) {
if (strcmp(name,"parseInt")==0) {
char buffer[16];
be_jse_symbol_t *v = be_jse_handle_single_arg_function();
symbol_to_str(v, buffer, 16);
symbol_unlock(v);
return new_int_symbol((be_jse_int_t)string_to_int(buffer));
}
if (strcmp(name,"valueOf")==0) {
// value of a single character
int c;
be_jse_symbol_t *v = be_jse_handle_single_arg_function(execInfo);
if (!symbol_is_string(v) || symbol_str_len(v)!=1) {
symbol_unlock(v);
return new_int_symbol(0);
}
c = (int)v->data.str[0];
symbol_unlock(v);
return new_int_symbol(c);
}
}
#endif
#ifdef USE_MATH
// --------------------------------- built-in Math
if (get_symbol_node_id(a) == execInfo->executor->mathClass) {
if (strcmp(name,"random")==0) {
if (be_jse_is_none_arg_function())
return new_float_symbol((be_jse_float_t)rand() / (be_jse_float_t)RAND_MAX);
}
}
#endif
#ifdef USE_JSON
// --------------------------------- built-in JSON
if (get_symbol_node_id(a) == execInfo->executor->jsonClass) {
if (strcmp(name,"stringify")==0) {
be_jse_symbol_t *v = be_jse_handle_single_arg_function();
be_jse_symbol_t *result = new_str_symbol("");
if(result)
symbol_to_json(v, result);
symbol_unlock(v);
return result;
}
if (strcmp(name,"parse")==0) {
be_jse_symbol_t *v = be_jse_handle_single_arg_function();
be_jse_symbol_t *res=0;
int len = symbol_str_len(v);
if(len) {
char *sourcePtr = aos_malloc(len+3);
sourcePtr[0] = '(';
symbol_to_str(v, sourcePtr+1, len);
sourcePtr[len+1] = ')';
sourcePtr[len+2] = 0;
res = be_jse_eval_string(execInfo->executor, sourcePtr);
printf("sourcePtr=%s\n",sourcePtr);
aos_free(sourcePtr);
}
symbol_unlock(v);
return res;
}
}
#endif
#ifdef USE_STRING
// ------------------------------------------ Built-in String
if (symbol_is_string(a)) {
if (strcmp(name,"charAt")==0) {
char buffer[2];
int idx = 0;
be_jse_symbol_t *v = be_jse_handle_single_arg_function();
idx = (int)get_symbol_int(v);
buffer[0] = get_char_in_str_symbol(a, idx);
buffer[1] = 0;
symbol_unlock(v);
return new_str_symbol(buffer);
}
if (strcmp(name,"substring")==0) {
be_jse_symbol_t *vStart, *vEnd, *res;
int pStart, pEnd;
//bepParseDoubleFunction(&vStart, &vEnd);
be_jse_handle_function(0,&vStart, &vEnd, 0, 0);
pStart = (int)get_symbol_int(vStart);
pEnd = symbol_is_undefined(vEnd) ? BE_JSE_SYMBOL_APPEND_STR_MAX_LEN : (int)get_symbol_int(vEnd);
symbol_unlock(vStart);
symbol_unlock(vEnd);
if (pStart<0) pStart=0;
if (pEnd<0) pEnd=0;
if (pEnd<pStart) {
int l = pStart;
pStart = pEnd;
pEnd = l;
}
res = new_symbol(BE_SYM_STRING);
if (!res) return 0; // out of memory
symbol_str_value_append(res, a, pStart, pEnd-pStart);
return res;
}
if (strcmp(name,"substr")==0) {
be_jse_symbol_t *vStart, *vLen, *res;
int pStart, pLen;
//bepParseDoubleFunction(&vStart, &vLen);
be_jse_handle_function(0,&vStart, &vLen, 0, 0);
pStart = (int)get_symbol_int(vStart);
pLen = symbol_is_undefined(vLen) ? BE_JSE_SYMBOL_APPEND_STR_MAX_LEN : (int)get_symbol_int(vLen);
symbol_unlock(vStart);
symbol_unlock(vLen);
if (pLen<0) pLen=0;
res = new_symbol(BE_SYM_STRING);
if (!res) return 0; // out of memory
symbol_str_value_append(res, a, pStart, pLen);
return res;
}
if (strcmp(name,"indexOf")==0) {
be_jse_symbol_t *v = str_to_symbol(be_jse_handle_single_arg_function(), true);
if (!v) return 0; // out of memory
int idx = -1;
int l = (int)symbol_str_len(a) - (int)symbol_str_len(v);
for (idx=0; idx<l; idx++) {
if (symbol_str_cmp(a, v, idx, 0, true)==0) {
symbol_unlock(v);
return new_int_symbol(idx);
}
}
symbol_unlock(v);
return new_int_symbol(-1);
}
}
#endif
if (symbol_is_string(a) || symbol_is_object(a)) {
if (strcmp(name,"clone")==0) {
if (be_jse_is_none_arg_function())
return symbol_cp(a);
}
}
#ifdef USE_STRING
// ------------------------------------------ Built-in Array
if (symbol_is_array(a)) {
if (strcmp(name,"contains")==0) {
be_jse_symbol_t *childValue = be_jse_handle_single_arg_function();
be_jse_node_t found = symbol_unlock(get_symbol_array_index(a, childValue));
symbol_unlock(childValue);
return new_bool_symbol(found!=0);
}
if (strcmp(name,"indexOf")==0) {
be_jse_symbol_t *childValue = be_jse_handle_single_arg_function();
be_jse_symbol_t *idxName = get_symbol_array_index(a, childValue);
symbol_unlock(childValue);
if (idxName==0) return new_undefined_symbol();
be_jse_symbol_t *idx = symbol_name_cp(idxName, false, false);
symbol_unlock(idxName);
return idx;
}
if (strcmp(name,"push")==0) {
be_jse_symbol_t *childValue = be_jse_handle_single_arg_function();
be_jse_int_t newSize = symbol_array_push(a, childValue);
symbol_unlock(childValue);
return new_int_symbol(newSize);
}
if (strcmp(name,"pop")==0) {
be_jse_handle_function(0,0, 0, 0, 0);
be_jse_symbol_t *item = symbol_array_pop(a);
item = unlock_symbol_value(item);
return item;
}
}
#endif
// unhandled
return BE_JSE_FUNC_UNHANDLED;
}

View file

@ -0,0 +1,144 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include "be_iot_module.h"
#ifdef USE_ALINK
#include "module_alink.h"
#include "aos_alink_impl.h"
#endif
#ifdef USE_PROCESS
#include "module_process.h"
#endif
#ifdef USE_GPIO
#include "module_gpio.h"
#endif
#ifdef USE_TIMERS
#include "module_timers.h"
#endif
#ifdef USE_UART
#include "module_uart.h"
#endif
be_jse_symbol_t *be_iot_module_handle_cb(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *var, const char *name)
{
be_jse_symbol_t* value = BE_JSE_FUNC_UNHANDLED;
#ifdef USE_ALINK
value = alink_module_handle_cb(execInfo, var, name);
if( value != BE_JSE_FUNC_UNHANDLED )
return value;
#endif
#ifdef USE_PROCESS
value = process_module_handle_cb(execInfo, var, name);
if( value != BE_JSE_FUNC_UNHANDLED )
return value;
#endif
#ifdef USE_GPIO
value = gpio_module_handle_cb(execInfo, var, name);
if( value != BE_JSE_FUNC_UNHANDLED )
return value;
#endif
#ifdef USE_TIMERS
value = timers_module_handle_cb(execInfo, var, name);
if (value != BE_JSE_FUNC_UNHANDLED)
return value;
#endif
#ifdef USE_UART
value = uart_module_handle_cb(execInfo, var, name);
if( value != BE_JSE_FUNC_UNHANDLED )
return value;
#endif
return value;
}
void be_module_init(be_jse_executor_ctx_t *executor)
{
be_jse_symbol_t *name;
#ifdef USE_ALINK
// alink 协议扩展
name = lookup_named_child_symbol(executor->root, "alink", true);
name->flags |= BE_SYM_NATIVE;
if (!name->first_child) name->first_child = symbol_unlock(INC_SYMBL_REF(new_symbol(BE_SYM_OBJECT)));
executor->alinkClass = INC_SYMBL_REF_BY_ID(name->first_child);
symbol_unlock(name);
// only demo
// 使用 健康-体重秤
// alink初始化
aos_alink_init();
#endif
#ifdef USE_PROCESS
// process 扩展
name = lookup_named_child_symbol(executor->root, "process", true);
name->flags |= BE_SYM_NATIVE;
if (!name->first_child) name->first_child = symbol_unlock(INC_SYMBL_REF(new_symbol(BE_SYM_OBJECT)));
executor->processClass = INC_SYMBL_REF_BY_ID(name->first_child);
symbol_unlock(name);
#if 0
/*
be_jse_symbol_t* process_module_handle_cb(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *var, const char *name)
JS应用程序只读访问
*/
// 如下方法是注册到JSE符号表中, JS应用程序可以读写
be_jse_symbol_t* value = new_str_symbol("0.0.1");
symbol_unlock(add_symbol_node_name(executor->processClass, get_symbol_node_id(value), "version"));
symbol_unlock(value);
value = new_str_symbol(aos_get_product_model());
symbol_unlock(add_symbol_node_name(executor->processClass, get_symbol_node_id(value), "platform"));
symbol_unlock(value);
#endif
#endif
#ifdef USE_GPIO
// gpio 扩展
name = lookup_named_child_symbol(executor->root, "gpio", true);
name->flags |= BE_SYM_NATIVE;
if (!name->first_child) name->first_child = symbol_unlock(INC_SYMBL_REF(new_symbol(BE_SYM_OBJECT)));
executor->gpioClass = INC_SYMBL_REF_BY_ID(name->first_child);
symbol_unlock(name);
gpio_module_init();
#endif
#ifdef USE_UART
name = lookup_named_child_symbol(executor->root, "uart", true);
name->flags |= BE_SYM_NATIVE;
if (!name->first_child) name->first_child = symbol_unlock(INC_SYMBL_REF(new_symbol(BE_SYM_OBJECT)));
executor->uartClass = INC_SYMBL_REF_BY_ID(name->first_child);
symbol_unlock(name);
#endif
}
void be_module_exit()
{
// only debug
#ifdef USE_ALINK
aos_alink_exit();
alink_module_release();
#endif
}

View file

@ -0,0 +1,270 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include "be_jse_api.h"
#include "module_alink.h"
#ifdef USE_ALINK
static ALINK_CMD_CB cmdFunc = NULL;
// 事件
typedef enum {
onStatusChange = 0,
onSetAttrs,
onGetAttrs
} ALINK_EVENT_e;
static be_jse_symbol_t *onStatusChangeFunc = NULL;
static be_jse_symbol_t *onSetAttrsFunc = NULL;
static be_jse_symbol_t *onGetAttrsFunc = NULL;
// c call javascript
void alink_jse_save_event_func(ALINK_EVENT_e event, be_jse_symbol_t *listener)
{
switch( event ) {
case onStatusChange:
if( onStatusChangeFunc ) {
DEC_SYMBL_REF(onStatusChangeFunc);
onStatusChangeFunc = NULL;
}
onStatusChangeFunc = listener;
if( onStatusChangeFunc )
INC_SYMBL_REF(onStatusChangeFunc);
break;
case onSetAttrs:
if( onSetAttrsFunc ) {
DEC_SYMBL_REF(onSetAttrsFunc);
onSetAttrsFunc = NULL;
}
onSetAttrsFunc = listener;
if( onSetAttrsFunc )
INC_SYMBL_REF(onSetAttrsFunc);
break;
case onGetAttrs:
if( onGetAttrsFunc ) {
DEC_SYMBL_REF(onGetAttrsFunc);
onGetAttrsFunc = NULL;
}
onGetAttrsFunc = listener;
if( onGetAttrsFunc )
INC_SYMBL_REF(onGetAttrsFunc);
break;
default:
return;
}
}
void alink_module_register_cmd_callback(ALINK_CMD_CB cb)
{
cmdFunc = cb;
}
void alink_module_onStatusChange(int status, const char* uuid)
{
if (onStatusChangeFunc) {
be_jse_symbol_t* argv[2];
argv[0] = symbol_lock(get_symbol_node_id(new_int_symbol(status))); // status
if( uuid )
argv[1] = symbol_lock(get_symbol_node_id(new_str_symbol(uuid))); // uuid
else
argv[1] = symbol_lock(get_symbol_node_id(new_symbol(BE_SYM_NULL)));
symbol_relock(onStatusChangeFunc);
be_jse_execute_func(bone_engine_get_executor(), onStatusChangeFunc, 2, argv);
symbol_unlock(argv[0]);
symbol_unlock(argv[1]);
symbol_unlock(onStatusChangeFunc);
}
}
static void alink_jse_onAttrs(be_jse_symbol_t* func, const char* jsonBuf)
{
if( func) {
be_jse_symbol_t* argv[2];
argv[0] = symbol_lock(get_symbol_node_id(new_str_symbol(jsonBuf)));
symbol_relock(func);
be_jse_execute_func(bone_engine_get_executor(), func, 1, argv);
symbol_unlock(argv[0]);
symbol_unlock(func);
}
}
void alink_module_onSetAttrs(const char* jsonBuf)
{
alink_jse_onAttrs(onSetAttrsFunc, jsonBuf);
}
void alink_module_onGetAttrs(const char* jsonBuf)
{
alink_jse_onAttrs(onGetAttrsFunc, jsonBuf);
}
void alink_module_release()
{
if( onStatusChangeFunc ) {
DEC_SYMBL_REF(onStatusChangeFunc);
onStatusChangeFunc = NULL;
}
if( onSetAttrsFunc ) {
DEC_SYMBL_REF(onSetAttrsFunc);
onSetAttrsFunc = NULL;
}
if( onGetAttrsFunc ) {
DEC_SYMBL_REF(onGetAttrsFunc);
onGetAttrsFunc = NULL;
}
}
be_jse_symbol_t *alink_module_handle_cb(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *var, const char *name)
{
be_jse_symbol_t *arg;
be_jse_symbol_t *eventName;
be_jse_symbol_t *listener;
int arg0=0;
char method[32];
char buf[256]; // 限定JSON字符串的最大长度, 根据实际情况修改或使用aos_malloc
if (get_symbol_node_id(var) == execInfo->executor->alinkClass) {
if (strcmp(name,"on")==0) {
be_jse_handle_function(0, &eventName, &listener, 0, 0);
symbol_to_str(eventName, buf, 256);
printf("[%s][%d] Alink.on(%s, listener = %p) \n", __FUNCTION__, __LINE__, buf, listener);
if(strcmp(buf, "onStatusChange")==0) {
alink_jse_save_event_func(onStatusChange,listener);
} else if(strcmp(buf, "onSetAttrs")==0) {
alink_jse_save_event_func(onSetAttrs,listener);
} else if(strcmp(buf, "onGetAttrs")==0) {
alink_jse_save_event_func(onGetAttrs,listener);
}
symbol_unlock(eventName);
symbol_unlock(listener);
return new_symbol(BE_SYM_NULL);
}
if(strcmp(name, "getloglevel")==0) {
be_jse_handle_function(0, 0, 0, 0, 0);
arg0 = 0;
if(cmdFunc)
arg0 = cmdFunc(ALINK_GETLOGLEVEL, 0, NULL, NULL);
return new_int_symbol(arg0);
}
if( strcmp(name, "setloglevel")==0) {
be_jse_handle_function(0, &arg, 0, 0, 0);
arg0 = (int)get_symbol_int(arg);
symbol_unlock(arg);
if(cmdFunc)
cmdFunc(ALINK_SETLOGLEVEL, arg0, NULL, NULL);
return new_symbol(BE_SYM_NULL);
}
if( strcmp(name, "getuuid")==0) {
buf[0] = 0;
be_jse_handle_function(0, 0, 0, 0, 0);
if(cmdFunc)
arg0 = cmdFunc(ALINK_GETUUID, 0, buf, NULL);
return new_str_symbol(buf);
}
if( strcmp(name, "getstatus")==0) {
be_jse_handle_function(0, 0, 0, 0, 0);
arg0 = 0;
if(cmdFunc)
arg0 = cmdFunc(ALINK_GETSTATUS, 0, NULL, NULL);
return new_int_symbol(arg0);
}
if( strcmp(name, "isrunning")==0) {
be_jse_handle_function(0, 0, 0, 0, 0);
arg0 = 0;
if(cmdFunc)
arg0 = cmdFunc(ALINK_ISRUNNING, 0, NULL, NULL);
return new_int_symbol(arg0);
}
if( strcmp(name, "start")==0) {
be_jse_handle_function(0, 0, 0, 0, 0);
if(cmdFunc)
arg0 = cmdFunc(ALINK_START, 0, NULL, NULL);
return new_int_symbol(arg0);
}
if( strcmp(name, "stop")==0) {
be_jse_handle_function(0, 0, 0, 0, 0);
if(cmdFunc)
arg0 = cmdFunc(ALINK_STOP, 0, NULL, NULL);
return new_int_symbol(arg0);
}
if( strcmp(name, "postdata")==0) {
be_jse_handle_function(0, &arg, &eventName, 0, 0);
symbol_to_str(arg, method, 32);
symbol_to_str(eventName, buf, 256);
printf("[%s][%d] Alink.postdata(jsonStr = %s) cmdFunc = %p \n", __FUNCTION__, __LINE__, buf, cmdFunc);
if(cmdFunc)
arg0 = cmdFunc(ALINK_POSTDATA, 0, method, buf);
symbol_unlock(arg);
symbol_unlock(eventName);
return new_symbol(BE_SYM_NULL);
}
}
return BE_JSE_FUNC_UNHANDLED;
}
#endif

View file

@ -0,0 +1,133 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include "module_gpio.h"
#include "be_jse_api.h"
#ifdef USE_GPIO
#include "aos/kernel.h"
#include "aos/yloop.h"
#include "hal/soc/soc.h"
/*
board.h中定义
// 根据实现情况配置GPIO
#define GPIO_COUNT 5
// GPIO id号, 与硬件对应
static const int gpio_id[GPIO_COUNT]= {1,2,3,4,5};
*/
// GPIO HAL
static gpio_dev_t gpioList[GPIO_COUNT];
static int bInit = 0;
void gpio_module_init()
{
if(bInit)
return;
bInit = 1;
int i;
memset(gpioList, 0, sizeof(gpioList));
for(i=0; i<GPIO_COUNT; i++) {
gpioList[i].port = gpio_id[i];
}
}
be_jse_symbol_t* gpio_module_handle_cb(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *var, const char *name)
{
int ret=-1;
be_jse_symbol_t* arg0;
be_jse_symbol_t* arg1;
int id;
int value;
if (get_symbol_node_id(var) == execInfo->executor->gpioClass) {
if (strcmp(name,"open")==0) {
be_jse_handle_function(0, &arg0, &arg1, 0, 0);
id = get_symbol_int(arg0);
value = get_symbol_int(arg1);
symbol_unlock(arg0);
symbol_unlock(arg1);
if( id >=0 && id <= GPIO_COUNT ) {
gpioList[id].config = value;
LOGD(__FILE__, "hal_gpio_init, gpio port= %d, config=%d ", gpioList[id].port, gpioList[id].config);
ret = hal_gpio_init(&gpioList[id]);
}
return new_int_symbol(ret);
}
if(strcmp(name, "write")==0) {
be_jse_handle_function(0, &arg0, &arg1, 0, 0);
id = get_symbol_int(arg0);
value = get_symbol_int(arg1);
symbol_unlock(arg0);
symbol_unlock(arg1);
if( id >=0 && id <= GPIO_COUNT ) {
LOGD(__FILE__, "hal_gpio_output, port=%d value=%d ", gpioList[id].port, value);
if( value > 0)
ret = hal_gpio_output_high(&gpioList[id]);
else
ret = hal_gpio_output_low(&gpioList[id]);
}
return new_int_symbol(ret);
}
if(strcmp(name, "read")==0) {
be_jse_handle_function(0, &arg0, &arg1, 0, 0);
id = get_symbol_int(arg0);
value = get_symbol_int(arg1);
symbol_unlock(arg0);
symbol_unlock(arg1);
if( id >=0 && id <= GPIO_COUNT ) {
// hal_gpio_input_get 没返回值
value = -2;
ret = hal_gpio_input_get(&gpioList[id], &value);
ret = value;
}
return new_int_symbol(ret);
}
if(strcmp(name, "close")==0) {
be_jse_handle_function(0, &arg0, &arg1, 0, 0);
id = get_symbol_int(arg0);
value = get_symbol_int(arg1);
symbol_unlock(arg0);
symbol_unlock(arg1);
if( id >=0 && id <= GPIO_COUNT ) {
ret = hal_gpio_finalize(&gpioList[id]);
}
return new_int_symbol(ret);
}
}
return BE_JSE_FUNC_UNHANDLED;
}
#endif

View file

@ -0,0 +1,80 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include "module_process.h"
#include "be_jse_api.h"
#ifdef USE_PROCESS
#include "aos/kernel.h"
#include "aos/yloop.h"
void nextTick_cb(void *arg)
{
be_jse_symbol_t* func = (be_jse_symbol_t*)arg;
be_jse_execute_func(bone_engine_get_executor(), func, 0, NULL);
DEC_SYMBL_REF(func);
}
be_jse_symbol_t* process_module_handle_cb(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *var, const char *name)
{
int ret;
be_jse_symbol_t* arg0;
char buf[128]= {0};
if (get_symbol_node_id(var) == execInfo->executor->processClass) {
printf("[%s][%d] process.%s \n", __FUNCTION__, __LINE__, name);
if (strcmp(name,"nextTick")==0) {
be_jse_handle_function(0, &arg0, 0, 0, 0);
if( symbol_is_function(arg0) ) {
ret = aos_schedule_call(nextTick_cb, arg0);
if( ret >= 0 ) {
// success
INC_SYMBL_REF(arg0);
}
}
symbol_unlock(arg0);
return new_symbol(BE_SYM_NULL);
}
if(strcmp(name,"uptime")==0) {
be_jse_handle_function(0, 0, 0, 0, 0);
return new_int_symbol(aos_now_ms()/1000L);
}
if(strcmp(name,"memoryUsage")==0) {
be_jse_handle_function(0, 0, 0, 0, 0);
arg0 = new_str_symbol("");
#ifdef DUMP_SYMBL_USAGE
snprintf(buf, 127, "{ heapTotal: %d,\r\n heapUsed: %d }", BE_JSE_SYMBOL_TABLE_SIZE, be_jse_get_memory_usage());
#endif
symbol_str_append(arg0, buf);
return arg0;
}
#ifdef USE_AOS
if (strcmp(name,"version")==0) {
lexer_token_cmp(execInfo->lex, BE_TOKEN_ID);
return new_str_symbol("0.0.1");
}
if (strcmp(name,"platform")==0) {
lexer_token_cmp(execInfo->lex, BE_TOKEN_ID);
return new_str_symbol(aos_get_product_model());
}
#endif
}
return BE_JSE_FUNC_UNHANDLED;
}
#endif

View file

@ -0,0 +1,138 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include <aos/aos.h>
#include "be_jse_api.h"
#include "module_timers.h"
#ifdef USE_TIMERS
#define MAGIC 0x55ff0055
struct timer_wrap {
int magic;
be_jse_symbol_t *cbv;
long ms;
int repeat;
};
typedef struct timer_wrap timer_wrap_t;
static void timer_action(void *arg);
static void call_action(void *arg)
{
be_jse_symbol_t *func = (be_jse_symbol_t*)arg;
be_jse_execute_func(bone_engine_get_executor(), func, 0, NULL);
DEC_SYMBL_REF(func);
}
static void timer_action(void *arg)
{
LOGD("MODULE_TIMERS"," 1 aos_task_name=%s \r\n", aos_task_name());
timer_wrap_t *t = (timer_wrap_t *)arg;
LOGD("MODULE_TIMERS","JS handle =%d \n", t);
if( t->magic == MAGIC ) {
be_jse_symbol_t *func = get_symbol_value(t->cbv);
if (symbol_is_function(func)) {
INC_SYMBL_REF(func);
// 需要考虑在callback中clearInterval/clearTimeout自身
aos_schedule_call(call_action, func);
}
symbol_unlock(func);
if (t->repeat) {
aos_post_delayed_action(t->ms, timer_action, t);
} else {
symbol_unlock(t->cbv);
t->magic = 0;
aos_free(t);
LOGI("MODULE_TIMERS","aos_free(%p) \n", t);
}
} else {
LOGW("MODULE_TIMERS","alread free \n");
}
LOGD("MODULE_TIMERS"," 2 aos_task_name=%s \r\n", aos_task_name());
}
static be_jse_symbol_t *setup_timer(int repeat)
{
be_jse_symbol_t *cbv;
be_jse_symbol_t *msv;
be_jse_handle_function(0, &cbv, &msv, NULL, NULL);
be_jse_symbol_t *func = get_symbol_value(cbv);
if( !func || !msv || (!symbol_is_function(func))) {
LOGE("MODULE_TIMERS","process timer parameter error\n");
symbol_unlock(func);
symbol_unlock(cbv);
symbol_unlock(msv);
return new_symbol(BE_SYM_NULL);
}
symbol_unlock(func);
long ms = get_symbol_value_int(msv);
symbol_unlock(msv);
timer_wrap_t *t = aos_malloc(sizeof(*t));
t->magic = MAGIC;
t->cbv = cbv;
t->ms = ms;
t->repeat = repeat;
aos_post_delayed_action(ms, timer_action, t);
LOGD("MODULE_TIMERS","JS handle =%d \n", t);
return new_int_symbol((be_jse_int_t)t);
}
static be_jse_symbol_t* clear_timer()
{
be_jse_symbol_t *hv = be_jse_handle_single_arg_function();
if (hv) {
timer_wrap_t *t = (timer_wrap_t *)get_symbol_value_int(hv);
LOGD("MODULE_TIMERS","JS handle =%d \n", t);
if( t->magic == MAGIC ) {
aos_cancel_delayed_action(t->ms, timer_action, t);
symbol_unlock(t->cbv);
t->magic = 0;
aos_free(t);
LOGW("MODULE_TIMERS","aos_free(%p) \n", t);
} else {
LOGW("MODULE_TIMERS","alread free \n");
}
}
symbol_unlock(hv);
return new_symbol(BE_SYM_NULL);
}
be_jse_symbol_t *timers_module_handle_cb(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *var, const char *name)
{
if (var)
return BE_JSE_FUNC_UNHANDLED;
if (!strcmp(name, "setTimeout"))
return setup_timer(0);
if (!strcmp(name, "clearTimeout"))
return clear_timer();
if (!strcmp(name, "setInterval"))
return setup_timer(1);
if (!strcmp(name, "clearInterval"))
return clear_timer();
return BE_JSE_FUNC_UNHANDLED;
}
#endif

View file

@ -0,0 +1,205 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include "module_uart.h"
#include "hal/soc/soc.h"
#include <aos/aos.h>
// 最多支持两个串口
#define UART_COUNT 2
static uart_dev_t uart[UART_COUNT];
static bool uartStatus[UART_COUNT] = {-1,-1}; // 0: opened
#ifdef USE_UART
be_jse_symbol_t* uart_module_handle_cb(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *var, const char *name)
{
int ret=-1;
be_jse_symbol_t* arg0;
be_jse_symbol_t* arg1;
be_jse_symbol_t* child;
int port=0;
int value;
uart_dev_t *pUart=NULL;
char data[128];
if (get_symbol_node_id(var) == execInfo->executor->uartClass) {
if (strcmp(name,"open")==0) {
be_jse_handle_function(0, &arg0, 0, 0, 0);
if( symbol_is_object(arg0)) {
child = lookup_named_child_symbol(get_symbol_node_id(arg0), "port", false);
if( child ) {
port = get_symbol_value_int(child);
symbol_unlock(child);
if( port < 0 || port >=UART_COUNT ) {
LOGE("MODULE_UART","parameter error, port = %d", port);
return new_int_symbol((be_jse_int_t)ret);
}
} else {
LOGE("MODULE_UART","invalid parameter, need port !");
return new_int_symbol(ret);
}
if(uartStatus[port]==0) {
LOGE("MODULE_UART","uart port=%d, alread open !", port);
return new_int_symbol(ret);
}
pUart = &uart[port];
pUart->port = port;
// 默认参数
pUart->config.baud_rate = 115200;
pUart->config.data_width = DATA_WIDTH_8BIT;
pUart->config.parity = NO_PARITY;
pUart->config.stop_bits = STOP_BITS_1;
pUart->config.flow_control = FLOW_CONTROL_DISABLED;
child = lookup_named_child_symbol(get_symbol_node_id(arg0), "baudRate", false);
if( child ) {
pUart->config.baud_rate = get_symbol_value_int(child);
symbol_unlock(child);
}
child = lookup_named_child_symbol(get_symbol_node_id(arg0), "dataBits", false);
if( child ) {
value = get_symbol_value_int(child);
symbol_unlock(child);
switch(value) {
case 5:
pUart->config.data_width = DATA_WIDTH_5BIT;
break;
case 6:
pUart->config.data_width = DATA_WIDTH_6BIT;
break;
case 7:
pUart->config.data_width = DATA_WIDTH_7BIT;
break;
case 8:
pUart->config.data_width = DATA_WIDTH_8BIT;
break;
case 9:
pUart->config.data_width = DATA_WIDTH_9BIT;
break;
default:
break;
}
}
}
symbol_unlock(arg0);
LOGW("MODULE_UART","pUart->port=%d", pUart->port);
LOGW("MODULE_UART","pUart->config.baud_rate=%d", pUart->config.baud_rate);
LOGW("MODULE_UART","pUart->config.data_width=%d", pUart->config.data_width);
uartStatus[port] = hal_uart_init(pUart);
return new_int_symbol(uartStatus[port]);
}
if(strcmp(name,"close")==0) {
be_jse_handle_function(0, &arg0, &arg1, 0, 0);
port = get_symbol_int(arg0);
symbol_to_str(arg1, data, 127);
symbol_unlock(arg0);
symbol_unlock(arg1);
if( port < 0 || port >=UART_COUNT ) {
LOGE("MODULE_UART","parameter error, port = %d", port);
return new_int_symbol(ret);
}
if(uartStatus[port]!=0) {
LOGE("MODULE_UART","uart port=%d, need open !", port);
return new_int_symbol(ret);
}
pUart = &uart[port];
ret = hal_uart_finalize(pUart);
return new_int_symbol(ret);
}
if(strcmp(name,"write")==0) {
be_jse_handle_function(0, &arg0, &arg1, 0, 0);
port = get_symbol_int(arg0);
symbol_to_str(arg1, data, 127);
symbol_unlock(arg0);
symbol_unlock(arg1);
if( port < 0 || port >=UART_COUNT ) {
LOGE("MODULE_UART","parameter error, port = %d", port);
return new_int_symbol(ret);
}
if(uartStatus[port]!=0) {
LOGE("MODULE_UART","uart port=%d, need open !", port);
return new_int_symbol(ret);
}
pUart = &uart[port];
value = strlen(data);
LOGW("MODULE_UART", "uart port=%d, write=%s, len=%d", port, data, value);
ret = hal_uart_send(pUart, data, value, AOS_WAIT_FOREVER);
return new_int_symbol(ret);
}
if(strcmp(name,"read")==0) {
be_jse_handle_function(0, &arg0, &arg1, 0, 0);
port = get_symbol_int(arg0);
value = get_symbol_int(arg1); // timeout
symbol_unlock(arg0);
symbol_unlock(arg1);
if( port < 0 || port >=UART_COUNT ) {
LOGE("MODULE_UART","parameter error, port = %d", port);
return new_int_symbol(ret);
}
if(uartStatus[port]!=0) {
LOGE("MODULE_UART","uart port=%d, need open !", port);
return new_int_symbol(ret);
}
//LOGW("MODULE_UART", "timeout=%d", value);
if( value < 0 )
value = 0;
if( value > 10*1000)
value = 10*1000;
pUart = &uart[port];
memset(data, 0, sizeof(data));
ret = hal_uart_recv_II(pUart, data, 127, &value, value);
//LOGW("MODULE_UART", "uart port=%d, read=%s, value=%d, ret=%d", port, data, value, ret);
return new_str_symbol(data);
}
}
return BE_JSE_FUNC_UNHANDLED;
}
#endif

View file

@ -0,0 +1,123 @@
/*
* Copyright (C) 2015-2017 Alibaba Group Holding Limited
*/
#include "be_jse.h"
#include "be_jse_api.h"
#ifdef USE_AOS
#include "aos/aos.h" // LOGW LOGD
#endif
#include "be_bi_module.h"
#include "be_iot_module.h"
static be_jse_executor_ctx_t beJseExecutor;
static BE_JSE_FUNCTION_EXECUTE_CB be_user_ext_function_cb = 0;
be_jse_executor_ctx_t* bone_engine_get_executor()
{
return &beJseExecutor;
}
void bone_engine_native_function_register(BE_JSE_FUNCTION_EXECUTE_CB extension)
{
be_user_ext_function_cb = extension;
}
be_jse_symbol_t *be_native_module_handle_cb(be_jse_vm_ctx_t *execInfo, be_jse_symbol_t *var, const char *name)
{
be_jse_symbol_t* value = BE_JSE_FUNC_UNHANDLED;
// modules 对象扩展
value = be_iot_module_handle_cb(execInfo, var, name);
if( value != BE_JSE_FUNC_UNHANDLED )
return value;
// 用户注册的对扩展
if (be_user_ext_function_cb) {
value = be_user_ext_function_cb(execInfo, var, name);
if (value != BE_JSE_FUNC_UNHANDLED)
return value;
}
return value;
}
void bone_engine_init()
{
be_jse_symbol_table_init();
be_jse_executor_init(&beJseExecutor);
be_module_init(&beJseExecutor);
be_jse_register_function_cb(be_native_module_handle_cb);
}
/*
bone_engine_init之后调用
*/
be_jse_node_t bone_engine_native_object_register(const char* objectName)
{
be_jse_node_t objRef = 0;
be_jse_symbol_t *name;
name = lookup_named_child_symbol(beJseExecutor.root, objectName, true);
name->flags |= BE_SYM_NATIVE;
if (!name->first_child) name->first_child = symbol_unlock(INC_SYMBL_REF(new_symbol(BE_SYM_OBJECT)));
objRef = INC_SYMBL_REF_BY_ID(name->first_child);
symbol_unlock(name);
return objRef;
}
void bone_engine_exit()
{
be_module_exit();
#ifdef TRACE_JSE_INFO
trace_symbol_info(beJseExecutor.root, 0);
#endif
#ifdef DUMP_SYMBL_USAGE
LOGW("bone_engine","befor: %d Memory Records Used\n", be_jse_get_memory_usage());
#endif
be_jse_executor_deinit(&beJseExecutor);
#ifdef DUMP_SYMBL_USAGE
LOGW("bone_engine","after: %d Memory Records Used (should be 0!)\n", be_jse_get_memory_usage());
be_jse_show_symbol_table_used();
#endif
}
void bone_engine_start(const char* js)
{
be_jse_symbol_t* value;
value = be_jse_eval_string(&beJseExecutor, js);
symbol_unlock(value);
}
void bone_engine_restart(const char* js)
{
be_jse_symbol_t* value;
bone_engine_exit();
bone_engine_init();
value = be_jse_eval_string(&beJseExecutor, js);
symbol_unlock(value);
}